CLI exit handling helpers: clean signals, exit codes, and error printing
Project description
lib_cli_exit_tools
Small helpers for robust CLI exit handling:
- Portable signal handling (SIGINT, SIGTERM/SIGBREAK)
- Consistent exception → exit code mapping
- Concise error printing with optional traceback and subprocess stdout/stderr capture
Install
Pick one of the options below. All methods register the lib_cli_exit_tools and cli-exit-tools commands on your PATH.
1) Standard virtualenv (pip)
python -m venv .venv
source .venv/bin/activate # Windows: .venv\\Scripts\\activate
pip install -e .[dev] # dev install
# or for runtime only:
pip install .
2) Per-user (no venv)
pip install --user .
Note: respects PEP 668; avoid on system Python if “externally managed”. Ensure ~/.local/bin (POSIX) is on PATH.
3) pipx (isolated, recommended for end users)
pipx install .
pipx upgrade lib_cli_exit_tools
# From Git tag/commit:
pipx install "git+https://github.com/bitranox/lib_cli_exit_tools@v0.1.0"
4) uv (fast installer/runner)
uv pip install -e .[dev]
uv tool install .
uvx lib_cli_exit_tools --help
5) From artifacts
python -m build
pip install dist/lib_cli_exit_tools-*.whl
pip install dist/lib_cli_exit_tools-*.tar.gz # sdist
6) Poetry / PDM (project-managed envs)
# Poetry
poetry add lib_cli_exit_tools # as dependency
poetry install # for local dev
# PDM
pdm add lib_cli_exit_tools
pdm install
7) From Git via pip (CI-friendly)
pip install "git+https://github.com/bitranox/lib_cli_exit_tools@v0.1.0#egg=lib_cli_exit_tools"
8) Conda/mamba (optional)
mamba create -n cli-exit python=3.12 pip
mamba activate cli-exit
pip install .
9) System package managers (optional distribution)
- Homebrew formula (macOS):
brew install lib_cli_exit_tools(if published) - Nix: flake/package for reproducible installs
- Deb/RPM via
fpmfor OS-native packages
Make Targets
| Target | Description |
|---|---|
help |
Show help |
install |
Install package editable |
dev |
Install package with dev extras |
test |
Lint, type-check, run tests with coverage, upload to Codecov |
run |
Run module CLI (requires dev install or src on PYTHONPATH) |
version-current |
Print current version from pyproject.toml |
bump |
Bump version: VERSION=X.Y.Z or PART=major |
bump-patch |
Bump patch version (X.Y.Z -> X.Y.(Z+1)) |
bump-minor |
Bump minor version (X.Y.Z -> X.(Y+1).0) |
bump-major |
Bump major version ((X+1).0.0) |
clean |
Remove caches, build artifacts, and coverage |
push |
Commit all changes once and push to GitHub (no CI monitoring) |
build |
Build wheel/sdist and attempt conda, brew, and nix builds (auto-installs tools if missing) |
Target Details
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).- Auto‑bootstrap:
make testwill try to install dev tools (pip install -e .[dev]) ifruff/pyright/pytestare missing. SetSKIP_BOOTSTRAP=1to skip this behavior. build: convenient builder — creates Python wheel/sdist, then attempts Conda, Homebrew, and Nix builds. It auto‑installs missing tools (Miniforge, Homebrew, Nix) when needed.install/dev/user-install: common install flows for editable or per‑user installs.version-current: prints current version frompyproject.toml.bump: updatespyproject.tomlversion and inserts a new section inCHANGELOG.md. UseVERSION=X.Y.Z make bumpormake bump-minor/bump-major/bump-patch.pipx-*anduv-*: isolated CLI installations for end users and fast developer tooling.which-cmd/verify-install: quick diagnostics to ensure the command is on PATH.
Usage
Console script:
# After install (pip/pipx/uv tool)
lib_cli_exit_tools --help
cli-exit-tools --help # alias
lib_cli_exit_tools info
Library:
import lib_cli_exit_tools
lib_cli_exit_tools.config.traceback = False # show short messages
try:
raise FileNotFoundError("missing.txt")
except Exception as e:
code = lib_cli_exit_tools.get_system_exit_code(e) # 2 on POSIX
lib_cli_exit_tools.print_exception_message() # prints: FileNotFoundError: missing.txt
raise SystemExit(code)
Command names registered on install
- lib_cli_exit_tools (default)
- cli-exit-tools (alias)
- python -m lib_cli_exit_tools (module entry)
If you installed with --user or in a venv, make sure the corresponding bin directory is on PATH:
- Linux/macOS venv: .venv/bin
- Linux/macOS user: ~/.local/bin
- Windows venv: .venv\Scripts
- Windows user: %APPDATA%\Python\PythonXY\Scripts
Exit Codes
- SIGINT → 130, SIGTERM → 143 (POSIX), SIGBREAK → 149 (Windows)
- SystemExit(n) → n
- Common exceptions map to POSIX/Windows codes (FileNotFoundError, PermissionError, ValueError, etc.)
Broken pipe behavior
- Default: exit 141 quietly (128+SIGPIPE), no noisy error output.
- Configure:
config.broken_pipe_exit_code = 0to treat as benign truncation, or32(EPIPE).
Sysexits mode (optional)
- Set
config.exit_code_style = "sysexits"to map ValueError/TypeError → EX_USAGE(64), FileNotFoundError → EX_NOINPUT(66), PermissionError → EX_NOPERM(77), generic OSError → EX_IOERR(74).
Development
make test # ruff + pyright + pytest + coverage (default ON)
SKIP_BOOTSTRAP=1 make test # skip auto-install of dev deps
COVERAGE=off make test # disable coverage locally
COVERAGE=on make test # force coverage and generate coverage.xml/codecov.xml
Packaging sync (Conda/Brew/Nix)
-
make testandmake pushautomatically align the packaging skeletons inpackaging/with the currentpyproject.toml:- Conda: updates
{% set version = "X.Y.Z" %}and bothpython >=X.Yconstraints to matchrequires-python. - Homebrew: updates the source URL tag to
vX.Y.Zand setsdepends_on "python@X.Y"to matchrequires-python. - Nix: updates the package
version, examplerev = "vX.Y.Z", and switchespkgs.pythonXYZPackages/pkgs.pythonXYZto match the minimum Python version fromrequires-python.
- Conda: updates
-
To run just the sync without bumping versions:
python tools/bump_version.py --sync-packaging. -
On release tags (
v*.*.*), CI validates that packaging files are consistent withpyproject.tomland will fail if they drift.
Versioning & Metadata
- Single source of truth for package metadata is
pyproject.toml([project]). - The library reads its own installed metadata at runtime via
importlib.metadata(seesrc/lib_cli_exit_tools/__init__conf__.py). - Do not duplicate the version in code; bump only
pyproject.tomland updateCHANGELOG.md. - Console script name is discovered from entry points; defaults to
lib_cli_exit_tools.
Packaging Skeletons
Starter files for package managers live under packaging/:
- Conda:
packaging/conda/recipe/meta.yaml(update version + sha256) - Homebrew:
packaging/brew/Formula/lib-cli-exit-tools.rb(fill sha256 and vendored resources) - Nix:
packaging/nix/flake.nix(use working tree or pin to GitHub rev with sha256)
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.
CI & Publishing
GitHub Actions workflows are included:
.github/workflows/ci.yml— lint/type/test, build wheel/sdist, verify pipx and uv installs, Nix and Conda builds (CI-only; no local install required)..github/workflows/release.yml— on tagsv*.*.*, builds artifacts and publishes to PyPI whenPYPI_API_TOKENsecret is set.
To publish a release:
- Bump
pyproject.tomlversion and updateCHANGELOG.md. - Tag the commit (
git tag v0.1.1 && git push --tags). - Ensure
PYPI_API_TOKENsecret is configured in the repo. - Release workflow uploads wheel/sdist to PyPI.
Conda/Homebrew/Nix: use files in packaging/ to submit to their ecosystems. CI also attempts builds to validate recipes, but does not publish automatically.
Local Codecov uploads
make test(with coverage enabled) generatescoverage.xmlandcodecov.xml, then attempts to upload via the Codecov CLI or the bash uploader.- For private repos, set
CODECOV_TOKEN(see.env.example) or export it in your shell. - For public repos, a token is typically not required.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lib_cli_exit_tools-1.0.1.tar.gz.
File metadata
- Download URL: lib_cli_exit_tools-1.0.1.tar.gz
- Upload date:
- Size: 33.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1410e595a83f20f288369ef387fced048099a781db4af9a80363a28d688734d2
|
|
| MD5 |
f65f8312d53d01abd3406dcae0040633
|
|
| BLAKE2b-256 |
4734de8a44af982c3fee7db9d852b7bf62e6aa5b41dae020bfbc050f45e1822f
|
File details
Details for the file lib_cli_exit_tools-1.0.1-py3-none-any.whl.
File metadata
- Download URL: lib_cli_exit_tools-1.0.1-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cfdf03ed0f73a8c92de192ae10e76724294746800e5caf3133d07b8d4e28097d
|
|
| MD5 |
bfadfd573f3ce758084a7e68b8f07826
|
|
| BLAKE2b-256 |
3d4f72b99f780a284ba5b437032578fc799b7f71ab5f3d4a98fd95a0714a2f9c
|