lib-cli-exit-tools 2.3.1__tar.gz → 2.3.3__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.
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.codacy/cli-config.yaml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.codacy/codacy.yaml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.codacy/tools-configs/lizard.yaml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.codacy/tools-configs/trivy.yaml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.data_arch_violations.json +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.devcontainer/devcontainer.json +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.devcontainer/settings.json +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.env.example +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/actions/extract-metadata/action.yml +16 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/dependabot.yml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/workflows/codeql.yml +1 -1
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/workflows/default_cicd_public.yml +64 -14
- lib_cli_exit_tools-2.3.3/.github/workflows/default_release_public.yml +95 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.gitignore +6 -1
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.qlty/qlty.toml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.snyk +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/CHANGELOG.md +17 -1
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/CONTRIBUTING.md +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/DEVELOPMENT.md +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/INSTALL.md +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/LICENSE +0 -0
- lib_cli_exit_tools-2.3.3/Makefile +453 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/PKG-INFO +18 -17
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/README.md +5 -4
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/codecov.yml +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/docs/system-design/module_reference.md +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/notebooks/Quickstart.ipynb +5 -4
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/pyproject.toml +69 -15
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/__init__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/__init__conf__.py +4 -2
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/__main__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/adapters/signals.py +7 -7
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/application/__init__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/application/runner.py +21 -17
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/cli/__init__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/cli/commands.py +1 -2
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/cli/group.py +8 -5
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/cli/styling.py +4 -1
- lib_cli_exit_tools-2.3.3/src/lib_cli_exit_tools/cli/typed_click.py +51 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/core/__init__.py +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/core/configuration.py +8 -6
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/core/exit_codes.py +4 -4
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +12 -12
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/src/lib_cli_exit_tools/py.typed +0 -0
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/conftest.py +3 -1
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_adapters_signals.py +0 -1
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_application_runner.py +6 -4
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_behaviors.py +7 -6
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_cli.py +6 -5
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_core_configuration.py +7 -7
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_core_exit_codes.py +2 -2
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_metadata.py +18 -18
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_module_entry.py +4 -3
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/tests/test_signals_integration.py +6 -5
- lib_cli_exit_tools-2.3.1/.github/workflows/default_release_public.yml +0 -69
- lib_cli_exit_tools-2.3.1/Makefile +0 -260
- {lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.codacy/cli.sh +0 -0
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/actions/extract-metadata/action.yml
RENAMED
|
@@ -29,6 +29,11 @@ outputs:
|
|
|
29
29
|
BANDIT_SKIP_FLAG:
|
|
30
30
|
description: Bandit skip flag string (e.g. "-s B101,B601") or empty
|
|
31
31
|
value: ${{ steps.meta.outputs.BANDIT_SKIP_FLAG }}
|
|
32
|
+
PYTEST_MARKER_EXPR:
|
|
33
|
+
description: >-
|
|
34
|
+
Marker expression for the CI test run (e.g. "not local_only and not integration"),
|
|
35
|
+
built from tool.ci.pytest-exclude-markers
|
|
36
|
+
value: ${{ steps.meta.outputs.PYTEST_MARKER_EXPR }}
|
|
32
37
|
|
|
33
38
|
runs:
|
|
34
39
|
using: composite
|
|
@@ -69,6 +74,15 @@ runs:
|
|
|
69
74
|
bandit_skips = data.get('tool', {}).get('bandit', {}).get('skips', [])
|
|
70
75
|
bandit_skip_flag = f"-s {','.join(bandit_skips)}" if bandit_skips else ""
|
|
71
76
|
|
|
77
|
+
# --- [tool.ci] section ---
|
|
78
|
+
# CI always skips local_only (those tests need a dev box). A project whose
|
|
79
|
+
# suite also carries markers CI cannot satisfy - integration tests needing a
|
|
80
|
+
# container that a separate workflow starts - names them here, rather than
|
|
81
|
+
# every such repo forking this workflow to edit one -m expression.
|
|
82
|
+
ci_config = data.get('tool', {}).get('ci', {})
|
|
83
|
+
exclude_markers = ['local_only', *ci_config.get('pytest-exclude-markers', [])]
|
|
84
|
+
pytest_marker_expr = ' and '.join(f'not {m}' for m in exclude_markers)
|
|
85
|
+
|
|
72
86
|
# Write to GITHUB_OUTPUT for composite action outputs
|
|
73
87
|
with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as out:
|
|
74
88
|
out.write(f"PROJECT_NAME={project}\n")
|
|
@@ -79,6 +93,7 @@ runs:
|
|
|
79
93
|
out.write(f"COV_REPORT_FILE={cov_report_file}\n")
|
|
80
94
|
out.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
|
|
81
95
|
out.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
|
|
96
|
+
out.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
|
|
82
97
|
|
|
83
98
|
# Also write to GITHUB_ENV so subsequent steps can use ${{ env.VAR }}
|
|
84
99
|
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
@@ -90,3 +105,4 @@ runs:
|
|
|
90
105
|
env.write(f"COV_REPORT_FILE={cov_report_file}\n")
|
|
91
106
|
env.write(f"COV_FAIL_UNDER={cov_fail_under}\n")
|
|
92
107
|
env.write(f"BANDIT_SKIP_FLAG={bandit_skip_flag}\n")
|
|
108
|
+
env.write(f"PYTEST_MARKER_EXPR={pytest_marker_expr}\n")
|
|
File without changes
|
{lib_cli_exit_tools-2.3.1 → lib_cli_exit_tools-2.3.3}/.github/workflows/default_cicd_public.yml
RENAMED
|
@@ -18,8 +18,8 @@ jobs:
|
|
|
18
18
|
python-latest: ${{ steps.metadata.outputs.python-latest }}
|
|
19
19
|
os-matrix: ${{ steps.metadata.outputs.os-matrix }}
|
|
20
20
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
22
|
-
- uses: actions/setup-python@
|
|
21
|
+
- uses: actions/checkout@v7
|
|
22
|
+
- uses: actions/setup-python@v7
|
|
23
23
|
with:
|
|
24
24
|
python-version: "3.x"
|
|
25
25
|
- name: Parse pyproject.toml for Python versions and OS matrix
|
|
@@ -66,8 +66,8 @@ jobs:
|
|
|
66
66
|
UV_LINK_MODE: "copy"
|
|
67
67
|
UV_BREAK_SYSTEM_PACKAGES: "1"
|
|
68
68
|
steps:
|
|
69
|
-
- uses: actions/checkout@
|
|
70
|
-
- uses: actions/setup-python@
|
|
69
|
+
- uses: actions/checkout@v7
|
|
70
|
+
- uses: actions/setup-python@v7
|
|
71
71
|
with:
|
|
72
72
|
python-version: ${{ matrix.python }}
|
|
73
73
|
- name: Install uv
|
|
@@ -169,7 +169,7 @@ jobs:
|
|
|
169
169
|
- name: Restore ruff cache
|
|
170
170
|
if: runner.environment == 'github-hosted'
|
|
171
171
|
id: ruff-cache
|
|
172
|
-
uses: actions/cache/restore@
|
|
172
|
+
uses: actions/cache/restore@v6
|
|
173
173
|
with:
|
|
174
174
|
path: .ruff_cache
|
|
175
175
|
key: ruff-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
|
|
@@ -201,7 +201,7 @@ jobs:
|
|
|
201
201
|
# and stale journal files cause "database is locked" errors.
|
|
202
202
|
COVERAGE_FILE: "${{ runner.temp }}/.coverage"
|
|
203
203
|
run: >-
|
|
204
|
-
pytest -m "
|
|
204
|
+
pytest -m "${{ env.PYTEST_MARKER_EXPR }}"
|
|
205
205
|
--cov=${{ env.SRC_PATH }}/${{ env.PACKAGE_MODULE }}
|
|
206
206
|
--cov-report=term-missing
|
|
207
207
|
--cov-report=xml:${{ env.COV_REPORT_FILE }}
|
|
@@ -214,7 +214,7 @@ jobs:
|
|
|
214
214
|
&& steps.pytest.outcome == 'success'
|
|
215
215
|
&& matrix.os == 'ubuntu-latest'
|
|
216
216
|
&& matrix.python == needs.setup.outputs.python-latest
|
|
217
|
-
uses: codecov/codecov-action@
|
|
217
|
+
uses: codecov/codecov-action@v7
|
|
218
218
|
with:
|
|
219
219
|
files: ${{ env.COV_REPORT_FILE }}
|
|
220
220
|
fail_ci_if_error: false
|
|
@@ -236,12 +236,62 @@ jobs:
|
|
|
236
236
|
continue-on-error: true
|
|
237
237
|
shell: python
|
|
238
238
|
run: |
|
|
239
|
-
import subprocess, sys
|
|
239
|
+
import subprocess, sys, tempfile
|
|
240
240
|
import rtoml
|
|
241
241
|
from pathlib import Path
|
|
242
|
+
|
|
243
|
+
# Audit the project's OWN resolved dependency tree, not the ambient
|
|
244
|
+
# environment. "Install dev deps" uses --system, so the interpreter
|
|
245
|
+
# being audited is the runner image's, and that image ships packages
|
|
246
|
+
# this project neither declares nor distributes (setuptools, pip,
|
|
247
|
+
# wheel). Auditing those reported CVEs no consumer of this project is
|
|
248
|
+
# exposed to, and a scan that is permanently yellow is a scan everyone
|
|
249
|
+
# learns to ignore. Resolving pyproject.toml here keeps the result
|
|
250
|
+
# identical on every OS/python and dependent only on what we declare.
|
|
242
251
|
data = rtoml.load(Path("pyproject.toml"))
|
|
252
|
+
|
|
253
|
+
# Not every project declares dev dependencies, and those that do may use
|
|
254
|
+
# either an extra or a PEP 735 group. Asking uv for one that does not
|
|
255
|
+
# exist is a hard error ("Requested extra not found"), which would leave
|
|
256
|
+
# the audit permanently broken here rather than merely noisy, so select
|
|
257
|
+
# the flag from what this project actually declares.
|
|
258
|
+
selector = []
|
|
259
|
+
if "dev" in data.get("project", {}).get("optional-dependencies", {}):
|
|
260
|
+
selector = ["--extra", "dev"]
|
|
261
|
+
elif "dev" in data.get("dependency-groups", {}):
|
|
262
|
+
selector = ["--group", "dev"]
|
|
263
|
+
|
|
264
|
+
tmp = Path(tempfile.mkdtemp())
|
|
265
|
+
req = tmp / "compiled-requirements.txt"
|
|
266
|
+
subprocess.check_call(
|
|
267
|
+
["uv", "pip", "compile", *selector, "pyproject.toml", "-o", str(req), "--quiet"]
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Drop direct URL references ("pkg @ git+https://...") before auditing.
|
|
271
|
+
# pip-audit cannot audit those (they are not on PyPI) but, given a
|
|
272
|
+
# requirements file, first tries to `git clone` each one to resolve a
|
|
273
|
+
# version - a slow, credential-dependent fetch. No public project here
|
|
274
|
+
# uses one today, yet "allow-direct-references" is enabled, so this
|
|
275
|
+
# guards the day one appears and keeps this step identical to the
|
|
276
|
+
# default_cicd_private template's.
|
|
277
|
+
audit_req = tmp / "audit-requirements.txt"
|
|
278
|
+
kept, dropped = [], []
|
|
279
|
+
for line in req.read_text(encoding="utf-8").splitlines():
|
|
280
|
+
if " @ " in line and not line.lstrip().startswith("#"):
|
|
281
|
+
dropped.append(line.split(" @ ", 1)[0].strip())
|
|
282
|
+
else:
|
|
283
|
+
kept.append(line)
|
|
284
|
+
audit_req.write_text("\n".join(kept) + "\n", encoding="utf-8")
|
|
285
|
+
if dropped:
|
|
286
|
+
# Never drop coverage silently: name what is not being audited here.
|
|
287
|
+
print(f"::notice::pip-audit: not auditing {len(dropped)} direct-URL dependency/ies "
|
|
288
|
+
f"(audited in their own repo): {', '.join(sorted(dropped))}")
|
|
289
|
+
|
|
290
|
+
req = audit_req
|
|
243
291
|
vulns = data.get("tool", {}).get("pip-audit", {}).get("ignore-vulns", [])
|
|
244
|
-
|
|
292
|
+
# --no-deps: the compiled file is already a complete pinned resolution,
|
|
293
|
+
# so pip-audit must audit it verbatim rather than re-resolving it.
|
|
294
|
+
cmd = ["pip-audit", "--no-deps", "-r", str(req)]
|
|
245
295
|
for v in vulns:
|
|
246
296
|
cmd.extend(["--ignore-vuln", v])
|
|
247
297
|
sys.exit(subprocess.call(cmd))
|
|
@@ -293,7 +343,7 @@ jobs:
|
|
|
293
343
|
|
|
294
344
|
- name: Save ruff cache
|
|
295
345
|
if: always() && runner.environment == 'github-hosted' && steps.ruff-cache.outputs.cache-hit != 'true'
|
|
296
|
-
uses: actions/cache/save@
|
|
346
|
+
uses: actions/cache/save@v6
|
|
297
347
|
with:
|
|
298
348
|
path: .ruff_cache
|
|
299
349
|
key: ruff-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
|
|
@@ -302,8 +352,8 @@ jobs:
|
|
|
302
352
|
name: pipx/uv verification (ubuntu)
|
|
303
353
|
runs-on: ubuntu-latest
|
|
304
354
|
steps:
|
|
305
|
-
- uses: actions/checkout@
|
|
306
|
-
- uses: actions/setup-python@
|
|
355
|
+
- uses: actions/checkout@v7
|
|
356
|
+
- uses: actions/setup-python@v7
|
|
307
357
|
with:
|
|
308
358
|
python-version: "3.14"
|
|
309
359
|
|
|
@@ -341,8 +391,8 @@ jobs:
|
|
|
341
391
|
name: Execute notebooks (ubuntu, Python 3.14)
|
|
342
392
|
runs-on: ubuntu-latest
|
|
343
393
|
steps:
|
|
344
|
-
- uses: actions/checkout@
|
|
345
|
-
- uses: actions/setup-python@
|
|
394
|
+
- uses: actions/checkout@v7
|
|
395
|
+
- uses: actions/setup-python@v7
|
|
346
396
|
with:
|
|
347
397
|
python-version: "3.14"
|
|
348
398
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# The tag push is the only release event bmk guarantees: it runs
|
|
4
|
+
# `git push <remote> <tag>` unconditionally, whereas `gh release create` sits
|
|
5
|
+
# behind a gh-availability check and runs with check=False, so a missing or
|
|
6
|
+
# failing gh would leave nothing to publish. Listening for `release: published`
|
|
7
|
+
# as well fired a second, redundant run that raced the first to the upload and
|
|
8
|
+
# only ever logged "Skipping ... already exists".
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags:
|
|
12
|
+
- 'v*'
|
|
13
|
+
workflow_dispatch: {}
|
|
14
|
+
|
|
15
|
+
# One publish at a time per tag, so a workflow_dispatch re-run cannot overlap
|
|
16
|
+
# the run the tag push started.
|
|
17
|
+
concurrency:
|
|
18
|
+
group: release-${{ github.ref_name }}
|
|
19
|
+
cancel-in-progress: false
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
build:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
env:
|
|
27
|
+
UV_LINK_MODE: "copy"
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
- uses: actions/setup-python@v7
|
|
31
|
+
with:
|
|
32
|
+
python-version: '3.14'
|
|
33
|
+
|
|
34
|
+
- name: Install uv
|
|
35
|
+
uses: astral-sh/setup-uv@v7
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
prune-cache: false
|
|
39
|
+
|
|
40
|
+
- name: Build artifacts
|
|
41
|
+
run: uv build
|
|
42
|
+
|
|
43
|
+
- name: Upload artifacts
|
|
44
|
+
uses: actions/upload-artifact@v7
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/*
|
|
48
|
+
|
|
49
|
+
- name: Prune uv cache
|
|
50
|
+
continue-on-error: true
|
|
51
|
+
run: uv cache prune --ci
|
|
52
|
+
|
|
53
|
+
publish:
|
|
54
|
+
needs: build
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
environment: pypi
|
|
57
|
+
permissions:
|
|
58
|
+
contents: read
|
|
59
|
+
# id-token is required for OIDC / PyPI Trusted Publisher. It is harmless when
|
|
60
|
+
# a PYPI_API_TOKEN secret is configured, in which case the token path runs.
|
|
61
|
+
id-token: write
|
|
62
|
+
steps:
|
|
63
|
+
- name: Select PyPI auth method
|
|
64
|
+
id: auth
|
|
65
|
+
env:
|
|
66
|
+
PYPI_API_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
67
|
+
run: |
|
|
68
|
+
if [ -n "$PYPI_API_TOKEN" ]; then
|
|
69
|
+
echo "PYPI_API_TOKEN is set; publishing with the API token."
|
|
70
|
+
echo "method=token" >> "$GITHUB_OUTPUT"
|
|
71
|
+
else
|
|
72
|
+
echo "No PYPI_API_TOKEN; publishing via OIDC Trusted Publisher."
|
|
73
|
+
echo "method=oidc" >> "$GITHUB_OUTPUT"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
- name: Download artifacts
|
|
77
|
+
uses: actions/download-artifact@v8
|
|
78
|
+
with:
|
|
79
|
+
name: dist
|
|
80
|
+
path: dist/
|
|
81
|
+
|
|
82
|
+
- name: Publish to PyPI (API token)
|
|
83
|
+
if: steps.auth.outputs.method == 'token'
|
|
84
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
85
|
+
with:
|
|
86
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
87
|
+
attestations: false
|
|
88
|
+
skip-existing: true
|
|
89
|
+
|
|
90
|
+
- name: Publish to PyPI (Trusted Publisher / OIDC)
|
|
91
|
+
if: steps.auth.outputs.method == 'oidc'
|
|
92
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
93
|
+
with:
|
|
94
|
+
attestations: true
|
|
95
|
+
skip-existing: true
|
|
File without changes
|
|
File without changes
|
|
@@ -4,6 +4,22 @@ All notable changes to this project are documented here. The format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.3.3] 2026-07-24 16:09:16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- `print_info()` now writes via `sys.stdout.write()` instead of `print()`, and `print_exception_message()`'s `trace_back` / `length_limit` / `stream` parameters are keyword-only, along with several private `application/runner.py` helpers (`_resolve_traceback_choice`, `_render_exception_view`, `_session_config_manager`, `_install_signal_handlers_when_requested`) - closing the ruff PLR0917/FBT001 boolean-positional-argument findings that a newer ruff started reporting. All call sites (in this repo and downstream) already passed these by keyword, so this is not a breaking change.
|
|
11
|
+
- Replaced `typing.Callable`/`Iterable`/`Sequence`/`ContextManager` imports with their `collections.abc`/`contextlib` equivalents (ruff UP035), sorted `__all__` lists (RUF022), quoted `typing.cast()` type arguments (TC006), and moved a handful of type-checking-only imports behind `TYPE_CHECKING` (TC003) across `src` and `tests`.
|
|
12
|
+
- Replaced ambiguous en-dash characters in docstrings with ASCII hyphens (RUF002).
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Added an explicit, curated `[tool.ruff.lint].select` (the fleet-standard rule set) to `pyproject.toml` instead of relying on ruff's default rule set, which had grown to roughly 900 rules on the installed ruff release and was about to make CI red on unrelated, previously-unenforced rule families. Added matching `per-file-ignores` for tests, the CLI layer, `notebooks/Quickstart.ipynb`, and `application/runner.py`'s intentionally-wide dependency-injection seams (`PLR0913`).
|
|
16
|
+
- Documented the three narrow places where suppressing a lint finding is correct rather than fixing it: the `SigIntInterrupt`/`SigTermInterrupt`/`SigBreakInterrupt` exception names stay as-is (`# noqa: N818`) because renaming them would break every downstream `except Sig...Interrupt`; `getattr(signal, "SIGBREAK"/"CTRL_BREAK_EVENT")` and `getattr(exc, "winerror")` stay as `getattr()` (`# noqa: B009`) because typeshed only declares those attributes on Windows/`OSError`, so direct attribute access fails pyright strict on other platforms/types; and the `echo=lambda ...` test double stays a lambda (`# noqa: PLW0108`) because `messages.append` alone cannot accept the `err` keyword the echo protocol requires.
|
|
17
|
+
|
|
18
|
+
## [2.3.2] 2026-06-14
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- Added a `cli/typed_click.py` facade that wraps rich-click's `option` / `version_option` decorators behind explicit, fully-known signatures. This keeps the CLI layer clean under pyright 1.1.410 strict mode (which reports `reportUnknownMemberType` for rich-click's re-exported click decorators) without disabling the rule - the single `# pyright: ignore` is isolated to the facade boundary.
|
|
22
|
+
|
|
7
23
|
## [2.3.1] - 2026-04-24
|
|
8
24
|
|
|
9
25
|
### Fixed
|
|
@@ -152,7 +168,7 @@ All notable changes to this project are documented here. The format follows [Kee
|
|
|
152
168
|
### Changed
|
|
153
169
|
- Hardened `get_system_exit_code` handling for non-integer payloads and switched OS detection to `os.name`.
|
|
154
170
|
- Updated `_print_output` to decode both `bytes` and `str`, trimming assertions in favour of resilient diagnostics.
|
|
155
|
-
- Standardised signal messages (
|
|
171
|
+
- Standardised signal messages ("Aborted (SIGINT).", etc.) and cached metadata lookups in `__init__conf__`.
|
|
156
172
|
- Enforced an 85% coverage threshold (in line with `pyproject.toml` and Codecov settings) and removed spurious coverage pragmas to reflect the new test suite.
|
|
157
173
|
- Repartitioned the library into `core`, `adapters`, and `application` layers with `lib_cli_exit_tools` acting as the facade.
|
|
158
174
|
- `run_cli` now accepts injectable `exception_handler` and `signal_installer` hooks, and rich-click configuration is applied lazily from `main()`.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|