Workflow
The bohicalog module has codified its workflow using tox.
Quick Start
To get started, you need to install tox:
$ pip install tox
Then, you can run the tests using tox:
$ tox
For example, by default it will:
$ tox
lint: commands[0]> black .
All done! ✨ 🍰 ✨
28 files left unchanged.
lint: commands[1]> isort .
Skipped 4 files
lint: commands[2]> nbqa isort .
No notebooks found in given path(s)
lint: OK ✔ in 0.76 seconds
manifest: commands[0]> check-manifest
...
lint: OK (0.76=setup[0.02]+cmd[0.18,0.10,0.45] seconds)
manifest: FAIL code 1 (8.50=setup[0.01]+cmd[8.49] seconds)
pyroma: OK (0.50=setup[0.01]+cmd[0.48] seconds)
flake8: FAIL code 1 (1.48=setup[0.01]+cmd[1.47] seconds)
mypy: OK (0.13=setup[0.01]+cmd[0.12] seconds)
doc8: FAIL code 1 (0.22=setup[0.01]+cmd[0.21] seconds)
docstr-coverage: OK (0.16=setup[0.01]+cmd[0.15] seconds)
docs-test: FAIL code 2 (4.97=setup[2.85]+cmd[0.01,0.01,2.10] seconds)
py: OK (2.93=setup[2.43]+cmd[0.31,0.06,0.13] seconds)
evaluation failed :( (19.78 seconds)
The above is defined by the tox section of the tox.ini file.
Tox Commands
The tox.ini file also defines a number of environments, which can be ran individually:
doctests: runs document tests, xdoctest
coverge-clean: cleans up the coverage files, coverage erase
lint: runs linting, black, isort, nbqa isort
doclint: runs linting on the documentation. This will fail on custom directives, rstfmt
manifest: checks the manifest, check-manifest
flake8: runs flake8 linting
pyroma: runs pyroma to check the package friendliness of the project, pyroma
mypy: runs mypy type checking, mypy
doc8: runs doc8 to check the documentation, doc8
docstr-coverage: runs docstr-coverage to check the documentation coverage, docstr-coverage
docs: builds the documentation, sphinx
docs-test: Test building the documentation in an isolated environment, sphinx
coverage-report: generates a coverage report, coverage report
bumpversion: bumps the version, bumpversion
build: builds the package, python setup.py sdist bdist_wheel
release: releases the package, twine
testrelease: releases the package to test.pypi.org, twine
finish: finishes the release, bumpversion
To run a specific environment, you can use the -e flag:
$ tox -e lint
Release Workflow
The release workflow is defined below:
tox -e lint
tox -e manifest
tox -e pyroma
tox -e flake8
tox -e mypy
tox -e doc8
tox -e docstr-coverage
tox -e docs-test
tox -e py
tox
tox -e bumpversion – {major, minor} <– Only if required, finish automatically bumps the minor version after each release
tox -e finish
Ensure you have the following environment variables set:
TWINE_USERNAME
TWINE_PASSWORD
TELEGRAM_BOT_TOKEN
TELEGRAM_BOT_CHAT_ID
Execute steps 1-10 to ensure that the code is ready for release. If any of the steps fail, fix the issues and repeat the steps.
If the release is a major or minor release, execute step 11 to bump the version. If the release is a patch release, skip step 11.
Execute step 12 to finish the release. This will automatically bump the version to the next minor version. This is to ensure that the version is always ahead of the latest release.
Tox File
The full tox.ini is listed below:
1# Tox (http://tox.testrun.org/) is a tool for running tests
2# in multiple virtualenvs. This configuration file will run the
3# test suite on all supported python versions. To use it, "pip install tox"
4# and then run "tox" from this directory.
5
6[tox]
7# To use a PEP 517 build-backend you are required to configure tox to use an isolated_build:
8# https://tox.readthedocs.io/en/latest/example/package.html
9isolated_build = True
10
11# These environments are run in order if you just use `tox`:
12envlist =
13 # always keep coverage-clean first
14 # coverage-clean
15 # code linters/stylers
16 lint
17 manifest
18 pyroma
19 flake8
20 mypy
21 # documentation linters/checkers
22 doc8
23 docstr-coverage
24 docs-test
25 # the actual tests
26 py
27 # always keep coverage-report last
28 # coverage-report
29
30[testenv]
31# Runs on the "tests" directory by default, or passes the positional
32# arguments from `tox -e py <posargs_1> ... <posargs_n>
33commands =
34 coverage run -p -m pytest --durations=20 {posargs:tests}
35 coverage combine
36 coverage xml
37extras =
38 # See the [options.extras_require] entry in setup.cfg for "tests"
39 tests
40
41[testenv:doctests]
42commands =
43 xdoctest -m src
44deps =
45 xdoctest
46 pygments
47
48[testenv:coverage-clean]
49deps = coverage
50skip_install = true
51commands = coverage erase
52
53[testenv:lint]
54deps =
55 black[jupyter]
56 isort
57 nbqa
58skip_install = true
59commands =
60 black .
61 isort .
62 nbqa isort .
63description = Run linters.
64
65[testenv:doclint]
66deps =
67 rstfmt
68skip_install = true
69commands =
70 rstfmt docs/source/
71description = Run documentation linters.
72
73[testenv:manifest]
74deps = check-manifest
75skip_install = true
76commands = check-manifest
77description = Check that the MANIFEST.in is written properly and give feedback on how to fix it.
78
79[testenv:flake8]
80skip_install = true
81deps =
82 darglint
83 flake8
84 flake8-black
85 flake8-bandit
86 flake8-bugbear
87 flake8-colors
88 flake8-docstrings
89 flake8-isort
90 flake8-print
91 pep8-naming
92 pydocstyle
93commands =
94 flake8 src/ tests/
95description = Run the flake8 tool with several plugins (bandit, docstrings, import order, pep8 naming). See https://cthoyt.com/2020/04/25/how-to-code-with-me-flake8.html for more information.
96
97[testenv:pyroma]
98deps =
99 pygments
100 pyroma
101skip_install = true
102commands = pyroma --min=10 .
103description = Run the pyroma tool to check the package friendliness of the project.
104
105[testenv:mypy]
106deps = mypy
107skip_install = true
108commands = mypy --install-types --non-interactive --ignore-missing-imports src/
109description = Run the mypy tool to check static typing on the project.
110
111[testenv:doc8]
112skip_install = true
113deps =
114 sphinx
115 doc8
116commands =
117 doc8 docs/source/
118description = Run the doc8 tool to check the style of the RST files in the project docs.
119
120[testenv:docstr-coverage]
121skip_install = true
122deps =
123 docstr-coverage
124commands =
125 docstr-coverage src/ tests/ --skip-private --skip-magic
126description = Run the docstr-coverage tool to check documentation coverage
127
128[testenv:docs]
129description = Build the documentation locally.
130extras =
131 # See the [options.extras_require] entry in setup.cfg for "docs"
132 docs
133 # You might need to add additional extras if your documentation covers it
134commands =
135 pip install -e .
136 python -m sphinx -W -b html -d docs/build/doctrees docs/source docs/build/html -a -E
137
138[testenv:docs-test]
139description = Test building the documentation in an isolated environment.
140changedir = docs
141extras =
142 {[testenv:docs]extras}
143commands =
144 mkdir -p {envtmpdir}
145 cp -r source {envtmpdir}/source
146 cp -r ../.github {envtmpdir}/../.github
147 cp -r ../tox.ini {envtmpdir}/../tox.ini
148 cp -r ../.env.secret {envtmpdir}/../.env.secret
149 python -m sphinx -W -b html -d {envtmpdir}/build/doctrees {envtmpdir}/source {envtmpdir}/build/html
150 python -m sphinx -W -b coverage -d {envtmpdir}/build/doctrees {envtmpdir}/source {envtmpdir}/build/coverage
151 cat {envtmpdir}/build/coverage/c.txt
152 cat {envtmpdir}/build/coverage/python.txt
153allowlist_externals =
154 cp
155 cat
156 mkdir
157
158[testenv:coverage-report]
159deps = coverage
160skip_install = true
161commands =
162 coverage combine
163 coverage report
164
165####################
166# Deployment tools #
167####################
168
169[testenv:bumpversion]
170commands = bumpversion {posargs}
171skip_install = true
172passenv = HOME
173deps =
174 bumpversion
175
176[testenv:build]
177skip_install = true
178deps =
179 wheel
180 build
181commands =
182 python -m build --sdist --wheel --no-isolation
183
184[testenv:release]
185description = Release the code to PyPI so users can pip install it
186skip_install = true
187deps =
188 {[testenv:build]deps}
189 twine >= 1.5.0
190commands =
191 {[testenv:build]commands}
192 twine upload --skip-existing dist/*
193
194[testenv:testrelease]
195description = Release the code to the test PyPI site
196skip_install = true
197deps =
198 {[testenv:build]deps}
199 twine >= 1.5.0
200commands =
201 {[testenv:build]commands}
202 twine upload --skip-existing --repository-url https://test.pypi.org/legacy/ dist/*
203
204[testenv:finish]
205skip_install = true
206passenv =
207 HOME
208 TWINE_USERNAME
209 TWINE_PASSWORD
210deps =
211 {[testenv:release]deps}
212 bump2version
213commands =
214 bump2version release --tag
215 {[testenv:release]commands}
216 git push --tags
217 bump2version patch
218 git push
219allowlist_externals =
220 git