2021-11-03 02:40:46 +00:00
#!/usr/bin/env bash
2021-07-26 01:15:54 +00:00
# A tool to create a new python project with less setup than usual.
# v1.0 Jul 2021 by Cronocide
2021-07-21 01:41:35 +00:00
2021-07-26 00:57:19 +00:00
# Boilerplate functions from bash_profile for convenience
2021-07-21 01:41:35 +00:00
OS = " $( uname -a) "
[ [ " $OS " = = *"iPhone" * || " $OS " = = *"iPad" * ] ] && export OS = "iOS"
[ [ " $OS " = = *"ndroid" * ] ] && export OS = "Android"
[ [ " $OS " = = *"kali" * ] ] && export OS = "Kali"
[ [ " $OS " = = *"indows" * ] ] && export OS = "Windows"
[ [ " $OS " = = *"arwin" * ] ] && export OS = "macOS"
[ [ " $OS " = = *"BSD" * ] ] && export OS = "BSD"
[ [ " $OS " = = *"inux" * ] ] && export OS = "Linux"
__no_req( ) {
[ [ " $( type $1 2>/dev/null) " = = "" ] ] && return 0;
return 1
}
__missing_reqs( ) {
for i in " $@ " ; do
[ [ " $0 " != " $i " ] ] && __no_req " $i " && echo " $i is required to perform this function. " && return 0;
done ;
return 1
}
__missing_sed( ) {
__no_req "sed" && __no_req "gsed" && echo "sed or gsed is required to perform this function." && return 0
}
2021-11-03 03:26:44 +00:00
__require_bash( ) {
__no_req "sort" && return 1;
[ [ $( printf " $1 \n $BASH_VERSION " | sort -V | head -n 1) != " $1 " ] ] && return 1;
return 0
}
2021-07-21 01:41:35 +00:00
sed_i( ) {
__missing_sed && return 1;
if [ [ " $OS " = = "macOS" ] ] ; then
if [ [ $( type gsed 2>/dev/null) != "" ] ] ; then
2021-07-26 00:27:31 +00:00
gsed -i " $@ " ;
2021-07-21 01:41:35 +00:00
else
2021-11-03 02:28:59 +00:00
sed -i '' " $@ " ;
2021-07-21 01:41:35 +00:00
fi ;
else
sed -i $@ ;
fi
}
# Project creation
new_python_tool( ) {
2021-11-03 03:26:44 +00:00
# Check that we can run this tool
if ! $( __require_bash "4.3" ) ; then echo "Bash 4.3 or greater is required to run this script." && return 1; fi
2021-07-21 01:41:35 +00:00
__missing_reqs 'sed git find grep sort mv' && return 1
2021-07-26 00:34:15 +00:00
if [ [ $( pwd ) = = *"python-tool" * ] ] ; then
echo "This script should not be run within the python-tool directory. Please move it to a neutral location to run." && return 1
2021-07-21 01:41:35 +00:00
fi
2021-11-03 02:43:19 +00:00
[ -z " $1 " ] && echo "Usage: new_python_tool <name_of_tool>" && return 1
2021-07-21 01:41:35 +00:00
NAME = " $1 "
if [ [ $( echo " $1 " | sed 's#^[a-z0-9\-]*$##' ) = = " $NAME " ] ] ; then
echo "Tool name '" " $NAME " "' is invalid." && return 1
fi
2021-11-03 03:26:44 +00:00
# Download and rename the template repo
2021-07-26 00:34:15 +00:00
if [ ! -d ./python-tool ] ; then
2021-07-21 01:41:35 +00:00
echo "Downloading template..."
2021-07-26 00:34:15 +00:00
git clone 'https://github.com/Cronocide/python-tool.git'
2021-07-21 01:41:35 +00:00
fi
echo "Renaming project..."
# Rather novel approach from https://stackoverflow.com/a/53734138
2021-07-26 00:34:15 +00:00
find ./ -depth -name '*python-tool*' | while IFS = read -r i; do mv $i ${ i %python-tool* } $NAME ${ i ##*python-tool } ; done
2021-07-21 01:41:35 +00:00
# "I'm assuming you have no spaces in the project name because you're not an idiot."
2021-07-26 00:34:15 +00:00
for i in $( grep -r 'python-tool' ./" $NAME " | grep -v '.git' | cut -d \: -f 1 | sort -u) ; do
sed_i " s#python-tool# $NAME #g " " $i "
2021-07-21 01:41:35 +00:00
done
mv ./" $NAME " /com.cronocide." $NAME " .plist ./" $NAME " /com." $USER " ." $NAME " .plist
echo "Configuring project..."
2021-07-26 00:27:31 +00:00
2021-11-03 03:26:44 +00:00
# Record setup instructions
declare -a PYTHON_TOOL_SETUP_INSTRUCTIONS
2021-11-03 03:53:01 +00:00
declare -a PYTHON_TOOL_WARNINGS
2021-11-03 03:26:44 +00:00
2021-07-26 00:27:31 +00:00
# Describe the project
echo "Describe the project: "
read DESCRIPTION
sed_i "s/## ->.*//g" ./" $NAME " /README.md
sed_i " s/## Description/## $DESCRIPTION /g " ./" $NAME " /README.md
sed_i " s/\(.*\)description='',/\1description=' $DESCRIPTION ',/g " ./" $NAME " /setup.py
2021-07-21 01:41:35 +00:00
# Configure package as a module?
while [ [ " $PYTHON_MODULE " != 'y' && " $PYTHON_MODULE " != "n" ] ] ; do
echo "Set up project as a module? (in addition to a singular executable script) (y/n)"
read PYTHON_MODULE
done
if [ " $PYTHON_MODULE " = = 'y' ] ; then
mkdir ./" $NAME " /" $NAME "
2021-11-03 03:42:36 +00:00
echo " from $NAME . $NAME import * " > ./" $NAME " /" $NAME " /__init__.py
2021-11-03 04:32:38 +00:00
# touch ./"$NAME"/"$NAME"/"$NAME".py
echo " # Write your modular code (classes, functions, etc) here. They'll be automatically imported in bin/ $NAME " > ./" $NAME " /" $NAME " /" $NAME " .py
2021-11-03 03:26:44 +00:00
PYTHON_TOOL_SETUP_INSTRUCTIONS += " Put your main classes and functionality in $NAME / $NAME .py and import/use that functionality in bin/ $NAME "
2021-11-03 04:32:38 +00:00
PYTHON_TOOL_WARNINGS += 'You can use this package as a library! Classes you define in ' " $NAME / $NAME .py " " can be imported with 'import $NAME .class_name "
2021-11-03 03:26:44 +00:00
else
2021-11-03 04:49:14 +00:00
sed_i " s#import $NAME ##g " ./" $NAME " /bin/" $NAME "
2021-07-21 01:41:35 +00:00
fi
2021-07-26 00:27:31 +00:00
2021-07-21 01:41:35 +00:00
# Configure package to install as a persistent service?
while [ [ " $SERVICE_FILE " != 'y' && " $SERVICE_FILE " != "n" ] ] ; do
2021-11-03 04:32:38 +00:00
echo "Install a persistent service file? (systemd/launchd services ONLY) (y/n)"
2021-07-21 01:41:35 +00:00
read SERVICE_FILE
done
if [ " $SERVICE_FILE " = = 'y' ] ; then
2021-07-26 00:47:45 +00:00
sed_i "s#INSTALL=\"\(.*\)\"#INSTALL=\"\1services \"#g" ./" $NAME " /setup.sh
2021-07-21 01:41:35 +00:00
# Configure service file to log output to file?
while [ [ " $SERVICE_LOG " != 'y' && " $SERVICE_LOG " != "n" ] ] ; do
echo "Configure the service file to log output? (y/n)"
read SERVICE_LOG
done
if [ " $SERVICE_LOG " != 'y' ] ; then
sed_i 's#.*Standard.*##g' ./" $NAME " /com." $USER " ." $NAME " .plist
sed_i 's#.*/var/log.*##g' ./" $NAME " /com." $USER " ." $NAME " .plist
sed_i 's#.*[sS]yslog.*##g' ./" $NAME " /" $NAME " .service
fi
# Don't forget to configure the service files.
2021-11-03 04:32:38 +00:00
PYTHON_TOOL_SETUP_INSTRUCTIONS += " Modify your service files ( $NAME .service and com. $USER . $NAME .plist) to schedule when the tool should run. By default, they run at boot and stay alive. "
# echo "Don't forget to configure your service files."
2021-07-21 01:41:35 +00:00
else
# Remove the custom setup scripts
2021-07-26 00:27:31 +00:00
rm ./" $NAME " /com." $USER " ." $NAME " .plist
2021-07-21 01:41:35 +00:00
rm ./" $NAME " /" $NAME " .service
fi
2021-07-26 00:27:31 +00:00
2021-07-21 01:41:35 +00:00
# Configure package to load plugins from plugins directory?
while [ [ " $USE_PLUGINS " != 'y' && " $USE_PLUGINS " != "n" ] ] ; do
echo "Configure package to load plugins? (y/n)"
read USE_PLUGINS
done
if [ " $USE_PLUGINS " = = 'y' ] ; then
2021-07-26 00:27:31 +00:00
# You've made Thomas Hatch proud.
2021-07-21 01:41:35 +00:00
! [ -d ./" $NAME " /" $NAME " ] && mkdir ./" $NAME " /" $NAME "
2021-11-03 04:32:38 +00:00
sed_i "s/.*##PLUGIN_\(.*\)/\1/g" ./" $NAME " /bin/" $NAME "
2021-07-21 01:41:35 +00:00
mkdir ./" $NAME " /" $NAME " /plugins
2021-11-03 04:49:14 +00:00
touch ./" $NAME " /" $NAME " /plugins/plugin.py
2021-07-21 01:41:35 +00:00
else :
sed_i 's#.*plugins.*##g' ./" $NAME " /setup.py
2021-11-03 04:32:38 +00:00
sed_i "s/.*##PLUGIN_\(.*\)//g" ./" $NAME " /bin/" $NAME "
2021-07-21 01:41:35 +00:00
fi
2021-07-26 00:27:31 +00:00
2021-07-21 01:41:35 +00:00
# Configure package to install a default configuration file?
2021-07-26 00:27:31 +00:00
while [ [ " $INSTALL_CONFIG " != 'y' && " $INSTALL_CONFIG " != "n" ] ] ; do
2021-11-03 03:42:36 +00:00
echo "Configure package to use and install a config file? (y/n)"
2021-07-26 00:27:31 +00:00
read INSTALL_CONFIG
done
if [ " $INSTALL_CONFIG " = = 'y' ] ; then
sed_i "s#INSTALL=\"\(.*\)\"#INSTALL=\"\1config \"#g" ./" $NAME " /setup.sh
2021-11-03 03:53:01 +00:00
sed_i "s/.*##CONFIG_\(.*\)/\1/g" ./" $NAME " /bin/" $NAME "
2021-11-03 04:32:38 +00:00
PYTHON_TOOL_WARNINGS += "You'll need to install a copy of the config file yourself for debugging, as config.yml will only be installed when the package is installed."
2021-11-03 02:37:08 +00:00
else
2021-11-03 03:53:01 +00:00
sed_i "s/.*##CONFIG_\(.*\)//g" ./" $NAME " /bin/" $NAME "
2021-11-03 02:37:08 +00:00
rm ./" $NAME " /config.yml
2021-07-26 00:27:31 +00:00
fi
# Remove setup.sh if our tool doesn't need it to install.
2021-07-26 00:34:15 +00:00
if [ [ " $SERVICE_FILE " != 'y' && " $INSTALL_CONFIG " != 'y' ] ] ; then
2021-11-03 02:28:59 +00:00
sed_i 's#cmdclass=.*##g' ./" $NAME " /setup.py
2021-07-26 00:27:31 +00:00
rm ./" $NAME " /setup.sh
2021-11-03 04:32:38 +00:00
else
PYTHON_TOOL_WARNINGS += "The target system will need to have bash to run the postinstall actions you've chosen."
2021-07-26 00:27:31 +00:00
fi
2021-07-21 01:41:35 +00:00
# Initialize the git repo
rm -rf ./" $NAME " /.git
git init ./" $NAME "
2021-07-26 01:15:54 +00:00
# Delete self from project_file
[ -f ./" $NAME " /new_python_tool.sh ] && echo "Removing project setup script..." && rm ./" $NAME " /new_python_tool.sh
echo " Python tool $NAME is ready to start. "
2021-07-21 01:41:35 +00:00
# Next steps
echo "Next steps:"
echo " 1. Modify your bin/ $NAME file to load your project libraries (if applicable) "
2021-07-26 00:27:31 +00:00
echo " 2. Add a remote to the git repo"
echo " 3. Add the correct dependencies in setup.py"
2021-07-21 01:41:35 +00:00
echo " 4. Update the execution and logging parameters in your service files (if applicable)"
echo " 5. Write the software"
2021-07-26 00:27:31 +00:00
echo " 6. ..."
echo " 7. Profit"
2021-07-21 01:41:35 +00:00
}
new_python_tool " $1 "