common-python-tasks 0.8.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

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.
@@ -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
@@ -1,2 +1,2 @@
1
1
  line-length = 88
2
- extend-exclude = [".dist", ".poetry", "build"]
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
  )
@@ -2,9 +2,7 @@ import ast
2
2
  import logging
3
3
  import os
4
4
  import re
5
- import shutil
6
5
  import tomllib
7
- from enum import StrEnum, auto
8
6
  from functools import lru_cache
9
7
  from importlib import metadata
10
8
  from pathlib import Path
@@ -17,20 +15,16 @@ from . import utils
17
15
 
18
16
  LOGGER = logging.getLogger(__name__)
19
17
 
20
- PACKAGE_MANAGER_ENV_VAR = "COMMON_PYTHON_TASKS_PACKAGE_MANAGER"
21
- PACKAGE_MANAGER_ENV_VARS = (
22
- PACKAGE_MANAGER_ENV_VAR,
23
- "COMMON_PYTHON_TASKS_BUILD_TOOL",
24
- "PACKAGE_MANAGER",
18
+ PUBLISH_REPOSITORY_ENV_VAR = "COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY"
19
+ PUBLISH_REPOSITORY_URL_ENV_VAR = "COMMON_PYTHON_TASKS_PUBLISH_URL"
20
+ PUBLISH_REPOSITORY_ENV_VARS = (
21
+ PUBLISH_REPOSITORY_ENV_VAR,
22
+ "UV_PUBLISH_INDEX",
23
+ )
24
+ PUBLISH_URL_ENV_VARS = (
25
+ PUBLISH_REPOSITORY_URL_ENV_VAR,
26
+ "UV_PUBLISH_URL",
25
27
  )
26
-
27
-
28
- class PackageManager(StrEnum):
29
- """Supported package-manager backends for build and publish workflows."""
30
-
31
- POETRY = auto()
32
- UV = auto()
33
- AUTO = auto()
34
28
 
35
29
 
36
30
  def _parse_tool_version_output(output: str, tool_name: str) -> str:
@@ -49,116 +43,88 @@ def _parse_tool_version_output(output: str, tool_name: str) -> str:
49
43
  utils.fatal(f"Unable to parse {tool_name} version output: {output!r}")
50
44
 
51
45
 
52
- def _find_package_manager_override() -> tuple[str, str] | None:
53
- for env_var in PACKAGE_MANAGER_ENV_VARS:
46
+ def _find_non_empty_env_override(env_vars: Sequence[str]) -> tuple[str, str] | None:
47
+ for env_var in env_vars:
54
48
  value = os.getenv(env_var)
55
49
  if value is not None and value.strip():
56
- return env_var, value.strip().lower()
50
+ return env_var, value.strip()
57
51
  return None
58
52
 
59
53
 
60
- def _ensure_package_manager_available(package_manager: PackageManager) -> None:
61
- if shutil.which(package_manager) is None:
62
- utils.fatal(
63
- f"Requested package manager '{package_manager}' is not installed or not in PATH"
64
- )
65
-
66
-
67
- def _detect_declared_package_manager(
68
- pyproject_data: dict[str, Any],
69
- ) -> PackageManager | None:
70
- build_backend = (
71
- pyproject_data.get("build-system", {}).get("build-backend", "") or ""
72
- )
73
- if isinstance(build_backend, str) and "poetry" in build_backend.lower():
74
- return PackageManager.POETRY
75
-
76
- if pyproject_data.get("tool", {}).get("poetry") is not None:
77
- return PackageManager.POETRY
78
-
79
- if pyproject_data.get("tool", {}).get("uv") is not None:
80
- return PackageManager.UV
81
-
82
- return None
83
-
84
-
85
- def _resolve_package_manager_auto() -> tuple[PackageManager, str]:
86
- has_poetry = shutil.which("poetry") is not None
87
- has_uv = shutil.which("uv") is not None
54
+ def _resolve_uv_publish_repository_from_config() -> str | None:
55
+ pyproject_data = read_pyproject_toml()
56
+ uv_config = pyproject_data.get("tool", {}).get("uv", {})
57
+ raw_indexes = uv_config.get("index")
58
+ if raw_indexes is None:
59
+ return None
88
60
 
89
- if has_uv and not has_poetry:
90
- return PackageManager.UV, "uv found and poetry missing"
61
+ if not isinstance(raw_indexes, list):
62
+ LOGGER.warning(
63
+ "Ignoring malformed [tool.uv.index] configuration: expected a list of tables"
64
+ )
65
+ return None
91
66
 
92
- if has_poetry and not has_uv:
93
- return PackageManager.POETRY, "poetry found and uv missing"
67
+ publishable_indexes = [
68
+ entry
69
+ for entry in raw_indexes
70
+ if isinstance(entry, dict)
71
+ and isinstance(entry.get("name"), str)
72
+ and entry.get("name", "").strip()
73
+ and isinstance(entry.get("publish-url"), str)
74
+ and entry.get("publish-url", "").strip()
75
+ ]
76
+ if not publishable_indexes:
77
+ return None
94
78
 
95
- if not has_poetry and not has_uv:
79
+ default_publishable_names = [
80
+ entry["name"].strip()
81
+ for entry in publishable_indexes
82
+ if entry.get("default") is True
83
+ ]
84
+ if len(default_publishable_names) > 1:
96
85
  utils.fatal(
97
- "No supported package manager found in PATH. Install poetry or uv, "
98
- "or set one via COMMON_PYTHON_TASKS_PACKAGE_MANAGER."
86
+ "Multiple publishable `[[tool.uv.index]]` entries are marked `default = true`. "
87
+ "Set one default publishable index or pass an explicit publish repository."
99
88
  )
89
+ if len(default_publishable_names) == 1:
90
+ return default_publishable_names[0]
100
91
 
101
- pyproject_data = read_pyproject_toml()
102
- declared_manager = _detect_declared_package_manager(pyproject_data)
103
- if declared_manager is not None:
104
- return declared_manager, "project metadata"
105
-
106
- return PackageManager.POETRY, "default fallback"
92
+ publishable_names = [entry["name"].strip() for entry in publishable_indexes]
93
+ if len(publishable_names) == 1:
94
+ return publishable_names[0]
107
95
 
96
+ utils.fatal(
97
+ "Multiple publishable `[[tool.uv.index]]` entries were found. "
98
+ "Set one as `default = true` or pass an explicit publish repository."
99
+ )
108
100
 
109
- @lru_cache
110
- def get_package_manager() -> PackageManager:
111
- """Resolve the package manager backend used for build and publish commands.
112
-
113
- Resolution order:
114
- 1. Environment overrides via `COMMON_PYTHON_TASKS_PACKAGE_MANAGER`,
115
- `COMMON_PYTHON_TASKS_BUILD_TOOL`, or `PACKAGE_MANAGER`, in that order.
116
- 2. Auto-discovery from installed executables and project metadata.
117
101
 
118
- Supported values are `poetry`, `uv`, and `auto`.
102
+ def _resolve_default_publish_target() -> tuple[str | None, str | None]:
103
+ repository_override = _find_non_empty_env_override(PUBLISH_REPOSITORY_ENV_VARS)
104
+ if repository_override is not None:
105
+ env_var, repository_name = repository_override
106
+ LOGGER.debug("Using uv publish index %s from %s", repository_name, env_var)
107
+ return repository_name, None
119
108
 
120
- Returns:
121
- The selected package manager backend.
122
- """
123
- override = _find_package_manager_override()
124
- if override is None:
125
- package_manager, reason = _resolve_package_manager_auto()
109
+ config_repository_name = _resolve_uv_publish_repository_from_config()
110
+ if config_repository_name is not None:
126
111
  LOGGER.debug(
127
- "Using package manager backend: %s (%s)",
128
- package_manager,
129
- reason,
112
+ "Using uv publish index %s from [[tool.uv.index]] configuration",
113
+ config_repository_name,
130
114
  )
131
- return package_manager
115
+ return config_repository_name, None
132
116
 
133
- env_var, raw_value = override
134
- if raw_value not in PackageManager:
135
- utils.fatal(
136
- f"Invalid {env_var} value {raw_value!r}. Use one of: poetry, uv, auto."
137
- )
117
+ repository_url_override = _find_non_empty_env_override(PUBLISH_URL_ENV_VARS)
118
+ if repository_url_override is None:
119
+ return None, None
138
120
 
139
- if raw_value == PackageManager.AUTO:
140
- package_manager, reason = _resolve_package_manager_auto()
141
- LOGGER.debug(
142
- "Using package manager backend: %s (%s via %s=%s)",
143
- package_manager,
144
- reason,
145
- env_var,
146
- raw_value,
147
- )
148
- return package_manager
149
-
150
- package_manager = PackageManager(raw_value)
151
- _ensure_package_manager_available(package_manager)
152
- LOGGER.debug(
153
- "Using package manager backend: %s (from %s)",
154
- package_manager,
155
- env_var,
156
- )
157
- return package_manager
121
+ env_var, repository_url = repository_url_override
122
+ LOGGER.debug("Using uv publish URL %s from %s", repository_url, env_var)
123
+ return None, repository_url
158
124
 
159
125
 
160
- def get_package_manager_build_command(wheel_only: bool = False) -> list[str]:
161
- """Return the build command for the selected package manager.
126
+ def get_build_command(wheel_only: bool = False) -> list[str]:
127
+ """Return the uv package build command.
162
128
 
163
129
  Args:
164
130
  wheel_only: Whether to build only a wheel artifact.
@@ -166,23 +132,16 @@ def get_package_manager_build_command(wheel_only: bool = False) -> list[str]:
166
132
  Returns:
167
133
  Command tokens for the package build command.
168
134
  """
169
- package_manager = PackageManager(get_package_manager())
170
- if package_manager == PackageManager.UV:
171
- command = ["uv", "build"]
172
- if wheel_only:
173
- command.append("--wheel")
174
- return command
175
-
176
- command = ["poetry", "build"]
135
+ command = ["uv", "build"]
177
136
  if wheel_only:
178
- command += ["--format", "wheel"]
137
+ command.append("--wheel")
179
138
  return command
180
139
 
181
140
 
182
- def get_package_manager_update_command(
141
+ def get_dependency_update_command(
183
142
  dependencies: Sequence[str] | None = None,
184
143
  ) -> list[str]:
185
- """Return the dependency update command for the selected package manager.
144
+ """Return the uv dependency update command.
186
145
 
187
146
  Args:
188
147
  dependencies: Optional dependency names to update. When omitted, all
@@ -194,21 +153,17 @@ def get_package_manager_update_command(
194
153
  if dependencies is None:
195
154
  dependencies = []
196
155
 
197
- package_manager = PackageManager(get_package_manager())
198
- if package_manager == PackageManager.UV:
199
- command = ["uv", "sync", "--upgrade"]
200
- for dependency in dependencies:
201
- command.extend(["--upgrade-package", dependency])
202
- return command
203
-
204
- return ["poetry", "update", *dependencies]
156
+ command = ["uv", "sync", "--upgrade"]
157
+ for dependency in dependencies:
158
+ command.extend(["--upgrade-package", dependency])
159
+ return command
205
160
 
206
161
 
207
- def get_package_manager_publish_command(
162
+ def get_publish_command(
208
163
  repository: str | None = None,
209
164
  repository_url: str | None = None,
210
165
  ) -> list[str]:
211
- """Return the publish command for the selected package manager.
166
+ """Return the uv package publish command.
212
167
 
213
168
  Args:
214
169
  repository: Optional configured repository name to publish to.
@@ -220,20 +175,14 @@ def get_package_manager_publish_command(
220
175
  if repository is not None and repository_url is not None:
221
176
  utils.fatal("Specify either `repository` or `repository_url`, not both.")
222
177
 
223
- package_manager = PackageManager(get_package_manager())
224
- command = [package_manager.value, "publish"]
178
+ if repository is None and repository_url is None:
179
+ repository, repository_url = _resolve_default_publish_target()
180
+
181
+ command = ["uv", "publish"]
225
182
  if repository_url is not None:
226
- if package_manager == PackageManager.POETRY:
227
- utils.fatal(
228
- "Poetry publish only supports configured repository names. "
229
- "Pass `repository` instead of `repository_url`."
230
- )
231
183
  command += ["--publish-url", repository_url]
232
184
  elif repository is not None:
233
- if package_manager == PackageManager.UV:
234
- command += ["--index", repository]
235
- else:
236
- command += ["-r", repository]
185
+ command += ["--index", repository]
237
186
  return command
238
187
 
239
188
 
@@ -251,79 +200,45 @@ def get_authors() -> list[tuple[str, str]]:
251
200
  ]
252
201
 
253
202
 
254
- def get_local_poetry_plugin_version(package_name: str) -> str | None:
255
- """Return a version from the local Poetry plugin installation if present.
256
-
257
- Args:
258
- package_name: The name of the package to check.
259
-
260
- Returns:
261
- The version of the local Poetry plugin if present, None otherwise.
262
- """
263
-
264
- plugins_dir = Path(".poetry/plugins")
265
- if not plugins_dir.is_dir():
266
- return None
267
-
268
- candidates = {
269
- package_name,
270
- utils.package_name_to_underscore(package_name),
271
- package_name.replace("_", "-"),
272
- }
273
-
274
- for metadata_path in plugins_dir.glob("*.dist-info/METADATA"):
275
- try:
276
- metadata_text = metadata_path.read_text(encoding="utf-8")
277
- except OSError:
278
- continue
279
-
280
- name = None
281
- version = None
282
- for line in metadata_text.splitlines():
283
- if line.startswith("Name:"):
284
- name = line.split(":", 1)[1].strip()
285
- elif line.startswith("Version:"):
286
- version = line.split(":", 1)[1].strip()
287
- if name is not None and version is not None:
288
- break
289
-
290
- if name and version and name in candidates:
291
- return version
292
- return None
293
-
294
-
295
203
  @lru_cache
296
- def get_poetry_version() -> str:
297
- """Return the installed Poetry version string.
204
+ def get_uv_version() -> str:
205
+ """Return the installed uv version string.
298
206
 
299
207
  Returns:
300
- The Poetry version parsed from the output of `poetry --version`.
208
+ The uv version parsed from the output of `uv --version`.
301
209
  """
302
210
  return _parse_tool_version_output(
303
- utils.run_command(["poetry", "--version"], capture_output=True).stdout,
304
- tool_name="poetry",
211
+ utils.run_command(["uv", "--version"], capture_output=True).stdout,
212
+ tool_name="uv",
305
213
  )
306
214
 
307
215
 
308
- def get_package_manager_version(package_manager: PackageManager | None = None) -> str:
309
- """Return the version string for the selected package manager.
310
-
311
- Args:
312
- package_manager: Optional explicit package manager backend.
216
+ def _query_uv_runtime_version(candidate: str) -> str | None:
217
+ result = utils.run_command(
218
+ [
219
+ "uv",
220
+ "run",
221
+ "python",
222
+ "-c",
223
+ "import importlib.metadata, sys; print(importlib.metadata.version(sys.argv[1]))",
224
+ candidate,
225
+ ],
226
+ capture_output=True,
227
+ acceptable_returncodes={0, 1},
228
+ )
229
+ if result is not None and result.returncode == 0:
230
+ return result.stdout.strip() or None
231
+ return None
313
232
 
314
- Returns:
315
- Parsed package-manager version.
316
- """
317
- selected_manager = PackageManager(package_manager or get_package_manager())
318
- if selected_manager == PackageManager.POETRY:
319
- return get_poetry_version()
320
233
 
321
- return _parse_tool_version_output(
322
- utils.run_command(
323
- [selected_manager.value, "--version"], capture_output=True
324
- ).stdout,
325
- tool_name=selected_manager.value,
326
- )
234
+ def _parse_package_show_version(output: str) -> str | None:
235
+ for line in output.splitlines():
236
+ if ":" not in line:
237
+ continue
238
+ key, value = line.split(":", 1)
239
+ if key.strip().lower() == "version":
240
+ return value.strip()
241
+ return None
327
242
 
328
243
 
329
244
  @lru_cache
@@ -336,8 +251,7 @@ def get_installed_requirement_version(requirement_name: str) -> str | None:
336
251
 
337
252
  It normalizes extras like `package[extra]` and tries common name variants
338
253
  with hyphens and underscores. If the package is not available to
339
- importlib.metadata, it falls back to package-manager runtime and package
340
- listing commands.
254
+ importlib.metadata, it falls back to uv runtime and package listing commands.
341
255
 
342
256
  Args:
343
257
  requirement_name: The requirement name to lookup.
@@ -358,64 +272,18 @@ def get_installed_requirement_version(requirement_name: str) -> str | None:
358
272
  except metadata.PackageNotFoundError:
359
273
  pass
360
274
 
361
- package_manager = PackageManager(get_package_manager())
362
-
363
- def _query_runtime_version(candidate: str) -> str | None:
364
- result = utils.run_command(
365
- [
366
- package_manager,
367
- "run",
368
- "python",
369
- "-c",
370
- "import importlib.metadata, sys; print(importlib.metadata.version(sys.argv[1]))",
371
- candidate,
372
- ],
373
- capture_output=True,
374
- acceptable_returncodes={0, 1},
375
- )
376
- if result is None:
377
- return None
378
- if result.returncode == 0:
379
- version = result.stdout.strip()
380
- if version:
381
- return version
382
- return None
383
-
384
- if package_manager == PackageManager.POETRY:
385
- version = get_local_poetry_plugin_version(package_name)
386
- if version:
387
- return version
388
-
389
275
  for candidate in candidates:
390
- version = _query_runtime_version(candidate)
276
+ version = _query_uv_runtime_version(candidate)
391
277
  if version:
392
278
  return version
393
279
 
394
- def _parse_package_show_version(output: str) -> str | None:
395
- for line in output.splitlines():
396
- if ":" not in line:
397
- continue
398
- key, value = line.split(":", 1)
399
- if key.strip().lower() == "version":
400
- return value.strip()
401
- return None
402
-
403
- show_commands = (
404
- (["poetry", "show", package_name], ["poetry", "self", "show", package_name])
405
- if package_manager == PackageManager.POETRY
406
- else (["uv", "pip", "show", package_name],)
280
+ result = utils.run_command(
281
+ ["uv", "pip", "show", package_name],
282
+ capture_output=True,
283
+ acceptable_returncodes={0, 1},
407
284
  )
408
-
409
- for cmd in show_commands:
410
- result = utils.run_command(
411
- list(cmd),
412
- capture_output=True,
413
- acceptable_returncodes={0, 1},
414
- )
415
- if result.returncode == 0:
416
- version = _parse_package_show_version(result.stdout)
417
- if version:
418
- return version
285
+ if result.returncode == 0:
286
+ return _parse_package_show_version(result.stdout)
419
287
  return None
420
288
 
421
289
 
@@ -623,28 +491,6 @@ def is_task_tag_included(tag: str) -> bool:
623
491
  return True
624
492
 
625
493
 
626
- def get_project_version_from_poetry() -> str:
627
- """Return the project version parsed from `poetry version` output.
628
-
629
- Returns:
630
- The parsed project version string.
631
- """
632
- poetry_version_output = utils.run_command(
633
- ["poetry", "version"],
634
- capture_output=True,
635
- acceptable_returncodes={0},
636
- ).stdout.strip()
637
- if not poetry_version_output:
638
- utils.fatal("Unable to determine project version from poetry version")
639
-
640
- parts = poetry_version_output.rsplit(" ", 1)
641
- if len(parts) != 2 or not parts[1].strip():
642
- utils.fatal(
643
- f"Unexpected poetry version output format: {poetry_version_output!r}"
644
- )
645
- return parts[1].strip()
646
-
647
-
648
494
  def _get_project_version_from_pyproject() -> str | None:
649
495
  """Return `project.version` from pyproject metadata when present.
650
496
 
@@ -674,17 +520,12 @@ def get_project_version_from_vcs() -> str | None:
674
520
  def get_project_version() -> str:
675
521
  """Return the current project version for release and tagging workflows.
676
522
 
677
- For Poetry projects, this uses `poetry version` to preserve
678
- poetry-dynamic-versioning behavior. For uv workflows, it prefers
679
- `project.version` and falls back to VCS-derived versioning.
523
+ Static `project.version` metadata takes precedence over a VCS-derived version.
524
+ Placeholder static versions fall back to VCS metadata when available.
680
525
 
681
526
  Returns:
682
527
  The resolved current project version.
683
528
  """
684
- package_manager = PackageManager(get_package_manager())
685
- if package_manager == PackageManager.POETRY:
686
- return get_project_version_from_poetry()
687
-
688
529
  pyproject_version = _get_project_version_from_pyproject()
689
530
  if pyproject_version and pyproject_version not in {"0.0.0", "0.0.0.dev0"}:
690
531
  return pyproject_version
@@ -710,15 +551,3 @@ def get_release_tag_from_project_version() -> str:
710
551
  Release tag prefixed with `v`.
711
552
  """
712
553
  return f"v{get_project_version()}"
713
-
714
-
715
- def get_release_tag_from_poetry_version() -> str:
716
- """Return release tag string in `v<version>` form.
717
-
718
- This function is retained for backward compatibility and now uses the
719
- selected package-manager backend.
720
-
721
- Returns:
722
- The release tag string prefixed with `v`.
723
- """
724
- return get_release_tag_from_project_version()
@@ -459,7 +459,6 @@ def build_image(
459
459
  resolve_extension_content,
460
460
  )
461
461
  from .project import (
462
- get_package_manager,
463
462
  has_debug_dependency_group,
464
463
  resolve_container_entrypoint_command,
465
464
  )
@@ -599,7 +598,6 @@ def build_image(
599
598
  dockerfile_text = render_template_text(
600
599
  load_data_file("Dockerfile.j2")[1],
601
600
  {
602
- "PACKAGE_MANAGER": get_package_manager(),
603
601
  "EXTENSION_CONTENT": combined_content,
604
602
  "CONTAINER_DEPS_IMAGE": deps_image_tag,
605
603
  "CONTAINER_DEPS_MOVE_SCRIPT": container_deps_move_script,
@@ -898,15 +896,13 @@ def publish_package(
898
896
  repository: Optional configured repository name to publish to.
899
897
  repository_url: Optional repository upload URL to publish to.
900
898
  """
901
- from .project import get_package_manager_publish_command
899
+ from .project import get_publish_command
902
900
  from .utils import run_command
903
901
 
904
902
  if build_first:
905
903
  build_package(clean_dist=True)
906
904
  run_command(
907
- get_package_manager_publish_command(
908
- repository=repository, repository_url=repository_url
909
- )
905
+ get_publish_command(repository=repository, repository_url=repository_url)
910
906
  )
911
907
 
912
908
 
@@ -1010,7 +1006,6 @@ def _get_changed_dependency_names() -> list[str]:
1010
1006
  "--unified=3",
1011
1007
  "--",
1012
1008
  "pyproject.toml",
1013
- "poetry.lock",
1014
1009
  "uv.lock",
1015
1010
  ],
1016
1011
  capture_output=True,
@@ -1028,7 +1023,6 @@ def _get_dependency_update_changed_files() -> list[Path]:
1028
1023
  "--porcelain",
1029
1024
  "--",
1030
1025
  "pyproject.toml",
1031
- "poetry.lock",
1032
1026
  "uv.lock",
1033
1027
  ],
1034
1028
  capture_output=True,
@@ -1065,7 +1059,7 @@ def update_dependencies(
1065
1059
  draft: bool = False,
1066
1060
  run_tests: bool = False,
1067
1061
  ) -> None:
1068
- """Update project dependencies with Poetry or uv.
1062
+ """Update project dependencies with uv.
1069
1063
 
1070
1064
  Args:
1071
1065
  *dependencies: Optional dependency names to update. When omitted, update
@@ -1080,14 +1074,14 @@ def update_dependencies(
1080
1074
  """
1081
1075
  from .git import get_current_branch, get_default_branch
1082
1076
  from .github import create_pull_request
1083
- from .project import get_package_manager_update_command
1077
+ from .project import get_dependency_update_command
1084
1078
  from .utils import run_command
1085
1079
 
1086
1080
  should_create_branch = branch or branch_name is not None or pr
1087
1081
  if should_create_branch or commit:
1088
1082
  _ensure_clean_dependency_update_worktree()
1089
1083
 
1090
- run_command(get_package_manager_update_command(dependencies))
1084
+ run_command(get_dependency_update_command(dependencies))
1091
1085
  if not _get_dependency_update_changed_files():
1092
1086
  LOGGER.info(
1093
1087
  "Dependency update completed with no lockfile or pyproject changes."
@@ -1117,7 +1111,6 @@ def update_dependencies(
1117
1111
  path
1118
1112
  for path in (
1119
1113
  Path("pyproject.toml"),
1120
- Path("poetry.lock"),
1121
1114
  Path("uv.lock"),
1122
1115
  )
1123
1116
  if path.exists()
@@ -1148,10 +1141,10 @@ def build_package(wheel_only: bool = False, clean_dist: bool = False) -> None:
1148
1141
  wheel_only: Whether to build only the wheel artifact.
1149
1142
  clean_dist: Whether to remove existing distribution artifacts first.
1150
1143
  """
1151
- from .project import get_package_manager_build_command
1144
+ from .project import get_build_command
1152
1145
  from .utils import run_command
1153
1146
 
1154
- command = get_package_manager_build_command(wheel_only=wheel_only)
1147
+ command = get_build_command(wheel_only=wheel_only)
1155
1148
  if clean_dist:
1156
1149
  dist_path = Path("dist")
1157
1150
  if dist_path.exists() and any(dist_path.iterdir()):
@@ -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.
@@ -0,0 +1,27 @@
1
+ common_python_tasks/__init__.py,sha256=HIumMQ0gSD2sVp6efGAILcQJVIUGiasNEij2Nrt3H7k,847
2
+ common_python_tasks/__main__.py,sha256=GpgSd_toMbEaWA_cZvgsZE7jo4XpzuI-awBVm2uhVyw,3512
3
+ common_python_tasks/docker.py,sha256=Xw3VWXkSImccHHgk2krzA1XYCjojvwLsYpXY5wKoYco,24187
4
+ common_python_tasks/docker_compose.py,sha256=OblQjlVa_8HoWNYqu3599gJc34eAYiSgJhrbWuWBJlc,21193
5
+ common_python_tasks/env.py,sha256=BQeRrFBeXMFUK_4Z7cUKprJdXBZn688EHfWrhbm0WD4,16819
6
+ common_python_tasks/git.py,sha256=XdDkrw26B4oJZjNoKMWURFlGwKK3_uBiujXkF6rmVM0,11509
7
+ common_python_tasks/github.py,sha256=_LVanl-z4PsdLM94L8y7tkX-AZO2n3Qy39FRY7reDhA,21589
8
+ common_python_tasks/project.py,sha256=Kz2oZjHPqwRKzIkV4KuOmBzB2wUapaVrUZznQL4FN9c,17128
9
+ common_python_tasks/tasks.py,sha256=HIKDaSC8xR4xi35cGxDm_CmAqjjulh0VQtoiIwUNJ3U,58840
10
+ common_python_tasks/utils.py,sha256=cmplbay7ElSD41qqQrTT5112CtuUkW-AN8o3iTLulBM,20653
11
+ common_python_tasks/data/dockerfile_extensions/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ common_python_tasks/data/fastapi/alembic.ini.j2,sha256=dOiAmZngzX6eyVXeM6BhzgQmes2zwUEdKwOgm8mxjMs,985
13
+ common_python_tasks/data/fastapi/compose-base.yml.j2,sha256=vDLPAdRJ66lsWZdsKbYqEvY_liXaHZ0ly4ljzqmJsyY,910
14
+ common_python_tasks/data/fastapi/compose-db-debug.yml.j2,sha256=iREdSy4F8tJ5m9rlB6CROBkj9OtDFVuGphqIuDvHhww,1193
15
+ common_python_tasks/data/fastapi/compose-db.yml.j2,sha256=16i2rrsYPIJIQn4gpopr5-8KBirMS7OwpXHPaAC03k8,1777
16
+ common_python_tasks/data/fastapi/compose-debug.yml.j2,sha256=sIH9IFvmRAszN6wSejpGVQygXh1g2lVmlzOgPhTx5CY,661
17
+ common_python_tasks/data/generic/.coveragerc,sha256=8zXwDq18wIKQV4NtW2NJYpo3nxCO4LsAChyluYTUoJc,85
18
+ common_python_tasks/data/generic/.dockerignore,sha256=NFTre70gSZ6yi3qg5jxyvcnj3G7FazXLgi--6fOJfQk,65
19
+ common_python_tasks/data/generic/Dockerfile.deps.j2,sha256=rCGsBwLHQIRsGFzDbiRi_nWc-SZ3MAFZ_BeZJFV28Ck,432
20
+ common_python_tasks/data/generic/Dockerfile.j2,sha256=l5PRPWg3R4mkLMb_WEQ_f8pLLSYLH-Y2fWIgy5wSCvQ,5620
21
+ common_python_tasks/data/generic/cliff.toml,sha256=po1MnEGEEgrpyBz3XLWr0h7emXb6ASX63lrU2r6o240,77
22
+ common_python_tasks/data/generic/pytest.ini,sha256=RHak5QrLzKHvUBjFmaaiOYFrd_8YBRQubXEOT0NJfco,134
23
+ common_python_tasks/data/generic/ruff.toml,sha256=njvd-5inSGmgY865SWCT4SR9IrKlzS7JQFZmAG2UT_E,53
24
+ common_python_tasks-0.9.0.dist-info/METADATA,sha256=XpzIcJPOkek42mCbOnlPJb1Iw5IqLQAsYaQk2LaHe40,21049
25
+ common_python_tasks-0.9.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
26
+ common_python_tasks-0.9.0.dist-info/licenses/LICENSE,sha256=RsSweM-DyzxFPx38fQOJqHrKyeT9Fiz8rO7yox-fOsw,1070
27
+ common_python_tasks-0.9.0.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- common_python_tasks/__init__.py,sha256=HIumMQ0gSD2sVp6efGAILcQJVIUGiasNEij2Nrt3H7k,847
2
- common_python_tasks/__main__.py,sha256=GpgSd_toMbEaWA_cZvgsZE7jo4XpzuI-awBVm2uhVyw,3512
3
- common_python_tasks/docker.py,sha256=T1uGH5FqjypkZ3qml83TNW46ax4gJLgZHB-L5P6-4Us,25101
4
- common_python_tasks/docker_compose.py,sha256=i0ebx615-rASwESVd75uwhveiPp40nLub8gPUfSCdrs,21391
5
- common_python_tasks/env.py,sha256=BQeRrFBeXMFUK_4Z7cUKprJdXBZn688EHfWrhbm0WD4,16819
6
- common_python_tasks/git.py,sha256=XdDkrw26B4oJZjNoKMWURFlGwKK3_uBiujXkF6rmVM0,11509
7
- common_python_tasks/github.py,sha256=khaGDvhilxCklMoWGoraofeKRngrW0pCD6bfO7zj7O0,20892
8
- common_python_tasks/project.py,sha256=8fHa5nudToSUP8gC1XUaDUKN3x34GVmYUzkXtHTq5Y8,22482
9
- common_python_tasks/tasks.py,sha256=_jIzHJy45g949RON1sNbyqG8lG-o6Tx-aKLnRHOFxEk,59132
10
- common_python_tasks/utils.py,sha256=cmplbay7ElSD41qqQrTT5112CtuUkW-AN8o3iTLulBM,20653
11
- common_python_tasks/data/dockerfile_extensions/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- common_python_tasks/data/fastapi/alembic.ini.j2,sha256=dOiAmZngzX6eyVXeM6BhzgQmes2zwUEdKwOgm8mxjMs,985
13
- common_python_tasks/data/fastapi/compose-base.yml.j2,sha256=JtXilJ0RfdW5PXSF2xDFRxE9-gUcanJBgHWvKdGJWEE,974
14
- common_python_tasks/data/fastapi/compose-db-debug.yml.j2,sha256=iREdSy4F8tJ5m9rlB6CROBkj9OtDFVuGphqIuDvHhww,1193
15
- common_python_tasks/data/fastapi/compose-db.yml.j2,sha256=FEWgBlebzkgdaaf98xAzDLqk_VGgsYNRF82onqRUhJw,1841
16
- common_python_tasks/data/fastapi/compose-debug.yml.j2,sha256=6397JFObue-YrweFDPyFg4anwe7H6XaMElRqyBee2Q0,665
17
- common_python_tasks/data/generic/.coveragerc,sha256=8zXwDq18wIKQV4NtW2NJYpo3nxCO4LsAChyluYTUoJc,85
18
- common_python_tasks/data/generic/.dockerignore,sha256=K1hgsu8R2Myq6vPIgL86Cvw9aKxly9HfVbcTr3IdKyY,69
19
- common_python_tasks/data/generic/Dockerfile.deps.j2,sha256=rCGsBwLHQIRsGFzDbiRi_nWc-SZ3MAFZ_BeZJFV28Ck,432
20
- common_python_tasks/data/generic/Dockerfile.j2,sha256=Zj48rM2XFvlXxY7KcLx1mLRZX_4pza7MbuEN97jlFHQ,7313
21
- common_python_tasks/data/generic/cliff.toml,sha256=po1MnEGEEgrpyBz3XLWr0h7emXb6ASX63lrU2r6o240,77
22
- common_python_tasks/data/generic/pytest.ini,sha256=RHak5QrLzKHvUBjFmaaiOYFrd_8YBRQubXEOT0NJfco,134
23
- common_python_tasks/data/generic/ruff.toml,sha256=m7oPo_t8_D10dXPd5504xay6BEkekauK-oCV4XPJW7g,64
24
- common_python_tasks-0.8.0.dist-info/METADATA,sha256=XOxRbLqZEDhoIljJdI83Rv00tVDNOznrV5WXN-XUk1g,20670
25
- common_python_tasks-0.8.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
26
- common_python_tasks-0.8.0.dist-info/licenses/LICENSE,sha256=RsSweM-DyzxFPx38fQOJqHrKyeT9Fiz8rO7yox-fOsw,1070
27
- common_python_tasks-0.8.0.dist-info/RECORD,,