|
| 1 | +# Project settings |
| 2 | +PROJECT := ethically |
| 3 | +PACKAGE := ethically |
| 4 | +REPOSITORY := shlomihod/ethically |
| 5 | + |
| 6 | +# Project paths |
| 7 | +PACKAGES := $(PACKAGE) tests |
| 8 | +CONFIG := $(wildcard *.py) |
| 9 | +MODULES := $(wildcard $(PACKAGE)/*.py) |
| 10 | + |
| 11 | +# Virtual environment paths |
| 12 | +export PIPENV_VENV_IN_PROJECT=true |
| 13 | +export PIPENV_IGNORE_VIRTUALENVS=true |
| 14 | +VENV := .venv |
| 15 | + |
| 16 | +# MAIN TASKS ################################################################## |
| 17 | + |
| 18 | +SNIFFER := pipenv run sniffer |
| 19 | + |
| 20 | +.PHONY: all |
| 21 | +all: install |
| 22 | + |
| 23 | +.PHONY: ci |
| 24 | +ci: check test ## Run all tasks that determine CI status |
| 25 | + |
| 26 | +.PHONY: watch |
| 27 | +watch: install .clean-test ## Continuously run all CI tasks when files chanage |
| 28 | + $(SNIFFER) |
| 29 | + |
| 30 | +.PHONY: run ## Start the program |
| 31 | +run: install |
| 32 | + pipenv run python $(PACKAGE)/__main__.py |
| 33 | + |
| 34 | +# SYSTEM DEPENDENCIES ######################################################### |
| 35 | + |
| 36 | +.PHONY: doctor |
| 37 | +doctor: ## Confirm system dependencies are available |
| 38 | + bin/verchew |
| 39 | + |
| 40 | +# PROJECT DEPENDENCIES ######################################################## |
| 41 | + |
| 42 | +DEPENDENCIES = $(VENV)/.pipenv-$(shell bin/checksum Pipfile* setup.py) |
| 43 | + |
| 44 | +.PHONY: install |
| 45 | +install: $(DEPENDENCIES) |
| 46 | + |
| 47 | +$(DEPENDENCIES): |
| 48 | + pipenv run python setup.py develop |
| 49 | + pipenv install --dev |
| 50 | + @ touch $@ |
| 51 | + |
| 52 | +# CHECKS ###################################################################### |
| 53 | + |
| 54 | +ISORT := pipenv run isort |
| 55 | +PYLINT := pipenv run pylint |
| 56 | +PYCODESTYLE := pipenv run pycodestyle |
| 57 | +PYDOCSTYLE := pipenv run pydocstyle |
| 58 | + |
| 59 | +.PHONY: check |
| 60 | +check: isort pylint pycodestyle pydocstyle ## Run linters and static analysis |
| 61 | + |
| 62 | +.PHONY: isort |
| 63 | +isort: install |
| 64 | + $(ISORT) $(PACKAGES) $(CONFIG) --recursive --apply |
| 65 | + |
| 66 | +.PHONY: pylint |
| 67 | +pylint: install |
| 68 | + $(PYLINT) $(PACKAGES) $(CONFIG) --rcfile=.pylint.ini |
| 69 | + |
| 70 | +.PHONY: pycodestyle |
| 71 | +pycodestyle: install |
| 72 | + $(PYCODESTYLE) $(PACKAGES) $(CONFIG) --config=.pycodestyle.ini |
| 73 | + |
| 74 | +.PHONY: pydocstyle |
| 75 | +pydocstyle: install |
| 76 | + $(PYDOCSTYLE) $(PACKAGES) $(CONFIG) |
| 77 | + |
| 78 | +# TESTS ####################################################################### |
| 79 | + |
| 80 | +PYTEST := pipenv run py.test |
| 81 | +COVERAGE := pipenv run coverage |
| 82 | +COVERAGE_SPACE := pipenv run coverage.space |
| 83 | + |
| 84 | +RANDOM_SEED ?= $(shell date +%s) |
| 85 | +FAILURES := .cache/v/cache/lastfailed |
| 86 | + |
| 87 | +PYTEST_OPTIONS := --random --random-seed=$(RANDOM_SEED) |
| 88 | +ifdef DISABLE_COVERAGE |
| 89 | +PYTEST_OPTIONS += --no-cov --disable-warnings |
| 90 | +endif |
| 91 | +PYTEST_RERUN_OPTIONS := --last-failed --exitfirst |
| 92 | + |
| 93 | +.PHONY: test |
| 94 | +test: test-all ## Run unit and integration tests |
| 95 | + |
| 96 | +.PHONY: test-unit |
| 97 | +test-unit: install |
| 98 | + @ ( mv $(FAILURES) $(FAILURES).bak || true ) > /dev/null 2>&1 |
| 99 | + $(PYTEST) $(PACKAGE) $(PYTEST_OPTIONS) |
| 100 | + @ ( mv $(FAILURES).bak $(FAILURES) || true ) > /dev/null 2>&1 |
| 101 | + $(COVERAGE_SPACE) $(REPOSITORY) unit |
| 102 | + |
| 103 | +.PHONY: test-int |
| 104 | +test-int: install |
| 105 | + @ if test -e $(FAILURES); then $(PYTEST) tests $(PYTEST_RERUN_OPTIONS); fi |
| 106 | + @ rm -rf $(FAILURES) |
| 107 | + $(PYTEST) tests $(PYTEST_OPTIONS) |
| 108 | + $(COVERAGE_SPACE) $(REPOSITORY) integration |
| 109 | + |
| 110 | +.PHONY: test-all |
| 111 | +test-all: install |
| 112 | + @ if test -e $(FAILURES); then $(PYTEST) $(PACKAGES) $(PYTEST_RERUN_OPTIONS); fi |
| 113 | + @ rm -rf $(FAILURES) |
| 114 | + $(PYTEST) $(PACKAGES) $(PYTEST_OPTIONS) |
| 115 | + $(COVERAGE_SPACE) $(REPOSITORY) overall |
| 116 | + |
| 117 | +.PHONY: read-coverage |
| 118 | +read-coverage: |
| 119 | + bin/open htmlcov/index.html |
| 120 | + |
| 121 | +# DOCUMENTATION ############################################################### |
| 122 | + |
| 123 | +PYREVERSE := pipenv run pyreverse |
| 124 | +MKDOCS := pipenv run mkdocs |
| 125 | + |
| 126 | +MKDOCS_INDEX := site/index.html |
| 127 | + |
| 128 | +.PHONY: docs |
| 129 | +docs: uml mkdocs ## Generate documentation |
| 130 | + |
| 131 | +.PHONY: uml |
| 132 | +uml: install docs/*.png |
| 133 | +docs/*.png: $(MODULES) |
| 134 | + $(PYREVERSE) $(PACKAGE) -p $(PACKAGE) -a 1 -f ALL -o png --ignore tests |
| 135 | + - mv -f classes_$(PACKAGE).png docs/classes.png |
| 136 | + - mv -f packages_$(PACKAGE).png docs/packages.png |
| 137 | + |
| 138 | +.PHONY: mkdocs |
| 139 | +mkdocs: install $(MKDOCS_INDEX) |
| 140 | +$(MKDOCS_INDEX): mkdocs.yml docs/*.md |
| 141 | + ln -sf `realpath README.md --relative-to=docs` docs/index.md |
| 142 | + ln -sf `realpath CHANGELOG.md --relative-to=docs/about` docs/about/changelog.md |
| 143 | + ln -sf `realpath CONTRIBUTING.md --relative-to=docs/about` docs/about/contributing.md |
| 144 | + ln -sf `realpath LICENSE.md --relative-to=docs/about` docs/about/license.md |
| 145 | + $(MKDOCS) build --clean --strict |
| 146 | + |
| 147 | +.PHONY: mkdocs-live |
| 148 | +mkdocs-live: mkdocs |
| 149 | + eval "sleep 3; bin/open http://127.0.0.1:8000" & |
| 150 | + $(MKDOCS) serve |
| 151 | + |
| 152 | +# BUILD ####################################################################### |
| 153 | + |
| 154 | +PYINSTALLER := pipenv run pyinstaller |
| 155 | +PYINSTALLER_MAKESPEC := pipenv run pyi-makespec |
| 156 | + |
| 157 | +DIST_FILES := dist/*.tar.gz dist/*.whl |
| 158 | +EXE_FILES := dist/$(PROJECT).* |
| 159 | + |
| 160 | +.PHONY: build |
| 161 | +build: dist |
| 162 | + |
| 163 | +.PHONY: dist |
| 164 | +dist: install $(DIST_FILES) |
| 165 | +$(DIST_FILES): $(MODULES) |
| 166 | + rm -f $(DIST_FILES) |
| 167 | + pipenv run python setup.py check --strict --metadata |
| 168 | + pipenv run python setup.py sdist |
| 169 | + pipenv run python setup.py bdist_wheel |
| 170 | + |
| 171 | +.PHONY: exe |
| 172 | +exe: install $(EXE_FILES) |
| 173 | +$(EXE_FILES): $(MODULES) $(PROJECT).spec |
| 174 | + # For framework/shared support: https://github.com/yyuu/pyenv/wiki |
| 175 | + $(PYINSTALLER) $(PROJECT).spec --noconfirm --clean |
| 176 | + |
| 177 | +$(PROJECT).spec: |
| 178 | + $(PYINSTALLER_MAKESPEC) $(PACKAGE)/__main__.py --onefile --windowed --name=$(PROJECT) |
| 179 | + |
| 180 | +# RELEASE ##################################################################### |
| 181 | + |
| 182 | +TWINE := pipenv run twine |
| 183 | + |
| 184 | +.PHONY: upload |
| 185 | +upload: dist ## Upload the current version to PyPI |
| 186 | + git diff --name-only --exit-code |
| 187 | + $(TWINE) upload dist/*.* |
| 188 | + bin/open https://pypi.org/project/$(PROJECT) |
| 189 | + |
| 190 | +# CLEANUP ##################################################################### |
| 191 | + |
| 192 | +.PHONY: clean |
| 193 | +clean: .clean-build .clean-docs .clean-test .clean-install ## Delete all generated and temporary files |
| 194 | + |
| 195 | +.PHONY: clean-all |
| 196 | +clean-all: clean |
| 197 | + rm -rf $(VENV) |
| 198 | + |
| 199 | +.PHONY: .clean-install |
| 200 | +.clean-install: |
| 201 | + find $(PACKAGES) -name '*.pyc' -delete |
| 202 | + find $(PACKAGES) -name '__pycache__' -delete |
| 203 | + rm -rf *.egg-info |
| 204 | + |
| 205 | +.PHONY: .clean-test |
| 206 | +.clean-test: |
| 207 | + rm -rf .cache .pytest .coverage htmlcov xmlreport |
| 208 | + |
| 209 | +.PHONY: .clean-docs |
| 210 | +.clean-docs: |
| 211 | + rm -rf *.rst docs/apidocs *.html docs/*.png site |
| 212 | + |
| 213 | +.PHONY: .clean-build |
| 214 | +.clean-build: |
| 215 | + rm -rf *.spec dist build |
| 216 | + |
| 217 | +# HELP ######################################################################## |
| 218 | + |
| 219 | +.PHONY: help |
| 220 | +help: all |
| 221 | + @ grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' |
| 222 | + |
| 223 | +.DEFAULT_GOAL := help |
0 commit comments