Skip to content

Instantly share code, notes, and snippets.

@Tabea-K
Last active August 28, 2018 12:38
Show Gist options
  • Save Tabea-K/18832ee43336481e9c8f48a041ab02c6 to your computer and use it in GitHub Desktop.
Save Tabea-K/18832ee43336481e9c8f48a041ab02c6 to your computer and use it in GitHub Desktop.
Bash script to generate the directory structure and files needed for the generation of an empty python project template. The first argument supplied is used as the main name of the python project, the second as the name of the main python code file. A directory "tests" is generated for unit tests, which also includes an example test case.
#!/bin/bash
# This creates a more or less empty template for a python package
# containing unit tests
# Author: Tabea Kischka, 2018-07-02
# Version 2.0, last update: 2018-08-28
###########################################################################################################
# get options
###########################################################################################################
usage(){
echo -ne "Run like this:\ncreate_empty_python_package_template.sh -p PACKAGENAME -m NAMEOFMAINSCRIPT -a AUTHORNAME\n"
echo -ne "-p\tPACKAGENAME\t\tThe name you choose for your python package\n"
echo -ne "-m\tNAMEOFMAINSCRIPT\t\tThe name you choose for the main script of your package\n"
echo -ne "-a\tAUTHOR\t\tYour name (will be included in the README file)\n"
echo -ne -ne "\n\nIn the end the directory structure will look like this:\n\n
.
├── README.rst
├── package_name
│   ├── __init__.py
│   ├── main_script_name.py
│   └── tests
│   ├── test_package_name.py
│   └── testdata.txt
└── setup.py\n\n"
exit 1
}
while getopts "p:m:a:h" opt
do
case "${opt}"
in
p) PACKAGENAME="$OPTARG";;
m) MAINSCRIPTNAME="$OPTARG";;
a) AUTHOR="$OPTARG";;
h) usage;;
*) usage;;
\?) echo "Invalid option: -$OPTARG" >&2; exit 1;;
:) echo "Option -$OPTARG requires an argument." >&2; exit 1;;
esac
done
if [ -z "${PACKAGENAME}" ] || [ -z "${MAINSCRIPTNAME}" ] || [ -z "${AUTHOR}" ]; then
usage
fi
if [ -d "$PACKAGENAME" ]
then
echo "ERROR: $PACKAGENAME already exists. Please choose another name."
exit 1
fi
###########################################################################################################
# start generating files...
###########################################################################################################
D=`date`
echo "
------------------------
Will now generate directory structure and files for the python project $PACKAGENAME
under the folder $PWD
------------------------
"
###########################################################################################################
# make main dir
###########################################################################################################
mkdir "$PACKAGENAME"
cd "$PACKAGENAME"
###########################################################################################################
# create readme files
###########################################################################################################
echo "Python package $PACKAGENAME created on $D by $AUTHOR" > README.rst
###########################################################################################################
# generate file setup.py
###########################################################################################################
echo "from setuptools import setup
def readme():
with open('README.rst') as f:
return f.read()
# if you want to include more test data within your package, you have to list it inside the list package_data in setup!
setup(name='${PACKAGENAME}',
version='0.1',
description='A super cool package that was generated with the python project template generator.',
long_description=readme(),
author='${AUTHOR}',
author_email='',
license='',
packages=['$PACKAGENAME'],
test_suite='nose.collector',
tests_require=['nose'],
package_data={'${PACKAGENAME}': ['README.rst', 'tests/testdata.txt']},
include_package_data=True,
entry_points={
'console_scripts': ['${PACKAGENAME}=${PACKAGENAME}.${MAINSCRIPTNAME}:main'],
},
zip_safe=False)" > setup.py
###########################################################################################################
# make python script dir
###########################################################################################################
mkdir "$PACKAGENAME"
cd "$PACKAGENAME"
###########################################################################################################
# make init file
###########################################################################################################
echo "from $MAINSCRIPTNAME import *" > __init__.py
echo -ne "#!/usr/bin/env python
import sys
import os
import argparse
import logging
__version__ = '1.0'
script_description = 'Description of the $MAINSCRIPTNAME script'
def hello_world():
return('hello world')
def print_infile_name(infile_fh):
return(infile_fh.name)
def main():
# parse arguments
parser = argparse.ArgumentParser(description=script_description)
parser.add_argument('infile',
help='input file',
nargs='?',
type=argparse.FileType('r'),
default=sys.stdin)
parser.add_argument('-d',
help='run in debug mode, print lots of information',
action='store_const',
dest='loglevel',
const=logging.DEBUG,
default=logging.WARNING)
parser.add_argument('-d',
help='run in debug mode, print lots of information',
action='store_const',
dest='loglevel',
const=logging.DEBUG,
default=logging.WARNING)
parser.add_argument('-v',
help='run in verbose mode, print some more information',
action='store_const',
dest='loglevel',
const=logging.INFO,
default=logging.WARNING)
args = parser.parse_args()
# set up logging module
logging.basicConfig(format='[%(asctime)s - %(levelname)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=args.loglevel)
logger = logging.getLogger(__name__)
logger.debug('logging set up!')
logger.debug('All arguments: %s' % args)
logger.info('Script starts!')
hello_world()
print_infile_name(args.infile)
" > "${MAINSCRIPTNAME}.py"
###########################################################################################################
# make test files
###########################################################################################################
mkdir tests
cd tests
echo "#!/usr/bin/env python
import unittest
import $MAINSCRIPTNAME
class MyTestCase(unittest.TestCase):
def test_hello_world(self):
text = $MAINSCRIPTNAME.hello_world()
self.assertEqual(text, 'hello world')
# Add more tests here
"> "test_${PACKAGENAME}.py"
echo -ne "This could be your test data\n" > testdata.txt
###########################################################################################################
# Last steps...
###########################################################################################################
# go back to the initial directory
cd ../..
echo "
Finished!
You now have an empty template for your $PACKAGENAME python project!
You can add unit tests to the file $PACKAGENAME/tests/test_${PACKAGENAME}.py and run the
unit tests using this command:
cd $PWD/$PACKAGENAME && \
python -m unittest discover -v -s tests
"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment