lib-cli-exit-tools 1.4.0__tar.gz → 1.6.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.
Files changed (98) hide show
  1. lib_cli_exit_tools-1.6.0/.codacy/cli-config.yaml +1 -0
  2. lib_cli_exit_tools-1.6.0/.codacy/cli.sh +149 -0
  3. lib_cli_exit_tools-1.6.0/.codacy/codacy.yaml +15 -0
  4. lib_cli_exit_tools-1.6.0/.codacy/tools-configs/lizard.yaml +50 -0
  5. lib_cli_exit_tools-1.6.0/.codacy/tools-configs/trivy.yaml +10 -0
  6. lib_cli_exit_tools-1.6.0/.devcontainer/devcontainer.json +22 -0
  7. lib_cli_exit_tools-1.6.0/.devcontainer/settings.json +6 -0
  8. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/.github/workflows/ci.yml +78 -30
  9. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/.github/workflows/release.yml +1 -1
  10. lib_cli_exit_tools-1.6.0/.qlty/qlty.toml +2 -0
  11. lib_cli_exit_tools-1.6.0/.snyk +5 -0
  12. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/AGENTS.md +9 -6
  13. lib_cli_exit_tools-1.6.0/CHANGELOG.md +110 -0
  14. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/CONTRIBUTING.md +16 -8
  15. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/DEVELOPMENT.md +7 -1
  16. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/INSTALL.md +5 -5
  17. lib_cli_exit_tools-1.6.0/Makefile +59 -0
  18. lib_cli_exit_tools-1.4.0/README.md → lib_cli_exit_tools-1.6.0/PKG-INFO +79 -4
  19. lib_cli_exit_tools-1.4.0/PKG-INFO → lib_cli_exit_tools-1.6.0/README.md +43 -35
  20. lib_cli_exit_tools-1.6.0/docs/system-design/module_reference.md +226 -0
  21. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/notebooks/Quickstart.ipynb +73 -1
  22. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/packaging/brew/Formula/lib-cli-exit-tools.rb +7 -8
  23. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/packaging/conda/recipe/meta.yaml +4 -4
  24. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/packaging/nix/flake.nix +7 -7
  25. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/pyproject.toml +47 -12
  26. lib_cli_exit_tools-1.6.0/scripts/__main__.py +7 -0
  27. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/_utils.py +148 -55
  28. lib_cli_exit_tools-1.6.0/scripts/build.py +78 -0
  29. lib_cli_exit_tools-1.6.0/scripts/bump.py +37 -0
  30. lib_cli_exit_tools-1.6.0/scripts/bump_major.py +24 -0
  31. lib_cli_exit_tools-1.6.0/scripts/bump_minor.py +24 -0
  32. lib_cli_exit_tools-1.6.0/scripts/bump_patch.py +24 -0
  33. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/bump_version.py +118 -57
  34. lib_cli_exit_tools-1.6.0/scripts/clean.py +48 -0
  35. lib_cli_exit_tools-1.6.0/scripts/cli.py +158 -0
  36. lib_cli_exit_tools-1.6.0/scripts/dev.py +25 -0
  37. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/generate_nix_flake.py +74 -34
  38. lib_cli_exit_tools-1.6.0/scripts/install.py +25 -0
  39. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/push.py +26 -14
  40. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/release.py +41 -25
  41. lib_cli_exit_tools-1.6.0/scripts/run_cli.py +51 -0
  42. lib_cli_exit_tools-1.6.0/scripts/test.py +429 -0
  43. lib_cli_exit_tools-1.6.0/scripts/version_current.py +25 -0
  44. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/__init__.py +46 -0
  45. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/__init__conf__.py +220 -0
  46. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/adapters/signals.py +189 -0
  47. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/application/runner.py +490 -0
  48. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/cli.py +211 -0
  49. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/core/configuration.py +68 -3
  50. lib_cli_exit_tools-1.6.0/src/lib_cli_exit_tools/core/exit_codes.py +344 -0
  51. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +29 -1
  52. lib_cli_exit_tools-1.6.0/tests/adapters/test_signals_poetry.py +119 -0
  53. lib_cli_exit_tools-1.6.0/tests/application/test_runner_poetry.py +385 -0
  54. lib_cli_exit_tools-1.6.0/tests/application/test_signal_poetry_posix.py +84 -0
  55. lib_cli_exit_tools-1.6.0/tests/application/test_signal_poetry_windows.py +93 -0
  56. lib_cli_exit_tools-1.6.0/tests/cli/test_cli_poetry.py +305 -0
  57. lib_cli_exit_tools-1.6.0/tests/conftest.py +28 -0
  58. lib_cli_exit_tools-1.6.0/tests/core/test_configuration.py +73 -0
  59. lib_cli_exit_tools-1.6.0/tests/core/test_exit_code_poetry.py +192 -0
  60. lib_cli_exit_tools-1.4.0/CHANGELOG.md +0 -89
  61. lib_cli_exit_tools-1.4.0/Makefile +0 -98
  62. lib_cli_exit_tools-1.4.0/docs/system-design/module_reference.md +0 -242
  63. lib_cli_exit_tools-1.4.0/qlty.toml +0 -2
  64. lib_cli_exit_tools-1.4.0/scripts/build.py +0 -66
  65. lib_cli_exit_tools-1.4.0/scripts/bump.py +0 -27
  66. lib_cli_exit_tools-1.4.0/scripts/bump_major.py +0 -17
  67. lib_cli_exit_tools-1.4.0/scripts/bump_minor.py +0 -17
  68. lib_cli_exit_tools-1.4.0/scripts/bump_patch.py +0 -17
  69. lib_cli_exit_tools-1.4.0/scripts/clean.py +0 -47
  70. lib_cli_exit_tools-1.4.0/scripts/dev.py +0 -18
  71. lib_cli_exit_tools-1.4.0/scripts/install.py +0 -19
  72. lib_cli_exit_tools-1.4.0/scripts/run_cli.py +0 -26
  73. lib_cli_exit_tools-1.4.0/scripts/test.py +0 -360
  74. lib_cli_exit_tools-1.4.0/scripts/version_current.py +0 -22
  75. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/__init__.py +0 -46
  76. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/__init__conf__.py +0 -230
  77. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/adapters/signals.py +0 -177
  78. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/application/runner.py +0 -323
  79. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/cli.py +0 -155
  80. lib_cli_exit_tools-1.4.0/src/lib_cli_exit_tools/core/exit_codes.py +0 -149
  81. lib_cli_exit_tools-1.4.0/tests/adapters/test_signals.py +0 -75
  82. lib_cli_exit_tools-1.4.0/tests/application/test_runner.py +0 -233
  83. lib_cli_exit_tools-1.4.0/tests/cli/test_cli_entrypoints.py +0 -103
  84. lib_cli_exit_tools-1.4.0/tests/conftest.py +0 -36
  85. lib_cli_exit_tools-1.4.0/tests/core/test_exit_codes.py +0 -151
  86. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/.env.example +0 -0
  87. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/.github/workflows/codeql.yml +0 -0
  88. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/.gitignore +0 -0
  89. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/LICENSE +0 -0
  90. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/codecov.yml +0 -0
  91. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/packaging/README.md +0 -0
  92. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/__init__.py +0 -0
  93. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/scripts/menu.py +0 -0
  94. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/__main__.py +0 -0
  95. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
  96. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/application/__init__.py +0 -0
  97. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/core/__init__.py +0 -0
  98. {lib_cli_exit_tools-1.4.0 → lib_cli_exit_tools-1.6.0}/src/lib_cli_exit_tools/py.typed +0 -0
@@ -0,0 +1 @@
1
+ mode: local
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env bash
2
+
3
+
4
+ set -e +o pipefail
5
+
6
+ # Set up paths first
7
+ bin_name="codacy-cli-v2"
8
+
9
+ # Determine OS-specific paths
10
+ os_name=$(uname)
11
+ arch=$(uname -m)
12
+
13
+ case "$arch" in
14
+ "x86_64")
15
+ arch="amd64"
16
+ ;;
17
+ "x86")
18
+ arch="386"
19
+ ;;
20
+ "aarch64"|"arm64")
21
+ arch="arm64"
22
+ ;;
23
+ esac
24
+
25
+ if [ -z "$CODACY_CLI_V2_TMP_FOLDER" ]; then
26
+ if [ "$(uname)" = "Linux" ]; then
27
+ CODACY_CLI_V2_TMP_FOLDER="$HOME/.cache/codacy/codacy-cli-v2"
28
+ elif [ "$(uname)" = "Darwin" ]; then
29
+ CODACY_CLI_V2_TMP_FOLDER="$HOME/Library/Caches/Codacy/codacy-cli-v2"
30
+ else
31
+ CODACY_CLI_V2_TMP_FOLDER=".codacy-cli-v2"
32
+ fi
33
+ fi
34
+
35
+ version_file="$CODACY_CLI_V2_TMP_FOLDER/version.yaml"
36
+
37
+
38
+ get_version_from_yaml() {
39
+ if [ -f "$version_file" ]; then
40
+ local version=$(grep -o 'version: *"[^"]*"' "$version_file" | cut -d'"' -f2)
41
+ if [ -n "$version" ]; then
42
+ echo "$version"
43
+ return 0
44
+ fi
45
+ fi
46
+ return 1
47
+ }
48
+
49
+ get_latest_version() {
50
+ local response
51
+ if [ -n "$GH_TOKEN" ]; then
52
+ response=$(curl -Lq --header "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
53
+ else
54
+ response=$(curl -Lq "https://api.github.com/repos/codacy/codacy-cli-v2/releases/latest" 2>/dev/null)
55
+ fi
56
+
57
+ handle_rate_limit "$response"
58
+ local version=$(echo "$response" | grep -m 1 tag_name | cut -d'"' -f4)
59
+ echo "$version"
60
+ }
61
+
62
+ handle_rate_limit() {
63
+ local response="$1"
64
+ if echo "$response" | grep -q "API rate limit exceeded"; then
65
+ fatal "Error: GitHub API rate limit exceeded. Please try again later"
66
+ fi
67
+ }
68
+
69
+ download_file() {
70
+ local url="$1"
71
+
72
+ echo "Downloading from URL: ${url}"
73
+ if command -v curl > /dev/null 2>&1; then
74
+ curl -# -LS "$url" -O
75
+ elif command -v wget > /dev/null 2>&1; then
76
+ wget "$url"
77
+ else
78
+ fatal "Error: Could not find curl or wget, please install one."
79
+ fi
80
+ }
81
+
82
+ download() {
83
+ local url="$1"
84
+ local output_folder="$2"
85
+
86
+ ( cd "$output_folder" && download_file "$url" )
87
+ }
88
+
89
+ download_cli() {
90
+ # OS name lower case
91
+ suffix=$(echo "$os_name" | tr '[:upper:]' '[:lower:]')
92
+
93
+ local bin_folder="$1"
94
+ local bin_path="$2"
95
+ local version="$3"
96
+
97
+ if [ ! -f "$bin_path" ]; then
98
+ echo "📥 Downloading CLI version $version..."
99
+
100
+ remote_file="codacy-cli-v2_${version}_${suffix}_${arch}.tar.gz"
101
+ url="https://github.com/codacy/codacy-cli-v2/releases/download/${version}/${remote_file}"
102
+
103
+ download "$url" "$bin_folder"
104
+ tar xzfv "${bin_folder}/${remote_file}" -C "${bin_folder}"
105
+ fi
106
+ }
107
+
108
+ # Warn if CODACY_CLI_V2_VERSION is set and update is requested
109
+ if [ -n "$CODACY_CLI_V2_VERSION" ] && [ "$1" = "update" ]; then
110
+ echo "⚠️ Warning: Performing update with forced version $CODACY_CLI_V2_VERSION"
111
+ echo " Unset CODACY_CLI_V2_VERSION to use the latest version"
112
+ fi
113
+
114
+ # Ensure version.yaml exists and is up to date
115
+ if [ ! -f "$version_file" ] || [ "$1" = "update" ]; then
116
+ echo "ℹ️ Fetching latest version..."
117
+ version=$(get_latest_version)
118
+ mkdir -p "$CODACY_CLI_V2_TMP_FOLDER"
119
+ echo "version: \"$version\"" > "$version_file"
120
+ fi
121
+
122
+ # Set the version to use
123
+ if [ -n "$CODACY_CLI_V2_VERSION" ]; then
124
+ version="$CODACY_CLI_V2_VERSION"
125
+ else
126
+ version=$(get_version_from_yaml)
127
+ fi
128
+
129
+
130
+ # Set up version-specific paths
131
+ bin_folder="${CODACY_CLI_V2_TMP_FOLDER}/${version}"
132
+
133
+ mkdir -p "$bin_folder"
134
+ bin_path="$bin_folder"/"$bin_name"
135
+
136
+ # Download the tool if not already installed
137
+ download_cli "$bin_folder" "$bin_path" "$version"
138
+ chmod +x "$bin_path"
139
+
140
+ run_command="$bin_path"
141
+ if [ -z "$run_command" ]; then
142
+ fatal "Codacy cli v2 binary could not be found."
143
+ fi
144
+
145
+ if [ "$#" -eq 1 ] && [ "$1" = "download" ]; then
146
+ echo "Codacy cli v2 download succeeded"
147
+ else
148
+ eval "$run_command $*"
149
+ fi
@@ -0,0 +1,15 @@
1
+ runtimes:
2
+ - dart@3.7.2
3
+ - go@1.22.3
4
+ - java@17.0.10
5
+ - node@22.2.0
6
+ - python@3.11.11
7
+ tools:
8
+ - dartanalyzer@3.7.2
9
+ - eslint@8.57.0
10
+ - lizard@1.17.31
11
+ - pmd@7.11.0
12
+ - pylint@3.3.6
13
+ - revive@1.7.0
14
+ - semgrep@1.78.0
15
+ - trivy@0.66.0
@@ -0,0 +1,50 @@
1
+ patterns:
2
+ Lizard_ccn-medium:
3
+ category: Complexity
4
+ description: Checks if the cyclomatic complexity of a function or logic block exceeds the medium threshold (default is 8).
5
+ explanation: |-
6
+ # Medium Cyclomatic Complexity control
7
+
8
+ Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Medium issue. The default threshold is 7.
9
+ id: Lizard_ccn-medium
10
+ level: Warning
11
+ severityLevel: Warning
12
+ threshold: 8
13
+ timeToFix: 10
14
+ title: Enforce Medium Cyclomatic Complexity Threshold
15
+ Lizard_file-nloc-medium:
16
+ category: Complexity
17
+ description: This rule checks if the number of lines of code (excluding comments) in a file exceeds a medium threshold, typically 500 lines.
18
+ explanation: ""
19
+ id: Lizard_file-nloc-medium
20
+ level: Warning
21
+ severityLevel: Warning
22
+ threshold: 500
23
+ timeToFix: 10
24
+ title: Enforce Medium File Length Limit Based on Number of Lines of Code
25
+ Lizard_nloc-medium:
26
+ category: Complexity
27
+ description: Checks if the number of lines of code (excluding comments) in a function exceeds a medium threshold (default 50 lines).
28
+ explanation: |-
29
+ # Medium NLOC control - Number of Lines of Code (without comments)
30
+
31
+ Check the number of lines of code (without comments) in a function. If the threshold is not met, raise a Medium issue. The default threshold is 50.
32
+ id: Lizard_nloc-medium
33
+ level: Warning
34
+ severityLevel: Warning
35
+ threshold: 50
36
+ timeToFix: 10
37
+ title: Enforce Medium Number of Lines of Code (NLOC) Limit
38
+ Lizard_parameter-count-medium:
39
+ category: Complexity
40
+ description: This rule checks the number of parameters passed to a function and raises an issue if it exceeds a medium threshold, which by default is 8 parameters.
41
+ explanation: |-
42
+ # Medium Parameter count control
43
+
44
+ Check the number of parameters sent to a function. If the threshold is not met, raise a Medium issue. The default threshold is 5.
45
+ id: Lizard_parameter-count-medium
46
+ level: Warning
47
+ severityLevel: Warning
48
+ threshold: 8
49
+ timeToFix: 10
50
+ title: Enforce Medium Parameter Count Limit
@@ -0,0 +1,10 @@
1
+ severity:
2
+ - LOW
3
+ - MEDIUM
4
+ - HIGH
5
+ - CRITICAL
6
+
7
+ scan:
8
+ scanners:
9
+ - vuln
10
+ - secret
@@ -0,0 +1,22 @@
1
+ {
2
+ "image": "mcr.microsoft.com/devcontainers/python:3.13",
3
+
4
+ "postCreateCommand": "bash -lc '\nPY=/usr/local/bin/python;\n$PY -m pip install -U pip && \\\n$PY -m pip install ipykernel && \\\n$PY -m pip install -e . && \\\n# register kernel using this exact interpreter\n$PY -m ipykernel install --name=python3 --display-name=\"Python 3 (3.13)\" --user && \\\n# patch the notebook to point to the python3 kernelspec (VS Code will bind to /usr/local/bin/python)\n$PY - <<\"PY\"\nimport json, pathlib\np = pathlib.Path(\"notebooks/Quickstart.ipynb\")\nif p.exists():\n nb = json.loads(p.read_text(encoding=\"utf-8\"))\n md = nb.setdefault(\"metadata\", {})\n md[\"kernelspec\"] = {\n \"name\": \"python3\",\n \"display_name\": \"Python 3 (3.13)\",\n \"language\": \"python\"\n }\n md[\"language_info\"] = {\"name\": \"python\"}\n p.write_text(json.dumps(nb, ensure_ascii=False, indent=1), encoding=\"utf-8\")\n print(\"Pinned kernelspec to python3 in\", p)\nelse:\n print(\"Notebook not found:\", p)\nPY'\n",
5
+
6
+ "customizations": {
7
+ "vscode": {
8
+ "extensions": ["ms-toolsai.jupyter", "ms-python.python"],
9
+ "settings": {
10
+ "workbench.startupEditor": "none",
11
+ "jupyter.alwaysTrustNotebooks": true,
12
+ "jupyter.kernelPickerType": "OnlyRecommended",
13
+ "python.defaultInterpreterPath": "/usr/local/bin/python"
14
+ }
15
+ },
16
+ "codespaces": {
17
+ "openFiles": ["README.md"]
18
+ }
19
+ },
20
+
21
+ "postAttachCommand": "bash -lc 'if [ -f notebooks/Quickstart.ipynb ]; then code -r notebooks/Quickstart.ipynb; fi'"
22
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "python.defaultInterpreterPath": "/usr/local/bin/python3.13",
3
+ "jupyter.alwaysTrustNotebooks": true,
4
+ "jupyter.kernelPickerType": "OnlyRecommended",
5
+ "jupyter.askForKernelRestart": false
6
+ }
@@ -14,13 +14,31 @@ jobs:
14
14
  fail-fast: false
15
15
  matrix:
16
16
  os: [ubuntu-latest, macos-latest, windows-latest]
17
- # Test against Python 3.10 and the latest 3.x available on Actions runners
18
- python: ["3.10", "3.x"]
17
+ # Test against Python 3.13 and the latest 3.x available on Actions runners
18
+ python: ["3.13", "3.x"]
19
19
  steps:
20
20
  - uses: actions/checkout@v4
21
21
  - uses: actions/setup-python@v5
22
22
  with:
23
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")
24
42
  - name: Install make on Windows
25
43
  if: runner.os == 'Windows'
26
44
  shell: pwsh
@@ -30,8 +48,7 @@ jobs:
30
48
  - name: Install dev deps
31
49
  shell: bash
32
50
  run: |
33
- python -m pip install --upgrade pip
34
- python -m pip install --upgrade click rich rich-click
51
+ python -m pip install --upgrade "pip!=25.2"
35
52
  pip install -e .[dev]
36
53
  - name: Run full test suite (lint, types, tests, coverage, codecov)
37
54
  shell: bash
@@ -45,7 +62,14 @@ jobs:
45
62
  python -m venv .venv_wheel
46
63
  . .venv_wheel/bin/activate 2>/dev/null || . .venv_wheel/Scripts/activate 2>/dev/null
47
64
  pip install dist/*.whl
48
- lib_cli_exit_tools --version || python -m lib_cli_exit_tools --version
65
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
66
+ - name: Verify sdist install in clean env
67
+ shell: bash
68
+ run: |
69
+ python -m venv .venv_sdist
70
+ . .venv_sdist/bin/activate 2>/dev/null || . .venv_sdist/Scripts/activate 2>/dev/null
71
+ pip install dist/*.tar.gz
72
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
49
73
 
50
74
  pipx-uv:
51
75
  name: pipx/uv verification (ubuntu)
@@ -54,22 +78,43 @@ jobs:
54
78
  - uses: actions/checkout@v4
55
79
  - uses: actions/setup-python@v5
56
80
  with:
57
- python-version: "3.12"
81
+ python-version: "3.13"
82
+ - name: Extract project metadata
83
+ shell: python
84
+ run: |
85
+ import os
86
+ import tomllib
87
+ from pathlib import Path
88
+
89
+ data = tomllib.loads(Path('pyproject.toml').read_text('utf-8'))
90
+ project = data['project']['name']
91
+ module = project.replace('-', '_')
92
+ dash = project.replace('_', '-')
93
+ scripts = list(data['project'].get('scripts', {}).keys())
94
+ cli_bin = scripts[0] if scripts else dash
95
+
96
+ with open(os.environ['GITHUB_ENV'], 'a', encoding='utf-8') as env:
97
+ env.write(f"PROJECT_NAME={project}\n")
98
+ env.write(f"PACKAGE_MODULE={module}\n")
99
+ env.write(f"CLI_BIN={cli_bin}\n")
58
100
  - name: Build wheel
59
101
  run: |
60
- python -m pip install --upgrade pip build
102
+ python -m pip install --upgrade "pip!=25.2"
103
+ python -m pip install --upgrade build
61
104
  python -m build
62
105
  - name: pipx install from wheel
63
106
  run: |
64
107
  python -m pip install pipx
65
108
  pipx install dist/*.whl
66
- lib_cli_exit_tools --version
109
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
110
+ - name: Install uv
111
+ uses: astral-sh/setup-uv@v7
112
+ with:
113
+ enable-cache: true
67
114
  - name: uv tool install
68
115
  run: |
69
- curl -LsSf https://astral.sh/uv/install.sh | sh
70
- export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$HOME/.local/share/uv/bin:$PATH"
71
116
  uv tool install .
72
- lib_cli_exit_tools --version
117
+ "$CLI_BIN" --version 2>/dev/null || python -m "$PACKAGE_MODULE" --version
73
118
 
74
119
  # nix and conda packaging builds are disabled for now to keep CI green.
75
120
  nix:
@@ -78,7 +123,7 @@ jobs:
78
123
  steps:
79
124
  - uses: actions/checkout@v4
80
125
  - name: Install Nix (flakes)
81
- uses: cachix/install-nix-action@v27
126
+ uses: cachix/install-nix-action@v31
82
127
  with:
83
128
  extra_nix_config: |
84
129
  experimental-features = nix-command flakes
@@ -97,7 +142,7 @@ jobs:
97
142
  uses: conda-incubator/setup-miniconda@v3
98
143
  with:
99
144
  auto-update-conda: true
100
- python-version: "3.12"
145
+ python-version: "3.13"
101
146
  - name: Build conda recipe (local source, no test)
102
147
  shell: bash -l {0}
103
148
  env:
@@ -109,16 +154,16 @@ jobs:
109
154
  conda build packaging/conda/recipe --no-test -c conda-forge -c defaults
110
155
 
111
156
  notebooks:
112
- name: Execute notebooks (ubuntu, Python 3.10)
157
+ name: Execute notebooks (ubuntu, Python 3.13)
113
158
  runs-on: ubuntu-latest
114
159
  steps:
115
160
  - uses: actions/checkout@v4
116
161
  - uses: actions/setup-python@v5
117
162
  with:
118
- python-version: "3.10"
163
+ python-version: "3.13"
119
164
  - name: Install notebook runner deps
120
165
  run: |
121
- python -m pip install --upgrade pip
166
+ python -m pip install --upgrade "pip!=25.2"
122
167
  pip install nbclient nbformat ipykernel jupyter_client
123
168
  python -m ipykernel install --user --name python3 --display-name "Python 3"
124
169
  - name: Execute Quickstart notebook
@@ -178,21 +223,21 @@ jobs:
178
223
  - name: Verify packaging matches pyproject
179
224
  run: |
180
225
  python - << 'PY'
181
- import re, sys
226
+ import re, sys, tomllib
182
227
  from pathlib import Path
183
228
 
184
- py = Path('pyproject.toml').read_text(encoding='utf-8')
185
- m_ver = re.search(r'^version\s*=\s*"([^"]+)"', py, re.M)
186
- m_req = re.search(r'^requires-python\s*=\s*"([^"]+)"', py, re.M)
187
- if not (m_ver and m_req):
188
- print('pyproject missing version or requires-python'); sys.exit(1)
189
- version = m_ver.group(1)
190
- requires = m_req.group(1)
191
- m_min = re.search(r'>=\s*(3\.[0-9]+)', requires)
192
- if not m_min:
193
- print('requires-python must be like ">=3.X"'); sys.exit(1)
194
- min_py = m_min.group(1)
229
+ data = tomllib.loads(Path('pyproject.toml').read_text(encoding='utf-8'))
230
+ project = data['project']['name']
231
+ version = data['project']['version']
232
+ requires = data['project']['requires-python']
233
+
234
+ min_match = re.search(r'([0-9]+\.[0-9]+)', requires)
235
+ if not min_match:
236
+ print('requires-python must declare a minimum like ">=3.X"'); sys.exit(1)
237
+ min_py = min_match.group(1)
195
238
  min_digits = min_py.replace('.', '')
239
+ project_dash = project.replace('_', '-')
240
+ project_module = project.replace('-', '_')
196
241
 
197
242
  # Conda
198
243
  conda = Path('packaging/conda/recipe/meta.yaml').read_text(encoding='utf-8')
@@ -202,7 +247,10 @@ jobs:
202
247
  print('conda/meta.yaml: python constraint not aligned (host/run)'); sys.exit(1)
203
248
 
204
249
  # Brew
205
- brew = Path('packaging/brew/Formula/lib-cli-exit-tools.rb').read_text(encoding='utf-8')
250
+ brew_path = Path(f'packaging/brew/Formula/{project_dash}.rb')
251
+ if not brew_path.exists():
252
+ print(f'brew formula missing: {brew_path}'); sys.exit(1)
253
+ brew = brew_path.read_text(encoding='utf-8')
206
254
  if f"refs/tags/v{version}.tar.gz" not in brew:
207
255
  print('brew formula: url tag mismatch'); sys.exit(1)
208
256
  if f'"python@{min_py}"' not in brew:
@@ -210,7 +258,7 @@ jobs:
210
258
 
211
259
  # Nix
212
260
  nix = Path('packaging/nix/flake.nix').read_text(encoding='utf-8')
213
- if not re.search(r'pname\s*=\s*"lib_cli_exit_tools";\s*[^}]*?version\s*=\s*"' + re.escape(version) + r'";', nix, re.S):
261
+ if not re.search(r'pname\s*=\s*"' + re.escape(project_module) + r'";\s*[^}]*?version\s*=\s*"' + re.escape(version) + r'";', nix, re.S):
214
262
  print('nix flake: version mismatch'); sys.exit(1)
215
263
  if not re.search(r'pypkgs\s*=\s*pkgs\.python' + re.escape(min_digits) + r'Packages', nix):
216
264
  print('nix flake: python package set not aligned'); sys.exit(1)
@@ -24,7 +24,7 @@ jobs:
24
24
  fi
25
25
  - uses: actions/setup-python@v5
26
26
  with:
27
- python-version: '3.12'
27
+ python-version: '3.13'
28
28
  - name: Build artifacts
29
29
  run: |
30
30
  python -m pip install --upgrade pip build
@@ -0,0 +1,2 @@
1
+ exclude_patterns = ["scripts/**"]
2
+ test_patterns = ["tests/**"]
@@ -0,0 +1,5 @@
1
+ # Snyk (https://snyk.io) policy file
2
+ exclude:
3
+ global:
4
+ - scripts/**
5
+ - tests/**
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## On session start
4
4
 
5
+ whenever You wait for user input or finished, execute "paplay /usr/share/sounds/codex/ready.wav"
6
+ whenever You have a question, execute "paplay /usr/share/sounds/codex/ready.wav"
7
+ whenever You have an error, execute "paplay /usr/share/sounds/codex/error.wav"
8
+
5
9
  Review the system prompt files in `/media/srv-main/softdev/*/projects/softwarestack/systemprompts` and keep their guidance in working memory:
6
10
 
7
11
  - core_programming_solid.md
@@ -16,6 +20,7 @@ Review the system prompt files in `/media/srv-main/softdev/*/projects/softwarest
16
20
  - python_jupyter_notebooks.md
17
21
  - python_testing.md
18
22
 
23
+
19
24
  always apply those Rules :
20
25
 
21
26
  - core_programming_solid.md
@@ -47,7 +52,7 @@ when writing or refracturing Python scripts, apply those Rules :
47
52
 
48
53
  - Single source of truth for the package version is `pyproject.toml` (`[project].version`).
49
54
  - Runtime code reads metadata via `importlib.metadata`; do not duplicate the version in code files.
50
- - On a version bump, update only `pyproject.toml` and the `CHANGELOG.md` entry; do not edit `src/lib_cli_exit_tools/__init__conf__.py` for versioning.
55
+ - On a version bump, update only `pyproject.toml` and the `CHANGELOG.md` entry; runtime code should continue to read the version via `importlib.metadata` (no separate `__init__conf__` file).
51
56
  - Tag releases `vX.Y.Z` and push tags; CI will build artifacts and publish when configured.
52
57
 
53
58
  ### Common Make Targets (Alphabetical)
@@ -73,6 +78,7 @@ when writing or refracturing Python scripts, apply those Rules :
73
78
 
74
79
 
75
80
  ## Coding Style & Naming Conventions
81
+ - apply python_clean_code.md
76
82
 
77
83
  ## Commit & Pull Request Guidelines
78
84
 
@@ -88,23 +94,20 @@ when writing or refracturing Python scripts, apply those Rules :
88
94
  ## Translations (App UI Strings)
89
95
 
90
96
  ## Changes in WEB Documentation
91
-
92
97
  - when asked to update documentation - only do that in the english docs under /website/docs because other languages will be translated automatically,
93
98
  unless stated otherwise by the user. In doubt - ask the user
94
99
 
95
100
  ## Changes in APP Strings
96
-
97
101
  - when i18 strings are changed, only to that in sources/\_locales/en because other languages will be translated automatically,
98
102
  unless stated otherwise by the user. In doubt - ask the user
99
103
 
100
104
  ## commit/push/GitHub policy
101
-
102
105
  - run "make test" before any push to avoid lint/test breakage.
103
106
  - after push, monitor errors in the github actions and try to correct the errors
104
107
 
105
- ---
108
+ ---
106
109
 
107
- # ONLY ON USER REQEST !!!! :
110
+ # ONLY ON USER REQEST !!!! :
108
111
 
109
112
  # 📘 Documentation Review & Enhancement Prompt
110
113
 
@@ -0,0 +1,110 @@
1
+ # Changelog
2
+
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
+
5
+
6
+ ## [1.6.0] - 2025-10-08
7
+
8
+ ### Added
9
+ - Property-based (Hypothesis) tests covering `SystemExit` payload handling and configurable broken-pipe exit codes.
10
+ - POSIX integration test that drives a subprocess through a SIGINT to assert real signal handling behaviour.
11
+
12
+ ### Changed
13
+ - Local `make test` runs skip packaging-sync enforcement unless running in CI or with `ENFORCE_PACKAGING_SYNC=1`, reducing friction for contributors.
14
+ - CLI rich-click styling now preserves coloured tracebacks when stderr supports UTF/TTY output even if stdout is piped.
15
+ - Centralised public API exports so `lib_cli_exit_tools` and its facade share a single authoritative symbol list.
16
+
17
+ ### Security
18
+ - Suppress pip-audit false positive for GHSA-4xh5-x5gv-qwph until an official fixed pip build is published.
19
+
20
+ ## [1.5.0] - 2025-10-08
21
+
22
+ ### Added
23
+ - Configuration helpers `config_overrides` and `reset_config` so embedders can
24
+ safely tweak and restore global CLI settings without bespoke fixtures.
25
+ - Expanded OS-aware test coverage (sysexits mappings, signal restoration, CLI
26
+ behaviours) and rewritten specs that no longer rely on private helpers.
27
+ - CI job that executes the Quickstart notebook on Python 3.13 and validations that ensure packaging metadata stays in sync at tag time.
28
+ - Automation that keeps Conda, Homebrew, and Nix specs aligned with `pyproject.toml`, including a dedicated `--sync-packaging` mode.
29
+ - Regression tests covering `SystemExit` variants, tolerant output rendering, English signal messages, and ValueError mappings on Windows.
30
+
31
+ ### Changed
32
+ - Hardened `get_system_exit_code` handling for non-integer payloads and switched OS detection to `os.name`.
33
+ - Updated `_print_output` to decode both `bytes` and `str`, trimming assertions in favour of resilient diagnostics.
34
+ - Standardised signal messages (“Aborted (SIGINT).”, etc.) and cached metadata lookups in `__init__conf__`.
35
+ - Enforced an 85% coverage threshold (in line with `pyproject.toml` and Codecov settings) and removed spurious coverage pragmas to reflect the new test suite.
36
+ - Repartitioned the library into `core`, `adapters`, and `application` layers with `lib_cli_exit_tools` acting as the facade.
37
+ - `run_cli` now accepts injectable `exception_handler` and `signal_installer` hooks, and rich-click configuration is applied lazily from `main()`.
38
+
39
+ ### Fixed
40
+ - Restored Pyright compatibility by typing metadata helpers against a minimal protocol.
41
+ - Removed a Ruff F401 false positive on the Quickstart notebook via per-file ignore.
42
+
43
+ ### Documentation
44
+ - Expanded the README with packaging sync guidance and notebook usage notes.
45
+ - Clarified release steps in CONTRIBUTING and refreshed developer docs.
46
+
47
+ ## [1.4.0] - 2025-09-26
48
+
49
+ ### Changed
50
+ - Refactored packaging automation and broadened the pytest suite to cover new CLI flows.
51
+
52
+ ## [1.3.1] - 2025-09-26
53
+
54
+ ### Fixed
55
+ - Adjusted coloured traceback behaviour to address regressions introduced in 1.3.0.
56
+
57
+ ## [1.3.0] - 2025-09-25
58
+
59
+ ### Added
60
+ - Introduced Rich-powered traceback rendering for CLI failures.
61
+
62
+ ## [1.2.0] - 2025-09-25
63
+
64
+ ### Changed
65
+ - Switched the CLI stack to rich-click and delivered associated fixes.
66
+
67
+ ## [1.1.1] - 2025-09-18
68
+
69
+ ### Added
70
+ - Documentation and doctest updates for newly exposed helpers.
71
+
72
+ ## [1.1.0] - 2025-09-16
73
+
74
+ ### Added
75
+ - `lib_cli_exit_tools.run_cli` helper to reduce Click boilerplate (see `cli.py`).
76
+
77
+ ## [1.0.3] - 2025-09-16
78
+
79
+ ### Added
80
+ - `make menu` target for the Textual-powered maintenance UI.
81
+
82
+ ## [1.0.2] - 2025-09-15
83
+
84
+ ### Changed
85
+ - Miscellaneous internal improvements.
86
+
87
+ ## [1.0.1] - 2025-09-15
88
+
89
+ ### Changed
90
+ - Miscellaneous internal improvements.
91
+
92
+ ## [1.0.0] - 2025-09-15
93
+
94
+ ### Added
95
+ - Initial public release.
96
+
97
+ ## [0.1.1] - 2025-09-15
98
+
99
+ ### Added
100
+ - Placeholder for early internal work.
101
+
102
+ ## [0.1.0] - 2025-09-14
103
+
104
+ ### Added
105
+ - Unified package naming, tightened public API exports, and added tests for exit-code mapping and CLI behaviour.
106
+
107
+ ## [0.0.1] - 2025-09-13
108
+
109
+ ### Added
110
+ - Initial internal release.