lib-cli-exit-tools 1.6.0__tar.gz → 2.0.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.
- lib_cli_exit_tools-2.0.0/.env.example +11 -0
- lib_cli_exit_tools-2.0.0/.github/dependabot.yml +22 -0
- lib_cli_exit_tools-2.0.0/.github/workflows/ci.yml +162 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.github/workflows/codeql.yml +4 -5
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.github/workflows/release.yml +2 -2
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/AGENTS.md +3 -4
- lib_cli_exit_tools-2.0.0/AGENTS_README.md +176 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/CHANGELOG.md +20 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/CONTRIBUTING.md +5 -16
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/DEVELOPMENT.md +19 -27
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/INSTALL.md +3 -25
- lib_cli_exit_tools-2.0.0/Makefile +54 -0
- lib_cli_exit_tools-1.6.0/README.md → lib_cli_exit_tools-2.0.0/PKG-INFO +258 -11
- lib_cli_exit_tools-1.6.0/PKG-INFO → lib_cli_exit_tools-2.0.0/README.md +222 -47
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/codecov.yml +0 -2
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/docs/system-design/module_reference.md +10 -10
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/pyproject.toml +15 -17
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/_utils.py +124 -164
- lib_cli_exit_tools-2.0.0/scripts/build.py +39 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/bump.py +4 -9
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/bump_major.py +2 -6
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/bump_minor.py +2 -6
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/bump_patch.py +2 -6
- lib_cli_exit_tools-2.0.0/scripts/bump_version.py +80 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/clean.py +2 -2
- lib_cli_exit_tools-2.0.0/scripts/cli.py +213 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/dev.py +2 -8
- lib_cli_exit_tools-2.0.0/scripts/help.py +41 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/install.py +2 -8
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/menu.py +36 -126
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/push.py +17 -21
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/release.py +26 -63
- lib_cli_exit_tools-2.0.0/scripts/run_cli.py +154 -0
- lib_cli_exit_tools-2.0.0/scripts/target_metadata.py +174 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/test.py +232 -120
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/version_current.py +1 -6
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/__init__.py +1 -0
- lib_cli_exit_tools-2.0.0/src/lib_cli_exit_tools/__main__.py +13 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/adapters/signals.py +19 -30
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/application/runner.py +229 -45
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/cli.py +10 -14
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/core/exit_codes.py +88 -29
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +2 -0
- lib_cli_exit_tools-2.0.0/tests/conftest.py +57 -0
- lib_cli_exit_tools-2.0.0/tests/test_adapters_signals.py +65 -0
- lib_cli_exit_tools-2.0.0/tests/test_application_runner.py +385 -0
- lib_cli_exit_tools-2.0.0/tests/test_behaviors.py +99 -0
- lib_cli_exit_tools-2.0.0/tests/test_cli.py +152 -0
- lib_cli_exit_tools-2.0.0/tests/test_core_configuration.py +47 -0
- lib_cli_exit_tools-2.0.0/tests/test_core_exit_codes.py +265 -0
- lib_cli_exit_tools-2.0.0/tests/test_metadata.py +101 -0
- lib_cli_exit_tools-2.0.0/tests/test_module_entry.py +137 -0
- lib_cli_exit_tools-2.0.0/tests/test_scripts.py +233 -0
- lib_cli_exit_tools-2.0.0/tests/test_signals_integration.py +122 -0
- lib_cli_exit_tools-1.6.0/.env.example +0 -18
- lib_cli_exit_tools-1.6.0/.github/workflows/ci.yml +0 -268
- lib_cli_exit_tools-1.6.0/Makefile +0 -59
- lib_cli_exit_tools-1.6.0/packaging/README.md +0 -68
- lib_cli_exit_tools-1.6.0/packaging/brew/Formula/lib-cli-exit-tools.rb +0 -30
- lib_cli_exit_tools-1.6.0/packaging/conda/recipe/meta.yaml +0 -46
- lib_cli_exit_tools-1.6.0/packaging/nix/flake.nix +0 -74
- lib_cli_exit_tools-1.6.0/scripts/build.py +0 -78
- lib_cli_exit_tools-1.6.0/scripts/bump_version.py +0 -614
- lib_cli_exit_tools-1.6.0/scripts/cli.py +0 -158
- lib_cli_exit_tools-1.6.0/scripts/generate_nix_flake.py +0 -231
- lib_cli_exit_tools-1.6.0/scripts/run_cli.py +0 -51
- lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/__main__.py +0 -11
- lib_cli_exit_tools-1.6.0/tests/adapters/test_signals_poetry.py +0 -119
- lib_cli_exit_tools-1.6.0/tests/application/test_runner_poetry.py +0 -385
- lib_cli_exit_tools-1.6.0/tests/application/test_signal_poetry_posix.py +0 -84
- lib_cli_exit_tools-1.6.0/tests/application/test_signal_poetry_windows.py +0 -93
- lib_cli_exit_tools-1.6.0/tests/cli/test_cli_poetry.py +0 -305
- lib_cli_exit_tools-1.6.0/tests/conftest.py +0 -28
- lib_cli_exit_tools-1.6.0/tests/core/test_configuration.py +0 -73
- lib_cli_exit_tools-1.6.0/tests/core/test_exit_code_poetry.py +0 -192
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.codacy/cli-config.yaml +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.codacy/cli.sh +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.codacy/codacy.yaml +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.codacy/tools-configs/lizard.yaml +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.codacy/tools-configs/trivy.yaml +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.devcontainer/devcontainer.json +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.devcontainer/settings.json +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.gitignore +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.qlty/qlty.toml +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/.snyk +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/LICENSE +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/notebooks/Quickstart.ipynb +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/__init__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/scripts/__main__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/__init__conf__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/application/__init__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/core/__init__.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/core/configuration.py +0 -0
- {lib_cli_exit_tools-1.6.0 → lib_cli_exit_tools-2.0.0}/src/lib_cli_exit_tools/py.typed +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Copy to .env and fill values as needed.
|
|
2
|
+
|
|
3
|
+
# Codecov upload token (required for private repos; optional for public repos)
|
|
4
|
+
CODECOV_TOKEN=
|
|
5
|
+
|
|
6
|
+
# PyPI API token for release workflow (.github/workflows/release.yml)
|
|
7
|
+
# Format: pypi-AgENdGVzdC5weXBpLm9yZwIk...
|
|
8
|
+
PYPI_API_TOKEN=
|
|
9
|
+
|
|
10
|
+
# Optional: GitHub token for API-limited tasks (e.g., higher rate limits on dependency audits)
|
|
11
|
+
GITHUB_TOKEN=
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
allow:
|
|
8
|
+
- dependency-type: "direct"
|
|
9
|
+
labels:
|
|
10
|
+
- "dependencies"
|
|
11
|
+
commit-message:
|
|
12
|
+
prefix: "deps"
|
|
13
|
+
include: "scope"
|
|
14
|
+
- package-ecosystem: "github-actions"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
18
|
+
labels:
|
|
19
|
+
- "dependencies"
|
|
20
|
+
commit-message:
|
|
21
|
+
prefix: "deps"
|
|
22
|
+
include: "scope"
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Tests (Python ${{ matrix.python }}, ${{ matrix.os }})
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
+
# Test against Python 3.13 and the latest 3.x available on Actions runners
|
|
18
|
+
python: ["3.13", "3.x"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
- uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python }}
|
|
24
|
+
- name: Extract project metadata
|
|
25
|
+
shell: python
|
|
26
|
+
run: |
|
|
27
|
+
import os
|
|
28
|
+
import tomllib
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
data = tomllib.loads(Path('pyproject.toml').read_text('utf-8'))
|
|
32
|
+
project = data['project']['name']
|
|
33
|
+
module = project.replace('-', '_')
|
|
34
|
+
dash = project.replace('_', '-')
|
|
35
|
+
scripts = list(data['project'].get('scripts', {}).keys())
|
|
36
|
+
cli_bin = scripts[0] if scripts else dash
|
|
37
|
+
|
|
38
|
+
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
39
|
+
env.write(f"PROJECT_NAME={project}\n")
|
|
40
|
+
env.write(f"PACKAGE_MODULE={module}\n")
|
|
41
|
+
env.write(f"CLI_BIN={cli_bin}\n")
|
|
42
|
+
- name: Install make on Windows
|
|
43
|
+
if: runner.os == 'Windows'
|
|
44
|
+
shell: pwsh
|
|
45
|
+
run: |
|
|
46
|
+
choco install -y make
|
|
47
|
+
echo "C:\\ProgramData\\chocolatey\\bin" >> $env:GITHUB_PATH
|
|
48
|
+
- name: Upgrade pip
|
|
49
|
+
shell: bash
|
|
50
|
+
run: python -m pip install --upgrade pip
|
|
51
|
+
|
|
52
|
+
- name: Install dev deps
|
|
53
|
+
shell: bash
|
|
54
|
+
run: |
|
|
55
|
+
pip install -e .[dev]
|
|
56
|
+
|
|
57
|
+
- name: Install Windows Event Log prerequisites
|
|
58
|
+
if: runner.os == 'Windows'
|
|
59
|
+
shell: bash
|
|
60
|
+
run: |
|
|
61
|
+
pip install pywin32
|
|
62
|
+
- name: Run full test suite (lint, types, tests, coverage, codecov)
|
|
63
|
+
shell: bash
|
|
64
|
+
env:
|
|
65
|
+
TEST_VERBOSE: "1"
|
|
66
|
+
run: make test
|
|
67
|
+
- name: Build wheel/sdist
|
|
68
|
+
shell: bash
|
|
69
|
+
run: python -m build
|
|
70
|
+
- name: Verify wheel install in clean env
|
|
71
|
+
shell: bash
|
|
72
|
+
run: |
|
|
73
|
+
python -m venv .venv_wheel
|
|
74
|
+
. .venv_wheel/bin/activate 2>/dev/null || . .venv_wheel/Scripts/activate 2>/dev/null
|
|
75
|
+
pip install dist/*.whl
|
|
76
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
77
|
+
|
|
78
|
+
pipx-uv:
|
|
79
|
+
name: pipx/uv verification (ubuntu)
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v5
|
|
83
|
+
- uses: actions/setup-python@v6
|
|
84
|
+
with:
|
|
85
|
+
python-version: "3.13"
|
|
86
|
+
- name: Extract project metadata
|
|
87
|
+
shell: python
|
|
88
|
+
run: |
|
|
89
|
+
import os
|
|
90
|
+
import tomllib
|
|
91
|
+
from pathlib import Path
|
|
92
|
+
|
|
93
|
+
data = tomllib.loads(Path('pyproject.toml').read_text('utf-8'))
|
|
94
|
+
project = data['project']['name']
|
|
95
|
+
module = project.replace('-', '_')
|
|
96
|
+
dash = project.replace('_', '-')
|
|
97
|
+
scripts = list(data['project'].get('scripts', {}).keys())
|
|
98
|
+
cli_bin = scripts[0] if scripts else dash
|
|
99
|
+
|
|
100
|
+
with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
|
|
101
|
+
env.write(f"PROJECT_NAME={project}\n")
|
|
102
|
+
env.write(f"PACKAGE_MODULE={module}\n")
|
|
103
|
+
env.write(f"CLI_BIN={cli_bin}\n")
|
|
104
|
+
- name: Build wheel
|
|
105
|
+
run: |
|
|
106
|
+
python -m pip install --upgrade pip build
|
|
107
|
+
python -m build
|
|
108
|
+
- name: pipx install from wheel
|
|
109
|
+
run: |
|
|
110
|
+
python -m pip install pipx
|
|
111
|
+
pipx install dist/*.whl
|
|
112
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
113
|
+
- name: Install uv
|
|
114
|
+
uses: astral-sh/setup-uv@v7
|
|
115
|
+
with:
|
|
116
|
+
enable-cache: true
|
|
117
|
+
- name: uv tool install
|
|
118
|
+
run: |
|
|
119
|
+
uv tool install .
|
|
120
|
+
"$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
|
|
121
|
+
|
|
122
|
+
notebooks:
|
|
123
|
+
name: Execute notebooks (ubuntu, Python 3.13)
|
|
124
|
+
runs-on: ubuntu-latest
|
|
125
|
+
steps:
|
|
126
|
+
- uses: actions/checkout@v5
|
|
127
|
+
- uses: actions/setup-python@v6
|
|
128
|
+
with:
|
|
129
|
+
python-version: "3.13"
|
|
130
|
+
- name: Install notebook runner deps
|
|
131
|
+
run: |
|
|
132
|
+
python -m pip install --upgrade pip
|
|
133
|
+
pip install nbclient nbformat ipykernel jupyter_client
|
|
134
|
+
python -m ipykernel install --user --name python3 --display-name "Python 3"
|
|
135
|
+
- name: Execute Quickstart notebook
|
|
136
|
+
env:
|
|
137
|
+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
|
138
|
+
PIP_NO_INPUT: "1"
|
|
139
|
+
run: |
|
|
140
|
+
python - << 'PY'
|
|
141
|
+
from pathlib import Path
|
|
142
|
+
|
|
143
|
+
import nbformat
|
|
144
|
+
from nbclient import NotebookClient
|
|
145
|
+
|
|
146
|
+
nb_path = Path('notebooks/Quickstart.ipynb')
|
|
147
|
+
if not nb_path.exists():
|
|
148
|
+
raise SystemExit(f"Notebook not found: {nb_path}")
|
|
149
|
+
|
|
150
|
+
notebook = nbformat.read(nb_path, as_version=4)
|
|
151
|
+
client = NotebookClient(
|
|
152
|
+
notebook,
|
|
153
|
+
timeout=900,
|
|
154
|
+
kernel_name='python3',
|
|
155
|
+
allow_errors=False,
|
|
156
|
+
)
|
|
157
|
+
client.execute()
|
|
158
|
+
|
|
159
|
+
out_path = Path('notebooks/Quickstart-executed.ipynb')
|
|
160
|
+
nbformat.write(notebook, out_path)
|
|
161
|
+
print(f"Executed notebook written to: {out_path}")
|
|
162
|
+
PY
|
|
@@ -23,18 +23,17 @@ jobs:
|
|
|
23
23
|
|
|
24
24
|
steps:
|
|
25
25
|
- name: Checkout repository
|
|
26
|
-
uses: actions/checkout@
|
|
26
|
+
uses: actions/checkout@v5
|
|
27
27
|
|
|
28
28
|
- name: Initialize CodeQL
|
|
29
|
-
uses: github/codeql-action/init@
|
|
29
|
+
uses: github/codeql-action/init@v4
|
|
30
30
|
with:
|
|
31
31
|
languages: ${{ matrix.language }}
|
|
32
32
|
|
|
33
33
|
- name: Autobuild
|
|
34
|
-
uses: github/codeql-action/autobuild@
|
|
34
|
+
uses: github/codeql-action/autobuild@v4
|
|
35
35
|
|
|
36
36
|
- name: Perform CodeQL Analysis
|
|
37
|
-
uses: github/codeql-action/analyze@
|
|
37
|
+
uses: github/codeql-action/analyze@v4
|
|
38
38
|
with:
|
|
39
39
|
category: "/language:${{ matrix.language }}"
|
|
40
|
-
|
|
@@ -14,7 +14,7 @@ jobs:
|
|
|
14
14
|
permissions:
|
|
15
15
|
contents: read
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v5
|
|
18
18
|
- name: Verify PyPI token is set
|
|
19
19
|
run: |
|
|
20
20
|
if [ -z "${{ secrets.PYPI_API_TOKEN }}" ]; then
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
echo "See: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions"
|
|
23
23
|
exit 1
|
|
24
24
|
fi
|
|
25
|
-
- uses: actions/setup-python@
|
|
25
|
+
- uses: actions/setup-python@v6
|
|
26
26
|
with:
|
|
27
27
|
python-version: '3.13'
|
|
28
28
|
- name: Build artifacts
|
|
@@ -45,8 +45,7 @@ when writing or refracturing Python scripts, apply those Rules :
|
|
|
45
45
|
|
|
46
46
|
- `src/lib_cli_exit_tools/`: Python package.
|
|
47
47
|
- `scripts/`: shared automation (build/test/release) reused from scaffold.
|
|
48
|
-
- `
|
|
49
|
-
- `tests/`: placeholder suite skipping until logging features exist.
|
|
48
|
+
- `tests/`: behaviour/spec integration suite covering CLI, metadata, and automation workflows.
|
|
50
49
|
|
|
51
50
|
### Versioning & Releases
|
|
52
51
|
|
|
@@ -60,7 +59,7 @@ when writing or refracturing Python scripts, apply those Rules :
|
|
|
60
59
|
|
|
61
60
|
| Target | One-line description |
|
|
62
61
|
|-------------------|--------------------------------------------------------------------------------|
|
|
63
|
-
| `build` | Build wheel/sdist
|
|
62
|
+
| `build` | Build wheel/sdist; validates the Python artifacts locally. |
|
|
64
63
|
| `bump` | Bump version (VERSION=X.Y.Z or PART=major\|minor\|patch) and update changelog. |
|
|
65
64
|
| `bump-major` | Increment major version ((X+1).0.0). |
|
|
66
65
|
| `bump-minor` | Increment minor version (X.Y.Z → X.(Y+1).0). |
|
|
@@ -71,7 +70,7 @@ when writing or refracturing Python scripts, apply those Rules :
|
|
|
71
70
|
| `install` | Editable install. |
|
|
72
71
|
| `menu` | Interactive TUI menu (make menu). |
|
|
73
72
|
| `push` | Commit changes once and push to GitHub (no CI monitoring). |
|
|
74
|
-
| `release` | Tag vX.Y.Z, push,
|
|
73
|
+
| `release` | Tag vX.Y.Z, push, and run the release helper (PyPI upload when configured). |
|
|
75
74
|
| `run` | Run module entry (`python -m ... --help`). |
|
|
76
75
|
| `test` | Lint, format, type-check, run tests with coverage, upload to Codecov. |
|
|
77
76
|
| `version-current` | Print current version from `pyproject.toml`. |
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# AGENTS README — Using `lib_cli_exit_tools`
|
|
2
|
+
|
|
3
|
+
This guide targets coding agents (Codex, Claude-CLI, etc.) that need to consume the
|
|
4
|
+
`lib_cli_exit_tools` library while building or refactoring Python CLIs. It focuses
|
|
5
|
+
on runtime usage rather than project maintenance.
|
|
6
|
+
|
|
7
|
+
## 1. Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install lib_cli_exit_tools
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If you are operating inside a virtual environment, ensure the environment is
|
|
14
|
+
active before installing so the console scripts (`lib_cli_exit_tools`,
|
|
15
|
+
`cli-exit-tools`, `lib-cli-exit-tools`) land on PATH.
|
|
16
|
+
|
|
17
|
+
## 2. Minimal Usage
|
|
18
|
+
|
|
19
|
+
Wrap an existing Click command with the bundled orchestration so signals and
|
|
20
|
+
exit codes work consistently:
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import click
|
|
26
|
+
from lib_cli_exit_tools import run_cli
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@click.command()
|
|
30
|
+
def hello() -> None:
|
|
31
|
+
click.echo("Hello world")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
raise SystemExit(run_cli(hello))
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`run_cli` intercepts `SIGINT`, `SIGTERM`/`SIGBREAK`, and standard exceptions,
|
|
39
|
+
translating them into predictable exit codes for shells and calling scripts.
|
|
40
|
+
|
|
41
|
+
## 3. Temporary Overrides with `cli_session`
|
|
42
|
+
|
|
43
|
+
Enable traceback output or other configuration for a single invocation:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from collections.abc import Sequence
|
|
47
|
+
from lib_cli_exit_tools import cli_session
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def run_command(argv: Sequence[str] | None = None, *, verbose: bool = False) -> int:
|
|
51
|
+
overrides = {"traceback": verbose}
|
|
52
|
+
with cli_session(overrides=overrides) as execute:
|
|
53
|
+
return execute(hello, argv=argv)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Outside the `with` block, global configuration reverts to its previous state,
|
|
57
|
+
so you can safely toggle verbose diagnostics based on flags or environment.
|
|
58
|
+
|
|
59
|
+
## 4. Global Configuration Surface
|
|
60
|
+
|
|
61
|
+
The module-level `config` object exposes runtime switches. Mutate them once
|
|
62
|
+
at process startup if you need persistent behaviour changes:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from lib_cli_exit_tools import config
|
|
66
|
+
|
|
67
|
+
config.traceback = True # always render full tracebacks
|
|
68
|
+
config.exit_code_style = "sysexits" # use BSD sysexits mapping
|
|
69
|
+
config.broken_pipe_exit_code = 0 # treat BrokenPipeError as success
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For scoped overrides (tests, nested CLIs), prefer `config_overrides`:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from lib_cli_exit_tools import config_overrides
|
|
76
|
+
|
|
77
|
+
with config_overrides(traceback=True, traceback_force_color=True):
|
|
78
|
+
run_something()
|
|
79
|
+
# state restored automatically
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 5. Direct Exit-Code Translation
|
|
83
|
+
|
|
84
|
+
If you catch exceptions manually, reuse the resolver:
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from lib_cli_exit_tools import get_system_exit_code, print_exception_message
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
risky_operation()
|
|
91
|
+
except Exception as exc:
|
|
92
|
+
print_exception_message()
|
|
93
|
+
raise SystemExit(get_system_exit_code(exc))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 6. Custom Signal Handling
|
|
97
|
+
|
|
98
|
+
You can supply your own `SignalSpec` list and installer when calling `run_cli`:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import signal
|
|
102
|
+
from contextlib import ExitStack
|
|
103
|
+
|
|
104
|
+
from lib_cli_exit_tools import SignalSpec, default_signal_specs, run_cli
|
|
105
|
+
|
|
106
|
+
CUSTOM_SIG = getattr(signal, "SIGUSR1", None)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def custom_specs() -> list[SignalSpec]:
|
|
110
|
+
specs = default_signal_specs()
|
|
111
|
+
if CUSTOM_SIG is not None:
|
|
112
|
+
specs.append(
|
|
113
|
+
SignalSpec(
|
|
114
|
+
signum=CUSTOM_SIG,
|
|
115
|
+
exception=RuntimeError,
|
|
116
|
+
message="USR1 received",
|
|
117
|
+
exit_code=75,
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
return specs
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def install_specs(specs: list[SignalSpec] | None) -> callable[[], None]:
|
|
124
|
+
stack = ExitStack()
|
|
125
|
+
for spec in specs or []:
|
|
126
|
+
def _handler(signum: int, frame: object | None, *, spec: SignalSpec = spec) -> None:
|
|
127
|
+
raise spec.exception(spec.message)
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
previous = signal.getsignal(spec.signum)
|
|
131
|
+
signal.signal(spec.signum, _handler)
|
|
132
|
+
except OSError:
|
|
133
|
+
continue
|
|
134
|
+
stack.callback(signal.signal, spec.signum, previous)
|
|
135
|
+
return stack.close
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
exit_code = run_cli(
|
|
139
|
+
hello,
|
|
140
|
+
signal_specs=custom_specs(),
|
|
141
|
+
signal_installer=install_specs,
|
|
142
|
+
)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The installer must return a zero-argument callable that restores prior handlers.
|
|
146
|
+
`run_cli` invokes it automatically during teardown.
|
|
147
|
+
|
|
148
|
+
## 7. Testing Your Integration
|
|
149
|
+
|
|
150
|
+
When you wire the library into your project, add behaviour tests that mirror the
|
|
151
|
+
bundled suite:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
PYTHONPATH=src python -m pytest tests/test_my_cli.py
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Focus on asserting exit codes and stderr text under failures or signals.
|
|
158
|
+
|
|
159
|
+
## 8. Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Symptom | Fix |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| Tracebacks not showing despite `--traceback` | Ensure you call `cli_session` or set `config.traceback = True` before running the command. |
|
|
164
|
+
| SIGINT doesn’t produce exit code 130 | Verify the command is executed via `run_cli` and no other signal handlers override the one supplied by the library. |
|
|
165
|
+
| Windows CTRL+BREAK ignored | Include `SignalSpec` for `SIGBREAK` or rely on `default_signal_specs()` which already accounts for it when available. |
|
|
166
|
+
| “Unknown configuration fields” error | Check the keyword names passed into `config_overrides`; they must match the dataclass fields (`traceback`, `exit_code_style`, `broken_pipe_exit_code`, `traceback_force_color`). |
|
|
167
|
+
|
|
168
|
+
## 9. Need a Quick Reference?
|
|
169
|
+
|
|
170
|
+
- **run_cli**: Orchestrates Click commands with signal-aware exit handling.
|
|
171
|
+
- **cli_session**: Context manager wrapping `run_cli` that applies temporary config overrides and returns a callable bound to the standard exception handler.
|
|
172
|
+
- **config/reset_config**: Global defaults; call `reset_config()` in tests to avoid leakage.
|
|
173
|
+
- **get_system_exit_code**: Standalone mapping from `BaseException` to numeric exit codes.
|
|
174
|
+
- **SignalSpec + default_signal_specs**: Build or extend the signal handling roster for `run_cli`.
|
|
175
|
+
|
|
176
|
+
Use these primitives to retrofit deterministic exit behaviour into any Click-based CLI your agent constructs.
|
|
@@ -3,6 +3,26 @@
|
|
|
3
3
|
All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [2.0.0] - 2025-10-12
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- Modernised runtime and automation tooling to rely on native Python 3.13 APIs, including updated signal adapters and simplified exception rendering.
|
|
10
|
+
- Raised development dependency floors (codecov-cli, import-linter, bandit, pip-audit, pyright, pytest, pytest-asyncio, ruff, textual) to the latest stable releases.
|
|
11
|
+
- Refined documentation to reflect the current behaviour-focused test suite and active automation scripts.
|
|
12
|
+
- Brought script modules and metadata fallbacks back into coverage reporting and removed ad-hoc sys.path manipulation from the automation launcher.
|
|
13
|
+
- Adopted PEP 604 union typing throughout the CLI runner and facade helpers to underline the Python 3.13-only baseline and to keep function signatures declarative.
|
|
14
|
+
- Updated packaging metadata to require `build>=1.3.0`, `pytest-cov>=7.0.0`, `twine>=6.2.0`, and `hatchling>=1.27.0`, matching the latest stable releases verified via `pip index`.
|
|
15
|
+
- Restored real signal integration coverage and Hypothesis-backed exit-code property tests to guard regression-prone paths.
|
|
16
|
+
|
|
17
|
+
### Removed
|
|
18
|
+
- Retired Conda/Homebrew/Nix packaging automation and updated documentation to reflect the PyPI-only distribution path.
|
|
19
|
+
- Dropped legacy ImportError-based script fallbacks now that automation entry points run as a proper package.
|
|
20
|
+
|
|
21
|
+
### Documentation
|
|
22
|
+
- Highlighted the Python 3.13 baseline, dependency refresh, and updated CI action set in the README.
|
|
23
|
+
- Documented the revived signal integration suite and property-based tests in the system module reference.
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
## [1.6.0] - 2025-10-08
|
|
7
27
|
|
|
8
28
|
### Added
|
|
@@ -21,22 +21,11 @@ Thanks for helping improve lib_cli_exit_tools! This guide keeps changes small, s
|
|
|
21
21
|
- Honour the documented system prompts: small functions, type hints throughout, and doctests that explain intent.
|
|
22
22
|
- No sweeping refactors in unrelated modules; keep pull requests reviewable.
|
|
23
23
|
|
|
24
|
-
## 4) Build &
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
- `make test` and `make push` run a sync step that aligns packaging files under `packaging/` with `pyproject.toml`.
|
|
30
|
-
- `make bump` also updates packaging files when bumping the version.
|
|
31
|
-
- What gets synced from `pyproject.toml`:
|
|
32
|
-
- Version and minimum Python (`requires-python`).
|
|
33
|
-
- Runtime dependencies (from `[project].dependencies`).
|
|
34
|
-
- Conda: rewrites `requirements: run` with `python >=X.Y` plus all deps (exact `==` pins kept; ranges copied as-is).
|
|
35
|
-
- Homebrew: ensures a `resource "<dep>"` for each dep; if pinned, uses that version; otherwise pins to the latest PyPI release, updating `url` + `sha256`.
|
|
36
|
-
- Nix: updates the package version, `pkgs.pythonXYZPackages`/`pkgs.pythonXYZ` to match the min Python, and `propagatedBuildInputs` to include all deps as `pypkgs.<name>`.
|
|
37
|
-
- Network note: Homebrew resource updates fetch PyPI metadata; if offline, those updates may be skipped.
|
|
38
|
-
- If packaging drifts, run: `python scripts/bump_version.py --sync-packaging`.
|
|
39
|
-
- CI enforces consistency on tags via a `packaging-consistency` job.
|
|
24
|
+
## 4) Build & Release
|
|
25
|
+
|
|
26
|
+
- `make build` produces the wheel/sdist that CI later uploads to PyPI.
|
|
27
|
+
- `make release` tags the repository and runs the release helper (publishes to PyPI when `PYPI_API_TOKEN` is configured).
|
|
28
|
+
- Third-party packaging targets (Conda, Homebrew, Nix) are no longer maintained.
|
|
40
29
|
|
|
41
30
|
## 5) Tests & Style
|
|
42
31
|
|
|
@@ -18,7 +18,7 @@ This guide aggregates everything maintainers need for building, testing, and rel
|
|
|
18
18
|
| `bump-major` | Bump major version ((X+1).0.0) |
|
|
19
19
|
| `clean` | Remove caches, build artifacts, and coverage |
|
|
20
20
|
| `push` | Commit all changes once and push to GitHub (no CI monitoring) |
|
|
21
|
-
| `build` | Build wheel/sdist
|
|
21
|
+
| `build` | Build wheel/sdist artifacts for PyPI distribution |
|
|
22
22
|
| `menu` | Interactive TUI to run targets and edit parameters (requires dev dep: textual) |
|
|
23
23
|
|
|
24
24
|
### Target Parameters (env vars)
|
|
@@ -36,7 +36,7 @@ This guide aggregates everything maintainers need for building, testing, and rel
|
|
|
36
36
|
- `TEST_VERBOSE=1` — echo each command executed by the test harness
|
|
37
37
|
- Also respects `CODECOV_TOKEN` when needed for uploads
|
|
38
38
|
- `run`
|
|
39
|
-
- No parameters via `make` (always shows `--help`). For custom args: `python scripts
|
|
39
|
+
- No parameters via `make` (always shows `--help`). For custom args: `python -m scripts.run_cli -- <args>`.
|
|
40
40
|
- `version-current`
|
|
41
41
|
- No parameters
|
|
42
42
|
- `bump`
|
|
@@ -52,10 +52,10 @@ This guide aggregates everything maintainers need for building, testing, and rel
|
|
|
52
52
|
- `push`
|
|
53
53
|
- `REMOTE=<name>` (default: `origin`) — git remote to push to
|
|
54
54
|
- `build`
|
|
55
|
-
- No parameters via `make`. Advanced:
|
|
55
|
+
- No parameters via `make`. Advanced: call `python -m scripts.build` directly for custom flows.
|
|
56
56
|
- `release`
|
|
57
57
|
- `REMOTE=<name>` (default: `origin`) — git remote to push to
|
|
58
|
-
- Advanced (via script): `python scripts
|
|
58
|
+
- Advanced (via script): `python -m scripts.release --retries 5 --retry-wait 3.0`
|
|
59
59
|
|
|
60
60
|
## Interactive Menu (Textual)
|
|
61
61
|
|
|
@@ -78,7 +78,7 @@ make menu
|
|
|
78
78
|
|
|
79
79
|
- `test`: single entry point for local CI — runs ruff lint + format check, pyright, pytest (including doctests) with coverage (enabled by default), and uploads coverage to Codecov if configured (reads `.env`).
|
|
80
80
|
- Auto‑bootstrap: `make test` will try to install dev tools (`pip install -e .[dev]`) if `ruff`/`pyright`/`pytest` are missing. Set `SKIP_BOOTSTRAP=1` to skip this behavior.
|
|
81
|
-
- `build`:
|
|
81
|
+
- `build`: creates Python wheel/sdist artifacts that match what CI uploads to PyPI.
|
|
82
82
|
- `install`/`dev`/`user-install`: common install flows for editable or per‑user installs.
|
|
83
83
|
- `version-current`: prints current version from `pyproject.toml`.
|
|
84
84
|
- `bump`: updates `pyproject.toml` version and inserts a new section in `CHANGELOG.md`. Use `VERSION=X.Y.Z make bump` or `make bump-minor`/`bump-major`/`bump-patch`.
|
|
@@ -92,8 +92,20 @@ make test # ruff + pyright + pytest + coverage (default ON)
|
|
|
92
92
|
SKIP_BOOTSTRAP=1 make test # skip auto-install of dev deps
|
|
93
93
|
COVERAGE=off make test # disable coverage locally
|
|
94
94
|
COVERAGE=on make test # force coverage and generate coverage.xml/codecov.xml
|
|
95
|
+
make coverage # python -m coverage run -m pytest -vv (no coverage CLI needed)
|
|
95
96
|
```
|
|
96
97
|
|
|
98
|
+
The same helper can be run directly without Make:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python -m scripts coverage
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The coverage helper sets `COVERAGE_NO_SQL=1` before launching pytest so the
|
|
105
|
+
legacy file-backed coverage data store is used instead of SQLite. This sidesteps
|
|
106
|
+
the "database is locked" failures that occur when multiple runs touch the same
|
|
107
|
+
workspace.
|
|
108
|
+
|
|
97
109
|
The pytest suite uses OS markers (`skipif` guards) to exercise POSIX-, Windows-,
|
|
98
110
|
and platform-agnostic behaviours. Run `make test` on every platform you ship to
|
|
99
111
|
keep the signal-handling guarantees honest.
|
|
@@ -104,16 +116,6 @@ keep the signal-handling guarantees honest.
|
|
|
104
116
|
- For private repos, set `CODECOV_TOKEN` (see `.env.example`) or export it in your shell.
|
|
105
117
|
- For public repos, a token is typically not required.
|
|
106
118
|
|
|
107
|
-
## Packaging Sync (Conda/Brew/Nix)
|
|
108
|
-
|
|
109
|
-
- `make test` and `make push` automatically align the packaging skeletons in `packaging/` with the current `pyproject.toml`:
|
|
110
|
-
- Conda: updates `{% set version = "X.Y.Z" %}` and both `python >=X.Y` constraints to match `requires-python`.
|
|
111
|
-
- Homebrew: updates the source URL tag to `vX.Y.Z` and sets `depends_on "python@X.Y"` to match `requires-python`.
|
|
112
|
-
- Nix: updates the package `version`, example `rev = "vX.Y.Z"`, and switches `pkgs.pythonXYZPackages` / `pkgs.pythonXYZ` to match the minimum Python version from `requires-python`.
|
|
113
|
-
- Local `make test` runs skip the sync unless you export `ENFORCE_PACKAGING_SYNC=1` (CI enables it automatically).
|
|
114
|
-
- To run just the sync without bumping versions: `python scripts/bump_version.py --sync-packaging`.
|
|
115
|
-
- On release tags (`v*.*.*`), CI validates that packaging files are consistent with `pyproject.toml` and will fail if they drift.
|
|
116
|
-
|
|
117
119
|
## Versioning & Metadata
|
|
118
120
|
|
|
119
121
|
- Single source of truth for package metadata is `pyproject.toml` (`[project]`).
|
|
@@ -121,21 +123,11 @@ keep the signal-handling guarantees honest.
|
|
|
121
123
|
- Do not duplicate the version in code; bump only `pyproject.toml` and update `CHANGELOG.md`.
|
|
122
124
|
- Console script name is discovered from entry points; defaults to `lib_cli_exit_tools`.
|
|
123
125
|
|
|
124
|
-
## Packaging Skeletons
|
|
125
|
-
|
|
126
|
-
Starter files for package managers live under `packaging/`:
|
|
127
|
-
|
|
128
|
-
- Conda: `packaging/conda/recipe/meta.yaml` (update version + sha256)
|
|
129
|
-
- Homebrew: `packaging/brew/Formula/lib-cli-exit-tools.rb` (fill sha256 and vendored resources)
|
|
130
|
-
- Nix: `packaging/nix/flake.nix` (use working tree or pin to GitHub rev with sha256)
|
|
131
|
-
|
|
132
|
-
These are templates; fill placeholders (e.g., sha256) before publishing. Version and Python constraints are auto-synced from `pyproject.toml` by `make test`/`make push` and during version bumps.
|
|
133
|
-
|
|
134
126
|
## CI & Publishing
|
|
135
127
|
|
|
136
128
|
GitHub Actions workflows are included:
|
|
137
129
|
|
|
138
|
-
- `.github/workflows/ci.yml` — lint/type/test, build wheel/sdist, verify pipx
|
|
130
|
+
- `.github/workflows/ci.yml` — lint/type/test, build wheel/sdist, and verify pipx/uv installs.
|
|
139
131
|
- `.github/workflows/release.yml` — on tags `v*.*.*`, builds artifacts and publishes to PyPI when `PYPI_API_TOKEN` secret is set.
|
|
140
132
|
|
|
141
133
|
To publish a release:
|
|
@@ -144,4 +136,4 @@ To publish a release:
|
|
|
144
136
|
3. Ensure `PYPI_API_TOKEN` secret is configured in the repo.
|
|
145
137
|
4. Release workflow uploads wheel/sdist to PyPI.
|
|
146
138
|
|
|
147
|
-
|
|
139
|
+
Third-party packaging targets (Conda, Homebrew, Nix) were removed; distribution now flows solely through PyPI.
|
|
@@ -6,7 +6,7 @@ This document collects every supported installation path for `lib_cli_exit_tools
|
|
|
6
6
|
pip install lib_cli_exit_tools
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
The sections below cover more specialised workflows, from editable installs to
|
|
9
|
+
The sections below cover more specialised workflows, from editable installs to alternate Python tooling.
|
|
10
10
|
|
|
11
11
|
## Table of Contents
|
|
12
12
|
- [Supported Python Versions](#supported-python-versions)
|
|
@@ -19,8 +19,6 @@ The sections below cover more specialised workflows, from editable installs to p
|
|
|
19
19
|
- [Installing from local artifacts](#installing-from-local-artifacts)
|
|
20
20
|
- [Poetry / PDM](#poetry--pdm)
|
|
21
21
|
- [Install directly from Git](#install-directly-from-git)
|
|
22
|
-
- [Conda / Mamba environments](#conda--mamba-environments)
|
|
23
|
-
- [System package managers](#system-package-managers)
|
|
24
22
|
- [Path configuration](#path-configuration)
|
|
25
23
|
- [Troubleshooting](#troubleshooting)
|
|
26
24
|
- [PEP 668 “externally managed environment” errors](#pep-668-externally-managed-environment-errors)
|
|
@@ -122,25 +120,7 @@ CI systems or early adopters can install from a specific revision:
|
|
|
122
120
|
pip install "git+https://github.com/bitranox/lib_cli_exit_tools@vX.Y.Z#egg=lib_cli_exit_tools"
|
|
123
121
|
```
|
|
124
122
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Create a dedicated Conda environment and install via `pip` inside it:
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
mamba create -n cli-exit python=3.13 pip
|
|
131
|
-
mamba activate cli-exit
|
|
132
|
-
pip install lib_cli_exit_tools
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### System package managers
|
|
136
|
-
|
|
137
|
-
Packages may be published for platform-native installers:
|
|
138
|
-
|
|
139
|
-
- **Homebrew (macOS):** `brew install lib_cli_exit_tools`
|
|
140
|
-
- **Nix:** `nix run github:bitranox/lib_cli_exit_tools` or `nix develop` with the provided flake
|
|
141
|
-
- **Deb/RPM:** build with `fpm` using the project’s `packaging/` scripts
|
|
142
|
-
|
|
143
|
-
Check the repository’s release notes for the current distribution status.
|
|
123
|
+
We distribute via PyPI only. If you prefer isolated CLI installs, use tools such as `pipx` or `uv tool install` with the published wheel/sdist. Third-party packaging recipes (Conda, Homebrew, Nix) have been removed.
|
|
144
124
|
|
|
145
125
|
## Path configuration
|
|
146
126
|
|
|
@@ -169,7 +149,7 @@ error: externally-managed-environment
|
|
|
169
149
|
|
|
170
150
|
**Fix:**
|
|
171
151
|
- Create a virtual environment (`python -m venv .venv`) and install inside it, or
|
|
172
|
-
- Use `pipx`, `
|
|
152
|
+
- Use `pipx`, `uv`, or another isolated environment manager.
|
|
173
153
|
|
|
174
154
|
### Missing command on PATH
|
|
175
155
|
|
|
@@ -180,5 +160,3 @@ If `lib_cli_exit_tools --help` returns “command not found”, confirm that the
|
|
|
180
160
|
Set `lib_cli_exit_tools.config.traceback_force_color = True` in your application to force Rich to emit coloured tracebacks even when stderr is not detected as a TTY. Alternatively, export `RICH_FORCE_TERMINAL=1` before running the CLI.
|
|
181
161
|
|
|
182
162
|
---
|
|
183
|
-
|
|
184
|
-
For additional environment automation (Conda, Nix, Homebrew formulas), consult the scripts under `packaging/` and the Makefile targets described in `README.md`.
|