Automating The Creation Of Projects With Python
6 Min Read
The Story
As a developer who always has fresh new app/package ideas, I got bored of doing the same thing every single time - the whole task of creating a project directory, README.md
and extra files. I got so used to the repetition to the point where it was just in my subconscious until I just had enough.
Hence this post, in this post I will try to detail a trick I have added in my dot-files. The function/trick automates the process of creating new projects and currently only supports Python, MicroPython, and Arduino projects.
In the past, I wrote a post detailing how I increased my productivity using my dotfiles, check it out here
DISCLAIMER: If you want to give these dotfiles a try, you should first fork this repository, review the code, and remove things you don’t want or need. Don’t blindly use my settings unless you know what that entails.
The How
I use cookiecutter a CLI utility that creates projects from templates, for both the Python and MicroPython projects, and Platformio for the Arduino related projects. After successful project creation, the function executes a Python script which uses PyGithub to create a repository on Github, then creates an automated commit and pushes my changes to Github. Finally opens the project folder in sublime text for me to continue with my work.
The Walk-through
First, let’s install cookiecutter and pygithub
pip install -U cookiecutter pygithub
PyGitHub
Once pygithub is installed, either you can generate a token or use your username & password. If you opt for using the token, go here to generate your token.
Once you have your token, we can test connecting to GitHub using pygithub. This should list all your repositories.
Usage
Run command in your python environment:
from github import Github
# First create a Github instance:
# using username and password
g = Github("user", "password")
# or using an access token
g = Github("access_token")
# Then play with your Github objects:
for repo in g.get_user().get_repos():
print(repo.name)
Cookiecutter
Now that we have PyGithub set up, we can test cookiecutter. There’s a pantry full of cookiecutters templates for you to choose on, you can find them here
I personally forked the Cookiecutter template for a Python package., and modified it to suit my needs.
I added a few features such as:
- Testing setup with
unittest
and/orpy.test
- Travis-CI: Ready for Travis Continuous Integration testing
- Codacy: Automated your code quality
- Github CHANGELOG Generator: Generate changelog with ease.
- Some README badges and etc.
If you fancy using my template go here: cookiecutter-python-package template
Usage
Run cookiecutter, this will create a skeleton Python package with everything you need. Follow the prompts.
cookiecutter https://github.com/mmphego/cookiecutter-python-package
The Implementation
Below you will find the bash-function implementation for creating my project with ease, It is pretty self-explanatory.
create_project () {
# Easily create a project x in current dir using cookiecutter templates
PACKAGES=("pygithub" "cookiecutter" "platformio")
PACKAGE_DIR=""
export DESCRIPTION="description goes here!"
PYTHON2_PIP="python2 -W ignore::DeprecationWarning -m pip -q --disable-pip-version-check"
PYTHON3_PIP="python3 -W ignore::DeprecationWarning -m pip -q --disable-pip-version-check"
IDE="subl"
for pkg in "${PACKAGES[@]}"; do
if ! ${PYTHON3_PIP} freeze | grep -i "${pkg}" >/dev/null 2>&1; then
${PYTHON3_PIP} install -q --user "${pkg}" >/dev/null 2>&1;
elif ! ${PYTHON2_PIP} freeze | grep -i "${pkg}" >/dev/null 2>&1; then
${PYTHON3_PIP} install -q --user "${pkg}" >/dev/null 2>&1;
fi
done
read -p "What is the language you using for the (or type of) project? " LANG
if [[ "${LANG}" =~ ^([pP])$thon ]]; then
gecho "Lets build your Python project, Please follow the prompts."
cookiecutter https://github.com/mmphego/cookiecutter-python-package
PACKAGE_DIR=$(ls -tr --color='never' | tail -n1)
export DESCRIPTION=$(grep -oP '(?<=DESCRIPTION = ).*' setup.py)
cd -- "${PACKAGE_DIR}"
elif [[ "${LANG}" =~ ^([uU])$python ]]; then
gecho "Lets build your Micropython project, Please follow the prompts."
cookiecutter https://github.com/mmphego/cookiecutter-micropython
PACKAGE_DIR=$(ls -tr --color='never' | tail -n1)
cd -- "${PACKAGE_DIR}"
export DESCRIPTION=$(grep -oP '(?<=DESCRIPTION = ).*' setup.py)
elif [[ "${LANG}" =~ ^([Aa])$duino ]]; then
gecho "Lets build your Arduino project, Please follow the prompts."
read -p "Enter name of the project directory? " PACKAGE_DIR
read -p "Enter type of board (nodemcu/uno)? " BOARD
read -p "What IDE would you like to use vscode/atom/vim? " IDE
read -p "Enter the description of the project? " DESCRIPTION
export DESCRIPTION="${DESCRIPTION}"
mkdir -p "${PACKAGE_DIR}"
python2 -m platformio init -s -d ${PACKAGE_DIR} -b ${BOARD} --ide ${IDE}
cd -- "${PACKAGE_DIR}"
fi
############################################################
if [[ "${PACKAGE_DIR}" == "$(basename $(pwd))" ]];then
git init -q
python3 -c """
from configparser import ConfigParser
from pathlib import Path
from os import getenv
from subprocess import check_output
from github import Github
try:
token = check_output(['git', 'config', 'user.token'])
token = token.strip().decode() if type(token) == bytes else token.strip()
except Exception:
p = pathlib.Path('.gitconfig.private')
config.read(p.absolute())
token = config['user']['token']
proj_name = Path.cwd().name
g = Github(token)
user = g.get_user()
user.create_repo(
proj_name,
description=getenv('DESCRIPTION', 'Description goes here!'),
has_wiki=False,
has_issues=True,
auto_init=False)
print('Successfully created repository %s' % proj_name)
"""
git add . > /dev/null 2>&1
git commit -q -nm "Automated commit" > /dev/null 2>&1
git remote add origin "git@github.com:$(git config user.username)/${PACKAGE_DIR}.git" > /dev/null 2>&1
git push -q -u origin master > /dev/null 2>&1
"${IDE}" .
fi
}
Demo
Also, I have challenged myself to VLog my work at least twice in a month (I am being optimistic). Below is a demo I made showing my function implementation and a code walk-through, so please subscribe and smash that notification bell so that you get the content while it is fresh.
Thank you for watching.