common-python-tasks 0.8.0__tar.gz → 0.9.0__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 (37) hide show
  1. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/PKG-INFO +33 -25
  2. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/README.md +32 -24
  3. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/pyproject.toml +1 -1
  4. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/add_common_python_tasks.py +8 -41
  5. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/fastapi/compose-base.yml.j2 +1 -2
  6. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/fastapi/compose-db.yml.j2 +1 -2
  7. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/fastapi/compose-debug.yml.j2 +1 -1
  8. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/.dockerignore +1 -1
  9. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/Dockerfile.j2 +1 -34
  10. common_python_tasks-0.9.0/src/common_python_tasks/data/generic/ruff.toml +2 -0
  11. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/docker.py +1 -21
  12. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/docker_compose.py +4 -7
  13. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/github.py +20 -1
  14. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/project.py +124 -295
  15. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/tasks.py +7 -14
  16. common_python_tasks-0.8.0/src/common_python_tasks/data/generic/ruff.toml +0 -2
  17. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/.gitignore +0 -0
  18. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/.poetry/plugins/poetry_dynamic_versioning-1.10.0.dist-info/licenses/LICENSE +0 -0
  19. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/.poetry/plugins/poetry_plugin_export-1.10.0.dist-info/licenses/LICENSE +0 -0
  20. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/LICENSE +0 -0
  21. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/__init__.py +0 -0
  22. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/readme_tasks_table.py +0 -0
  23. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/release_script.py +0 -0
  24. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/update_readme_tasks_table.py +0 -0
  25. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/scripts/utils.py +0 -0
  26. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/__init__.py +0 -0
  27. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/__main__.py +0 -0
  28. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/dockerfile_extensions/.gitkeep +0 -0
  29. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/fastapi/alembic.ini.j2 +0 -0
  30. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/fastapi/compose-db-debug.yml.j2 +0 -0
  31. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/.coveragerc +0 -0
  32. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/Dockerfile.deps.j2 +0 -0
  33. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/cliff.toml +0 -0
  34. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/data/generic/pytest.ini +0 -0
  35. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/env.py +0 -0
  36. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/git.py +0 -0
  37. {common_python_tasks-0.8.0 → common_python_tasks-0.9.0}/src/common_python_tasks/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: common-python-tasks
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Opinionated Poe the Poet tasks for Python package development.
5
5
  Project-URL: Homepage, http://github.com/ci-sourcerer/common-python-tasks
6
6
  Project-URL: Source, http://github.com/ci-sourcerer/common-python-tasks.git
@@ -43,9 +43,7 @@ It supplies sensible defaults for formatting, linting, testing, packaging, relea
43
43
  Add `common-python-tasks` as a development dependency from your project root.
44
44
 
45
45
  ```shell
46
- uv add --dev common-python-tasks==0.8.0
47
- # or, for Poetry projects
48
- poetry add --group dev common-python-tasks==0.8.0
46
+ uv add --dev common-python-tasks==0.9.0
49
47
  ```
50
48
 
51
49
  Configure Poe the Poet to expose the default `common` task set.
@@ -70,7 +68,7 @@ The helper script performs the same development-dependency installation and Poe
70
68
  ```shell
71
69
  curl --fail --silent --show-error --location \
72
70
  --output /tmp/add_common_python_tasks.py \
73
- https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.8.0/scripts/add_common_python_tasks.py
71
+ https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.9.0/scripts/add_common_python_tasks.py
74
72
  ```
75
73
 
76
74
  Review the downloaded script before executing it.
@@ -82,10 +80,10 @@ less /tmp/add_common_python_tasks.py
82
80
  Run the reviewed script with the same pinned package version.
83
81
 
84
82
  ```shell
85
- COMMON_PYTHON_TASKS_VERSION=0.8.0 python3 /tmp/add_common_python_tasks.py
83
+ COMMON_PYTHON_TASKS_VERSION=0.9.0 python3 /tmp/add_common_python_tasks.py
86
84
  ```
87
85
 
88
- To install another release, replace both occurrences of `0.8.0` with that release's version.
86
+ To install another release, replace both occurrences of `0.9.0` with that release's version.
89
87
 
90
88
  ## Available tasks
91
89
 
@@ -108,7 +106,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
108
106
  | --- | --- | --- |
109
107
  | `publish-package` | Publish the package to the PyPI server. | common, packaging |
110
108
  | `publish-github-release` | Publish or update a GitHub Release for the current repository. | common, packaging, release |
111
- | `update-dependencies` | Update project dependencies with Poetry or uv. | common, packaging |
109
+ | `update-dependencies` | Update project dependencies with uv. | common, packaging |
112
110
  | `build-package` | Build the package (wheel and sdist). | build, common, packaging |
113
111
  | `bump-version` | Bump the project version. | common, packaging |
114
112
  | `changelog` | Print the changelog for the current version based on git history and git-cliff. | common, packaging, release |
@@ -143,7 +141,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
143
141
 
144
142
  Every project needs a `pyproject.toml` file at its root and Poe the Poet available in its development environment.
145
143
 
146
- Tasks that install, build, publish, or update dependencies also require either Poetry or uv. Package and release tasks need a resolvable project version from `project.version`, Poetry's version resolution, or Git tags. Dynamic-versioning plugins are supported but are not a baseline requirement.
144
+ Tasks that install, build, publish, or update dependencies require uv. Package and release tasks need a resolvable project version from `project.version` or Git tags. Dynamic versioning is supported but is not a baseline requirement.
147
145
 
148
146
  ### Task selection
149
147
 
@@ -163,18 +161,27 @@ include_script = "common_python_tasks:tasks(include_tags=['common', 'containers'
163
161
 
164
162
  The `containers` tag also includes container-based development-stack tasks. Use the tags in the task tables to tailor a smaller task set.
165
163
 
166
- ### Package manager backend selection
164
+ ### Package management
167
165
 
168
- Packaging-related tasks, including `build-package`, `publish-package`, release version resolution, and container build metadata, support Poetry and uv.
166
+ Packaging-related tasks, including `build-package`, `publish-package`, dependency updates, release version resolution, and container build metadata, use uv exclusively. The `uv` executable must be available on `PATH`.
169
167
 
170
- Backend selection uses this precedence.
168
+ ### Publish target selection
171
169
 
172
- 1. `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
173
- 2. `COMMON_PYTHON_TASKS_BUILD_TOOL`
174
- 3. `PACKAGE_MANAGER`
175
- 4. Auto-discovery (`auto`) based on installed tools and project metadata
170
+ The `publish-package` task resolves publish targets with this precedence.
176
171
 
177
- Supported values are `poetry`, `uv`, and `auto`.
172
+ 1. Explicit task arguments (`repository` or `repository_url`)
173
+ 2. Environment-variable fallback
174
+ 3. uv project configuration fallback from `[[tool.uv.index]]`
175
+ 4. The `uv publish` default
176
+
177
+ uv prefers named publish indexes.
178
+
179
+ - `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`
180
+ - `UV_PUBLISH_INDEX`
181
+ - `COMMON_PYTHON_TASKS_PUBLISH_URL`
182
+ - `UV_PUBLISH_URL`
183
+
184
+ When using uv project configuration fallback, `[[tool.uv.index]]` must include both `name` and `publish-url` for publish selection. If multiple publishable indexes exist, set exactly one `default = true` or pass an explicit repository.
178
185
 
179
186
  ### Configuration precedence
180
187
 
@@ -196,7 +203,7 @@ After installing the package, a minimal project configuration looks like this.
196
203
  ```toml
197
204
  [project]
198
205
  name = "simple-cli-tool"
199
- version = "0.8.0"
206
+ version = "0.9.0"
200
207
 
201
208
  [tool.poe]
202
209
  include_script = "common_python_tasks:tasks()"
@@ -232,9 +239,10 @@ addopts = "-ra"
232
239
  #### Project and package settings
233
240
 
234
241
  - `PACKAGE_NAME`: Overrides the package name inferred from `pyproject.toml`
235
- - `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`: Selects the package-manager backend as `poetry`, `uv`, or `auto`
236
- - `COMMON_PYTHON_TASKS_BUILD_TOOL`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
237
- - `PACKAGE_MANAGER`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
242
+ - `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`: Preferred publish repository/index name for `publish-package`
243
+ - `COMMON_PYTHON_TASKS_PUBLISH_URL`: Preferred uv publish upload URL for `publish-package` when no repository/index is selected
244
+ - `UV_PUBLISH_INDEX`: uv publish-index fallback for `publish-package`
245
+ - `UV_PUBLISH_URL`: uv publish upload-url fallback for `publish-package`
238
246
 
239
247
  #### Container image settings
240
248
 
@@ -386,7 +394,7 @@ GITHUB_RELEASE_ASSETS="dist/*.whl:dist/*.tar.gz" poe publish-github-release
386
394
 
387
395
  ### Container build fails with "unable to find package"
388
396
 
389
- Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For Poetry projects, this commonly includes `[tool.poetry] packages = [{ include = "your_package", from = "src" }]`.
397
+ Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For a `src` layout built with Hatch, configure `[tool.hatch.build.targets.wheel] packages = ["src/your_package"]`.
390
398
 
391
399
  ### Stack fails to start or services cannot connect
392
400
 
@@ -411,9 +419,9 @@ Ensure the project-root `.env` file is writable and inspect its permissions with
411
419
 
412
420
  See the [standard Dockerfile template](src/common_python_tasks/data/generic/Dockerfile.j2) for the implementation.
413
421
 
414
- - Multi-stage build: The build stage installs the selected package-manager backend and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
415
- - Cache mounts: Pip and package-manager cache mounts speed up iterative builds without bloating the final image.
416
- - Explicit build metadata: `PYTHON_VERSION`, `PACKAGE_MANAGER`, `PACKAGE_MANAGER_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
422
+ - Multi-stage build: The build stage installs uv and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
423
+ - Cache mounts: Pip and uv cache mounts speed up iterative builds without bloating the final image.
424
+ - Explicit build metadata: `PYTHON_VERSION`, `UV_VERSION`, `PACKAGE_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
417
425
  - Project-level build settings: `CONTAINER_APT_PACKAGES`, `CONTAINER_CUSTOM_ENTRYPOINT`, and `CONTAINER_DEPS_IMAGE` configure generated image behavior without being encoded as generic Docker arguments.
418
426
  - Optional debug stage: The image exports and installs the `debug` dependency group only when present and does not include it in the default final image.
419
427
  - Stable package path: Symlinks give entrypoints and consumers consistent `/pkg` and `/_$PACKAGE_NAME` paths regardless of wheel layout.
@@ -11,9 +11,7 @@ It supplies sensible defaults for formatting, linting, testing, packaging, relea
11
11
  Add `common-python-tasks` as a development dependency from your project root.
12
12
 
13
13
  ```shell
14
- uv add --dev common-python-tasks==0.8.0
15
- # or, for Poetry projects
16
- poetry add --group dev common-python-tasks==0.8.0
14
+ uv add --dev common-python-tasks==0.9.0
17
15
  ```
18
16
 
19
17
  Configure Poe the Poet to expose the default `common` task set.
@@ -38,7 +36,7 @@ The helper script performs the same development-dependency installation and Poe
38
36
  ```shell
39
37
  curl --fail --silent --show-error --location \
40
38
  --output /tmp/add_common_python_tasks.py \
41
- https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.8.0/scripts/add_common_python_tasks.py
39
+ https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.9.0/scripts/add_common_python_tasks.py
42
40
  ```
43
41
 
44
42
  Review the downloaded script before executing it.
@@ -50,10 +48,10 @@ less /tmp/add_common_python_tasks.py
50
48
  Run the reviewed script with the same pinned package version.
51
49
 
52
50
  ```shell
53
- COMMON_PYTHON_TASKS_VERSION=0.8.0 python3 /tmp/add_common_python_tasks.py
51
+ COMMON_PYTHON_TASKS_VERSION=0.9.0 python3 /tmp/add_common_python_tasks.py
54
52
  ```
55
53
 
56
- To install another release, replace both occurrences of `0.8.0` with that release's version.
54
+ To install another release, replace both occurrences of `0.9.0` with that release's version.
57
55
 
58
56
  ## Available tasks
59
57
 
@@ -76,7 +74,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
76
74
  | --- | --- | --- |
77
75
  | `publish-package` | Publish the package to the PyPI server. | common, packaging |
78
76
  | `publish-github-release` | Publish or update a GitHub Release for the current repository. | common, packaging, release |
79
- | `update-dependencies` | Update project dependencies with Poetry or uv. | common, packaging |
77
+ | `update-dependencies` | Update project dependencies with uv. | common, packaging |
80
78
  | `build-package` | Build the package (wheel and sdist). | build, common, packaging |
81
79
  | `bump-version` | Bump the project version. | common, packaging |
82
80
  | `changelog` | Print the changelog for the current version based on git history and git-cliff. | common, packaging, release |
@@ -111,7 +109,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
111
109
 
112
110
  Every project needs a `pyproject.toml` file at its root and Poe the Poet available in its development environment.
113
111
 
114
- Tasks that install, build, publish, or update dependencies also require either Poetry or uv. Package and release tasks need a resolvable project version from `project.version`, Poetry's version resolution, or Git tags. Dynamic-versioning plugins are supported but are not a baseline requirement.
112
+ Tasks that install, build, publish, or update dependencies require uv. Package and release tasks need a resolvable project version from `project.version` or Git tags. Dynamic versioning is supported but is not a baseline requirement.
115
113
 
116
114
  ### Task selection
117
115
 
@@ -131,18 +129,27 @@ include_script = "common_python_tasks:tasks(include_tags=['common', 'containers'
131
129
 
132
130
  The `containers` tag also includes container-based development-stack tasks. Use the tags in the task tables to tailor a smaller task set.
133
131
 
134
- ### Package manager backend selection
132
+ ### Package management
135
133
 
136
- Packaging-related tasks, including `build-package`, `publish-package`, release version resolution, and container build metadata, support Poetry and uv.
134
+ Packaging-related tasks, including `build-package`, `publish-package`, dependency updates, release version resolution, and container build metadata, use uv exclusively. The `uv` executable must be available on `PATH`.
137
135
 
138
- Backend selection uses this precedence.
136
+ ### Publish target selection
139
137
 
140
- 1. `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
141
- 2. `COMMON_PYTHON_TASKS_BUILD_TOOL`
142
- 3. `PACKAGE_MANAGER`
143
- 4. Auto-discovery (`auto`) based on installed tools and project metadata
138
+ The `publish-package` task resolves publish targets with this precedence.
144
139
 
145
- Supported values are `poetry`, `uv`, and `auto`.
140
+ 1. Explicit task arguments (`repository` or `repository_url`)
141
+ 2. Environment-variable fallback
142
+ 3. uv project configuration fallback from `[[tool.uv.index]]`
143
+ 4. The `uv publish` default
144
+
145
+ uv prefers named publish indexes.
146
+
147
+ - `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`
148
+ - `UV_PUBLISH_INDEX`
149
+ - `COMMON_PYTHON_TASKS_PUBLISH_URL`
150
+ - `UV_PUBLISH_URL`
151
+
152
+ When using uv project configuration fallback, `[[tool.uv.index]]` must include both `name` and `publish-url` for publish selection. If multiple publishable indexes exist, set exactly one `default = true` or pass an explicit repository.
146
153
 
147
154
  ### Configuration precedence
148
155
 
@@ -164,7 +171,7 @@ After installing the package, a minimal project configuration looks like this.
164
171
  ```toml
165
172
  [project]
166
173
  name = "simple-cli-tool"
167
- version = "0.8.0"
174
+ version = "0.9.0"
168
175
 
169
176
  [tool.poe]
170
177
  include_script = "common_python_tasks:tasks()"
@@ -200,9 +207,10 @@ addopts = "-ra"
200
207
  #### Project and package settings
201
208
 
202
209
  - `PACKAGE_NAME`: Overrides the package name inferred from `pyproject.toml`
203
- - `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`: Selects the package-manager backend as `poetry`, `uv`, or `auto`
204
- - `COMMON_PYTHON_TASKS_BUILD_TOOL`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
205
- - `PACKAGE_MANAGER`: Alias for `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`
210
+ - `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`: Preferred publish repository/index name for `publish-package`
211
+ - `COMMON_PYTHON_TASKS_PUBLISH_URL`: Preferred uv publish upload URL for `publish-package` when no repository/index is selected
212
+ - `UV_PUBLISH_INDEX`: uv publish-index fallback for `publish-package`
213
+ - `UV_PUBLISH_URL`: uv publish upload-url fallback for `publish-package`
206
214
 
207
215
  #### Container image settings
208
216
 
@@ -354,7 +362,7 @@ GITHUB_RELEASE_ASSETS="dist/*.whl:dist/*.tar.gz" poe publish-github-release
354
362
 
355
363
  ### Container build fails with "unable to find package"
356
364
 
357
- Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For Poetry projects, this commonly includes `[tool.poetry] packages = [{ include = "your_package", from = "src" }]`.
365
+ Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For a `src` layout built with Hatch, configure `[tool.hatch.build.targets.wheel] packages = ["src/your_package"]`.
358
366
 
359
367
  ### Stack fails to start or services cannot connect
360
368
 
@@ -379,9 +387,9 @@ Ensure the project-root `.env` file is writable and inspect its permissions with
379
387
 
380
388
  See the [standard Dockerfile template](src/common_python_tasks/data/generic/Dockerfile.j2) for the implementation.
381
389
 
382
- - Multi-stage build: The build stage installs the selected package-manager backend and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
383
- - Cache mounts: Pip and package-manager cache mounts speed up iterative builds without bloating the final image.
384
- - Explicit build metadata: `PYTHON_VERSION`, `PACKAGE_MANAGER`, `PACKAGE_MANAGER_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
390
+ - Multi-stage build: The build stage installs uv and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
391
+ - Cache mounts: Pip and uv cache mounts speed up iterative builds without bloating the final image.
392
+ - Explicit build metadata: `PYTHON_VERSION`, `UV_VERSION`, `PACKAGE_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
385
393
  - Project-level build settings: `CONTAINER_APT_PACKAGES`, `CONTAINER_CUSTOM_ENTRYPOINT`, and `CONTAINER_DEPS_IMAGE` configure generated image behavior without being encoded as generic Docker arguments.
386
394
  - Optional debug stage: The image exports and installs the `debug` dependency group only when present and does not include it in the default final image.
387
395
  - Stable package path: Symlinks give entrypoints and consumers consistent `/pkg` and `/_$PACKAGE_NAME` paths regardless of wheel layout.
@@ -73,7 +73,7 @@ package = true
73
73
 
74
74
  [tool.ruff]
75
75
  line-length = 88
76
- extend-exclude = [".dist", ".poetry", "build"]
76
+ extend-exclude = [".dist", "build"]
77
77
 
78
78
  [tool.ruff.lint]
79
79
  select = ["E4", "E7", "E9", "F", "I", "W"]
@@ -10,11 +10,6 @@ import tomllib
10
10
  from pathlib import Path
11
11
 
12
12
  PACKAGE_NAME = "common-python-tasks"
13
- PACKAGE_MANAGER_ENV_VARS = (
14
- "COMMON_PYTHON_TASKS_PACKAGE_MANAGER",
15
- "COMMON_PYTHON_TASKS_BUILD_TOOL",
16
- "PACKAGE_MANAGER",
17
- )
18
13
  PYPROJECT_PATH = Path("pyproject.toml")
19
14
  TOOL_POE_PATTERN = re.compile(r"^\s*\[tool\.poe\]\s*(?:#.*)?$")
20
15
  TABLE_PATTERN = re.compile(r"^\s*\[")
@@ -26,47 +21,18 @@ def _require_command(command: str) -> None:
26
21
  sys.exit(f"Required command not found: {command}")
27
22
 
28
23
 
29
- def _get_requested_package_manager() -> str:
30
- for env_var in PACKAGE_MANAGER_ENV_VARS:
31
- if os.getenv(env_var, "").strip():
32
- return os.environ[env_var].strip().lower()
33
- return "auto"
34
-
35
-
36
- def _select_package_manager() -> str:
37
- requested_manager = _get_requested_package_manager()
38
- if requested_manager in {"poetry", "uv"}:
39
- _require_command(requested_manager)
40
- return requested_manager
41
- if requested_manager != "auto":
42
- sys.exit(f"Unsupported package manager: {requested_manager}")
43
-
44
- for lock_file, package_manager in (
45
- (Path("uv.lock"), "uv"),
46
- (Path("poetry.lock"), "poetry"),
47
- ):
48
- if lock_file.is_file() and shutil.which(package_manager) is not None:
49
- return package_manager
50
-
51
- for package_manager in ("uv", "poetry"):
52
- if shutil.which(package_manager) is not None:
53
- return package_manager
54
-
55
- sys.exit("Neither uv nor Poetry is installed.")
56
-
57
-
58
24
  def _get_package_requirement() -> str:
59
25
  if os.getenv("COMMON_PYTHON_TASKS_VERSION", "").strip():
60
26
  return f"{PACKAGE_NAME}=={os.environ['COMMON_PYTHON_TASKS_VERSION'].strip()}"
61
27
  return PACKAGE_NAME
62
28
 
63
29
 
64
- def _install_package(package_manager: str) -> None:
65
- if package_manager == "uv":
66
- command = ["uv", "add", "--dev", _get_package_requirement()]
67
- else:
68
- command = ["poetry", "add", "--group", "dev", _get_package_requirement()]
69
- subprocess.run(command, check=True, shell=False)
30
+ def _install_package() -> None:
31
+ subprocess.run(
32
+ ["uv", "add", "--dev", _get_package_requirement()],
33
+ check=True,
34
+ shell=False,
35
+ )
70
36
 
71
37
 
72
38
  def _get_include_script() -> str:
@@ -132,7 +98,8 @@ def _print_available_tasks() -> None:
132
98
 
133
99
  def main() -> None:
134
100
  """Install common tasks and configure Poe in the current project."""
135
- _install_package(_select_package_manager())
101
+ _require_command("uv")
102
+ _install_package()
136
103
  _configure_poe()
137
104
  print("\n\033[1;32mCommon Python tasks added to project.\033[0m")
138
105
  print("\n\033[1mAvailable tasks:\033[0m")
@@ -9,8 +9,7 @@ x-common-environment: &common-environment
9
9
  x-common-build-args: &common-build-args
10
10
  PACKAGE_NAME: ${PACKAGE_NAME}
11
11
  PYTHON_VERSION: ${PYTHON_VERSION}
12
- PACKAGE_MANAGER: ${PACKAGE_MANAGER}
13
- PACKAGE_MANAGER_VERSION: ${PACKAGE_MANAGER_VERSION}
12
+ UV_VERSION: ${UV_VERSION}
14
13
 
15
14
  services:
16
15
  api:
@@ -8,8 +8,7 @@ x-common-environment: &common-environment
8
8
  x-common-build-args: &common-build-args
9
9
  PACKAGE_NAME: ${PACKAGE_NAME}
10
10
  PYTHON_VERSION: ${PYTHON_VERSION}
11
- PACKAGE_MANAGER: ${PACKAGE_MANAGER}
12
- PACKAGE_MANAGER_VERSION: ${PACKAGE_MANAGER_VERSION}
11
+ UV_VERSION: ${UV_VERSION}
13
12
  WORKDIR_PATH: ${WORKDIR_PATH}
14
13
 
15
14
  services:
@@ -22,7 +22,7 @@ services:
22
22
  path: ./src/${PACKAGE_UNDERSCORE_NAME}
23
23
  target: /${PACKAGE_UNDERSCORE_NAME}
24
24
  - action: rebuild
25
- path: poetry.lock
25
+ path: uv.lock
26
26
  ports:
27
27
  - mode: ingress
28
28
  target: 5678
@@ -1,7 +1,7 @@
1
1
  *
2
2
  !dist/*.whl
3
3
  !pyproject.toml
4
- !poetry.lock
4
+ !uv.lock
5
5
  !README.md
6
6
  !LICENSE
7
7
 
@@ -7,33 +7,10 @@ ARG PYTHON_VERSION=3
7
7
  # See https://hub.docker.com/_/python for available variants
8
8
  ARG PYTHON_VARIANT=slim
9
9
  ARG WORKDIR_PATH=/workspace
10
- {% set package_manager = PACKAGE_MANAGER|default('poetry') %}
11
10
 
12
11
  FROM python:${PYTHON_VERSION} AS builder
13
12
 
14
13
  ARG PACKAGE_VERSION
15
-
16
- {% if package_manager == 'poetry' %}
17
- ARG POETRY_VERSION
18
- ARG POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION
19
- ARG POETRY_PLUGIN_EXPORT_VERSION
20
-
21
- # Bypass VCS-based version detection: use the host-computed version directly.
22
- # This avoids requiring a .git directory in the build context and prevents
23
- # false dirty-version detection from a partial working tree.
24
- ENV POETRY_DYNAMIC_VERSIONING_BYPASS=${PACKAGE_VERSION}
25
-
26
- # Install Poetry and required Poetry plugins for package build
27
- RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cache{{ CACHE_ID_SUFFIX }} \
28
- sh -c 'set -eu; \
29
- poetry_spec="poetry"; \
30
- if [ -n "${POETRY_VERSION:-}" ]; then poetry_spec="poetry==$POETRY_VERSION"; fi; \
31
- dynamic_spec="poetry-dynamic-versioning[plugin]"; \
32
- if [ -n "${POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION:-}" ]; then dynamic_spec="poetry-dynamic-versioning[plugin]==$POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION"; fi; \
33
- export_spec="poetry-plugin-export"; \
34
- if [ -n "${POETRY_PLUGIN_EXPORT_VERSION:-}" ]; then export_spec="poetry-plugin-export==$POETRY_PLUGIN_EXPORT_VERSION"; fi; \
35
- pip install --root-user-action=ignore "$poetry_spec" "$dynamic_spec" "$export_spec"'
36
- {% else %}
37
14
  ARG UV_VERSION
38
15
 
39
16
  # Bypass VCS-based version detection: use the host-computed version directly.
@@ -48,7 +25,6 @@ RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cache{{ CACHE_ID_SUFFIX }}
48
25
  else \
49
26
  pip install --root-user-action=ignore uv; \
50
27
  fi'
51
- {% endif %}
52
28
 
53
29
  # Build package
54
30
  WORKDIR /tmp/build
@@ -56,24 +32,15 @@ COPY . /tmp/build/
56
32
 
57
33
  {% if HAS_DEBUG_DEPS %}
58
34
  # Export debug requirements when the project defines a debug dependency group
59
- {% if package_manager == 'poetry' %}
60
- RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cache{{ CACHE_ID_SUFFIX }} \
61
- poetry export --only debug --without-hashes -f requirements.txt --output requirements-debug.txt
62
- {% else %}
63
35
  RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }} \
64
36
  uv export --group debug --no-hashes --format requirements-txt --output-file requirements-debug.txt
65
37
  {% endif %}
66
- {% endif %}
67
38
 
68
- # Build the wheel, caching the package-manager cache directory to speed up subsequent builds.
39
+ # Build the wheel, caching the uv cache directory to speed up subsequent builds.
69
40
  # If running this in a CI system, you must be using a persistent builder to take
70
41
  # advantage of the cache mount, and you should configure your CI to persist the
71
42
  # cache directory between builds
72
- {% if package_manager == 'poetry' %}
73
- RUN --mount=type=cache,target=/root/.cache/pypoetry,id=pypoetry-cache{{ CACHE_ID_SUFFIX }} poetry build --format=wheel
74
- {% else %}
75
43
  RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }} uv build --wheel
76
- {% endif %}
77
44
 
78
45
  FROM python:${PYTHON_VERSION}-${PYTHON_VARIANT} AS runtime
79
46
  ARG WORKDIR_PATH=/workspace
@@ -0,0 +1,2 @@
1
+ line-length = 88
2
+ extend-exclude = [".dist", "build"]
@@ -289,37 +289,17 @@ def render_build_image(
289
289
  commit_tag = version_tag
290
290
 
291
291
  python_version = platform.python_version()
292
- package_manager = project.get_package_manager()
293
- package_manager_version = project.get_package_manager_version(package_manager)
294
-
295
- manager_build_args: dict[str, str | None]
296
- if package_manager == project.PackageManager.POETRY:
297
- manager_build_args = {
298
- "POETRY_VERSION": package_manager_version,
299
- "POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION": project.get_installed_requirement_version(
300
- "poetry-dynamic-versioning[plugin]"
301
- ),
302
- "POETRY_PLUGIN_EXPORT_VERSION": project.get_installed_requirement_version(
303
- "poetry-plugin-export"
304
- ),
305
- }
306
- else:
307
- manager_build_args = {
308
- "UV_VERSION": package_manager_version,
309
- }
310
292
 
311
293
  build_args = _merge_build_args(
312
294
  {
313
295
  "PYTHON_VERSION": python_version,
314
- "PACKAGE_MANAGER": package_manager,
315
- "PACKAGE_MANAGER_VERSION": package_manager_version,
296
+ "UV_VERSION": project.get_uv_version(),
316
297
  "PACKAGE_VERSION": package_version,
317
298
  "PACKAGE_NAME": utils.get_package_name(use_underscores=True),
318
299
  "AUTHORS": ",".join(
319
300
  [f"{name} <{email}>" for name, email in project.get_authors()]
320
301
  ),
321
302
  "GIT_COMMIT": commit_tag,
322
- **manager_build_args,
323
303
  },
324
304
  extra_build_args,
325
305
  )
@@ -14,7 +14,7 @@ from poethepoet_tasks import TaskCollection
14
14
 
15
15
  from . import utils
16
16
  from .env import get_workdir_path
17
- from .project import get_package_manager, get_package_manager_version
17
+ from .project import get_uv_version
18
18
 
19
19
  LOGGER = logging.getLogger(__name__)
20
20
 
@@ -239,8 +239,7 @@ _COMPOSE_VAR_REQUIREMENTS: dict[str, dict[str, set[str]]] = {
239
239
  "ENVIRONMENT",
240
240
  "IMAGE_TAG",
241
241
  "PYTHON_VERSION",
242
- "PACKAGE_MANAGER",
243
- "PACKAGE_MANAGER_VERSION",
242
+ "UV_VERSION",
244
243
  },
245
244
  "compose-db": {
246
245
  "PACKAGE_NAME",
@@ -250,8 +249,7 @@ _COMPOSE_VAR_REQUIREMENTS: dict[str, dict[str, set[str]]] = {
250
249
  "DB_PORT",
251
250
  "IMAGE_TAG",
252
251
  "PYTHON_VERSION",
253
- "PACKAGE_MANAGER",
254
- "PACKAGE_MANAGER_VERSION",
252
+ "UV_VERSION",
255
253
  "POSTGRES_VERSION",
256
254
  "WORKDIR_PATH",
257
255
  },
@@ -337,13 +335,12 @@ def get_compose_env(
337
335
  "ENVIRONMENT": os.getenv("ENVIRONMENT", "production"),
338
336
  "IMAGE_TAG": image_tag or "latest",
339
337
  "PACKAGE_NAME": package_name,
340
- "PACKAGE_MANAGER": get_package_manager(),
341
- "PACKAGE_MANAGER_VERSION": get_package_manager_version(),
342
338
  "PACKAGE_UNDERSCORE_NAME": utils.package_name_to_underscore(package_name),
343
339
  "WORKDIR_PATH": get_workdir_path(),
344
340
  "POSTGRES_VERSION": os.getenv("POSTGRES_VERSION", "17"),
345
341
  "PYTHON_VERSION": platform.python_version(),
346
342
  "SECRET_KEY": os.getenv("SECRET_KEY", ""),
343
+ "UV_VERSION": get_uv_version(),
347
344
  }
348
345
 
349
346
  if compose_type and compose_files:
@@ -28,6 +28,18 @@ def _is_unreleased_placeholder(notes: str) -> bool:
28
28
  return normalized in {"[unreleased]", "## [unreleased]", "## unreleased"}
29
29
 
30
30
 
31
+ def _pattern_targets_hidden_paths(pattern: str) -> bool:
32
+ return any(
33
+ part.startswith(".")
34
+ for part in pattern.split("/")
35
+ if part and part not in {".", ".."}
36
+ )
37
+
38
+
39
+ def _path_has_hidden_segment(path: Path) -> bool:
40
+ return any(part.startswith(".") for part in path.parts if part not in {".", ".."})
41
+
42
+
31
43
  def _latest_tagged_changelog() -> str | None:
32
44
  result = utils.run_git_cliff(["--latest"], capture_output=True)
33
45
  changelog = result.stdout.strip()
@@ -538,6 +550,8 @@ def get_github_release_asset_paths(
538
550
  interpreted as colon-separated paths or glob patterns.
539
551
  If not provided, the default value is `dist/*`. An empty list
540
552
  explicitly disables asset selection.
553
+ Wildcard patterns only include hidden files when the pattern itself
554
+ explicitly targets hidden paths (for example, `dist/.*`).
541
555
 
542
556
  Returns:
543
557
  A sorted list of existing asset paths.
@@ -561,9 +575,14 @@ def get_github_release_asset_paths(
561
575
  asset_paths = []
562
576
  for part in source_items:
563
577
  if any(char in part for char in "*?[]"):
578
+ matches = [path for path in Path(".").glob(part) if path.is_file()]
579
+ if not _pattern_targets_hidden_paths(part):
580
+ matches = [
581
+ path for path in matches if not _path_has_hidden_segment(path)
582
+ ]
564
583
  asset_paths.extend(
565
584
  sorted(
566
- [path for path in Path(".").glob(part) if path.is_file()],
585
+ matches,
567
586
  key=lambda p: str(p),
568
587
  )
569
588
  )