common-python-tasks 0.3.1__tar.gz → 0.4.1__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 (41) hide show
  1. common_python_tasks-0.4.1/.gitignore +216 -0
  2. common_python_tasks-0.4.1/.poetry/plugins/poetry_dynamic_versioning-1.10.0.dist-info/licenses/LICENSE +21 -0
  3. common_python_tasks-0.4.1/.poetry/plugins/poetry_plugin_export-1.10.0.dist-info/licenses/LICENSE +20 -0
  4. common_python_tasks-0.4.1/PKG-INFO +436 -0
  5. common_python_tasks-0.4.1/README.md +401 -0
  6. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/pyproject.toml +17 -13
  7. common_python_tasks-0.4.1/scripts/add-common-python-tasks.sh +35 -0
  8. common_python_tasks-0.4.1/scripts/release_script.py +175 -0
  9. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/fastapi/compose-base.yml.j2 +2 -1
  10. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/fastapi/compose-db.yml.j2 +2 -1
  11. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/.dockerignore +0 -2
  12. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/Dockerfile.j2 +45 -8
  13. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/docker.py +128 -57
  14. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/docker_compose.py +15 -9
  15. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/env.py +53 -12
  16. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/git.py +27 -6
  17. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/github.py +19 -40
  18. common_python_tasks-0.4.1/src/common_python_tasks/project.py +628 -0
  19. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/tasks.py +185 -92
  20. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/utils.py +190 -13
  21. common_python_tasks-0.3.1/PKG-INFO +0 -428
  22. common_python_tasks-0.3.1/README.md +0 -394
  23. common_python_tasks-0.3.1/src/common_python_tasks/data/generic/.pytest_cache/.gitignore +0 -2
  24. common_python_tasks-0.3.1/src/common_python_tasks/data/generic/.pytest_cache/CACHEDIR.TAG +0 -4
  25. common_python_tasks-0.3.1/src/common_python_tasks/data/generic/.pytest_cache/README.md +0 -8
  26. common_python_tasks-0.3.1/src/common_python_tasks/data/generic/.pytest_cache/v/cache/lastfailed +0 -11
  27. common_python_tasks-0.3.1/src/common_python_tasks/data/generic/.pytest_cache/v/cache/nodeids +0 -412
  28. common_python_tasks-0.3.1/src/common_python_tasks/project.py +0 -338
  29. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/LICENSE +0 -0
  30. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/__init__.py +0 -0
  31. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/__main__.py +0 -0
  32. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/dockerfile_extensions/.gitkeep +0 -0
  33. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/fastapi/alembic.ini.j2 +0 -0
  34. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/fastapi/compose-db-debug.yml.j2 +0 -0
  35. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/fastapi/compose-debug.yml.j2 +0 -0
  36. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/.coveragerc +0 -0
  37. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/.flake8 +0 -0
  38. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/.isort.cfg +0 -0
  39. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/Dockerfile.deps.j2 +0 -0
  40. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/cliff.toml +0 -0
  41. {common_python_tasks-0.3.1 → common_python_tasks-0.4.1}/src/common_python_tasks/data/generic/pytest.ini +0 -0
@@ -0,0 +1,216 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+
204
+ # Ruff stuff:
205
+ .ruff_cache/
206
+
207
+ # PyPI configuration file
208
+ .pypirc
209
+
210
+ # Marimo
211
+ marimo/_static/
212
+ marimo/_lsp/
213
+ __marimo__/
214
+
215
+ # Streamlit
216
+ .streamlit/secrets.toml
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Matthew T. Kennerly (mtkennerly)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2022 Sébastien Eustace
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,436 @@
1
+ Metadata-Version: 2.4
2
+ Name: common-python-tasks
3
+ Version: 0.4.1
4
+ Summary: Opinionated Poe the Poet tasks for Python package development.
5
+ Project-URL: Homepage, http://github.com/ci-sourcerer/common-python-tasks
6
+ Project-URL: Source, http://github.com/ci-sourcerer/common-python-tasks.git
7
+ Project-URL: Issues, http://github.com/ci-sourcerer/common-python-tasks/issues
8
+ Author-email: Joseph Asbury <ci_sourcerer@yahoo.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Requires-Python: <4.0,>=3.11
20
+ Requires-Dist: autoflake<3.0.0,>=2.3.1
21
+ Requires-Dist: black<27.0.0,>=26.3.1
22
+ Requires-Dist: docker<8.0.0,>=7.1.0
23
+ Requires-Dist: dunamai<2.0.0,>=1.25.0
24
+ Requires-Dist: flake8<8.0.0,>=7.3.0
25
+ Requires-Dist: git-cliff<3.0.0,>=2.12.0
26
+ Requires-Dist: isort<9.0.0,>=8.0.1
27
+ Requires-Dist: jinja2<4.0.0,>=3.1.6
28
+ Requires-Dist: packaging<27.0,>=26.2
29
+ Requires-Dist: poethepoet-tasks<0.4.0,>=0.3.0
30
+ Requires-Dist: pytest-cov<8.0.0,>=7.0.0
31
+ Requires-Dist: pytest<10.0.0,>=9.0.3
32
+ Requires-Dist: requests<3.0.0,>=2.34.2
33
+ Requires-Dist: tomlkit<0.14.0,>=0.13.3
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Common Python Tasks
37
+
38
+ This package is a collection of (very) opinionated [Poe the Poet](https://poethepoet.natn.io/guides/packaged_tasks.html) Python tasks for common Python development workflows.
39
+
40
+ Instead of writing your own tasks for formatting, linting, testing, packaging, and more, you can use these prebuilt tasks that work immediately with reasonable defaults and support configuration overrides when needed. In the past, I found myself copying and pasting the same task definitions across projects, and this package is my attempt to DRY up that workflow and provide a single source of truth for common Python development tasks. I hope you can use them too.
41
+
42
+ ## Quick start
43
+
44
+ ### Automated setup
45
+
46
+ You can add `common-python-tasks` to a new project by using the handy automated installation script.
47
+
48
+ ```shell
49
+ curl -sSL https://api.github.com/repos/ci-sourcerer/common-python-tasks/contents/scripts/add-common-python-tasks.sh | jq -r '.content' | base64 -d | sh
50
+ ```
51
+
52
+ To install a specific release, set the environment variable `COMMON_PYTHON_TASKS_VERSION`.
53
+
54
+ ```shell
55
+ COMMON_PYTHON_TASKS_VERSION=0.4.1 \
56
+ sh -c "$(curl -sSL https://api.github.com/repos/ci-sourcerer/common-python-tasks/contents/scripts/add-common-python-tasks.sh | jq -r '.content' | base64 -d)"
57
+ ```
58
+
59
+ This will complete the following steps.
60
+
61
+ 1. Add the latest version of `common-python-tasks` to your `pyproject.toml` dependencies
62
+ 2. Configure Poe the Poet to expose the default common task set
63
+ 3. Install dependencies for your project
64
+
65
+ **Always review scripts before running them!** Even though I believe I write good software, it's best practice to verify any script you download from the Internet.
66
+
67
+ ### Manual setup
68
+
69
+ There's no real reason to run the automated script; I just like automating everything. You can achieve the same result by following these steps.
70
+
71
+ 1. Add `common-python-tasks` to your `pyproject.toml` and configure Poe the Poet
72
+
73
+ ```toml
74
+ [project]
75
+ dependencies = [
76
+ "common-python-tasks==0.4.1" # Always pin to a specific version
77
+ ]
78
+
79
+ [tool.poe]
80
+ include_script = "common_python_tasks:tasks()" # Uses the default `common` task set
81
+ ```
82
+
83
+ 2. Install the package
84
+
85
+ ```shell
86
+ uv sync
87
+ # or, for Poetry workflows
88
+ poetry install
89
+ ```
90
+
91
+ 3. Run tasks
92
+
93
+ ```shell
94
+ poe format # Format your code
95
+ poe lint # Check code quality
96
+ poe test # Run tests with coverage
97
+ ```
98
+
99
+ ## Available tasks
100
+
101
+ Internal tasks are used by other tasks and are not meant to be run directly.
102
+
103
+ <!-- tasks-table -->
104
+ | Task | Description | Tags |
105
+ | - | - | - |
106
+ | `test` | Run the test suite with coverage (if `pytest-cov` is installed). | common, test |
107
+ | `clean` | Clean up temporary files and directories. | clean, common |
108
+ | `format` | Format Python code with autoflake, black, and isort. | common, format |
109
+ | `lint` | Lint Python code with autoflake, black, isort, and flake8. | common, lint |
110
+ | `build-image` | Build the container image for this project using the Dockerfile template. | build, containers |
111
+ | `build-deps-image` | Build only the container dependency collector image for this project. | build, containers |
112
+ | `run-container` | Run the Docker image as a container for this project. By default (when `tag` is `None`) this will run the most-recently-built tag for the project's image. | containers |
113
+ | `push-image` | Push the Docker image for this project to the container registry. | containers, packaging, release |
114
+ | `publish-package` | Publish the package to the PyPI server. | common, packaging |
115
+ | `publish-github-release` | Publish or update a GitHub Release for the current repository. | common, packaging, release |
116
+ | `build-package` | Build the package (wheel and sdist). | build, common, packaging |
117
+ | `bump-version` | Bump the project version. | common, packaging |
118
+ | `changelog` | Print the changelog for the current version based on git history and git-cliff. | common, packaging, release |
119
+ | `release` | Run a full release flow for package and containers. | common, containers, packaging, release |
120
+ | `build` | Build the project and its containers. | common, containers, packaging |
121
+ | `stack-up` | Bring up the development stack for the application. | containers, fastapi, web |
122
+ | `stack-down` | Bring down the development stack for the application. | containers, fastapi, web |
123
+ | `reset-db` | Reset the database by deleting the database volume. | containers, database, fastapi, web |
124
+ | `run-db-migrations` | Run database migrations. | containers, database, fastapi, web |
125
+ | `db-shell` | Open a psql shell to the database container. | containers, database, fastapi, web |
126
+ | `container-shell` | Run the debug image with an interactive shell. | containers, debug |
127
+ <!-- end-tasks-table -->
128
+
129
+ ## Docker Compose Development Stacks
130
+
131
+ Some tasks of certain tags provide Docker Compose-based development stacks for running your application with supporting services (databases, caches, etc.). Currently supports FastAPI applications with PostgreSQL.
132
+
133
+ ### Configuration
134
+
135
+ #### `COMPOSE_TYPE`
136
+
137
+ Specifies the type of application stack. Currently supported:
138
+
139
+ - `fastapi`: FastAPI application with optional database support and Alembic migrations
140
+
141
+ Set via environment variable:
142
+
143
+ ```toml
144
+ [tool.poe.env]
145
+ COMPOSE_TYPE = "fastapi"
146
+ ```
147
+
148
+ #### `COMPOSE_ADDONS`
149
+
150
+ Colon-separated list of additional services to include. Available addons:
151
+
152
+ - `db`: PostgreSQL database with Alembic migration support and Adminer web UI
153
+
154
+ Example:
155
+
156
+ ```toml
157
+ [tool.poe.env]
158
+ COMPOSE_ADDONS = "db"
159
+ ```
160
+
161
+ For multiple addons (future): `COMPOSE_ADDONS = "db:redis:cache"`
162
+
163
+ ### Compose File Customization
164
+
165
+ The compose setup follows this precedence.
166
+
167
+ 1. **Environment override**: `COMPOSE_FILE` environment variable with colon separated paths
168
+ 2. **Automatically loaded files**: Based on `COMPOSE_TYPE` and `COMPOSE_ADDONS`
169
+ - `compose-base.yml`: Core application service
170
+ - `compose-{addon}.yml`: One file for each addon; for example, `compose-db.yml`
171
+ - `compose-debug.yml`: Used when the `--debug` flag is present
172
+ - `compose-{addon}-debug.yml`: Debug overlays for addons
173
+ 3. **Additional overlays**: `COMPOSE_OVERLAY_FILES` with colon separated paths
174
+
175
+ You can provide local compose files or let the tasks use bundled templates.
176
+
177
+ ### `fastapi`
178
+
179
+ The `fastapi` stack includes a service for your FastAPI application. It uses the standard Dockerfile included with this package.
180
+
181
+ #### Environment variables
182
+
183
+ - `API_PORT`: Port for the API server (default: `8080`)
184
+ - `SECRET_KEY`: Application secret key; generated automatically and stored in `.env` if not set
185
+ - `ENVIRONMENT`: Environment name such as `development` or `production` (default: `production`)
186
+ - `DEBUG_PORT`: Port for the Python debugger when using `--debug` (default: `5678`)
187
+ - `DB_PORT`: PostgreSQL port (default: `5432`)
188
+ - `DB_USER`: Database user (default: package name)
189
+ - `DB_BASE`: Database name (default: package name)
190
+ - `DB_PASS`: Database password; generated automatically and stored in `.env` if not set
191
+ - `POSTGRES_VERSION`: PostgreSQL Docker image version (default: `17`)
192
+ - `ADMINER_PORT`: Adminer web UI port (default: `8081`)
193
+
194
+ ## How it works
195
+
196
+ ### Prerequisites
197
+
198
+ Your project must meet the following requirements.
199
+
200
+ - Uses Poetry or uv for dependency management
201
+ - Uses Poe the Poet for task management
202
+ - Has `poetry-dynamic-versioning` or `uv-dynamic-versioning` as a dependency
203
+ - Has a `pyproject.toml` file at the root
204
+ - Has a package name (automatically inferred from `project.name` in `pyproject.toml` or set via `PACKAGE_NAME` environment variable)
205
+
206
+ ### Package manager backend selection
207
+
208
+ Packaging-related tasks (`build-package`, `publish-package`, release tagging/version resolution, and related container build metadata) support both Poetry and uv.
209
+
210
+ Backend selection uses this precedence.
211
+
212
+ 1. `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
213
+ 2. `COMMON_PYTHON_TASKS_BUILD_TOOL`
214
+ 3. `PACKAGE_MANAGER`
215
+ 4. Auto-discovery (`auto`) based on installed tools and project metadata
216
+
217
+ Supported values are `poetry`, `uv`, and `auto`.
218
+
219
+ ### Configuration precedence
220
+
221
+ Tasks that need configuration files (`pytest`, `coverage`, `flake8`, `isort`) follow this order of precedence.
222
+
223
+ 1. **`pyproject.toml` sections**: `[tool.pytest]`, `[tool.coverage]`, `[tool.isort]` take priority
224
+ 2. **Environment variables**: Override config paths; see [Environment Variables](#environment-variables)
225
+ 3. **Local config files**: `pytest.ini`, `.coveragerc`, `.flake8`, `.isort.cfg` in the project root
226
+ 4. **Bundled defaults**: Sensible defaults included with this package, found in the [`src/common_python_tasks/data`](src/common_python_tasks/data) directory
227
+
228
+ You can start with zero configuration and customize as needed.
229
+
230
+ ### Environment variables
231
+
232
+ #### Configuration files
233
+
234
+ The following environment variables configure the paths to configuration files.
235
+
236
+ - `PYTEST_CONFIG`: Specifies the path to the pytest configuration file
237
+ - `COVERAGE_RCFILE`: Specifies the path to the coverage configuration file
238
+ - `FLAKE8_CONFIG`: Specifies the path to the flake8 configuration file
239
+ - `ISORT_CONFIG`: Specifies the path to the isort configuration file
240
+
241
+ #### Package/Container settings
242
+
243
+ The following environment variables configure package and container behavior.
244
+
245
+ - `PACKAGE_NAME`: Overrides the package name; the default comes from `pyproject.toml`
246
+ - `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`: Selects package manager backend (`poetry`, `uv`, or `auto`)
247
+ - `COMMON_PYTHON_TASKS_BUILD_TOOL`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
248
+ - `PACKAGE_MANAGER`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
249
+ - `CONTAINER_REGISTRY_USERNAME`: Specifies the container registry username for image tagging; the default is the current local user
250
+ - `CONTAINER_REGISTRY_URL`: Specifies the registry URL (default: `docker.io/{username}`)
251
+ - `CONTAINER_BUILD_ARGS`: Provides additional Docker build arguments in `KEY=VALUE:OTHER=VALUE` format
252
+ - `CONTAINER_EXTENSION_FILES`: Specifies colon delimited local extension Dockerfile paths to include in the rendered build
253
+ - `CONTAINER_EXTENSIONS`: Specifies colon delimited extension bundle names or parameterized bundle values to include in the rendered build
254
+ - `CONTAINER_ENV`: Provides colon delimited `KEY=VALUE` declarations to inject into the builder stage of the rendered Dockerfile
255
+ - `.containerenv`: Can also supply the same declarations from a file in the project root. It is loaded first, then `container_envfile`, then `CONTAINER_ENV`, and finally `container_env`.
256
+ - `CONTAINER_PRUNE_KEEP`: Controls image pruning after builds (`-1` keeps all, `0` keeps the latest only, `N` keeps the latest plus `N` previous)
257
+ - `CUSTOM_ENTRYPOINT`: Specifies a custom entrypoint script name for containers
258
+ - `CONTAINER_DEPS_CONTENT`: Supplies inline Dockerfile instructions for a dependency image that installs artifacts into `/tmp/deps`
259
+ - `CONTAINER_DEPS_FILE`: Points to one or more explicit Dockerfiles to build the dependency image. It may be a colon delimited list of file paths and is used only when `CONTAINER_DEPS_CONTENT` is unset
260
+ - `CONTAINER_DEPS_MAPPINGS`: Maps copied dependency names from `/tmp/deps` into destination paths as space separated `name:/target/path` entries. This is used only when `CONTAINER_DEPS_MOVE_SCRIPT` or `CONTAINER_DEPS_MOVE_SCRIPT_PATH` is not set
261
+ - `CONTAINER_DEPS_MOVE_SCRIPT`: Supplies a raw executable script to run after `/tmp/deps` is copied into the image. The script is written to `/tmp/container-deps-move-script` and executed with its own shebang
262
+ - `CONTAINER_DEPS_MOVE_SCRIPT_PATH`: Supplies a host path to a script file to run after `/tmp/deps` is copied into the image. This path takes precedence over `CONTAINER_DEPS_MOVE_SCRIPT` when both are set
263
+ - `GITHUB_RELEASE_ASSETS`: Colon separated list of file paths or glob patterns to attach to the GitHub Release (default: `dist/*`)
264
+ - `SKIP_GITHUB_RELEASE`: Truthy value to skip GitHub Release publication
265
+ - `GITHUB_TOKEN` or `GH_TOKEN`: GitHub authentication token used to publish releases and upload assets
266
+ - `GITHUB_REPOSITORY`: Optional override for the repository slug used when publishing a GitHub Release
267
+ - `GITHUB_API_URL` and `GITHUB_SERVER_URL`: Configure the GitHub API host for GitHub Enterprise environments
268
+ - `GITHUB_RELEASE_TAG`: Optional tag name to publish for the GitHub Release
269
+ - `GITHUB_RELEASE_NAME`: Optional release title to use for the GitHub Release
270
+ - `GITHUB_RELEASE_BODY`: Optional release body text to use for the GitHub Release
271
+ - `RELEASE_UPDATE_CHANGELOG`: Truthy value to update `CHANGELOG.md` by prepending the `git-cliff --unreleased --tag "$RELEASE_TAG"` output before the release tag is created. This is enabled by default; set it to a falsy value if you want to disable changelog commits during release
272
+ - `RELEASE_PRE_SCRIPT`: Optional shell command to run before the release steps
273
+ - `RELEASE_POST_SCRIPT`: Optional shell command to run after the release completes
274
+ - Hook commands: Receive the following env vars; `RELEASE_SCRIPT_PHASE`, `RELEASE_TAG`, `RELEASE_VERSION`, `RELEASE_STAGE`, `RELEASE_COMPONENT`, and `RELEASE_DRY_RUN`
275
+
276
+ #### Docker Compose settings
277
+
278
+ The following environment variables configure Docker Compose stacks (when using the `web` tag).
279
+
280
+ - `COMPOSE_TYPE`: Specifies the type of application stack; for example, `fastapi`
281
+ - `COMPOSE_ADDONS`: Colon separated list of services to include; for example, `db` for database support
282
+ - `COMPOSE_FILE`: Overrides all compose files with colon separated paths
283
+ - `COMPOSE_OVERLAY_FILES`: Additional compose files to merge; uses colon separated paths
284
+ - `API_PORT`: Port for the API server (default: `8080`)
285
+ - `SECRET_KEY`: Application secret key; generated automatically if not set
286
+ - `ENVIRONMENT`: Environment name (default: `production`)
287
+ - `DEBUG_PORT`: Port for the Python debugger in debug mode (default: `5678`)
288
+ - `DB_PORT`: PostgreSQL port (default: `5432`)
289
+ - `DB_USER`: Database user (default: package name)
290
+ - `DB_BASE`: Database name (default: package name)
291
+ - `DB_PASS`: Database password; generated automatically if not set
292
+ - `POSTGRES_VERSION`: PostgreSQL version (default: `17`)
293
+ - `ADMINER_PORT`: Adminer web UI port (default: `8081`)
294
+
295
+ #### Debugging
296
+
297
+ The following environment variable enables debugging output.
298
+
299
+ - `COMMON_PYTHON_TASKS_LOG_LEVEL`: Set this to `DEBUG` to see detailed configuration resolution
300
+
301
+ ### Usage examples
302
+
303
+ By default, `tasks()` exposes the common task set. You can still include or exclude tags in your `pyproject.toml` when needed.
304
+
305
+ #### Minimal setup
306
+
307
+ ```toml
308
+ [project]
309
+ name = "simple-cli-tool"
310
+ version = "0.4.1"
311
+ dependencies = ["common-python-tasks==0.4.1"]
312
+
313
+ [tool.poe]
314
+ include_script = "common_python_tasks:tasks()"
315
+ ```
316
+
317
+ Available tasks: common defaults such as `format`, `lint`, `test`, and `build`.
318
+
319
+ #### Container-based project
320
+
321
+ ```toml
322
+ [project]
323
+ dependencies = ["common-python-tasks==0.4.1"]
324
+
325
+ [tool.poe]
326
+ include_script = "common_python_tasks:tasks(include_tags=['common', 'containers'])"
327
+
328
+ [tool.poe.env]
329
+ CONTAINER_REGISTRY_USERNAME = "myusername"
330
+ PACKAGE_NAME = "containerized-app"
331
+ ```
332
+
333
+ Available tasks: All tasks including `build-image` and `push-image`.
334
+
335
+ #### Custom pytest configuration
336
+
337
+ ```toml
338
+ [project]
339
+ dependencies = ["common-python-tasks==0.4.1"]
340
+
341
+ [tool.poe]
342
+ include_script = "common_python_tasks:tasks()"
343
+
344
+ [tool.pytest.ini_options]
345
+ testpaths = ["tests", "integration"]
346
+ addopts = "-ra"
347
+ ```
348
+
349
+ The `test` task will automatically use your `[tool.pytest.ini_options]` configuration.
350
+
351
+ ## Troubleshooting
352
+
353
+ ### Tasks not showing up with `poe --help`
354
+
355
+ Check your `[tool.poe]` configuration in `pyproject.toml`. Make sure you're using `include_script`.
356
+
357
+ ```toml
358
+ # Correct
359
+ [tool.poe]
360
+ include_script = "common_python_tasks:tasks(exclude_tags=['internal'])"
361
+
362
+ # Incorrect
363
+ [tool.poe]
364
+ includes = "common_python_tasks:tasks"
365
+ ```
366
+
367
+ ### Config files not being used
368
+
369
+ Check the configuration precedence (see [How it works](#how-it-works)). Use debug logging to see which config is selected.
370
+
371
+ ### GitHub Release assets not uploading
372
+
373
+ If your release task does not attach assets, confirm `dist/` contains the built wheels and sdists. You can override the default asset selection using `GITHUB_RELEASE_ASSETS`, for example:
374
+
375
+ ```shell
376
+ GITHUB_RELEASE_ASSETS="dist/*.whl:dist/*.tar.gz" poe publish-github-release
377
+ ```
378
+
379
+ ```shell
380
+ COMMON_PYTHON_TASKS_LOG_LEVEL=DEBUG poe test
381
+ ```
382
+
383
+ ### Container build fails with "unable to find package"
384
+
385
+ Make sure your `pyproject.toml` contains the following.
386
+
387
+ - A correct package name in `[project]`
388
+ - Package discovery settings required by your chosen build backend (for Poetry projects, this is commonly `[tool.poetry] packages = [{ include = "your_package", from = "src" }]`)
389
+
390
+ ### Stack fails to start or services won't connect
391
+
392
+ If `stack-up` builds successfully but services can't connect:
393
+
394
+ - Check that required environment variables are set (`COMPOSE_TYPE` at minimum)
395
+ - Verify ports aren't already in use (defaults: 8080 for API, 5432 for database, 8081 for Adminer)
396
+ - Check Docker daemon is running: `docker info`
397
+ - View service logs: `docker compose logs` in your project directory
398
+
399
+ ### Database migrations fail
400
+
401
+ If `run-db-migrations` fails:
402
+
403
+ - Ensure the `db` addon is included: `COMPOSE_ADDONS=db`
404
+ - Check that your project has Alembic configured with migrations in the expected location
405
+ - Verify database credentials in `.env` match your Alembic configuration
406
+ - Manually inspect the database: `poe db-shell`
407
+
408
+ ### Secrets not being generated
409
+
410
+ If `SECRET_KEY` or `DB_PASS` aren't auto-generated:
411
+
412
+ - Ensure `.env` file is writable in your project root
413
+ - Check file permissions: `ls -la .env`
414
+ - Generate manually: `python -c "import secrets; print(secrets.token_hex(32))"`
415
+
416
+ ## Design choices
417
+
418
+ ### Dockerfile (see [`src/common_python_tasks/data/generic/Dockerfile.j2`](src/common_python_tasks/data/generic/Dockerfile.j2))
419
+
420
+ The standard Python Dockerfile incorporates several intentional design choices.
421
+
422
+ - Multi-stage build: The build stage installs the selected package manager backend (Poetry or uv) and builds a wheel while the runtime stage installs only the wheel to keep the final image slim and reproducible
423
+ - Pip and package-manager cache mounts: Speed up iterative builds without bloating the final image
424
+ - Explicit inputs through build args: `PYTHON_VERSION`, `PACKAGE_MANAGER`, `PACKAGE_MANAGER_VERSION`, `PACKAGE_NAME`, `AUTHORS`, `GIT_COMMIT`, and `CUSTOM_ENTRYPOINT` make image metadata and behavior predictable and auditable
425
+ - Optional debug stage: Exports and installs the `debug` dependency group only when present, without failing otherwise, and is not part of the default final image
426
+ - Stable package path: Creates symlinks to the installed package so entrypoints and consumers have a consistent `/pkg` and `/_$PACKAGE_NAME` path regardless of wheel layout. This ensures that the package can be imported and executed from a known location and supports the less common case of reading files directly from the package path
427
+ - Safe entrypoint selection: The default entrypoint resolves the console script matching the package name, while `CUSTOM_ENTRYPOINT` allows an override at build time and keeps runtime behavior predictable
428
+ - Minimal final image: Uses the slim Python base by default, cleans wheel artifacts and caches, and sets `runtime` as the explicit final target so the debug stage remains optional
429
+
430
+ ## Notes
431
+
432
+ - This project dogfoods itself; it uses `common-python-tasks` for its own development. **That said, you must set the environment variable `PYTHONPATH=src` when running tasks locally to ensure you are using the local version of the package instead of the installed version**
433
+ - `RELEASE_UPDATE_CHANGELOG` is enabled by default for releases and prepends a tagged section into `CHANGELOG.md` before the release tag is created. Set it to a falsy value if you prefer to manage changelog commits yourself.
434
+ - `RELEASE_PRE_SCRIPT` and `RELEASE_POST_SCRIPT` hooks may not be necessary for most users, as this package promotes dynamic versioning and `git-cliff` to automate versioning and changelog generation based on git history. One advanced use case for the `RELEASE_PRE_SCRIPT` hook is to edit another file before release, such as a README that references the current stable version number. This allows you to keep the README up to date with the latest version without hardcoding it.
435
+ - Contributions welcome! Open an issue/discussion to discuss changes before submitting a PR. I do not claim to have all the answers, and you can help determine the future of low-code solutions for Python. I am very interested in your feedback as I don't want to work in a vacuum
436
+ - Alpha status: Expect breaking changes between minor versions until 1.0.0