lib-cli-exit-tools 1.3.0__tar.gz → 1.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/CHANGELOG.md +4 -0
  2. lib_cli_exit_tools-1.3.1/INSTALL.md +184 -0
  3. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/PKG-INFO +92 -91
  4. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/README.md +91 -90
  5. lib_cli_exit_tools-1.3.1/docs/system-design/module_reference.md +251 -0
  6. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/packaging/brew/Formula/lib-cli-exit-tools.rb +1 -1
  7. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/packaging/conda/recipe/meta.yaml +1 -1
  8. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/packaging/nix/flake.nix +1 -1
  9. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/pyproject.toml +1 -1
  10. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/__init__.py +1 -1
  11. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +26 -4
  12. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/tests/test_lib_extra.py +34 -0
  13. lib_cli_exit_tools-1.3.0/docs/system-design/reference.md +0 -341
  14. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/.env.example +0 -0
  15. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/.github/workflows/ci.yml +0 -0
  16. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/.github/workflows/codeql.yml +0 -0
  17. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/.github/workflows/release.yml +0 -0
  18. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/.gitignore +0 -0
  19. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/AGENTS.md +0 -0
  20. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/CONTRIBUTING.md +0 -0
  21. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/DEVELOPMENT.md +0 -0
  22. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/LICENSE +0 -0
  23. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/Makefile +0 -0
  24. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/codecov.yml +0 -0
  25. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/notebooks/Quickstart.ipynb +0 -0
  26. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/packaging/README.md +0 -0
  27. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/qlty.toml +0 -0
  28. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/__init__.py +0 -0
  29. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/_utils.py +0 -0
  30. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/build.py +0 -0
  31. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/bump.py +0 -0
  32. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/bump_major.py +0 -0
  33. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/bump_minor.py +0 -0
  34. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/bump_patch.py +0 -0
  35. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/bump_version.py +0 -0
  36. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/clean.py +0 -0
  37. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/dev.py +0 -0
  38. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/generate_nix_flake.py +0 -0
  39. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/install.py +0 -0
  40. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/menu.py +0 -0
  41. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/push.py +0 -0
  42. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/release.py +0 -0
  43. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/run_cli.py +0 -0
  44. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/test.py +0 -0
  45. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/scripts/version_current.py +0 -0
  46. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/__init__conf__.py +0 -0
  47. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/__main__.py +0 -0
  48. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/cli.py +0 -0
  49. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/src/lib_cli_exit_tools/py.typed +0 -0
  50. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/tests/test_cli.py +0 -0
  51. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/tests/test_cli_extra.py +0 -0
  52. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/tests/test_exit_tools.py +0 -0
  53. {lib_cli_exit_tools-1.3.0 → lib_cli_exit_tools-1.3.1}/tests/test_extend_cli.py +0 -0
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.1] - 2025-09-26
4
+
5
+ - patch colored traceback
6
+
3
7
  ## [1.3.0] - 2025-09-25
4
8
 
5
9
  - colored traceback
@@ -0,0 +1,184 @@
1
+ # Installation Guide
2
+
3
+ This document collects every supported installation path for `lib_cli_exit_tools`, plus notes on platform quirks and troubleshooting. If you only need the standard release from PyPI, see the short "Install" section in `README.md` or run:
4
+
5
+ ```bash
6
+ pip install lib_cli_exit_tools
7
+ ```
8
+
9
+ The sections below cover more specialised workflows, from editable installs to package-manager builds.
10
+
11
+ ## Table of Contents
12
+ - [Supported Python Versions](#supported-python-versions)
13
+ - [Installation Flows](#installation-flows)
14
+ - [PyPI (latest release)](#pypi-latest-release)
15
+ - [Editable install in a virtual environment](#editable-install-in-a-virtual-environment)
16
+ - [Per-user installs (`pip --user`)](#per-user-installs-pip---user)
17
+ - [pipx](#pipx)
18
+ - [uv](#uv)
19
+ - [Installing from local artifacts](#installing-from-local-artifacts)
20
+ - [Poetry / PDM](#poetry--pdm)
21
+ - [Install directly from Git](#install-directly-from-git)
22
+ - [Conda / Mamba environments](#conda--mamba-environments)
23
+ - [System package managers](#system-package-managers)
24
+ - [Path configuration](#path-configuration)
25
+ - [Troubleshooting](#troubleshooting)
26
+ - [PEP 668 “externally managed environment” errors](#pep-668-externally-managed-environment-errors)
27
+ - [Missing command on PATH](#missing-command-on-path)
28
+ - [Colour output not appearing](#colour-output-not-appearing)
29
+
30
+ ## Supported Python Versions
31
+
32
+ `lib_cli_exit_tools` targets Python 3.9 and newer. Wheels are published for CPython on Linux, macOS, and Windows. For alternative interpreters (PyPy) install from source using `pip install lib_cli_exit_tools`.
33
+
34
+ ## Installation Flows
35
+
36
+ ### PyPI (latest release)
37
+
38
+ The quickest path for production use:
39
+
40
+ ```bash
41
+ pip install lib_cli_exit_tools
42
+ # Pin to a specific release when reproducibility matters
43
+ pip install "lib_cli_exit_tools==1.1.0"
44
+ # Upgrade later
45
+ pip install --upgrade lib_cli_exit_tools
46
+ ```
47
+
48
+ This command registers the `lib_cli_exit_tools`, `cli-exit-tools`, and `lib-cli-exit-tools` entry points on your PATH.
49
+
50
+ ### Editable install in a virtual environment
51
+
52
+ Use this flow when developing the library locally:
53
+
54
+ ```bash
55
+ python -m venv .venv
56
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
57
+ pip install -e .[dev]
58
+ # Alternatively, install runtime dependencies only
59
+ pip install .
60
+ ```
61
+
62
+ ### Per-user installs (`pip --user`)
63
+
64
+ Install to the user site-packages directory without creating a virtual environment:
65
+
66
+ ```bash
67
+ pip install --user lib_cli_exit_tools
68
+ ```
69
+
70
+ Ensure `~/.local/bin` (POSIX) or `%APPDATA%\Python\PythonXY\Scripts` (Windows) is on your PATH. This approach respects [PEP 668](https://peps.python.org/pep-0668/)—avoid running it in system-managed Python installs that disallow modifications.
71
+
72
+ ### pipx
73
+
74
+ `pipx` isolates CLI tools in dedicated environments, making upgrades easy:
75
+
76
+ ```bash
77
+ pipx install lib_cli_exit_tools
78
+ pipx upgrade lib_cli_exit_tools
79
+ # Install directly from a tagged release or commit
80
+ pipx install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0"
81
+ ```
82
+
83
+ ### uv
84
+
85
+ [uv](https://github.com/astral-sh/uv) provides fast installs and execution:
86
+
87
+ ```bash
88
+ uv pip install -e .[dev]
89
+ uv tool install lib_cli_exit_tools
90
+ uvx lib_cli_exit_tools --help
91
+ ```
92
+
93
+ ### Installing from local artifacts
94
+
95
+ Build a wheel or sdist locally and install it in offline environments:
96
+
97
+ ```bash
98
+ python -m build
99
+ pip install dist/lib_cli_exit_tools-*.whl
100
+ pip install dist/lib_cli_exit_tools-*.tar.gz
101
+ ```
102
+
103
+ ### Poetry / PDM
104
+
105
+ Add the library to a project managed by Poetry or PDM:
106
+
107
+ ```bash
108
+ # Poetry
109
+ poetry add lib_cli_exit_tools
110
+ poetry install
111
+
112
+ # PDM
113
+ pdm add lib_cli_exit_tools
114
+ pdm install
115
+ ```
116
+
117
+ ### Install directly from Git
118
+
119
+ CI systems or early adopters can install from a specific revision:
120
+
121
+ ```bash
122
+ pip install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0#egg=lib_cli_exit_tools"
123
+ ```
124
+
125
+ ### Conda / Mamba environments
126
+
127
+ Create a dedicated Conda environment and install via `pip` inside it:
128
+
129
+ ```bash
130
+ mamba create -n cli-exit python=3.12 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.
144
+
145
+ ## Path configuration
146
+
147
+ After installation the following commands should resolve:
148
+
149
+ - `lib_cli_exit_tools`
150
+ - `cli-exit-tools`
151
+ - `python -m lib_cli_exit_tools`
152
+
153
+ If you installed inside a virtual environment, activate it before running the commands. For user installs, ensure the relevant `bin`/`Scripts` directory is included in your PATH:
154
+
155
+ - Linux/macOS venv: `<venv>/bin`
156
+ - Linux/macOS user site: `~/.local/bin`
157
+ - Windows venv: `<venv>\Scripts`
158
+ - Windows user site: `%APPDATA%\Python\PythonXY\Scripts`
159
+
160
+ ## Troubleshooting
161
+
162
+ ### PEP 668 “externally managed environment” errors
163
+
164
+ Some OS distributions (Ubuntu, Fedora, Debian) mark the system Python as externally managed. Running `pip install` directly into that interpreter raises an error similar to:
165
+
166
+ ```
167
+ error: externally-managed-environment
168
+ ```
169
+
170
+ **Fix:**
171
+ - Create a virtual environment (`python -m venv .venv`) and install inside it, or
172
+ - Use `pipx`, `conda`, `uv`, or another isolated environment manager.
173
+
174
+ ### Missing command on PATH
175
+
176
+ If `lib_cli_exit_tools --help` returns “command not found”, confirm that the installation location is on PATH. The most common fix is adding `~/.local/bin` (POSIX) or `%APPDATA%\Python\PythonXY\Scripts` (Windows) to your PATH environment variable, then re-opening the shell.
177
+
178
+ ### Colour output not appearing
179
+
180
+ 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
+
182
+ ---
183
+
184
+ For additional environment automation (Conda, Nix, Homebrew formulas), consult the scripts under `packaging/` and the Makefile targets described in `README.md`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lib_cli_exit_tools
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: CLI exit handling helpers: clean signals, exit codes, and error printing
5
5
  Project-URL: Homepage, https://github.com/bitranox/lib_cli_exit_tools
6
6
  Project-URL: Repository, https://github.com/bitranox/lib_cli_exit_tools.git
@@ -50,93 +50,11 @@ Small helpers for robust CLI exit handling:
50
50
 
51
51
  ## Install
52
52
 
53
- Pick one of the options below. All methods register the `lib_cli_exit_tools`, `cli-exit-tools`, and `lib-cli-exit-tools` commands on your PATH.
54
-
55
- ### 0) PyPI (latest release)
56
-
57
53
  ```bash
58
54
  pip install lib_cli_exit_tools
59
- # Pin to the current release if you need reproducibility
60
- pip install "lib_cli_exit_tools==1.1.0"
61
- # Upgrade to the newest release later
62
- pip install --upgrade lib_cli_exit_tools
63
- ```
64
-
65
- ### 1) Standard virtualenv (pip)
66
-
67
- ```bash
68
- python -m venv .venv
69
- source .venv/bin/activate # Windows: .venv\\Scripts\\activate
70
- pip install -e .[dev] # dev install
71
- # or for runtime only:
72
- pip install .
73
- ```
74
-
75
- ### 2) Per-user (no venv)
76
-
77
- ```bash
78
- pip install --user .
79
- ```
80
-
81
- Note: respects PEP 668; avoid on system Python if “externally managed”. Ensure `~/.local/bin` (POSIX) is on PATH.
82
-
83
- ### 3) pipx (isolated, recommended for end users)
84
-
85
- ```bash
86
- pipx install .
87
- pipx upgrade lib_cli_exit_tools
88
- # From Git tag/commit:
89
- pipx install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0"
90
- ```
91
-
92
- ### 4) uv (fast installer/runner)
93
-
94
- ```bash
95
- uv pip install -e .[dev]
96
- uv tool install .
97
- uvx lib_cli_exit_tools --help
98
- ```
99
-
100
- ### 5) From artifacts
101
-
102
- ```bash
103
- python -m build
104
- pip install dist/lib_cli_exit_tools-*.whl
105
- pip install dist/lib_cli_exit_tools-*.tar.gz # sdist
106
- ```
107
-
108
- ### 6) Poetry / PDM (project-managed envs)
109
-
110
- ```bash
111
- # Poetry
112
- poetry add lib_cli_exit_tools # as dependency
113
- poetry install # for local dev
114
-
115
- # PDM
116
- pdm add lib_cli_exit_tools
117
- pdm install
118
- ```
119
-
120
- ### 7) From Git via pip (CI-friendly)
121
-
122
- ```bash
123
- pip install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0#egg=lib_cli_exit_tools"
124
55
  ```
125
56
 
126
- ### 8) Conda/mamba (optional)
127
-
128
- ```bash
129
- mamba create -n cli-exit python=3.12 pip
130
- mamba activate cli-exit
131
- pip install .
132
- ```
133
-
134
- ### 9) System package managers (optional distribution)
135
-
136
- - Homebrew formula (macOS): `brew install lib_cli_exit_tools` (if published)
137
- - Nix: flake/package for reproducible installs
138
- - Deb/RPM via `fpm` for OS-native packages
139
-
57
+ See [INSTALL.md](INSTALL.md) for editable installs, pipx/uv, package-manager builds, and troubleshooting tips.
140
58
 
141
59
  ## Usage
142
60
 
@@ -225,6 +143,89 @@ Field reference:
225
143
 
226
144
  Remember that `config` is module-level—if you call the library from multiple threads or embed it in another CLI, configure it once during bootstrap before handing control to user code.
227
145
 
146
+ ## Public API Reference
147
+
148
+ The package re-exports the helpers below via `lib_cli_exit_tools.__all__`. Import them directly with `from lib_cli_exit_tools import …`.
149
+
150
+ ### `config`
151
+ Mutable dataclass-like singleton holding process-wide settings. Configure it during CLI startup.
152
+
153
+ - `traceback` (`bool`): `True` to surface full Python tracebacks; `False` keeps short, coloured summaries.
154
+ - `exit_code_style` (`'errno' | 'sysexits'`): Selects POSIX/Windows errno-style exit codes or BSD `sysexits` semantics.
155
+ - `broken_pipe_exit_code` (`int`): Overrides the exit status for `BrokenPipeError` (default `141`).
156
+ - `traceback_force_color` (`bool`): Forces Rich-coloured tracebacks even when stderr is not a TTY.
157
+
158
+ ### `run_cli(cli, argv=None, *, prog_name=None, signal_specs=None, install_signals=True) -> int`
159
+ Wrap a Click command or group so every invocation shares the same signal handling and exit-code policy. Returns the numeric exit code instead of exiting the process.
160
+
161
+ Parameters:
162
+ - `cli`: `click.BaseCommand` to execute.
163
+ - `argv`: Optional iterable of CLI arguments (excluding program name).
164
+ - `prog_name`: Override the program name shown in help/version output.
165
+ - `signal_specs`: Iterable of `SignalSpec` objects to customise signal handling; defaults to `default_signal_specs()`.
166
+ - `install_signals`: Set `False` when the host application already manages signal handlers.
167
+
168
+ ### `handle_cli_exception(exc, *, signal_specs=None, echo=None) -> int`
169
+ Translate exceptions raised by Click commands into deterministic exit codes, honouring configured signal mappings and traceback policy.
170
+
171
+ Parameters:
172
+ - `exc`: Exception instance to classify.
173
+ - `signal_specs`: Optional iterable of `SignalSpec` objects for custom signal handling.
174
+ - `echo`: Callable matching `click.echo` signature, allowing custom stderr routing during tests or embedding.
175
+
176
+ ### `get_system_exit_code(exc) -> int`
177
+ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on POSIX/Windows or BSD `sysexits` when enabled).
178
+
179
+ Parameters:
180
+ - `exc`: Exception instance to classify.
181
+
182
+ ### `print_exception_message(trace_back=config.traceback, length_limit=500, stream=None) -> None`
183
+ Emit the active exception using Rich formatting. Produces a coloured traceback when `trace_back` is `True`, otherwise prints a truncated summary in red. Respects `config.traceback_force_color`.
184
+
185
+ Parameters:
186
+ - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
187
+ - `length_limit`: Maximum characters for summary output.
188
+ - `stream`: Target text stream; defaults to `sys.stderr`.
189
+
190
+ ### `flush_streams() -> None`
191
+ Best-effort flush of `sys.stdout` and `sys.stderr`, ensuring buffered output is written before exit.
192
+
193
+ ### `default_signal_specs() -> list[SignalSpec]`
194
+ Return the default signal mapping for the current platform (always includes `SIGINT`, plus `SIGTERM`/`SIGBREAK` when available).
195
+
196
+ ### `install_signal_handlers(specs=None) -> Callable[[], None]`
197
+ Register handlers that raise structured exceptions for the provided specs and return a restoration callback. Invoke the callback (typically in a `finally` block) to restore previous handlers.
198
+
199
+ Parameters:
200
+ - `specs`: Iterable of `SignalSpec` objects; defaults to `default_signal_specs()`.
201
+
202
+ ### `SignalSpec(signum: int, exception: type[BaseException], message: str, exit_code: int)`
203
+ Lightweight dataclass describing how a signal maps to an exception, stderr message, and exit code.
204
+
205
+ Fields:
206
+ - `signum`: Numeric signal value passed to `signal.signal`.
207
+ - `exception`: Exception type raised by the handler.
208
+ - `message`: Human-readable text echoed when the signal fires.
209
+ - `exit_code`: Exit status returned to the OS.
210
+
211
+ ### `CliSignalError` and subclasses
212
+ Hierarchy of marker exceptions raised when signal handlers trigger. Use them to differentiate signal-driven exits from other failures.
213
+
214
+ - `CliSignalError`: Base class.
215
+ - `SigIntInterrupt`: Raised on `SIGINT` (Ctrl+C); maps to exit code `130`.
216
+ - `SigTermInterrupt`: Raised on `SIGTERM`; maps to exit code `143`.
217
+ - `SigBreakInterrupt`: Raised on Windows `SIGBREAK`; maps to exit code `149`.
218
+
219
+ ### `default_signal_specs`, `install_signal_handlers`, and `run_cli` contract summary
220
+ When `run_cli` executes your Click command it will:
221
+ 1. Build a signal spec list (custom or default).
222
+ 2. Optionally install handlers that raise the exceptions above.
223
+ 3. Execute the command with `standalone_mode=False`.
224
+ 4. Funnel any exception through `handle_cli_exception`.
225
+ 5. Restore prior signal handlers and flush streams before returning.
226
+
227
+ This behaviour keeps CLI wiring consistent across projects embedding `lib_cli_exit_tools`.
228
+
228
229
  ### Advanced CLI wiring
229
230
 
230
231
  For larger applications, keep module execution, console scripts, and shared helpers aligned. The snippet below shows how `__main__.py` can catch unexpected errors and map them through `lib_cli_exit_tools` before exiting:
@@ -327,11 +328,11 @@ When installed, the generated console scripts (`lib_cli_exit_tools`, `cli-exit-t
327
328
  - Set `config.exit_code_style = "sysexits"` to map ValueError/TypeError → EX_USAGE(64),
328
329
  FileNotFoundError → EX_NOINPUT(66), PermissionError → EX_NOPERM(77), generic OSError → EX_IOERR(74).
329
330
 
330
- ## Development
331
-
332
- See [DEVELOPMENT.md](DEVELOPMENT.md) for contributor workflows, make targets, packaging sync details, and CI/publishing guidance.
333
-
334
-
335
- ## License
331
+ ## Additional Documentation
336
332
 
337
- MIT
333
+ - [INSTALL](INSTALL.md)
334
+ - [CHANGELOG](CHANGELOG.md)
335
+ - [CONTRIBUTING](CONTRIBUTING.md)
336
+ - [DEVELOPMENT](DEVELOPMENT.md)
337
+ - [MODULE REFERENCE](docs/system-design/module_reference.md)
338
+ - [LICENSE](LICENSE)
@@ -19,93 +19,11 @@ Small helpers for robust CLI exit handling:
19
19
 
20
20
  ## Install
21
21
 
22
- Pick one of the options below. All methods register the `lib_cli_exit_tools`, `cli-exit-tools`, and `lib-cli-exit-tools` commands on your PATH.
23
-
24
- ### 0) PyPI (latest release)
25
-
26
22
  ```bash
27
23
  pip install lib_cli_exit_tools
28
- # Pin to the current release if you need reproducibility
29
- pip install "lib_cli_exit_tools==1.1.0"
30
- # Upgrade to the newest release later
31
- pip install --upgrade lib_cli_exit_tools
32
- ```
33
-
34
- ### 1) Standard virtualenv (pip)
35
-
36
- ```bash
37
- python -m venv .venv
38
- source .venv/bin/activate # Windows: .venv\\Scripts\\activate
39
- pip install -e .[dev] # dev install
40
- # or for runtime only:
41
- pip install .
42
- ```
43
-
44
- ### 2) Per-user (no venv)
45
-
46
- ```bash
47
- pip install --user .
48
- ```
49
-
50
- Note: respects PEP 668; avoid on system Python if “externally managed”. Ensure `~/.local/bin` (POSIX) is on PATH.
51
-
52
- ### 3) pipx (isolated, recommended for end users)
53
-
54
- ```bash
55
- pipx install .
56
- pipx upgrade lib_cli_exit_tools
57
- # From Git tag/commit:
58
- pipx install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0"
59
- ```
60
-
61
- ### 4) uv (fast installer/runner)
62
-
63
- ```bash
64
- uv pip install -e .[dev]
65
- uv tool install .
66
- uvx lib_cli_exit_tools --help
67
- ```
68
-
69
- ### 5) From artifacts
70
-
71
- ```bash
72
- python -m build
73
- pip install dist/lib_cli_exit_tools-*.whl
74
- pip install dist/lib_cli_exit_tools-*.tar.gz # sdist
75
- ```
76
-
77
- ### 6) Poetry / PDM (project-managed envs)
78
-
79
- ```bash
80
- # Poetry
81
- poetry add lib_cli_exit_tools # as dependency
82
- poetry install # for local dev
83
-
84
- # PDM
85
- pdm add lib_cli_exit_tools
86
- pdm install
87
- ```
88
-
89
- ### 7) From Git via pip (CI-friendly)
90
-
91
- ```bash
92
- pip install "git+https://github.com/bitranox/lib_cli_exit_tools@v1.1.0#egg=lib_cli_exit_tools"
93
24
  ```
94
25
 
95
- ### 8) Conda/mamba (optional)
96
-
97
- ```bash
98
- mamba create -n cli-exit python=3.12 pip
99
- mamba activate cli-exit
100
- pip install .
101
- ```
102
-
103
- ### 9) System package managers (optional distribution)
104
-
105
- - Homebrew formula (macOS): `brew install lib_cli_exit_tools` (if published)
106
- - Nix: flake/package for reproducible installs
107
- - Deb/RPM via `fpm` for OS-native packages
108
-
26
+ See [INSTALL.md](INSTALL.md) for editable installs, pipx/uv, package-manager builds, and troubleshooting tips.
109
27
 
110
28
  ## Usage
111
29
 
@@ -194,6 +112,89 @@ Field reference:
194
112
 
195
113
  Remember that `config` is module-level—if you call the library from multiple threads or embed it in another CLI, configure it once during bootstrap before handing control to user code.
196
114
 
115
+ ## Public API Reference
116
+
117
+ The package re-exports the helpers below via `lib_cli_exit_tools.__all__`. Import them directly with `from lib_cli_exit_tools import …`.
118
+
119
+ ### `config`
120
+ Mutable dataclass-like singleton holding process-wide settings. Configure it during CLI startup.
121
+
122
+ - `traceback` (`bool`): `True` to surface full Python tracebacks; `False` keeps short, coloured summaries.
123
+ - `exit_code_style` (`'errno' | 'sysexits'`): Selects POSIX/Windows errno-style exit codes or BSD `sysexits` semantics.
124
+ - `broken_pipe_exit_code` (`int`): Overrides the exit status for `BrokenPipeError` (default `141`).
125
+ - `traceback_force_color` (`bool`): Forces Rich-coloured tracebacks even when stderr is not a TTY.
126
+
127
+ ### `run_cli(cli, argv=None, *, prog_name=None, signal_specs=None, install_signals=True) -> int`
128
+ Wrap a Click command or group so every invocation shares the same signal handling and exit-code policy. Returns the numeric exit code instead of exiting the process.
129
+
130
+ Parameters:
131
+ - `cli`: `click.BaseCommand` to execute.
132
+ - `argv`: Optional iterable of CLI arguments (excluding program name).
133
+ - `prog_name`: Override the program name shown in help/version output.
134
+ - `signal_specs`: Iterable of `SignalSpec` objects to customise signal handling; defaults to `default_signal_specs()`.
135
+ - `install_signals`: Set `False` when the host application already manages signal handlers.
136
+
137
+ ### `handle_cli_exception(exc, *, signal_specs=None, echo=None) -> int`
138
+ Translate exceptions raised by Click commands into deterministic exit codes, honouring configured signal mappings and traceback policy.
139
+
140
+ Parameters:
141
+ - `exc`: Exception instance to classify.
142
+ - `signal_specs`: Optional iterable of `SignalSpec` objects for custom signal handling.
143
+ - `echo`: Callable matching `click.echo` signature, allowing custom stderr routing during tests or embedding.
144
+
145
+ ### `get_system_exit_code(exc) -> int`
146
+ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on POSIX/Windows or BSD `sysexits` when enabled).
147
+
148
+ Parameters:
149
+ - `exc`: Exception instance to classify.
150
+
151
+ ### `print_exception_message(trace_back=config.traceback, length_limit=500, stream=None) -> None`
152
+ Emit the active exception using Rich formatting. Produces a coloured traceback when `trace_back` is `True`, otherwise prints a truncated summary in red. Respects `config.traceback_force_color`.
153
+
154
+ Parameters:
155
+ - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
156
+ - `length_limit`: Maximum characters for summary output.
157
+ - `stream`: Target text stream; defaults to `sys.stderr`.
158
+
159
+ ### `flush_streams() -> None`
160
+ Best-effort flush of `sys.stdout` and `sys.stderr`, ensuring buffered output is written before exit.
161
+
162
+ ### `default_signal_specs() -> list[SignalSpec]`
163
+ Return the default signal mapping for the current platform (always includes `SIGINT`, plus `SIGTERM`/`SIGBREAK` when available).
164
+
165
+ ### `install_signal_handlers(specs=None) -> Callable[[], None]`
166
+ Register handlers that raise structured exceptions for the provided specs and return a restoration callback. Invoke the callback (typically in a `finally` block) to restore previous handlers.
167
+
168
+ Parameters:
169
+ - `specs`: Iterable of `SignalSpec` objects; defaults to `default_signal_specs()`.
170
+
171
+ ### `SignalSpec(signum: int, exception: type[BaseException], message: str, exit_code: int)`
172
+ Lightweight dataclass describing how a signal maps to an exception, stderr message, and exit code.
173
+
174
+ Fields:
175
+ - `signum`: Numeric signal value passed to `signal.signal`.
176
+ - `exception`: Exception type raised by the handler.
177
+ - `message`: Human-readable text echoed when the signal fires.
178
+ - `exit_code`: Exit status returned to the OS.
179
+
180
+ ### `CliSignalError` and subclasses
181
+ Hierarchy of marker exceptions raised when signal handlers trigger. Use them to differentiate signal-driven exits from other failures.
182
+
183
+ - `CliSignalError`: Base class.
184
+ - `SigIntInterrupt`: Raised on `SIGINT` (Ctrl+C); maps to exit code `130`.
185
+ - `SigTermInterrupt`: Raised on `SIGTERM`; maps to exit code `143`.
186
+ - `SigBreakInterrupt`: Raised on Windows `SIGBREAK`; maps to exit code `149`.
187
+
188
+ ### `default_signal_specs`, `install_signal_handlers`, and `run_cli` contract summary
189
+ When `run_cli` executes your Click command it will:
190
+ 1. Build a signal spec list (custom or default).
191
+ 2. Optionally install handlers that raise the exceptions above.
192
+ 3. Execute the command with `standalone_mode=False`.
193
+ 4. Funnel any exception through `handle_cli_exception`.
194
+ 5. Restore prior signal handlers and flush streams before returning.
195
+
196
+ This behaviour keeps CLI wiring consistent across projects embedding `lib_cli_exit_tools`.
197
+
197
198
  ### Advanced CLI wiring
198
199
 
199
200
  For larger applications, keep module execution, console scripts, and shared helpers aligned. The snippet below shows how `__main__.py` can catch unexpected errors and map them through `lib_cli_exit_tools` before exiting:
@@ -296,11 +297,11 @@ When installed, the generated console scripts (`lib_cli_exit_tools`, `cli-exit-t
296
297
  - Set `config.exit_code_style = "sysexits"` to map ValueError/TypeError → EX_USAGE(64),
297
298
  FileNotFoundError → EX_NOINPUT(66), PermissionError → EX_NOPERM(77), generic OSError → EX_IOERR(74).
298
299
 
299
- ## Development
300
-
301
- See [DEVELOPMENT.md](DEVELOPMENT.md) for contributor workflows, make targets, packaging sync details, and CI/publishing guidance.
302
-
303
-
304
- ## License
300
+ ## Additional Documentation
305
301
 
306
- MIT
302
+ - [INSTALL](INSTALL.md)
303
+ - [CHANGELOG](CHANGELOG.md)
304
+ - [CONTRIBUTING](CONTRIBUTING.md)
305
+ - [DEVELOPMENT](DEVELOPMENT.md)
306
+ - [MODULE REFERENCE](docs/system-design/module_reference.md)
307
+ - [LICENSE](LICENSE)