Skip to content

Instantly share code, notes, and snippets.

@brutus
Created August 16, 2017 13:22
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brutus/2dfd02917a939577a8dd561fb091e872 to your computer and use it in GitHub Desktop.
Save brutus/2dfd02917a939577a8dd561fb091e872 to your computer and use it in GitHub Desktop.
Makefile for Python projects
# Python Project
#
# Some targets to lint your code, run tests, builds and do some cleanup.
# Works fine with tox and Travis, etc.
#
# This setup assumes that you take care of the virtual environment setup
# yourself and that the needed requirements are installed. And also that
# you configure your tools. So edit your own `setup.cfg` or `.tox.ini`
# with the settings needed for the tools.
#
# # TOOLS
#
# - isort
# - pylama
# - pyflakes
# - pycodestyle
# - pydocstyle
# - mccabe
# - pylint
# - pylint (optional)
# - coverage
#
# # SETUP
#
# You should set _SOURCE_ to the path that contains your source (a relative
# path from this file is fine). All checks and stuff will be run from the
# directory containing this file, but the path given is used as base for the
# commands.
#
# If you have multiple directories, that should be checked, thats fine. You
# can set _SOURCE_ to a list of space separated paths instead.
#
# NOTE: Take care though if you set `.` as a directory: Your virtual
# environment, the tox directory, you tests, etc. might also be affected, if
# they are in this directory, which is probably not what you want.
#
# Also, if you set _DJANGO_ to `1`, the tests will be run by the
# `django-admin test` command instead of the default unittest discovery.
#
# And lastly, the commands are printed by choice, so you can see whats
# happening. To disable this, perpend `@` to the commands in the
# targets.
#
# TARGETS
#
# ## CHECKS and TESTS:
# - __style__ (default): checks syntax and code conventions.
# - __tests__: runs doctest from Python files and all unittests discovered.
# - __check__: runs both (_style_ & _tests_).
# - __lint__: checks for opinionated code smells (_mccabe_ & _pylama_).
# - __full__: runs all three (_style_, _lint_ and _tests_).
#
# ## TOOLS:
# - __cover__: runs the unittests and prints a coverage report.
# - __pylint__: prints a _very_ opinionated code smell report.
# - __isort__: sorts all imports (this might change your Python files).
#
# ## BUILD:
# - __build__: builds a source distribution and a wheel (needs `setup.py`).
# - __upload__: uploads builds to PyPi (needs `.pypirc`).
# _ __clean__: removes temporary files and caches.
#
# ## PIP
# _ __outdated__: lists outdated packages.
# _ __update__: updates outdated packages.
# --- SETTINGS -------------------------------------------------------------
# Set this to the directory, where your code is. If you have multiple
# directories, you want to check, use a space separated list instead.
SOURCE = .
# Set this to the string used for the `--source` argument to coverage.
COVARAGE_SOURCES = .
# Should the Django test runner be used instead of unittest discovery? If
# so, set this to `1` instead of `0`. This is needed to run the tests for
# Django projects.
DJANGO = 0
# --- COMMANDS -------------------------------------------------------------
# The commands that are run by the targets… feel free to change (them).
PWD = $(shell pwd)
CFG = $(PWD)/setup.cfg
EXCLUDES = \( \
-path './.git/*' -o \
-path './.venv/*' -o \
-path './venv/*' -o \
-path './env/*' -o \
-path './.tox/*' -o \
-path '.*/node_modules/*' -o \
-path '.*/bower_components/*' \
\) -prune -o
# Isort
CMD_ISORT = isort --settings-path $(CFG) --apply
CMD_ISORT_CHECK = isort --settings-path $(CFG) --check-only --quiet
# Linters
CMD_PYLAMA_ISORT_CHECK = pylama --options $(CFG) -l isort
CMD_PYLAMA_SYNTAX_CHECK = pylama --options $(CFG) -l pyflakes
CMD_PYLAMA_STYLE_CHECK_CODE = pylama --options $(CFG) -l pycodestyle
CMD_PYLAMA_STYLE_CHECK_DOCS = pylama --options $(CFG) -l pydocstyle
CMD_PYLAMA_COMPLEXITY_CHECK = pylama --options $(CFG) -l mccabe
CMD_PYLAMA_PYLINT_CHECK = pylama --options $(CFG) -l pylint
CMD_PYLINT_CHECK = find . $(EXCLUDES) -name '*.py' -print0 | xargs -0 \
pylint --rcfile $(PWD)/.pylintrc
CMD_PYLINT_REPORT = $(CMD_PYLINT_CHECK) -ry
# Test Runners
CMD_DOCTEST = find $(dir) $(EXCLUDES) -name '*.py' -print0 | xargs -0 \
python -m doctest
ifeq ($(DJANGO), 1)
CMD_COVERAGE_TEST = -m django test
CMD_TEST = python $(CMD_COVERAGE_TEST)
else
CMD_COVERAGE_TEST = -m unittest discover
CMD_TEST = python $(CMD_COVERAGE_TEST)
endif
CMD_COVERAGE_RUN = coverage run --append --source $(COVARAGE_SOURCES) $(CMD_COVERAGE_TEST)
# Build Package
CMD_BUILD = python setup.py sdist bdist_wheel
CMD_UPLOAD = twine upload --skip-existing dist/*
# Pip
CMD_PIP_OUTDATED = pip list --outdated --format=columns
CMD_PIP_UPDATE = $(CMD_PIP_OUTDATED) | tail -n +3 | cut -d' ' -f1 | \
xargs -r pip install --upgrade
# --- TARGETS --------------------------------------------------------------
.PHONY: default style_check style tests check lint full isort isort_check syntax_check style_check_code style_check_docs code_check pylama pylint doctests unittests cover build upload clean outdated update
default: style
style_check: style_check_code style_check_docs
style: syntax_check isort_check style_check
tests: doctests unittests
check: style tests
lint: complexity_check pylama
full: check lint
build: mk_build clean
isort:
# Sort imports in all `*.py` files.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_ISORT))
isort_check:
# Checks for correctly sorted imports in all `*.py` files.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_ISORT_CHECK))
syntax_check:
# Checks source files for syntax errors.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_SYNTAX_CHECK))
style_check_code:
# Checks source files for common code style conventions.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_STYLE_CHECK_CODE))
style_check_docs:
# Checks source files for common documentation style conventions.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_STYLE_CHECK_DOCS))
complexity_check:
# Checks source files for too much complexity.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_COMPLEXITY_CHECK))
pylama:
# Checks the source files for opinionated code smells.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLAMA_PYLINT_CHECK))
pylint:
# Prints a report of _very_ opinionated code smells in the source files.
$(foreach dir,$(SOURCE),cd $(dir); $(CMD_PYLINT_REPORT))
doctests:
# Runs doctest found in the source files.
$(foreach dir,$(SOURCE),$(CMD_DOCTEST))
unittests:
# Runs all unittests that follow common naming schemes.
$(CMD_TEST)
cover:
# Runs all those unittests with coverage and prints a report.
$(CMD_COVERAGE_RUN)
coverage report -m
mk_build:
# Builds a Python distribution (source distribution and wheel).
$(CMD_BUILD)
upload:
# Uploads builds to PyPi.
$(CMD_UPLOAD)
clean:
# Removes caches and bytecode files.
find . $(EXCLUDES) -print0 | xargs -0 -r rm -r
outdated:
# Lists outdated packages.
$(CMD_PIP_OUTDATED)
update:
# Updates outdated packages.
$(CMD_PIP_UPDATE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment