diff --git a/.gitignore b/.gitignore index ef2b4aea..38aff747 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ __pycache__ .pytest_cache +/.venv-3.8 + # C extensions *.so diff --git a/Makefile b/Makefile index e1c0ee09..7932cb88 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +include repo-tools/base.mk + .PHONY: clean compile_translations coverage diff_cover docs dummy_translations \ extract_translations fake_translations help pull_translations push_translations \ quality requirements selfcheck test test-all upgrade validate @@ -20,63 +22,61 @@ help: ## display this help message @echo "Please use \`make ' where is one of" @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-25s\033[0m %s\n", $$1, $$2}' -clean: ## remove generated byte code, coverage reports, and build artifacts +clean: $(coverage) ## remove generated byte code, coverage reports, and build artifacts find . -name '__pycache__' -exec rm -rf {} + find . -name '*.pyc' -exec rm -f {} + find . -name '*.pyo' -exec rm -f {} + find . -name '*~' -exec rm -f {} + - coverage erase + $(coverage) erase rm -fr build/ rm -fr dist/ rm -fr *.egg-info -coverage: clean ## generate and view HTML coverage report - pytest --cov-report html +coverage: clean $(pytest) ## generate and view HTML coverage report + $(pytest) --cov-report html $(BROWSER) htmlcov/index.html -docs: ## generate Sphinx HTML documentation, including API docs - tox -e docs +docs: $(tox) ## generate Sphinx HTML documentation, including API docs + $(tox) -e docs $(BROWSER) docs/_build/html/index.html upgrade: export CUSTOM_COMPILE_COMMAND=make upgrade -upgrade: ## update the requirements/*.txt files with the latest packages satisfying requirements/*.in - pip install -qr requirements/pip-tools.txt +upgrade: $(pip) $(pip-sync) ## update the requirements/*.txt files with the latest packages satisfying requirements/*.in + $(pip) install -qr requirements/pip-tools.txt # Make sure to compile files after any other files they include! - pip-compile --allow-unsafe --rebuild --upgrade -o requirements/pip.txt requirements/pip.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/pip-tools.txt requirements/pip-tools.in - pip install -qr requirements/pip.txt - pip install -qr requirements/pip-tools.txt - pip-compile --no-emit-trusted-host --upgrade -o requirements/base.txt requirements/base.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/test.txt requirements/test.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/doc.txt requirements/doc.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/quality.txt requirements/quality.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/ci.txt requirements/ci.in - pip-compile --no-emit-trusted-host --upgrade -o requirements/dev.txt requirements/dev.in + $(pip-compile) --allow-unsafe --rebuild --upgrade -o requirements/pip.txt requirements/pip.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/pip-tools.txt requirements/pip-tools.in + $(pip) install -qr requirements/pip.txt + $(pip) install -qr requirements/pip-tools.txt + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/base.txt requirements/base.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/test.txt requirements/test.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/doc.txt requirements/doc.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/quality.txt requirements/quality.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/ci.txt requirements/ci.in + $(pip-compile) --no-emit-trusted-host --upgrade -o requirements/dev.txt requirements/dev.in # Let tox control the Django version for tests sed '/^[dD]jango==/d' requirements/test.txt > requirements/test.tmp mv requirements/test.tmp requirements/test.txt -isort: ## fixes isort issues found during quality check - tox -e isort +isort: $(tox) ## fixes isort issues found during quality check + $(tox) -e isort quality: ## check coding style with pycodestyle and pylint - tox -e quality + $(tox) -e quality -requirements: ## install development environment requirements - pip install -r requirements/pip.txt - pip install -qr requirements/pip-tools.txt - pip-sync requirements/dev.txt requirements/private.* - pip install . # CLI entry points +requirements: $(pip) $(pip-sync) ## install development environment requirements + $(pip-sync) requirements/dev.txt requirements/private.* + $(pip) install . # CLI entry points -test: clean ## run tests in the current virtualenv - pytest +test: clean $(pytest) ## run tests in the current virtualenv + $(pytest) -diff_cover: test ## find diff lines that need test coverage - diff-cover coverage.xml +diff_cover: test $(diff-cover) ## find diff lines that need test coverage + $(diff-cover) coverage.xml -test-all: ## run tests on every supported Python/Django combination - tox -e quality - tox +test-all: $(tox) ## run tests on every supported Python/Django combination + $(tox) -e quality + $(tox) validate: quality test ## run tests and quality checks diff --git a/repo-tools/base.mk b/repo-tools/base.mk new file mode 100644 index 00000000..19a4ab4f --- /dev/null +++ b/repo-tools/base.mk @@ -0,0 +1,38 @@ +# Base Makefile components to build on. +# +# Ideally, this would be pulled in from another repo by a `git subtree` +# reference and would include most of the Makefile so that upgrading +# repos to the latest functionality (and keeping them standardized) +# would be fast and simple. + +PYTHON_VER := 3.8 + +# These are required for bootstrapping a virtualenv to the point where +# requirements can be installed. + +venv_name := .venv-$(PYTHON_VER) +pip := $(venv_name)/bin/pip +pip-compile := $(venv_name)/bin/pip-compile +pip-sync := $(venv_name)/bin/pip-sync + +$(venv_name): ## Create the virtualenv, or recreate it if it already exists + python$(PYTHON_VER) -m venv $(venv_name) --clear + +$(pip): $(venv_name) + pip install -r requirements/pip.txt + +$(pip-compile) $(pip-sync): $(venv_name) + $(pip) install -r requirements/pip-tools.txt + +# The rest of the Python tools are listed here, and all are fulfilled +# by the same target. By calling them from their explicit virtualenv +# paths, we ensure that the virtualenv will be used (including by +# other tools they call). + +coverage := $(venv_name)/bin/coverage +diff-cover := $(venv_name)/bin/diff-cover +pytest := $(venv_name)/bin/pytest +tox := $(venv_name)/bin/tox + +$(venv_name)/bin/%: $(venv_name) + make requirements