-
Notifications
You must be signed in to change notification settings - Fork 1
/
Makefile
411 lines (356 loc) · 10.1 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
MAKEFLAGS += --silent
SHELL := /usr/bin/env
.SHELLFLAGS := bash -c -e +x
.DEFAULT_GOAL := help
PYTHON_DEPENDENCIES_DIRECTORY := ./requirements
PYTHON_SOURCE_DIRECTORY := ./src
PYTHON_DOCS_DIRECTORY := ./docs
PYTHON_DIST_DIRECTORY := ./dist
PYTHON_SOURCE_SCRIPTS_PATTERN := "${PYTHON_SOURCE_DIRECTORY}/**/*.py"
PYTHON_TEST_SCRIPTS_PATTERN := "**/tests/*.py"
PYTHON_SKIP_TEST_SCRIPTS_PATTERN := "./src/*tests*"
PYTHON_SOURCE_SCRIPTS := $(shell find ${PYTHON_SOURCE_DIRECTORY} -type f -name "*.py")
define check_install_status =
$(shell python3 -m pip show ${1} > /dev/null 2>&1)
if [ ${.SHELLSTATUS} -eq 1 ]; then
python3 -m pip install --upgrade ${1}
fi
endef
## help
## list all wrapper targets
## show documentations of wrapper targets
.PHONY: help
help: Makefile
@sed -n 's/^## //p' $<
.ONESHELL:
venv:
python3 -m venv .venv
echo "*" > .venv/.gitignore
source .venv/bin/activate
python3 -m pip install --upgrade pip setuptools wheel
python3 -m pip install --editable ".[all]"
.ONESHELL:
.PHONY: pre-commit-install
pre-commit-install: venv
source .venv/bin/activate
$(call check_install_status, pre-commit)
pre-commit install
## setup
## create isolated environment with editable package and dependencies (venv)
## add pre-commit to git hooks (pre-commit-install)
.PHONY: setup
setup: venv pre-commit-install
.ONESHELL:
venv-upgrade: venv
source .venv/bin/activate
python3 -m pip install --upgrade pip setuptools wheel
python3 -m pip install --upgrade \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.dev.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.doc.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.format.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.lint.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.release.txt \
--requirement ${PYTHON_DEPENDENCIES_DIRECTORY}/requirements.test.txt
.ONESHELL:
.PHONY: pre-commit-autoupdate
pre-commit-autoupdate: venv
source .venv/bin/activate
pre-commit autoupdate
## update
## upgrade isolated environment to latest package and dependencies (venv-upgrade)
## update versions of pre-commit hooks (pre-commit-autoupdate)
.PHONY: update
update: venv-upgrade pre-commit-autoupdate
.ONESHELL:
.PHONY: autoflake
autoflake: venv
source .venv/bin/activate
$(call check_install_status, autoflake)
autoflake $(PYTHON_SOURCE_SCRIPTS)
.ONESHELL:
.PHONY: black
black: venv
source .venv/bin/activate
$(call check_install_status, black)
black ${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: blacken-docs
blacken-docs: venv
source .venv/bin/activate
$(call check_install_status, blacken-docs)
blacken-docs \
--line-length 87 \
--target-version py310 \
$(PYTHON_SOURCE_SCRIPTS)
.ONESHELL:
.PHONY: docformatter
docformatter: venv
source .venv/bin/activate
$(call check_install_status, docformatter)
$(call check_install_status, tomli)
docformatter ${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: isort
isort: venv
source .venv/bin/activate
$(call check_install_status, isort)
isort ${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: pyupgrade
pyupgrade: venv
source .venv/bin/activate
$(call check_install_status, pyupgrade)
pyupgrade --py310-plus $(PYTHON_SOURCE_SCRIPTS)
## format
## change codes for older versions (pyupgrade)
## remove pyflake detected issues (autoflake)
## sort imports (isort)
## format docstrings (docformatter)
## format code style (black)
.PHONY: format
format: pyupgrade autoflake isort docformatter blacken-docs black
.ONESHELL:
.PHONY: bandit
bandit: venv
source .venv/bin/activate
$(call check_install_status, bandit)
bandit \
--recursive \
--severity-level high \
--confidence-level high \
${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: flake8
flake8: venv
source .venv/bin/activate
$(call check_install_status, flake8)
flake8 \
--extend-ignore E203 \
--per-file-ignores __init__.py:F401 \
--max-line-length 99 \
${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: interrogate
interrogate: venv
source .venv/bin/activate
$(call check_install_status, interrogate)
interrogate ${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: pylint
pylint: venv
source .venv/bin/activate
$(call check_install_status, pylint)
pylint ${PYTHON_SOURCE_DIRECTORY}
.ONESHELL:
.PHONY: vulture
vulture: venv
source .venv/bin/activate
$(call check_install_status, vulture)
vulture
## lint
## find security issues (bandit)
## lint all python scripts (flake8)
## check docstring coverage (interrogate)
## lint all python scripts (pylint)
## find dead code (vulture)
.PHONY: lint
lint: bandit flake8 interrogate pylint vulture
.ONESHELL:
.PHONY: pytest-doctest
pytest-doctest: venv
source .venv/bin/activate
$(call check_install_status, pytest)
pytest -k "not test_"
.ONESHELL:
.PHONY: pytest-failure
pytest-failure: venv
source .venv/bin/activate
$(call check_install_status, pytest)
pytest -k "failure"
.ONESHELL:
.PHONY: pytest-hypotheses
pytest-hypotheses: venv
source .venv/bin/activate
$(call check_install_status, hypothesis)
$(call check_install_status, pytest)
pytest -k "hypothesis"
.ONESHELL:
.PHONY: pytest-others
pytest-others: venv
source .venv/bin/activate
$(call check_install_status, pytest)
pytest -k "test and not failure and not hypothesis and not successful"
.ONESHELL:
.PHONY: pytest-successful
pytest-successful: venv
source .venv/bin/activate
$(call check_install_status, pytest)
pytest -k "successful"
## test
## test doctests (pytest-doctest)
## test successful operations (pytest-successful)
## test failed operations (pytest-failure)
## test hypotheses (pytest-others)
## test other unit tests (pytest-others)
.PHONY: test
test: pytest-doctest pytest-successful pytest-failure pytest-hypotheses pytest-others
.ONESHELL:
.PHONY: coverage-erase
coverage-erase: venv
source .venv/bin/activate
$(call check_install_status, coverage)
$(call check_install_status, tomli)
coverage erase
.ONESHELL:
.PHONY: coverage-html
coverage-html: venv
source .venv/bin/activate
$(call check_install_status, coverage)
$(call check_install_status, tomli)
coverage html
.ONESHELL:
.PHONY: coverage-report
coverage-report: venv
source .venv/bin/activate
$(call check_install_status, coverage)
$(call check_install_status, tomli)
coverage report
.ONESHELL:
.PHONY: coverage-run
coverage-run: venv
source .venv/bin/activate
$(call check_install_status, coverage)
$(call check_install_status, hypothesis)
$(call check_install_status, pytest)
$(call check_install_status, tomli)
coverage run
.ONESHELL:
.PHONY: coverage-xml
coverage-xml: venv
source .venv/bin/activate
$(call check_install_status, coverage)
$(call check_install_status, tomli)
coverage xml
## coverage
## test all doctests and unit tests (coverage-run)
## create test coverage report (coverage-html)
## delete collected coverage data (coverage-erase)
.PHONY: coverage
coverage: coverage-run coverage-report coverage-html coverage-xml coverage-erase
.ONESHELL:
.PHONY: sphinx-source
sphinx-source: venv
source .venv/bin/activate
$(call check_install_status, Sphinx)
sphinx-apidoc \
--output-dir ${PYTHON_DOCS_DIRECTORY}/source \
--maxdepth 3 \
--force \
--follow-links \
--separate \
${PYTHON_SOURCE_DIRECTORY} \
${PYTHON_SKIP_TEST_SCRIPTS_PATTERN}
.ONESHELL:
.PHONY: sphinx-build
sphinx-build: venv
source .venv/bin/activate
$(call check_install_status, furo)
$(call check_install_status, Sphinx)
$(call check_install_status, sphinx-copybutton)
sphinx-build \
-b html \
${PYTHON_DOCS_DIRECTORY}/source \
${PYTHON_DOCS_DIRECTORY}/build
## docs
## prepare documentation sources with directives (sphinx-source)
## create HTML documentation from source files (sphinx-build)
.PHONY: docs
docs: sphinx-source sphinx-build
.ONESHELL:
.PHONY: build
build: venv
source .venv/bin/activate
$(call check_install_status, build)
python3 -m build --outdir ${PYTHON_DIST_DIRECTORY}
.ONESHELL:
.PHONY: twine-check
twine-check: venv
source .venv/bin/activate
$(call check_install_status, twine)
twine check --strict ${PYTHON_DIST_DIRECTORY}/*
.ONESHELL:
.PHONY: twine-upload
twine-upload: venv
source .venv/bin/activate
$(call check_install_status, twine)
twine upload ${PYTHON_DIST_DIRECTORY}/*
## release
## create distribution files (build)
## check package description (twine-check)
## upload distribution files (twine-upload)
.PHONY: release
release: build twine-check twine-upload
.PHONY: clean-coverage
clean-coverage:
find . \
-type f -name .coverage -delete \
-o \
-type d -name htmlcov \
-exec rm -r "{}" +
.PHONY: clean-mypy_cache
clean-mypy_cache:
find . \
-type d -name .mypy_cache \
-exec rm -r "{}" +
.PHONY: clean-pycache
clean-pycache:
find . \
-type f -name '*.py[co]' -delete \
-o \
-type d -name __pycache__ -delete
.PHONY: clean-pytest_cache
clean-pytest_cache:
find . \
-type d -name .pytest_cache \
-exec rm -r "{}" +
## cleanup
## delete all pycache directories and other cache files (clean-pycache)
## delete all mypy cache (clean-mypy_cache)
## delete all unit test cache (clean-pytest_cache)
## delete all coverage results (clean-coverage)
.PHONY: cleanup
cleanup: clean-pycache clean-mypy_cache clean-pytest_cache clean-coverage
.ONESHELL:
.PHONY: mypy
mypy: venv
source .venv/bin/activate
$(call check_install_status, mypy)
$(call check_install_status, pydantic)
mypy
.ONESHELL:
.PHONY: mypy-stubgen
mypy-stubgen: venv
source .venv/bin/activate
$(call check_install_status, mypy)
stubgen \
--output typing-stubs-for-package-name-to-install-with \
--module module_that_can_be_imported_directly \
--module module_that_can_be_invoked_from_cli \
--module module_that_can_invoke_gui_from_cli \
--package package_name_to_import_with
.ONESHELL:
.PHONY: pyright
pyright: venv
source .venv/bin/activate
$(call check_install_status, pyright)
pyright
.ONESHELL:
.PHONY: pyright-stubs
pyright-stubs: venv
source .venv/bin/activate
$(call check_install_status, pyright)
pyright --createstub package_name_to_import_with
pyright --createstub module_that_can_be_imported_directly
pyright --createstub module_that_can_be_invoked_from_cli
pyright --createstub module_that_can_invoke_gui_from_cli