invoke-tasklib 0.0.7__tar.gz → 0.1.0a0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. {invoke_tasklib-0.0.7 → invoke_tasklib-0.1.0a0}/.gitignore +2 -0
  2. invoke_tasklib-0.1.0a0/PKG-INFO +348 -0
  3. invoke_tasklib-0.1.0a0/README.md +320 -0
  4. invoke_tasklib-0.1.0a0/invoke_tasklib/__init__.py +248 -0
  5. invoke_tasklib-0.1.0a0/invoke_tasklib/_coverage.py +147 -0
  6. invoke_tasklib-0.1.0a0/invoke_tasklib/_discover.py +270 -0
  7. invoke_tasklib-0.1.0a0/invoke_tasklib/_files.py +225 -0
  8. invoke_tasklib-0.1.0a0/invoke_tasklib/_graph.py +499 -0
  9. invoke_tasklib-0.1.0a0/invoke_tasklib/_pyproject.py +75 -0
  10. invoke_tasklib-0.1.0a0/invoke_tasklib/_steps.py +388 -0
  11. invoke_tasklib-0.1.0a0/invoke_tasklib/check.py +165 -0
  12. invoke_tasklib-0.1.0a0/invoke_tasklib/clean.py +446 -0
  13. invoke_tasklib-0.1.0a0/invoke_tasklib/config/__init__.py +50 -0
  14. invoke_tasklib-0.1.0a0/invoke_tasklib/config/__main__.py +44 -0
  15. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_constants.py +27 -0
  16. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_derive.py +80 -0
  17. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_invoke.py +160 -0
  18. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_resolve.py +181 -0
  19. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_schema.py +439 -0
  20. invoke_tasklib-0.1.0a0/invoke_tasklib/config/_validate.py +579 -0
  21. invoke_tasklib-0.1.0a0/invoke_tasklib/doc.py +405 -0
  22. invoke_tasklib-0.1.0a0/invoke_tasklib/env.py +270 -0
  23. invoke_tasklib-0.1.0a0/invoke_tasklib/fix.py +91 -0
  24. invoke_tasklib-0.1.0a0/invoke_tasklib/formatting.py +241 -0
  25. invoke_tasklib-0.1.0a0/invoke_tasklib/imports.py +126 -0
  26. invoke_tasklib-0.1.0a0/invoke_tasklib/lint.py +116 -0
  27. invoke_tasklib-0.1.0a0/invoke_tasklib/output.py +251 -0
  28. invoke_tasklib-0.1.0a0/invoke_tasklib/release.py +452 -0
  29. invoke_tasklib-0.1.0a0/invoke_tasklib/runner.py +324 -0
  30. invoke_tasklib-0.1.0a0/invoke_tasklib/security.py +64 -0
  31. invoke_tasklib-0.1.0a0/invoke_tasklib/show.py +182 -0
  32. invoke_tasklib-0.1.0a0/invoke_tasklib/testing.py +449 -0
  33. invoke_tasklib-0.1.0a0/invoke_tasklib/tools.py +404 -0
  34. invoke_tasklib-0.1.0a0/invoke_tasklib/typecheck.py +76 -0
  35. invoke_tasklib-0.1.0a0/pyproject.toml +284 -0
  36. invoke_tasklib-0.1.0a0/tests/__init__.py +0 -0
  37. invoke_tasklib-0.1.0a0/tests/benchmarks/__init__.py +0 -0
  38. invoke_tasklib-0.1.0a0/tests/benchmarks/test_config_benchmark.py +41 -0
  39. invoke_tasklib-0.1.0a0/tests/benchmarks/test_files_benchmark.py +30 -0
  40. invoke_tasklib-0.1.0a0/tests/benchmarks/test_graph_benchmark.py +51 -0
  41. invoke_tasklib-0.1.0a0/tests/benchmarks/test_init_benchmark.py +24 -0
  42. invoke_tasklib-0.1.0a0/tests/benchmarks/test_runner_benchmark.py +17 -0
  43. invoke_tasklib-0.1.0a0/tests/helpers.py +110 -0
  44. invoke_tasklib-0.1.0a0/tests/integration/__init__.py +0 -0
  45. invoke_tasklib-0.1.0a0/tests/integration/helpers.py +48 -0
  46. invoke_tasklib-0.1.0a0/tests/integration/test_check.py +80 -0
  47. invoke_tasklib-0.1.0a0/tests/integration/test_clean.py +86 -0
  48. invoke_tasklib-0.1.0a0/tests/integration/test_doc.py +144 -0
  49. invoke_tasklib-0.1.0a0/tests/integration/test_docs.py +151 -0
  50. invoke_tasklib-0.1.0a0/tests/integration/test_doctest.py +17 -0
  51. invoke_tasklib-0.1.0a0/tests/integration/test_env_config.py +176 -0
  52. invoke_tasklib-0.1.0a0/tests/integration/test_env_install.py +57 -0
  53. invoke_tasklib-0.1.0a0/tests/integration/test_env_python.py +31 -0
  54. invoke_tasklib-0.1.0a0/tests/integration/test_env_tools.py +82 -0
  55. invoke_tasklib-0.1.0a0/tests/integration/test_exit_codes.py +88 -0
  56. invoke_tasklib-0.1.0a0/tests/integration/test_files.py +132 -0
  57. invoke_tasklib-0.1.0a0/tests/integration/test_fix_converges.py +66 -0
  58. invoke_tasklib-0.1.0a0/tests/integration/test_formatting.py +86 -0
  59. invoke_tasklib-0.1.0a0/tests/integration/test_imports.py +271 -0
  60. invoke_tasklib-0.1.0a0/tests/integration/test_output.py +35 -0
  61. invoke_tasklib-0.1.0a0/tests/integration/test_project.py +204 -0
  62. invoke_tasklib-0.1.0a0/tests/integration/test_quoting.py +21 -0
  63. invoke_tasklib-0.1.0a0/tests/integration/test_read_only.py +74 -0
  64. invoke_tasklib-0.1.0a0/tests/integration/test_readme.py +28 -0
  65. invoke_tasklib-0.1.0a0/tests/integration/test_release.py +169 -0
  66. invoke_tasklib-0.1.0a0/tests/integration/test_runner.py +67 -0
  67. invoke_tasklib-0.1.0a0/tests/integration/test_security.py +49 -0
  68. invoke_tasklib-0.1.0a0/tests/integration/test_testing.py +158 -0
  69. invoke_tasklib-0.1.0a0/tests/unit/__init__.py +0 -0
  70. invoke_tasklib-0.1.0a0/tests/unit/config/__init__.py +0 -0
  71. invoke_tasklib-0.1.0a0/tests/unit/config/conftest.py +15 -0
  72. invoke_tasklib-0.1.0a0/tests/unit/config/test___main__.py +60 -0
  73. invoke_tasklib-0.1.0a0/tests/unit/config/test__derive.py +134 -0
  74. invoke_tasklib-0.1.0a0/tests/unit/config/test__invoke.py +135 -0
  75. invoke_tasklib-0.1.0a0/tests/unit/config/test__resolve.py +699 -0
  76. invoke_tasklib-0.1.0a0/tests/unit/config/test__schema.py +309 -0
  77. invoke_tasklib-0.1.0a0/tests/unit/config/test__validate.py +566 -0
  78. invoke_tasklib-0.1.0a0/tests/unit/conftest.py +29 -0
  79. invoke_tasklib-0.1.0a0/tests/unit/test__coverage.py +151 -0
  80. invoke_tasklib-0.1.0a0/tests/unit/test__discover.py +276 -0
  81. invoke_tasklib-0.1.0a0/tests/unit/test__files.py +352 -0
  82. invoke_tasklib-0.1.0a0/tests/unit/test__graph.py +708 -0
  83. invoke_tasklib-0.1.0a0/tests/unit/test__pyproject.py +79 -0
  84. invoke_tasklib-0.1.0a0/tests/unit/test__steps.py +708 -0
  85. invoke_tasklib-0.1.0a0/tests/unit/test_architecture.py +330 -0
  86. invoke_tasklib-0.1.0a0/tests/unit/test_check.py +512 -0
  87. invoke_tasklib-0.1.0a0/tests/unit/test_clean.py +1019 -0
  88. invoke_tasklib-0.1.0a0/tests/unit/test_doc.py +582 -0
  89. invoke_tasklib-0.1.0a0/tests/unit/test_docstrings.py +107 -0
  90. invoke_tasklib-0.1.0a0/tests/unit/test_env.py +675 -0
  91. invoke_tasklib-0.1.0a0/tests/unit/test_fix.py +145 -0
  92. invoke_tasklib-0.1.0a0/tests/unit/test_formatting.py +278 -0
  93. invoke_tasklib-0.1.0a0/tests/unit/test_helpers.py +62 -0
  94. invoke_tasklib-0.1.0a0/tests/unit/test_imports.py +315 -0
  95. invoke_tasklib-0.1.0a0/tests/unit/test_init.py +461 -0
  96. invoke_tasklib-0.1.0a0/tests/unit/test_lint.py +126 -0
  97. invoke_tasklib-0.1.0a0/tests/unit/test_output.py +372 -0
  98. invoke_tasklib-0.1.0a0/tests/unit/test_program_hints.py +66 -0
  99. invoke_tasklib-0.1.0a0/tests/unit/test_release.py +809 -0
  100. invoke_tasklib-0.1.0a0/tests/unit/test_runner.py +487 -0
  101. invoke_tasklib-0.1.0a0/tests/unit/test_security.py +54 -0
  102. invoke_tasklib-0.1.0a0/tests/unit/test_show.py +238 -0
  103. invoke_tasklib-0.1.0a0/tests/unit/test_testing.py +853 -0
  104. invoke_tasklib-0.1.0a0/tests/unit/test_tools.py +671 -0
  105. invoke_tasklib-0.1.0a0/tests/unit/test_typecheck.py +112 -0
  106. invoke_tasklib-0.0.7/PKG-INFO +0 -247
  107. invoke_tasklib-0.0.7/README.md +0 -219
  108. invoke_tasklib-0.0.7/invoke_tasklib/__init__.py +0 -63
  109. invoke_tasklib-0.0.7/invoke_tasklib/clean.py +0 -55
  110. invoke_tasklib-0.0.7/invoke_tasklib/config.py +0 -124
  111. invoke_tasklib-0.0.7/invoke_tasklib/doc.py +0 -59
  112. invoke_tasklib-0.0.7/invoke_tasklib/env.py +0 -103
  113. invoke_tasklib-0.0.7/invoke_tasklib/format.py +0 -89
  114. invoke_tasklib-0.0.7/invoke_tasklib/imports.py +0 -47
  115. invoke_tasklib-0.0.7/invoke_tasklib/lint.py +0 -34
  116. invoke_tasklib-0.0.7/invoke_tasklib/release.py +0 -47
  117. invoke_tasklib-0.0.7/invoke_tasklib/security.py +0 -22
  118. invoke_tasklib-0.0.7/invoke_tasklib/test.py +0 -169
  119. invoke_tasklib-0.0.7/invoke_tasklib/types.py +0 -25
  120. invoke_tasklib-0.0.7/pyproject.toml +0 -279
  121. {invoke_tasklib-0.0.7 → invoke_tasklib-0.1.0a0}/LICENSE +0 -0
  122. {invoke_tasklib-0.0.7 → invoke_tasklib-0.1.0a0}/invoke_tasklib/py.typed +0 -0
@@ -47,6 +47,7 @@ nosetests.xml
47
47
  coverage.xml
48
48
  *.cover
49
49
  *.py.cover
50
+ .benchmarks/
50
51
  .hypothesis/
51
52
  .pytest_cache/
52
53
  cover/
@@ -166,6 +167,7 @@ venv.bak/
166
167
 
167
168
  # mkdocs documentation
168
169
  /site
170
+ /docs/site
169
171
 
170
172
  # mypy
171
173
  .mypy_cache/
@@ -0,0 +1,348 @@
1
+ Metadata-Version: 2.5
2
+ Name: invoke-tasklib
3
+ Version: 0.1.0a0
4
+ Summary: Reusable Invoke tasks shared across Python projects.
5
+ Project-URL: Homepage, https://github.com/durandtibo/invoke-tasklib
6
+ Project-URL: Repository, https://github.com/durandtibo/invoke-tasklib
7
+ Project-URL: Documentation, https://durandtibo.github.io/invoke-tasklib/
8
+ Project-URL: Changelog, https://github.com/durandtibo/invoke-tasklib/releases
9
+ Project-URL: Issues, https://github.com/durandtibo/invoke-tasklib/issues
10
+ Author-email: Thibaut Durand <durand.tibo+gh@gmail.com>
11
+ License-Expression: BSD-3-Clause
12
+ License-File: LICENSE
13
+ Keywords: automation,devtools,invoke,tasks
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
+ Classifier: Topic :: Software Development :: Build Tools
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.11
26
+ Requires-Dist: invoke<4.0,>=3.0
27
+ Description-Content-Type: text/markdown
28
+
29
+ # invoke-tasklib
30
+
31
+ <p align="center">
32
+ <a href="https://github.com/durandtibo/invoke-tasklib/actions/workflows/ci.yaml">
33
+ <img alt="CI" src="https://github.com/durandtibo/invoke-tasklib/actions/workflows/ci.yaml/badge.svg">
34
+ </a>
35
+ <a href="https://github.com/durandtibo/invoke-tasklib/actions/workflows/nightly-package.yaml">
36
+ <img alt="Nightly Package Tests" src="https://github.com/durandtibo/invoke-tasklib/actions/workflows/nightly-package.yaml/badge.svg">
37
+ </a>
38
+ <a href="https://codecov.io/gh/durandtibo/invoke-tasklib">
39
+ <img alt="Codecov" src="https://codecov.io/gh/durandtibo/invoke-tasklib/branch/main/graph/badge.svg">
40
+ </a>
41
+ <br/>
42
+ <a href="https://durandtibo.github.io/invoke-tasklib/">
43
+ <img alt="Documentation" src="https://github.com/durandtibo/invoke-tasklib/actions/workflows/release-docs.yaml/badge.svg">
44
+ </a>
45
+ <a href="https://durandtibo.github.io/invoke-tasklib/dev/">
46
+ <img alt="Documentation" src="https://github.com/durandtibo/invoke-tasklib/actions/workflows/release-docs-dev.yaml/badge.svg">
47
+ </a>
48
+ <br/>
49
+ <a href="https://google.github.io/styleguide/pyguide.html#s3.8-comments-and-docstrings">
50
+ <img alt="Doc style: google" src="https://img.shields.io/badge/%20style-google-3666d6.svg">
51
+ </a>
52
+ <a href="https://github.com/astral-sh/ruff">
53
+ <img alt="Ruff" src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json">
54
+ </a>
55
+ <a href="https://github.com/guilatrova/tryceratops">
56
+ <img alt="try/except style: tryceratops" src="https://img.shields.io/badge/try%2Fexcept%20style-tryceratops%20%F0%9F%A6%96%E2%9C%A8-black">
57
+ </a>
58
+ <br/>
59
+ <a href="https://pypi.org/project/invoke-tasklib/">
60
+ <img alt="PYPI version" src="https://img.shields.io/pypi/v/invoke-tasklib">
61
+ </a>
62
+ <a href="https://pypi.org/project/invoke-tasklib/">
63
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/invoke-tasklib.svg">
64
+ </a>
65
+ <a href="https://opensource.org/licenses/BSD-3-Clause">
66
+ <img alt="BSD-3-Clause" src="https://img.shields.io/pypi/l/invoke-tasklib">
67
+ </a>
68
+ <br/>
69
+ <a href="https://pepy.tech/project/invoke-tasklib">
70
+ <img alt="Downloads" src="https://static.pepy.tech/badge/invoke-tasklib">
71
+ </a>
72
+ <a href="https://pepy.tech/project/invoke-tasklib">
73
+ <img alt="Monthly downloads" src="https://static.pepy.tech/badge/invoke-tasklib/month">
74
+ </a>
75
+ <a href="https://github.com/durandtibo/invoke-tasklib/stargazers">
76
+ <img alt="GitHub stars" src="https://img.shields.io/github/stars/durandtibo/invoke-tasklib">
77
+ </a>
78
+ <br/>
79
+ <a href="https://www.bestpractices.dev/projects/14387">
80
+ <img src="https://www.bestpractices.dev/projects/14387/badge">
81
+ </a>
82
+ <a href="https://scorecard.dev/viewer/?uri=github.com/durandtibo/invoke-tasklib">
83
+ <img alt="OpenSSF Scorecard" src="https://img.shields.io/badge/dynamic/json?url=https://api.scorecard.dev/projects/github.com/durandtibo/invoke-tasklib&label=openssf%20scorecard&query=score">
84
+ </a>
85
+ </p>
86
+
87
+ Reusable [Invoke](https://www.pyinvoke.org/) tasks shared across Python
88
+ projects: formatting, linting, type-checking, testing, environment setup,
89
+ security auditing, releasing, documentation, and cleanup — all as a single
90
+ importable package instead of a `tasks.py` you copy-paste and let drift
91
+ between repositories.
92
+
93
+ :book: **Full documentation:** <https://durandtibo.github.io/invoke-tasklib/>
94
+
95
+ ## Install
96
+
97
+ ```shell
98
+ uv add --dev invoke-tasklib
99
+ ```
100
+
101
+ or with `pip`:
102
+
103
+ ```shell
104
+ pip install invoke-tasklib
105
+ ```
106
+
107
+ **Prerequisite:** most tasks (`env.*`, `release.*`, `security.audit`) run
108
+ [`uv`](https://docs.astral.sh/uv/getting-started/installation/), so install
109
+ it even if you install `invoke-tasklib` with `pip`.
110
+
111
+ **Platforms:** Linux and macOS. Windows is not supported: the tasks rely on
112
+ a POSIX shell (for the quoting of the commands), and `make_ns` emits a
113
+ `RuntimeWarning` on Windows.
114
+
115
+ ## Quickstart
116
+
117
+ **1. Add a `tasks.py`** at the root of your project:
118
+
119
+ ```python
120
+ # tasks.py
121
+ from invoke_tasklib import make_ns
122
+
123
+ ns = make_ns()
124
+ ```
125
+
126
+ **2. Add an `invoke.yaml`** with, at minimum, your package name:
127
+
128
+ ```yaml
129
+ tasklib:
130
+ package:
131
+ name: my_package
132
+ ```
133
+
134
+ **3. List and run the tasks:**
135
+
136
+ ```shell
137
+ invoke --list
138
+ invoke format.check-python lint.check-python
139
+ invoke test.unit
140
+ ```
141
+
142
+ If a task fails because a tool like `ruff` or `pytest` isn't installed yet,
143
+ run `invoke env.install` first.
144
+
145
+ See the [Get Started guide](https://durandtibo.github.io/invoke-tasklib/get_started/)
146
+ for a full walkthrough.
147
+
148
+ ## Tasks
149
+
150
+ Tasks are grouped into namespaces, one per module. Each task either
151
+ **checks/reports** (read-only, exits non-zero on violations) or
152
+ **mutates** (formats, builds, publishes) — the table below flags which.
153
+
154
+ | Namespace | Task | Behavior | Mutates? |
155
+ | ---------- | ----------------------------- | ---------------------------------------------------------------------------------------- | :------: |
156
+ | `format` | `format.check-python` | Check Python formatting with ruff | ❌ |
157
+ | `format` | `format.fix-python` | Format Python code with ruff | ✅ |
158
+ | `format` | `format.check-docstrings` | Check docstring formatting with docformatter | ❌ |
159
+ | `format` | `format.fix-docstrings` | Format docstrings with docformatter | ✅ |
160
+ | `format` | `format.check-shell` | Check shell scripts with shellcheck | ❌ |
161
+ | `format` | `format.check-shell-format` | Check the format of shell scripts with shfmt | ❌ |
162
+ | `format` | `format.fix-shell` | Format shell scripts with shfmt | ✅ |
163
+ | `lint` | `lint.check-python` | Check linting with ruff | ❌ |
164
+ | `lint` | `lint.fix-python` | Fix auto-fixable linting issues with ruff | ✅ |
165
+ | `lint` | `lint.check-spelling` | Check the spelling with codespell | ❌ |
166
+ | `lint` | `lint.pre-commit` | Run all the pre-commit hooks | ✅ |
167
+ | `imports` | `imports.check-cycles` | Check for cyclic import dependencies | ❌ |
168
+ | `imports` | `imports.check-isolated` | Check that every module imports on its own | ❌ |
169
+ | `types` | `types.check` | Check type hints with ty (`--complete` also runs pyright) | ❌ |
170
+ | `test` | `test.doctest` | Run doctests on source code and markdown files | ❌ |
171
+ | `test` | `test.doctest-src` | Run doctests on source code | ❌ |
172
+ | `test` | `test.doctest-markdown` | Run doctests on Python examples in markdown files | ❌ |
173
+ | `test` | `test.unit` | Run unit tests | ❌ |
174
+ | `test` | `test.integration` | Run integration tests | ❌ |
175
+ | `test` | `test.functional` | Run functional tests | ❌ |
176
+ | `test` | `test.all` | Run unit, integration, and functional tests | ❌ |
177
+ | `test` | `test.coverage-report` | Generate an HTML/terminal report from existing coverage data | ❌ |
178
+ | `test` | `test.benchmark` | Run performance benchmarks | ❌ |
179
+ | `env` | `env.create-venv` | Create a virtual environment and install the project | ✅ |
180
+ | `env` | `env.install` | Install project dependencies and the package (editable) | ✅ |
181
+ | `env` | `env.check-tools` | Check which tools (ruff, pyright, ...) are available | ❌ |
182
+ | `env` | `env.update` | Update dependencies and pre-commit hooks | ✅ |
183
+ | `env` | `env.show-installed-packages` | Show the installed packages | ❌ |
184
+ | `env` | `env.show-python-config` | Show the Python configuration | ❌ |
185
+ | `release` | `release.build` | Build the package and verify installation (`--check` also validates metadata with twine) | ✅ |
186
+ | `release` | `release.publish` | Build and publish the package to PyPI | ✅ |
187
+ | `doc` | `doc.publish-dev` | Publish development (unstable) docs | ✅ |
188
+ | `doc` | `doc.publish-latest` | Publish latest (stable) docs | ✅ |
189
+ | `doc` | `doc.build` | Build the docs, failing on warnings (`mkdocs build --strict`) | ❌ |
190
+ | `doc` | `doc.serve` | Serve the docs locally | ❌ |
191
+ | `security` | `security.audit` | Audit the locked dependencies for known vulnerabilities with pip-audit | ❌ |
192
+ | `check` | `check.all` (or `check`) | Run the main read-only checks | ❌ |
193
+ | `fix` | `fix.all` (or `fix`) | Fix the lint and format issues | ✅ |
194
+ | `clean` | `clean.all` (or `clean`) | Remove build artifacts and caches | ✅ |
195
+ | `clean` | `clean.pycache` | Remove all `__pycache__` directories | ✅ |
196
+ | `config` | `config.show` | Show the resolved config and where each value comes from | ❌ |
197
+
198
+ `format.*` and `lint.*` follow a naming convention: read-only checks are
199
+ named `check_<target>`, and the matching in-place fixer is named
200
+ `fix_<target>` (e.g. `check_python`/`fix_python`), so the counterpart of a
201
+ task is always easy to find. Follow this convention when adding new tasks
202
+ to these namespaces.
203
+
204
+ For task-by-task details, options (like `--cov` on `test.*` tasks), and the
205
+ tools each one wraps, see the
206
+ [User Guide](https://durandtibo.github.io/invoke-tasklib/uguide/).
207
+
208
+ ## Configuration
209
+
210
+ Only `tasklib.package.name` is required — everything else has a sensible
211
+ default derived from it:
212
+
213
+ ```yaml
214
+ tasklib:
215
+ package:
216
+ name: my_package # required
217
+ import_name: my_package # default: <package.name> with - replaced by _
218
+ python_version: "3.14" # used by env.create-venv (default: the version that uv chooses)
219
+ paths:
220
+ src: src/my_package # default: src/<package.import_name>
221
+ tests: tests
222
+ unit_tests: tests/unit # default: <tests>/unit
223
+ integration_tests: tests/integration # default: <tests>/integration
224
+ functional_tests: tests/functional # default: <tests>/functional
225
+ benchmarks: tests/benchmarks # default: <tests>/benchmarks
226
+ docs_config: docs/mkdocs.yml
227
+ groups:
228
+ install: dev # dependency groups of env.install
229
+ update: dev,docs # dependency groups of env.update
230
+ test:
231
+ unit_timeout: 10 # seconds, also integration_timeout and functional_timeout
232
+ xdoctest: true # pytest --xdoctest (needs xdoctest)
233
+ timeout: true # pytest --timeout (needs pytest-timeout)
234
+ cov_fail_under: 90 # threshold of --cov (default: not set)
235
+ cov_reports: html,xml,term
236
+ types:
237
+ checker: ty # type checker of types.check: ty, pyright or mypy
238
+ check:
239
+ tasks: format-python,format-docstrings,lint,types,imports,unit # steps of check.all
240
+ cov: false # run the unit step of check.all with --cov
241
+ fix:
242
+ tasks: lint,format-python,format-docstrings # steps of fix.all
243
+ ```
244
+
245
+ `check.tasks` also accepts `doctest`, `shell`, `spelling`, `docs` and `audit`; `fix.tasks` also
246
+ accepts `shell`. `invoke config.show` prints the resolved values and where each one comes from.
247
+
248
+ See the [Config reference](https://durandtibo.github.io/invoke-tasklib/uguide/config/)
249
+ for how each path default is derived.
250
+
251
+ Every key can also be set with an `INVOKE_TASKLIB_<SECTION>_<KEY>` environment variable, for example
252
+ `INVOKE_TASKLIB_PATHS_SRC=lib` or `INVOKE_TASKLIB_TEST_UNIT_TIMEOUT=30`, which wins over
253
+ `invoke.yaml`. An invalid value, an unknown key (with the closest valid key suggested) or a wrong
254
+ working directory exits with the code 2 before any command runs. For editor completion, the JSON
255
+ schema of the `tasklib` section is published at
256
+ <https://durandtibo.github.io/invoke-tasklib/schema.json> (`python -m invoke_tasklib.config` prints
257
+ it).
258
+
259
+ ## Conventions
260
+
261
+ - **Arguments:** the tasks that run a tool take `--args` (extra arguments for the tool, as one
262
+ string, e.g. `--args "-k foo -x"`) and, for the tasks that work on files, `--paths` (files or
263
+ directories instead of the default ones). Both are quoted, so a glob or `~` reaches the tool as
264
+ it is.
265
+ - **Exit codes:** `0` the task passed, or had nothing to do (a `⏭️` line says why); `1` the checked
266
+ thing failed; `2` invalid usage or config; `127` a tool is missing. A missing program or Python
267
+ module is reported with the command that installs it.
268
+ - **Composite tasks:** `invoke check` runs the main read-only checks and `invoke fix` the fixers;
269
+ `--only`, `--skip` and `--keep-going` select the steps and report all the failures at the end.
270
+ - **Dangerous tasks ask first:** `env.create-venv` asks before it clears `.venv` and
271
+ `release.publish` checks the git state and asks before it uploads (`--yes` skips the question,
272
+ `--dry-run` publishes nothing). `clean` stays inside the project and keeps what git tracks.
273
+ - **ASCII output:** set `INVOKE_TASKLIB_ASCII=1` to replace the emojis of the messages with
274
+ `[ok]`, `[fail]` and `[skip]`.
275
+
276
+ ## Composing a custom subset of tasks
277
+
278
+ Need a different set of tasks, or a one-off task alongside the shared ones?
279
+ Use `make_ns`, which returns a new collection each time, so adding or removing tasks never affects
280
+ other importers. Leave out the tasks you do not use (for example the ones that publish):
281
+
282
+ ```python
283
+ # tasks.py
284
+ from invoke import task
285
+ from invoke_tasklib import make_ns
286
+
287
+
288
+ @task
289
+ def my_custom_task(c):
290
+ r"""Run a one-off command."""
291
+ c.run("echo hello")
292
+
293
+
294
+ ns = make_ns(exclude=["release.publish", "doc"])
295
+ ns.add_task(my_custom_task)
296
+ ```
297
+
298
+ `tasks.py` is imported by Invoke as a top-level module, so a task defined in another file of the
299
+ project is imported with an absolute import (`from my_tasks import my_custom_task`), not a
300
+ relative one (`from . import my_custom_task`), which fails with an `ImportError`.
301
+
302
+ or keep only some of them with `include`, e.g. `make_ns(include=["lint", "test.unit"])`. The names
303
+ are namespaces (`"doc"`) or tasks (`"release.publish"`); an unknown name raises a `ValueError`. The
304
+ `make_ns()` with no argument has all the tasks (the former pre-built `invoke_tasklib.ns`, one
305
+ collection shared by every importer, was removed). Individual task modules can also be composed by
306
+ hand:
307
+
308
+ ```python
309
+ # tasks.py
310
+ from invoke import Collection, task
311
+ from invoke_tasklib import lint, testing
312
+
313
+
314
+ @task
315
+ def my_custom_task(c):
316
+ r"""Run a one-off command."""
317
+ c.run("echo hello")
318
+
319
+
320
+ ns = Collection(lint, Collection.from_module(testing, name=testing.NAMESPACE), my_custom_task)
321
+ ```
322
+
323
+ The modules of the `format`, `types` and `test` namespaces are named `formatting`, `typecheck`
324
+ and `testing` so that they do not shadow the standard library (`types`, `test`) or a builtin
325
+ (`format`); pass `name=module.NAMESPACE` (every task module has the name of its namespace in `NAMESPACE`)
326
+ to `Collection.from_module` to keep the task names.
327
+
328
+ Prefer adding a config knob to a shared task over forking it; reserve custom
329
+ composition for things that are genuinely one-off to a single project.
330
+
331
+ ## API Stability
332
+
333
+ :warning: `invoke-tasklib` is under active development and its API is not
334
+ yet stable — pin a specific version in your project's dependencies for
335
+ consistent behavior across releases.
336
+
337
+ ## Contributing
338
+
339
+ Contributions are welcome! Please open an issue first to discuss
340
+ significant changes. See the
341
+ [developer guide](https://durandtibo.github.io/invoke-tasklib/dev/development/)
342
+ for how to set up a development environment.
343
+
344
+ ## License
345
+
346
+ `invoke-tasklib` is licensed under the BSD 3-Clause "New" or "Revised"
347
+ license available in
348
+ [LICENSE](https://github.com/durandtibo/invoke-tasklib/blob/main/LICENSE).