lib-cli-exit-tools 2.2.2__tar.gz → 2.2.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.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/ci.yml +2 -2
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/release.yml +1 -1
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/CHANGELOG.md +17 -0
- lib_cli_exit_tools-2.2.3/CLAUDE.md +164 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/INSTALL.md +3 -2
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/PKG-INFO +41 -34
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/README.md +39 -32
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/docs/system-design/module_reference.md +2 -2
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/pyproject.toml +5 -2
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__init__conf__.py +1 -1
- lib_cli_exit_tools-2.2.2/AGENTS.md +0 -208
- lib_cli_exit_tools-2.2.2/AGENTS_README.md +0 -176
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/cli-config.yaml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/cli.sh +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/codacy.yaml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/tools-configs/lizard.yaml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/tools-configs/trivy.yaml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.devcontainer/devcontainer.json +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.devcontainer/settings.json +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.env.example +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/dependabot.yml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/codeql.yml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.gitignore +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.qlty/qlty.toml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.snyk +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/CONTRIBUTING.md +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/DEVELOPMENT.md +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/LICENSE +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/Makefile +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/codecov.yml +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/notebooks/Quickstart.ipynb +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/__main__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/_utils.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/build.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_major.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_minor.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_patch.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_version.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/clean.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/cli.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/dependencies.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/dev.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/help.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/install.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/menu.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/push.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/release.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/run_cli.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/target_metadata.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/test.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/toml_config.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/version_current.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__main__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/adapters/signals.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/application/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/application/runner.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/cli.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/__init__.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/configuration.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/exit_codes.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/py.typed +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/conftest.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_adapters_signals.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_application_runner.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_behaviors.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_cli.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_core_configuration.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_core_exit_codes.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_metadata.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_module_entry.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_scripts.py +0 -0
- {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_signals_integration.py +0 -0
|
@@ -83,14 +83,14 @@ jobs:
|
|
|
83
83
|
run: |
|
|
84
84
|
uv pip install pywin32 --system
|
|
85
85
|
- name: Cache ruff
|
|
86
|
-
uses: actions/cache@
|
|
86
|
+
uses: actions/cache@v5
|
|
87
87
|
with:
|
|
88
88
|
path: .ruff_cache
|
|
89
89
|
key: ruff-${{ runner.os }}-${{ github.sha }}
|
|
90
90
|
restore-keys: |
|
|
91
91
|
ruff-${{ runner.os }}-
|
|
92
92
|
- name: Cache pyright
|
|
93
|
-
uses: actions/cache@
|
|
93
|
+
uses: actions/cache@v5
|
|
94
94
|
with:
|
|
95
95
|
path: .pyright
|
|
96
96
|
key: pyright-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
|
|
@@ -3,6 +3,23 @@
|
|
|
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.2.3] - 2025-12-17
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- Corrected README examples to use `rich_click` instead of plain `click` for consistency with library internals.
|
|
10
|
+
- Fixed Example 2 (cli_session) to avoid nested `run_cli` calls.
|
|
11
|
+
- Fixed Example 3 (multi-command CLI) so `--traceback` flag actually controls traceback display.
|
|
12
|
+
- Added missing blank line in Example 4 (custom signal handlers).
|
|
13
|
+
- Updated `print_exception_message` API reference signature to show `trace_back=None` default.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Updated CLAUDE.md with correct `docs/system-design/` path and added missing `python_data_architecture_enforcement.md` guideline.
|
|
17
|
+
- Removed irrelevant Documentation & Translations section from CLAUDE.md.
|
|
18
|
+
- Updated INSTALL.md to list all three console script entry points consistently.
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
- Added filelock CVE-2025-68146 to pip-audit ignore list (transitive dev dependency, fix pending upstream).
|
|
22
|
+
|
|
6
23
|
## [2.2.2] - 2025-12-12
|
|
7
24
|
|
|
8
25
|
### Changed
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Claude Code Guidelines for lib_cli_exit_tools
|
|
2
|
+
|
|
3
|
+
## Session Initialization
|
|
4
|
+
|
|
5
|
+
When starting a new session, read and apply the following system prompt files from `/media/srv-main-softdev/projects/softwarestack/systemprompts`:
|
|
6
|
+
|
|
7
|
+
### Core Guidelines (Always Apply)
|
|
8
|
+
- `core_programming_solid.md`
|
|
9
|
+
|
|
10
|
+
### Bash-Specific Guidelines
|
|
11
|
+
When working with Bash scripts:
|
|
12
|
+
- `core_programming_solid.md`
|
|
13
|
+
- `bash_clean_architecture.md`
|
|
14
|
+
- `bash_clean_code.md`
|
|
15
|
+
- `bash_small_functions.md`
|
|
16
|
+
|
|
17
|
+
### Python-Specific Guidelines
|
|
18
|
+
When working with Python code:
|
|
19
|
+
- `core_programming_solid.md`
|
|
20
|
+
- `python_solid_architecture_enforcer.md`
|
|
21
|
+
- `python_clean_architecture.md`
|
|
22
|
+
- `python_clean_code.md`
|
|
23
|
+
- `python_small_functions_style.md`
|
|
24
|
+
- `python_libraries_to_use.md`
|
|
25
|
+
- `python_data_architecture_enforcement.md`
|
|
26
|
+
|
|
27
|
+
### Additional Guidelines
|
|
28
|
+
- `self_documenting.md`
|
|
29
|
+
- `self_documenting_template.md`
|
|
30
|
+
- `python_jupyter_notebooks.md`
|
|
31
|
+
- `python_testing.md`
|
|
32
|
+
|
|
33
|
+
## Project Structure
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
lib_cli_exit_tools/
|
|
37
|
+
├── .github/
|
|
38
|
+
│ └── workflows/ # GitHub Actions CI/CD workflows
|
|
39
|
+
├── .devcontainer/ # Dev container configuration
|
|
40
|
+
├── docs/ # Project documentation
|
|
41
|
+
│ └── system-design/ # System design documents
|
|
42
|
+
├── notebooks/ # Jupyter notebooks for experiments
|
|
43
|
+
├── scripts/ # Build and automation scripts
|
|
44
|
+
│ ├── __init__.py # Package marker
|
|
45
|
+
│ ├── __main__.py # Module entry point
|
|
46
|
+
│ ├── _utils.py # Shared utilities
|
|
47
|
+
│ ├── build.py # Build wheel/sdist
|
|
48
|
+
│ ├── bump.py # Version bump (generic)
|
|
49
|
+
│ ├── bump_major.py # Bump major version
|
|
50
|
+
│ ├── bump_minor.py # Bump minor version
|
|
51
|
+
│ ├── bump_patch.py # Bump patch version
|
|
52
|
+
│ ├── bump_version.py # Version bump utilities
|
|
53
|
+
│ ├── clean.py # Clean build artifacts
|
|
54
|
+
│ ├── cli.py # CLI for scripts
|
|
55
|
+
│ ├── dependencies.py # Dependency management
|
|
56
|
+
│ ├── dev.py # Development install
|
|
57
|
+
│ ├── help.py # Show help
|
|
58
|
+
│ ├── install.py # Install package
|
|
59
|
+
│ ├── menu.py # Interactive TUI menu
|
|
60
|
+
│ ├── push.py # Git push
|
|
61
|
+
│ ├── release.py # Create releases
|
|
62
|
+
│ ├── run_cli.py # Run CLI
|
|
63
|
+
│ ├── target_metadata.py # Metadata generation
|
|
64
|
+
│ ├── test.py # Run tests with coverage
|
|
65
|
+
│ ├── toml_config.py # TOML configuration utilities
|
|
66
|
+
│ └── version_current.py # Print current version
|
|
67
|
+
├── src/
|
|
68
|
+
│ └── lib_cli_exit_tools/ # Main Python package
|
|
69
|
+
│ ├── __init__.py # Package initialization
|
|
70
|
+
│ ├── __init__conf__.py # Configuration constants
|
|
71
|
+
│ ├── __main__.py # CLI entry point
|
|
72
|
+
│ ├── cli.py # CLI implementation
|
|
73
|
+
│ ├── lib_cli_exit_tools.py # Core library functions
|
|
74
|
+
│ ├── py.typed # PEP 561 marker
|
|
75
|
+
│ ├── adapters/ # Adapter layer
|
|
76
|
+
│ │ └── signals.py # Signal handling adapters
|
|
77
|
+
│ ├── application/ # Application layer
|
|
78
|
+
│ │ └── runner.py # Application runner
|
|
79
|
+
│ └── core/ # Core domain layer
|
|
80
|
+
│ ├── configuration.py # Configuration management
|
|
81
|
+
│ └── exit_codes.py # Exit code definitions
|
|
82
|
+
├── tests/ # Test suite
|
|
83
|
+
├── .env.example # Example environment variables
|
|
84
|
+
├── CLAUDE.md # Claude Code guidelines (this file)
|
|
85
|
+
├── CHANGELOG.md # Version history
|
|
86
|
+
├── CONTRIBUTING.md # Contribution guidelines
|
|
87
|
+
├── DEVELOPMENT.md # Development setup guide
|
|
88
|
+
├── INSTALL.md # Installation instructions
|
|
89
|
+
├── LICENSE # MIT License
|
|
90
|
+
├── Makefile # Make targets for common tasks
|
|
91
|
+
├── pyproject.toml # Project metadata & dependencies
|
|
92
|
+
├── codecov.yml # Codecov configuration
|
|
93
|
+
└── README.md # Project overview
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Versioning & Releases
|
|
97
|
+
|
|
98
|
+
- **Single Source of Truth**: Package version is in `pyproject.toml` (`[project].version`)
|
|
99
|
+
- **Version Bumps**: update `pyproject.toml`, `CHANGELOG.md` and update the constants in `src/lib_cli_exit_tools/__init__conf__.py` according to `pyproject.toml`
|
|
100
|
+
- Automation rewrites `src/lib_cli_exit_tools/__init__conf__.py` from `pyproject.toml`, so runtime code imports generated constants instead of querying `importlib.metadata`.
|
|
101
|
+
- After updating project metadata (version, summary, URLs, authors) run `make test` (or `python -m scripts.test`) to regenerate the metadata module before committing.
|
|
102
|
+
- **Release Tags**: Format is `vX.Y.Z` (push tags for CI to build and publish)
|
|
103
|
+
|
|
104
|
+
## Common Make Targets
|
|
105
|
+
|
|
106
|
+
| Target | Description |
|
|
107
|
+
|-------------------|---------------------------------------------------------------------------------|
|
|
108
|
+
| `build` | Build wheel/sdist artifacts |
|
|
109
|
+
| `bump` | Bump version (VERSION=X.Y.Z or PART=major\|minor\|patch) and update changelog |
|
|
110
|
+
| `bump-major` | Increment major version ((X+1).0.0) |
|
|
111
|
+
| `bump-minor` | Increment minor version (X.Y.Z → X.(Y+1).0) |
|
|
112
|
+
| `bump-patch` | Increment patch version (X.Y.Z → X.Y.(Z+1)) |
|
|
113
|
+
| `clean` | Remove caches, coverage, and build artifacts (includes `dist/` and `build/`) |
|
|
114
|
+
| `dev` | Install package with dev extras |
|
|
115
|
+
| `help` | Show make targets |
|
|
116
|
+
| `install` | Editable install |
|
|
117
|
+
| `menu` | Interactive TUI menu |
|
|
118
|
+
| `push` | Commit changes and push to GitHub (no CI monitoring) |
|
|
119
|
+
| `release` | Tag vX.Y.Z, push, sync packaging, run gh release if available |
|
|
120
|
+
| `run` | Run module entry (`python -m ... --help`) |
|
|
121
|
+
| `test` | Lint, format, type-check, run tests with coverage, upload to Codecov |
|
|
122
|
+
| `version-current` | Print current version from `pyproject.toml` |
|
|
123
|
+
|
|
124
|
+
## Coding Style & Naming Conventions
|
|
125
|
+
|
|
126
|
+
Follow the guidelines in `python_clean_code.md` for all Python code.
|
|
127
|
+
|
|
128
|
+
## Architecture Overview
|
|
129
|
+
|
|
130
|
+
This library follows Clean Architecture with three layers:
|
|
131
|
+
- **core/**: Domain layer with exit codes and configuration (no external dependencies)
|
|
132
|
+
- **application/**: Application services and runners
|
|
133
|
+
- **adapters/**: External interfaces (signal handling)
|
|
134
|
+
|
|
135
|
+
Import rules (enforced by import-linter):
|
|
136
|
+
- `core` cannot import from `application`, `adapters`, or `cli`
|
|
137
|
+
- `application` cannot import from `cli`
|
|
138
|
+
|
|
139
|
+
Apply principles from `python_clean_architecture.md` when designing and implementing features.
|
|
140
|
+
|
|
141
|
+
## Security & Configuration
|
|
142
|
+
|
|
143
|
+
- `.env` files are for local tooling only (CodeCov tokens, etc.)
|
|
144
|
+
- **NEVER** commit secrets to version control
|
|
145
|
+
- Rich logging should sanitize payloads before rendering
|
|
146
|
+
|
|
147
|
+
## Commit & Push Policy
|
|
148
|
+
|
|
149
|
+
### Pre-Push Requirements
|
|
150
|
+
- **Always run `make test` before pushing** to avoid lint/test breakage
|
|
151
|
+
- Ensure all tests pass and code is properly formatted
|
|
152
|
+
|
|
153
|
+
### Post-Push Monitoring
|
|
154
|
+
- Monitor GitHub Actions for errors after pushing
|
|
155
|
+
- Attempt to correct any CI/CD errors that appear
|
|
156
|
+
|
|
157
|
+
## Claude Code Workflow
|
|
158
|
+
|
|
159
|
+
When working on this project:
|
|
160
|
+
1. Read relevant system prompts at session start
|
|
161
|
+
2. Apply appropriate coding guidelines based on file type
|
|
162
|
+
3. Run `make test` before commits
|
|
163
|
+
4. Follow versioning guidelines for releases
|
|
164
|
+
5. Monitor CI after pushing changes
|
|
@@ -126,8 +126,9 @@ We distribute via PyPI only. If you prefer isolated CLI installs, use tools such
|
|
|
126
126
|
|
|
127
127
|
After installation the following commands should resolve:
|
|
128
128
|
|
|
129
|
-
- `
|
|
130
|
-
- `
|
|
129
|
+
- `lib-cli-exit-tools` (default console script)
|
|
130
|
+
- `lib_cli_exit_tools` (alias)
|
|
131
|
+
- `cli-exit-tools` (alias)
|
|
131
132
|
- `python -m lib_cli_exit_tools`
|
|
132
133
|
|
|
133
134
|
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:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lib_cli_exit_tools
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
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
|
|
@@ -31,7 +31,7 @@ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
|
|
|
31
31
|
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
32
32
|
Requires-Dist: rtoml>=0.13.0; extra == 'dev'
|
|
33
33
|
Requires-Dist: ruff>=0.14.9; extra == 'dev'
|
|
34
|
-
Requires-Dist: textual>=6.
|
|
34
|
+
Requires-Dist: textual>=6.10.0; extra == 'dev'
|
|
35
35
|
Requires-Dist: twine>=6.2.0; extra == 'dev'
|
|
36
36
|
Description-Content-Type: text/markdown
|
|
37
37
|
|
|
@@ -130,7 +130,7 @@ CLI that demonstrates configuration hooks and structured error handling.
|
|
|
130
130
|
```python
|
|
131
131
|
from __future__ import annotations
|
|
132
132
|
|
|
133
|
-
import click
|
|
133
|
+
import rich_click as click
|
|
134
134
|
|
|
135
135
|
from lib_cli_exit_tools import run_cli
|
|
136
136
|
|
|
@@ -138,7 +138,6 @@ from lib_cli_exit_tools import run_cli
|
|
|
138
138
|
@click.command()
|
|
139
139
|
def hello() -> None:
|
|
140
140
|
"""Say hello with automatic signal-aware exit handling."""
|
|
141
|
-
|
|
142
141
|
click.echo("Hello from lib_cli_exit_tools!")
|
|
143
142
|
|
|
144
143
|
|
|
@@ -157,29 +156,32 @@ python hello.py
|
|
|
157
156
|
```python
|
|
158
157
|
from __future__ import annotations
|
|
159
158
|
|
|
160
|
-
import click
|
|
161
|
-
|
|
162
|
-
from lib_cli_exit_tools import cli_session, run_cli
|
|
163
|
-
|
|
159
|
+
import rich_click as click
|
|
164
160
|
|
|
165
|
-
|
|
166
|
-
@click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
|
|
167
|
-
def cli(traceback: bool) -> int:
|
|
168
|
-
with cli_session(overrides={"traceback": traceback}) as execute:
|
|
169
|
-
return execute(failable, argv=[])
|
|
161
|
+
from lib_cli_exit_tools import cli_session
|
|
170
162
|
|
|
171
163
|
|
|
172
164
|
@click.command()
|
|
173
165
|
def failable() -> None:
|
|
166
|
+
"""Command that always fails to demonstrate traceback handling."""
|
|
174
167
|
raise RuntimeError("toggle --traceback to see the full traceback")
|
|
175
168
|
|
|
176
169
|
|
|
170
|
+
def main(*, traceback: bool = False) -> int:
|
|
171
|
+
"""Run failable with optional traceback display."""
|
|
172
|
+
with cli_session(overrides={"traceback": traceback}) as run:
|
|
173
|
+
return run(failable)
|
|
174
|
+
|
|
175
|
+
|
|
177
176
|
if __name__ == "__main__":
|
|
178
|
-
|
|
177
|
+
import sys
|
|
178
|
+
|
|
179
|
+
enable_traceback = "--traceback" in sys.argv
|
|
180
|
+
raise SystemExit(main(traceback=enable_traceback))
|
|
179
181
|
```
|
|
180
182
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
Running `python cli.py --traceback` enables coloured tracebacks for that
|
|
184
|
+
session. The `cli_session` context manager restores configuration afterwards.
|
|
183
185
|
|
|
184
186
|
#### 3. Full-featured multi-command CLI
|
|
185
187
|
|
|
@@ -187,9 +189,10 @@ run and resets the configuration afterwards.
|
|
|
187
189
|
from __future__ import annotations
|
|
188
190
|
|
|
189
191
|
import json
|
|
192
|
+
import sys
|
|
190
193
|
from dataclasses import dataclass
|
|
191
194
|
|
|
192
|
-
import click
|
|
195
|
+
import rich_click as click
|
|
193
196
|
|
|
194
197
|
from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
|
|
195
198
|
|
|
@@ -197,21 +200,19 @@ from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
|
|
|
197
200
|
@dataclass(slots=True)
|
|
198
201
|
class Settings:
|
|
199
202
|
pretty: bool
|
|
200
|
-
traceback: bool
|
|
201
203
|
|
|
202
204
|
|
|
203
205
|
@click.group()
|
|
204
206
|
@click.option("--pretty/--no-pretty", default=True)
|
|
205
|
-
@click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
|
|
206
207
|
@click.pass_context
|
|
207
|
-
def cli(ctx: click.Context, pretty: bool
|
|
208
|
-
ctx.obj = Settings(pretty=pretty
|
|
208
|
+
def cli(ctx: click.Context, pretty: bool) -> None:
|
|
209
|
+
ctx.obj = Settings(pretty=pretty)
|
|
209
210
|
|
|
210
211
|
|
|
211
212
|
@cli.command()
|
|
212
213
|
@click.pass_obj
|
|
213
214
|
def info(settings: Settings) -> None:
|
|
214
|
-
payload = {"
|
|
215
|
+
payload = {"pretty": settings.pretty}
|
|
215
216
|
click.echo(json.dumps(payload, indent=2 if settings.pretty else None))
|
|
216
217
|
|
|
217
218
|
|
|
@@ -223,20 +224,24 @@ def fail(settings: Settings) -> None:
|
|
|
223
224
|
|
|
224
225
|
|
|
225
226
|
def main() -> int:
|
|
226
|
-
|
|
227
|
+
# Parse --traceback early before entering cli_session
|
|
228
|
+
traceback = "--traceback" in sys.argv
|
|
229
|
+
argv = [arg for arg in sys.argv[1:] if arg != "--traceback"]
|
|
230
|
+
|
|
231
|
+
overrides = {"traceback": traceback, "traceback_force_color": traceback}
|
|
227
232
|
signals: list[SignalSpec] = default_signal_specs()
|
|
228
233
|
with cli_session(overrides=overrides) as execute:
|
|
229
|
-
return execute(cli, signal_specs=signals)
|
|
234
|
+
return execute(cli, argv=argv, signal_specs=signals)
|
|
230
235
|
|
|
231
236
|
|
|
232
237
|
if __name__ == "__main__":
|
|
233
238
|
raise SystemExit(main())
|
|
234
239
|
```
|
|
235
240
|
|
|
236
|
-
This version
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
`lib_cli_exit_tools`.
|
|
241
|
+
This version parses `--traceback` early (before Click sees it), then wires
|
|
242
|
+
configuration overrides, custom signal specs, and multiple commands into a
|
|
243
|
+
single composition point—mirroring how a production CLI can layer policy logic
|
|
244
|
+
around Click while still delegating exit-code translation to `lib_cli_exit_tools`.
|
|
240
245
|
|
|
241
246
|
#### 4. Custom signal handlers
|
|
242
247
|
|
|
@@ -251,7 +256,7 @@ import signal
|
|
|
251
256
|
from contextlib import ExitStack
|
|
252
257
|
from typing import Callable
|
|
253
258
|
|
|
254
|
-
import click
|
|
259
|
+
import rich_click as click
|
|
255
260
|
|
|
256
261
|
from lib_cli_exit_tools import SignalSpec, default_signal_specs, run_cli
|
|
257
262
|
|
|
@@ -271,6 +276,8 @@ def custom_signal_specs() -> list[SignalSpec]:
|
|
|
271
276
|
)
|
|
272
277
|
)
|
|
273
278
|
return specs
|
|
279
|
+
|
|
280
|
+
|
|
274
281
|
def install_custom_signals(specs: list[SignalSpec] | None) -> Callable[[], None]:
|
|
275
282
|
stack = ExitStack()
|
|
276
283
|
|
|
@@ -478,11 +485,11 @@ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on
|
|
|
478
485
|
Parameters:
|
|
479
486
|
- `exc`: Exception instance to classify.
|
|
480
487
|
|
|
481
|
-
### `print_exception_message(trace_back=
|
|
488
|
+
### `print_exception_message(trace_back=None, length_limit=500, stream=None) -> None`
|
|
482
489
|
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` and mirrors the behaviour of `handle_cli_exception` (tracebacks are rendered before the helper returns an exit status).
|
|
483
490
|
|
|
484
491
|
Parameters:
|
|
485
|
-
- `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
|
|
492
|
+
- `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`). When `None` (default), uses `config.traceback`.
|
|
486
493
|
- `length_limit`: Maximum characters for summary output.
|
|
487
494
|
- `stream`: Target text stream; defaults to `sys.stderr`.
|
|
488
495
|
|
|
@@ -557,7 +564,8 @@ from __future__ import annotations
|
|
|
557
564
|
|
|
558
565
|
from typing import Sequence
|
|
559
566
|
|
|
560
|
-
import click
|
|
567
|
+
import rich_click as click
|
|
568
|
+
|
|
561
569
|
import lib_cli_exit_tools
|
|
562
570
|
|
|
563
571
|
from . import __init__conf__
|
|
@@ -614,7 +622,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
614
622
|
)
|
|
615
623
|
```
|
|
616
624
|
|
|
617
|
-
When installed,
|
|
625
|
+
When installed, your package's console scripts (defined in `pyproject.toml`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
|
|
618
626
|
|
|
619
627
|
## Exit Codes
|
|
620
628
|
|
|
@@ -643,5 +651,4 @@ When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-t
|
|
|
643
651
|
- [CONTRIBUTING](CONTRIBUTING.md)
|
|
644
652
|
- [DEVELOPMENT](DEVELOPMENT.md)
|
|
645
653
|
- [MODULE REFERENCE](docs/system-design/module_reference.md)
|
|
646
|
-
- [AGENTS_README](AGENTS_README.md)
|
|
647
654
|
- [LICENSE](LICENSE)
|
|
@@ -93,7 +93,7 @@ CLI that demonstrates configuration hooks and structured error handling.
|
|
|
93
93
|
```python
|
|
94
94
|
from __future__ import annotations
|
|
95
95
|
|
|
96
|
-
import click
|
|
96
|
+
import rich_click as click
|
|
97
97
|
|
|
98
98
|
from lib_cli_exit_tools import run_cli
|
|
99
99
|
|
|
@@ -101,7 +101,6 @@ from lib_cli_exit_tools import run_cli
|
|
|
101
101
|
@click.command()
|
|
102
102
|
def hello() -> None:
|
|
103
103
|
"""Say hello with automatic signal-aware exit handling."""
|
|
104
|
-
|
|
105
104
|
click.echo("Hello from lib_cli_exit_tools!")
|
|
106
105
|
|
|
107
106
|
|
|
@@ -120,29 +119,32 @@ python hello.py
|
|
|
120
119
|
```python
|
|
121
120
|
from __future__ import annotations
|
|
122
121
|
|
|
123
|
-
import click
|
|
124
|
-
|
|
125
|
-
from lib_cli_exit_tools import cli_session, run_cli
|
|
126
|
-
|
|
122
|
+
import rich_click as click
|
|
127
123
|
|
|
128
|
-
|
|
129
|
-
@click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
|
|
130
|
-
def cli(traceback: bool) -> int:
|
|
131
|
-
with cli_session(overrides={"traceback": traceback}) as execute:
|
|
132
|
-
return execute(failable, argv=[])
|
|
124
|
+
from lib_cli_exit_tools import cli_session
|
|
133
125
|
|
|
134
126
|
|
|
135
127
|
@click.command()
|
|
136
128
|
def failable() -> None:
|
|
129
|
+
"""Command that always fails to demonstrate traceback handling."""
|
|
137
130
|
raise RuntimeError("toggle --traceback to see the full traceback")
|
|
138
131
|
|
|
139
132
|
|
|
133
|
+
def main(*, traceback: bool = False) -> int:
|
|
134
|
+
"""Run failable with optional traceback display."""
|
|
135
|
+
with cli_session(overrides={"traceback": traceback}) as run:
|
|
136
|
+
return run(failable)
|
|
137
|
+
|
|
138
|
+
|
|
140
139
|
if __name__ == "__main__":
|
|
141
|
-
|
|
140
|
+
import sys
|
|
141
|
+
|
|
142
|
+
enable_traceback = "--traceback" in sys.argv
|
|
143
|
+
raise SystemExit(main(traceback=enable_traceback))
|
|
142
144
|
```
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
Running `python cli.py --traceback` enables coloured tracebacks for that
|
|
147
|
+
session. The `cli_session` context manager restores configuration afterwards.
|
|
146
148
|
|
|
147
149
|
#### 3. Full-featured multi-command CLI
|
|
148
150
|
|
|
@@ -150,9 +152,10 @@ run and resets the configuration afterwards.
|
|
|
150
152
|
from __future__ import annotations
|
|
151
153
|
|
|
152
154
|
import json
|
|
155
|
+
import sys
|
|
153
156
|
from dataclasses import dataclass
|
|
154
157
|
|
|
155
|
-
import click
|
|
158
|
+
import rich_click as click
|
|
156
159
|
|
|
157
160
|
from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
|
|
158
161
|
|
|
@@ -160,21 +163,19 @@ from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
|
|
|
160
163
|
@dataclass(slots=True)
|
|
161
164
|
class Settings:
|
|
162
165
|
pretty: bool
|
|
163
|
-
traceback: bool
|
|
164
166
|
|
|
165
167
|
|
|
166
168
|
@click.group()
|
|
167
169
|
@click.option("--pretty/--no-pretty", default=True)
|
|
168
|
-
@click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
|
|
169
170
|
@click.pass_context
|
|
170
|
-
def cli(ctx: click.Context, pretty: bool
|
|
171
|
-
ctx.obj = Settings(pretty=pretty
|
|
171
|
+
def cli(ctx: click.Context, pretty: bool) -> None:
|
|
172
|
+
ctx.obj = Settings(pretty=pretty)
|
|
172
173
|
|
|
173
174
|
|
|
174
175
|
@cli.command()
|
|
175
176
|
@click.pass_obj
|
|
176
177
|
def info(settings: Settings) -> None:
|
|
177
|
-
payload = {"
|
|
178
|
+
payload = {"pretty": settings.pretty}
|
|
178
179
|
click.echo(json.dumps(payload, indent=2 if settings.pretty else None))
|
|
179
180
|
|
|
180
181
|
|
|
@@ -186,20 +187,24 @@ def fail(settings: Settings) -> None:
|
|
|
186
187
|
|
|
187
188
|
|
|
188
189
|
def main() -> int:
|
|
189
|
-
|
|
190
|
+
# Parse --traceback early before entering cli_session
|
|
191
|
+
traceback = "--traceback" in sys.argv
|
|
192
|
+
argv = [arg for arg in sys.argv[1:] if arg != "--traceback"]
|
|
193
|
+
|
|
194
|
+
overrides = {"traceback": traceback, "traceback_force_color": traceback}
|
|
190
195
|
signals: list[SignalSpec] = default_signal_specs()
|
|
191
196
|
with cli_session(overrides=overrides) as execute:
|
|
192
|
-
return execute(cli, signal_specs=signals)
|
|
197
|
+
return execute(cli, argv=argv, signal_specs=signals)
|
|
193
198
|
|
|
194
199
|
|
|
195
200
|
if __name__ == "__main__":
|
|
196
201
|
raise SystemExit(main())
|
|
197
202
|
```
|
|
198
203
|
|
|
199
|
-
This version
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
`lib_cli_exit_tools`.
|
|
204
|
+
This version parses `--traceback` early (before Click sees it), then wires
|
|
205
|
+
configuration overrides, custom signal specs, and multiple commands into a
|
|
206
|
+
single composition point—mirroring how a production CLI can layer policy logic
|
|
207
|
+
around Click while still delegating exit-code translation to `lib_cli_exit_tools`.
|
|
203
208
|
|
|
204
209
|
#### 4. Custom signal handlers
|
|
205
210
|
|
|
@@ -214,7 +219,7 @@ import signal
|
|
|
214
219
|
from contextlib import ExitStack
|
|
215
220
|
from typing import Callable
|
|
216
221
|
|
|
217
|
-
import click
|
|
222
|
+
import rich_click as click
|
|
218
223
|
|
|
219
224
|
from lib_cli_exit_tools import SignalSpec, default_signal_specs, run_cli
|
|
220
225
|
|
|
@@ -234,6 +239,8 @@ def custom_signal_specs() -> list[SignalSpec]:
|
|
|
234
239
|
)
|
|
235
240
|
)
|
|
236
241
|
return specs
|
|
242
|
+
|
|
243
|
+
|
|
237
244
|
def install_custom_signals(specs: list[SignalSpec] | None) -> Callable[[], None]:
|
|
238
245
|
stack = ExitStack()
|
|
239
246
|
|
|
@@ -441,11 +448,11 @@ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on
|
|
|
441
448
|
Parameters:
|
|
442
449
|
- `exc`: Exception instance to classify.
|
|
443
450
|
|
|
444
|
-
### `print_exception_message(trace_back=
|
|
451
|
+
### `print_exception_message(trace_back=None, length_limit=500, stream=None) -> None`
|
|
445
452
|
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` and mirrors the behaviour of `handle_cli_exception` (tracebacks are rendered before the helper returns an exit status).
|
|
446
453
|
|
|
447
454
|
Parameters:
|
|
448
|
-
- `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
|
|
455
|
+
- `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`). When `None` (default), uses `config.traceback`.
|
|
449
456
|
- `length_limit`: Maximum characters for summary output.
|
|
450
457
|
- `stream`: Target text stream; defaults to `sys.stderr`.
|
|
451
458
|
|
|
@@ -520,7 +527,8 @@ from __future__ import annotations
|
|
|
520
527
|
|
|
521
528
|
from typing import Sequence
|
|
522
529
|
|
|
523
|
-
import click
|
|
530
|
+
import rich_click as click
|
|
531
|
+
|
|
524
532
|
import lib_cli_exit_tools
|
|
525
533
|
|
|
526
534
|
from . import __init__conf__
|
|
@@ -577,7 +585,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
577
585
|
)
|
|
578
586
|
```
|
|
579
587
|
|
|
580
|
-
When installed,
|
|
588
|
+
When installed, your package's console scripts (defined in `pyproject.toml`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
|
|
581
589
|
|
|
582
590
|
## Exit Codes
|
|
583
591
|
|
|
@@ -606,5 +614,4 @@ When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-t
|
|
|
606
614
|
- [CONTRIBUTING](CONTRIBUTING.md)
|
|
607
615
|
- [DEVELOPMENT](DEVELOPMENT.md)
|
|
608
616
|
- [MODULE REFERENCE](docs/system-design/module_reference.md)
|
|
609
|
-
- [AGENTS_README](AGENTS_README.md)
|
|
610
617
|
- [LICENSE](LICENSE)
|
{lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/docs/system-design/module_reference.md
RENAMED
|
@@ -221,6 +221,6 @@ Downstream CLIs and automation pipelines need deterministic exit codes, signal h
|
|
|
221
221
|
|
|
222
222
|
---
|
|
223
223
|
|
|
224
|
-
**Created:** 2025-10-08 by Codex (automated)
|
|
225
|
-
**Last Updated:** 2025-
|
|
224
|
+
**Created:** 2025-10-08 by Codex (automated)
|
|
225
|
+
**Last Updated:** 2025-12-17
|
|
226
226
|
**Review Cycle:** Revisit every 90 days or after major CLI/runtime changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lib_cli_exit_tools"
|
|
3
|
-
version = "2.2.
|
|
3
|
+
version = "2.2.3"
|
|
4
4
|
description = "CLI exit handling helpers: clean signals, exit codes, and error printing"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -36,7 +36,7 @@ dev = [
|
|
|
36
36
|
"pytest-asyncio>=1.3.0",
|
|
37
37
|
"pytest-cov>=7.0.0",
|
|
38
38
|
"ruff>=0.14.9",
|
|
39
|
-
"textual>=6.
|
|
39
|
+
"textual>=6.10.0",
|
|
40
40
|
"rtoml>=0.13.0",
|
|
41
41
|
"twine>=6.2.0"
|
|
42
42
|
]
|
|
@@ -159,10 +159,13 @@ forbidden_modules = [
|
|
|
159
159
|
# PYSEC-2022-43012, CVE-2024-6345, PYSEC-2025-49: setuptools vulnerabilities
|
|
160
160
|
# These are build-time dependencies only, not runtime. The virtual environment
|
|
161
161
|
# setuptools version is managed by the CI environment/pip itself.
|
|
162
|
+
# CVE-2025-68146: filelock <3.20.1 vulnerability, transitive dev dependency
|
|
163
|
+
# Will be resolved when upstream packages update their dependencies.
|
|
162
164
|
ignore-vulns = [
|
|
163
165
|
"GHSA-4xh5-x5gv-qwph",
|
|
164
166
|
"PYSEC-2022-42969",
|
|
165
167
|
"PYSEC-2022-43012",
|
|
166
168
|
"CVE-2024-6345",
|
|
167
169
|
"PYSEC-2025-49",
|
|
170
|
+
"CVE-2025-68146",
|
|
168
171
|
]
|
{lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__init__conf__.py
RENAMED
|
@@ -24,7 +24,7 @@ name = "lib_cli_exit_tools"
|
|
|
24
24
|
#: Human-readable summary shown in CLI help output.
|
|
25
25
|
title = "CLI exit handling helpers: clean signals, exit codes, and error printing"
|
|
26
26
|
#: Current release version pulled from ``pyproject.toml`` by automation.
|
|
27
|
-
version = "2.2.
|
|
27
|
+
version = "2.2.3"
|
|
28
28
|
#: Repository homepage presented to users.
|
|
29
29
|
homepage = "https://github.com/bitranox/lib_cli_exit_tools"
|
|
30
30
|
#: Author attribution surfaced in CLI output.
|