bitranox-template-py-cli 1.7.1__tar.gz → 1.7.2__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.
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/CHANGELOG.md +9 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/Makefile +38 -4
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/PKG-INFO +14 -14
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/pyproject.toml +14 -14
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/__init__conf__.py +1 -1
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/safe_console.py +9 -4
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/overrides.py +69 -2
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_config_overrides.py +32 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_safe_console.py +24 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.devcontainer/devcontainer.json +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.devcontainer/settings.json +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.env.example +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.gitattributes +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/actions/extract-metadata/action.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/dependabot.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/workflows/codeql.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/workflows/default_cicd_public.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/workflows/default_release_public.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.gitignore +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.qlty/qlty.toml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.snyk +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/CONFIG.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/CONTRIBUTING.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/DEVELOPMENT.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/INSTALL.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/LICENSE +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/README.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/SECURITY.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/ai-stance.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/ai-transparency.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/codecov.yml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/docs/adr/0001-memory-adapters-in-src.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/docs/systemdesign/module_reference.md +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/notebooks/Quickstart.ipynb +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/rename.sh +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/rename_dry.sh +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/reset_git_history.sh +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/__main__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/config.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/email/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/email/_common.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/email/send_email.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/email/send_notification.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/info.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/commands/logging.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/constants.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/context.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/exit_codes.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/main.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/root.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/cli/typed_click.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/defaultconfig.d/40-layered-config.toml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/defaultconfig.d/50-mail.toml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/defaultconfig.d/90-logging.toml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/defaultconfig.toml +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/deploy.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/display.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/loader.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/permissions.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/config/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/config.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/sender.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/transport.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/email/validation.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/logging/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/logging/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/logging/setup.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/memory/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/memory/config.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/memory/email.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/memory/logging.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/adapters/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/application/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/application/ports.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/application/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/composition/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/composition/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/domain/__init__.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/domain/behaviors.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/domain/enums.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/domain/errors.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/domain/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/entry.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/src/bitranox_template_py_cli/py.typed +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/conftest.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_behaviors.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cache_effectiveness.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_config.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_core.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_email.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_env_file.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_exit_codes.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_overrides.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_validation.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_deploy_permissions.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_display.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_enums.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_errors.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_logging.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_mail.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_metadata.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_metadata_sync.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_module_entry.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_ports.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_property_email.py +0 -0
- {bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_property_overrides.py +0 -0
|
@@ -6,6 +6,15 @@ the [Keep a Changelog](https://keepachangelog.com/) format.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.7.2] 2026-09-12 02:11:47
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **`--set` overrides now report the CLI as their source.** `Config.with_overrides` returns the
|
|
13
|
+
merged data with the ORIGINAL provenance map by design, so an overridden key kept naming the
|
|
14
|
+
file it replaced and `config` sent a reader to a file holding the old value. The override path
|
|
15
|
+
rebuilds provenance, naming layer `cli` with no path for exactly the keys `--set` supplied and
|
|
16
|
+
leaving every other key's source alone.
|
|
17
|
+
|
|
9
18
|
## [1.7.1] 2026-08-01 01:02:45
|
|
10
19
|
|
|
11
20
|
Re-release of 1.7.0, which was tagged but never published: PyPI rejected the upload because
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# BMK MAKEFILE 3.
|
|
1
|
+
# BMK MAKEFILE 3.17.0
|
|
2
2
|
# do not alter this file - it might be overwritten on new versions of BMK
|
|
3
3
|
# if You want to alter it, remove the first line # BMK MAKEFILE 1.0 - then it is a custom makefile and will not be overwritten
|
|
4
4
|
# bmk Makefile - thin wrapper using `uv tool upgrade` for persistent bmk
|
|
@@ -186,16 +186,50 @@ endif
|
|
|
186
186
|
# BMK_MIN floors the FALLBACK install. The upgrade path does not consult it: uv re-resolves
|
|
187
187
|
# the requirement recorded at install time, which is itself a `bmk>=...`, so it always lands
|
|
188
188
|
# on the newest release and clears the floor anyway.
|
|
189
|
-
BMK_MIN := 3.
|
|
189
|
+
BMK_MIN := 3.17.0
|
|
190
190
|
|
|
191
191
|
# Absent env, missing check, or damaged env - all three mean "do not upgrade, rebuild".
|
|
192
192
|
# `test -x` keeps a fresh machine quiet: there is no interpreter to run yet.
|
|
193
193
|
BMK_INTACT := $(if $(BMK_PY),test -x "$(BMK_PY)" && "$(BMK_PY)" -m bmk_selfcheck,false)
|
|
194
194
|
|
|
195
|
+
# The env this recipe mutates is shared by EVERY repo on the machine, so the mutation has to
|
|
196
|
+
# wait for the bmk processes running out of it. Every bmk started from that env holds a
|
|
197
|
+
# SHARED lock on <uv tool dir>/.bmk-tool.lock for its whole lifetime; these wrappers take
|
|
198
|
+
# the same lock EXCLUSIVE for the length of the upgrade. Without it, a make here deleted the
|
|
199
|
+
# site-packages out from under a bmk minutes into a test suite in an UNRELATED repo, and it
|
|
200
|
+
# surfaced as an ImportError inside bmk's OWN dependencies that cleared on a re-run - so it
|
|
201
|
+
# read as a flake rather than as the environment vanishing mid-gate.
|
|
202
|
+
#
|
|
203
|
+
# `bmk_toollock` is a second stdlib-only TOP-LEVEL module bmk ships, run on the tool env's
|
|
204
|
+
# own interpreter. That is not circular: a uv tool env's bin/python is a SYMLINK to a base
|
|
205
|
+
# interpreter OUTSIDE the tool dir, so the stdlib the guard runs on is not part of the tree
|
|
206
|
+
# uv is about to replace, and the guard is read and compiled before uv is ever spawned.
|
|
207
|
+
#
|
|
208
|
+
# NOT uv's own <uv tool dir>/.lock, which uv does honour: `uv tool upgrade` and `uv tool
|
|
209
|
+
# list` block on it too (measured), and the upgrade runs before every target - so a
|
|
210
|
+
# gate-lifetime shared lock there would make every make on the machine, and every unrelated
|
|
211
|
+
# `uv tool install`, wait for the longest-running gate.
|
|
212
|
+
#
|
|
213
|
+
# $(wildcard) rather than a shell test: on a machine with no tool env yet these expand to
|
|
214
|
+
# NOTHING and the install runs bare, which is exactly what a first install needs.
|
|
215
|
+
#
|
|
216
|
+
# The bounded wait is load-bearing in both directions. An unbounded one would serialise
|
|
217
|
+
# every repo's make behind the longest gate on the machine. A SKIPPED upgrade costs nothing
|
|
218
|
+
# (the next make picks it up), so the upgrade skips. The REPAIR may not skip: proceeding
|
|
219
|
+
# would leave a damaged env in place, so it fails and drops through to the retry.
|
|
220
|
+
#
|
|
221
|
+
# The LAST attempt is deliberately NEVER guarded, and a test pins that. The guard lives
|
|
222
|
+
# inside the env being repaired, so on the path where that env is absent or broken the guard
|
|
223
|
+
# may be broken too; an unguarded last resort is what stops a defective guard from making
|
|
224
|
+
# `make` unrunnable in every repo at once. If bmk_toollock ever falls out of the wheel, every
|
|
225
|
+
# make everywhere drops to a full reinstall - there is a packaging test for exactly that.
|
|
226
|
+
BMK_LOCK := $(if $(wildcard $(BMK_PY)),"$(BMK_PY)" -m bmk_toollock --exclusive --timeout 10 --on-timeout skip --,)
|
|
227
|
+
BMK_LOCK_REPAIR := $(if $(wildcard $(BMK_PY)),"$(BMK_PY)" -m bmk_toollock --exclusive --timeout 60 --on-timeout fail --,)
|
|
228
|
+
|
|
195
229
|
.PHONY: _ensure_bmk
|
|
196
230
|
_ensure_bmk:
|
|
197
|
-
@$(BMK_INTACT) && uv tool upgrade bmk \
|
|
198
|
-
|| uv tool install --reinstall --force "bmk>=$(BMK_MIN)" \
|
|
231
|
+
@$(BMK_INTACT) && $(BMK_LOCK) uv tool upgrade bmk \
|
|
232
|
+
|| $(BMK_LOCK_REPAIR) uv tool install --reinstall --force "bmk>=$(BMK_MIN)" \
|
|
199
233
|
|| uv tool install --reinstall --force "bmk>=$(BMK_MIN)"
|
|
200
234
|
|
|
201
235
|
# ──────────────────────────────────────────────────────────────
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: bitranox_template_py_cli
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.2
|
|
4
4
|
Summary: Template CLI application with configuration management and structured logging
|
|
5
5
|
Project-URL: Homepage, https://github.com/bitranox/bitranox_template_py_cli
|
|
6
6
|
Project-URL: Repository, https://github.com/bitranox/bitranox_template_py_cli.git
|
|
@@ -25,30 +25,30 @@ Requires-Dist: btx-lib-mail>=1.5.2
|
|
|
25
25
|
Requires-Dist: lib-cli-exit-tools>=2.3.4
|
|
26
26
|
Requires-Dist: lib-layered-config>=5.6.2
|
|
27
27
|
Requires-Dist: lib-log-rich>=6.3.7
|
|
28
|
-
Requires-Dist: orjson>=3.
|
|
29
|
-
Requires-Dist: pydantic>=2.13.
|
|
30
|
-
Requires-Dist: rich-click>=1.9.
|
|
28
|
+
Requires-Dist: orjson>=3.12.0
|
|
29
|
+
Requires-Dist: pydantic>=2.13.5
|
|
30
|
+
Requires-Dist: rich-click>=1.9.9
|
|
31
31
|
Provides-Extra: dev
|
|
32
32
|
Requires-Dist: bandit>=1.9.4; extra == 'dev'
|
|
33
|
-
Requires-Dist: build>=1.
|
|
34
|
-
Requires-Dist: click>=8.
|
|
35
|
-
Requires-Dist: httpx2>=2.
|
|
36
|
-
Requires-Dist: hypothesis>=6.
|
|
37
|
-
Requires-Dist: import-linter>=2.
|
|
33
|
+
Requires-Dist: build>=1.6.1; extra == 'dev'
|
|
34
|
+
Requires-Dist: click>=8.5.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: httpx2>=2.12.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: hypothesis>=6.168.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: import-linter>=2.15; extra == 'dev'
|
|
38
38
|
Requires-Dist: jaraco-context>=6.1.2; extra == 'dev'
|
|
39
39
|
Requires-Dist: pip-audit>=2.10.1; extra == 'dev'
|
|
40
40
|
Requires-Dist: pynacl>=1.6.2; extra == 'dev'
|
|
41
|
-
Requires-Dist: pyright[nodejs]>=1.1.
|
|
41
|
+
Requires-Dist: pyright[nodejs]>=1.1.414; extra == 'dev'
|
|
42
42
|
Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
|
|
43
43
|
Requires-Dist: pytest>=9.1.1; extra == 'dev'
|
|
44
44
|
Requires-Dist: python-multipart>=0.0.32; extra == 'dev'
|
|
45
45
|
Requires-Dist: rtoml>=0.13.0; extra == 'dev'
|
|
46
|
-
Requires-Dist: ruff>=0.16.
|
|
46
|
+
Requires-Dist: ruff>=0.16.7; extra == 'dev'
|
|
47
47
|
Requires-Dist: textual>=8.2.8; extra == 'dev'
|
|
48
48
|
Requires-Dist: twine>=7.0.0; extra == 'dev'
|
|
49
49
|
Requires-Dist: urllib3>=2.7.0; extra == 'dev'
|
|
50
|
-
Requires-Dist: virtualenv>=21.7.
|
|
51
|
-
Requires-Dist: wheel>=0.
|
|
50
|
+
Requires-Dist: virtualenv>=21.7.9; extra == 'dev'
|
|
51
|
+
Requires-Dist: wheel>=0.48.0; extra == 'dev'
|
|
52
52
|
Description-Content-Type: text/markdown
|
|
53
53
|
|
|
54
54
|
# bitranox_template_py_cli
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "bitranox_template_py_cli"
|
|
3
|
-
version = "1.7.
|
|
3
|
+
version = "1.7.2"
|
|
4
4
|
description = "Template CLI application with configuration management and structured logging"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"rich-click>=1.9.
|
|
8
|
+
"rich-click>=1.9.9",
|
|
9
9
|
"lib_cli_exit_tools>=2.3.4",
|
|
10
10
|
"lib_log_rich>=6.3.7",
|
|
11
11
|
"lib_layered_config>=5.6.2",
|
|
12
12
|
"btx_lib_mail>=1.5.2",
|
|
13
|
-
"pydantic>=2.13.
|
|
14
|
-
"orjson>=3.
|
|
13
|
+
"pydantic>=2.13.5",
|
|
14
|
+
"orjson>=3.12.0",
|
|
15
15
|
]
|
|
16
16
|
license = { text = "MIT" }
|
|
17
17
|
authors = [{ name = "bitranox", email = "bitranox@gmail.com" }]
|
|
@@ -48,13 +48,13 @@ Issues = "https://github.com/bitranox/bitranox_template_py_cli/issues"
|
|
|
48
48
|
dev = [
|
|
49
49
|
"pytest>=9.1.1",
|
|
50
50
|
"pytest-cov>=7.1.0",
|
|
51
|
-
"hypothesis>=6.
|
|
52
|
-
"ruff>=0.16.
|
|
53
|
-
"pyright[nodejs]>=1.1.
|
|
51
|
+
"hypothesis>=6.168.0",
|
|
52
|
+
"ruff>=0.16.7",
|
|
53
|
+
"pyright[nodejs]>=1.1.414",
|
|
54
54
|
"bandit>=1.9.4",
|
|
55
55
|
# 1.5.1 was yanked upstream (unintended breaking changes), so 1.5.0 is the newest usable
|
|
56
56
|
# release; a >=1.5.1 floor has ZERO candidates and makes this extra unresolvable.
|
|
57
|
-
"build>=1.
|
|
57
|
+
"build>=1.6.1",
|
|
58
58
|
"twine>=7.0.0",
|
|
59
59
|
# codecov-cli is disabled, not dropped: it requires click<8.3.0, which drags click back to
|
|
60
60
|
# 8.2.1 - the version with CVE-2026-7246 (command injection in click.edit(), fixed in 8.3.3).
|
|
@@ -65,17 +65,17 @@ dev = [
|
|
|
65
65
|
# "codecov-cli>=11.2.8",
|
|
66
66
|
"pip-audit>=2.10.1",
|
|
67
67
|
"textual>=8.2.8",
|
|
68
|
-
"import-linter>=2.
|
|
68
|
+
"import-linter>=2.15",
|
|
69
69
|
"rtoml>=0.13.0",
|
|
70
|
-
"httpx2>=2.
|
|
70
|
+
"httpx2>=2.12.0",
|
|
71
71
|
# Transitive CVE pins
|
|
72
|
-
"click>=8.
|
|
72
|
+
"click>=8.5.0", # CVE-2026-7246
|
|
73
73
|
"jaraco-context>=6.1.2", # CVE-2025-23949
|
|
74
74
|
"python-multipart>=0.0.32", # CVE-2025-24486
|
|
75
|
-
"wheel>=0.
|
|
75
|
+
"wheel>=0.48.0", # CVE-2025-24049
|
|
76
76
|
"pynacl>=1.6.2", # CVE-2025-69277
|
|
77
77
|
"urllib3>=2.7.0", # CVE-2025-66471, CVE-2025-66418
|
|
78
|
-
"virtualenv>=21.7.
|
|
78
|
+
"virtualenv>=21.7.9", # CVE-2025-22702
|
|
79
79
|
]
|
|
80
80
|
|
|
81
81
|
[project.scripts]
|
|
@@ -83,7 +83,7 @@ bitranox_template_py_cli = "bitranox_template_py_cli.entry:main"
|
|
|
83
83
|
bitranox-template-py-cli = "bitranox_template_py_cli.entry:main"
|
|
84
84
|
|
|
85
85
|
[build-system]
|
|
86
|
-
requires = ["hatchling>=1.
|
|
86
|
+
requires = ["hatchling>=1.32.0"]
|
|
87
87
|
build-backend = "hatchling.build"
|
|
88
88
|
|
|
89
89
|
[tool.hatch.metadata]
|
|
@@ -40,7 +40,7 @@ name = "bitranox_template_py_cli"
|
|
|
40
40
|
#: Human-readable summary shown in CLI help output.
|
|
41
41
|
title = "Template CLI application with configuration management and structured logging"
|
|
42
42
|
#: Current release version pulled from ``pyproject.toml`` by automation.
|
|
43
|
-
version = "1.7.
|
|
43
|
+
version = "1.7.2"
|
|
44
44
|
#: Repository homepage presented to users.
|
|
45
45
|
homepage = "https://github.com/bitranox/bitranox_template_py_cli"
|
|
46
46
|
#: Author attribution surfaced in CLI output.
|
|
@@ -64,13 +64,19 @@ ASCII_FALLBACKS: Final[dict[str, str]] = {
|
|
|
64
64
|
_UNIVERSAL_ENCODINGS: Final[frozenset[str]] = frozenset({"utf-8", "utf8", "utf-16", "utf16", "utf-32", "utf32"})
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
def _stream_encoding(file: IO[Any] | None) -> str | None:
|
|
67
|
+
def _stream_encoding(file: IO[Any] | None, *, err: bool = False) -> str | None:
|
|
68
68
|
"""Return the target stream's encoding, or None when it cannot be determined.
|
|
69
69
|
|
|
70
70
|
An unknown encoding means the caller gets the original text: guessing would
|
|
71
71
|
degrade output that may well have been fine.
|
|
72
|
+
|
|
73
|
+
With no explicit `file` the answer comes from ``sys.stdout``/``sys.stderr``,
|
|
74
|
+
which is what :func:`click.echo` resolves its own default target from. click
|
|
75
|
+
exposes no supported way to ask for that stream: ``get_text_stream`` was
|
|
76
|
+
deprecated in click 8.5.0 and is removed in 9.0, its documented replacement
|
|
77
|
+
being to let ``echo`` resolve the stream itself.
|
|
72
78
|
"""
|
|
73
|
-
stream = file if file is not None else
|
|
79
|
+
stream = file if file is not None else (sys.stderr if err else sys.stdout)
|
|
74
80
|
encoding = getattr(stream, "encoding", None)
|
|
75
81
|
return encoding if isinstance(encoding, str) else None
|
|
76
82
|
|
|
@@ -135,8 +141,7 @@ def echo(message: object = "", *, file: IO[Any] | None = None, err: bool = False
|
|
|
135
141
|
Writes to the given stream.
|
|
136
142
|
"""
|
|
137
143
|
text = message if isinstance(message, str) else str(message)
|
|
138
|
-
|
|
139
|
-
click.echo(encode_safe(text, _stream_encoding(target)), file=target, nl=nl)
|
|
144
|
+
click.echo(encode_safe(text, _stream_encoding(file, err=err)), file=file, err=err, nl=nl)
|
|
140
145
|
|
|
141
146
|
|
|
142
147
|
class _SafeWriter:
|
|
@@ -2,13 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from collections.abc import Iterator, Mapping
|
|
5
6
|
from dataclasses import dataclass
|
|
6
7
|
from typing import TYPE_CHECKING, cast
|
|
7
8
|
|
|
8
9
|
import orjson
|
|
10
|
+
from lib_layered_config import Config
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
|
-
from lib_layered_config import
|
|
13
|
+
from lib_layered_config.domain.config import SourceInfo
|
|
14
|
+
|
|
15
|
+
CLI_LAYER = "cli"
|
|
16
|
+
"""Provenance layer recorded for a value that came from ``--set``.
|
|
17
|
+
|
|
18
|
+
It is not one of the library's file layers because it names no file: the
|
|
19
|
+
value was typed on the command line and there is nothing to open.
|
|
20
|
+
"""
|
|
12
21
|
|
|
13
22
|
CoercedValue = str | int | float | bool | None | list[object] | dict[str, object]
|
|
14
23
|
"""Union of types that :func:`coerce_value` can produce."""
|
|
@@ -145,6 +154,53 @@ def _nest_override(target: dict[str, dict[str, object]], override: ConfigOverrid
|
|
|
145
154
|
node[override.key_path[-1]] = override.value
|
|
146
155
|
|
|
147
156
|
|
|
157
|
+
def _dotted_keys(data: Mapping[str, object], prefix: str = "") -> Iterator[str]:
|
|
158
|
+
"""Yield every leaf key of a nested mapping in dotted form.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
data: The nested mapping to walk.
|
|
162
|
+
prefix: Dotted path accumulated by the caller, ending in a dot.
|
|
163
|
+
|
|
164
|
+
Yields:
|
|
165
|
+
One dotted path per leaf value.
|
|
166
|
+
|
|
167
|
+
Example:
|
|
168
|
+
>>> sorted(_dotted_keys({"a": {"b": 1, "c": {"d": 2}}}))
|
|
169
|
+
['a.b', 'a.c.d']
|
|
170
|
+
"""
|
|
171
|
+
for key, value in data.items():
|
|
172
|
+
path = f"{prefix}{key}"
|
|
173
|
+
if isinstance(value, Mapping):
|
|
174
|
+
yield from _dotted_keys(cast("Mapping[str, object]", value), f"{path}.")
|
|
175
|
+
else:
|
|
176
|
+
yield path
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _provenance_naming_the_cli(
|
|
180
|
+
config: Config, merged_as_dict: Mapping[str, object], overridden: frozenset[str]
|
|
181
|
+
) -> dict[str, SourceInfo]:
|
|
182
|
+
"""Copy a Config's provenance, relabelling the keys an override replaced.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
config: The Config the values came from, holding the original map.
|
|
186
|
+
merged_as_dict: The merged Config's own mapping, walked for the full
|
|
187
|
+
key set. Passed in already computed, because the caller needs the
|
|
188
|
+
same mapping to build the merged ``Config``.
|
|
189
|
+
overridden: Dotted keys that ``--set`` supplied.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
A provenance map naming the CLI for overridden keys and the original
|
|
193
|
+
source for every other one.
|
|
194
|
+
"""
|
|
195
|
+
provenance: dict[str, SourceInfo] = {}
|
|
196
|
+
for dotted in _dotted_keys(merged_as_dict):
|
|
197
|
+
if dotted in overridden:
|
|
198
|
+
provenance[dotted] = {"layer": CLI_LAYER, "path": None, "key": dotted}
|
|
199
|
+
elif (origin := config.origin(dotted)) is not None:
|
|
200
|
+
provenance[dotted] = origin
|
|
201
|
+
return provenance
|
|
202
|
+
|
|
203
|
+
|
|
148
204
|
def apply_overrides(config: Config, raw_overrides: tuple[str, ...]) -> Config:
|
|
149
205
|
"""Deep-merge CLI overrides into a Config instance.
|
|
150
206
|
|
|
@@ -168,6 +224,8 @@ def apply_overrides(config: Config, raw_overrides: tuple[str, ...]) -> Config:
|
|
|
168
224
|
>>> result = apply_overrides(cfg, ("s.k=2",))
|
|
169
225
|
>>> result["s"]["k"]
|
|
170
226
|
2
|
|
227
|
+
>>> result.origin("s.k")["layer"]
|
|
228
|
+
'cli'
|
|
171
229
|
>>> apply_overrides(cfg, ()) is cfg
|
|
172
230
|
True
|
|
173
231
|
"""
|
|
@@ -175,14 +233,23 @@ def apply_overrides(config: Config, raw_overrides: tuple[str, ...]) -> Config:
|
|
|
175
233
|
return config
|
|
176
234
|
|
|
177
235
|
overrides: dict[str, dict[str, object]] = {}
|
|
236
|
+
overridden: set[str] = set()
|
|
178
237
|
for raw in raw_overrides:
|
|
179
238
|
parsed = parse_override(raw)
|
|
180
239
|
_nest_override(overrides, parsed)
|
|
240
|
+
overridden.add(".".join((parsed.section, *parsed.key_path)))
|
|
181
241
|
|
|
182
|
-
|
|
242
|
+
# Rebuilt rather than returned straight from with_overrides, which shares
|
|
243
|
+
# the original provenance map by design: the merged value is the CLI's and
|
|
244
|
+
# its recorded origin still named the file it replaced, so `config` sent a
|
|
245
|
+
# reader to a file holding the old value.
|
|
246
|
+
merged = config.with_overrides(overrides)
|
|
247
|
+
merged_as_dict = merged.as_dict()
|
|
248
|
+
return Config(merged_as_dict, _provenance_naming_the_cli(config, merged_as_dict, frozenset(overridden)))
|
|
183
249
|
|
|
184
250
|
|
|
185
251
|
__all__ = [
|
|
252
|
+
"CLI_LAYER",
|
|
186
253
|
"CoercedValue",
|
|
187
254
|
"ConfigOverride",
|
|
188
255
|
"apply_overrides",
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_config_overrides.py
RENAMED
|
@@ -325,3 +325,35 @@ def test_apply_overrides_rejects_malformed_input() -> None:
|
|
|
325
325
|
|
|
326
326
|
with pytest.raises(ValueError, match="must contain '='"):
|
|
327
327
|
apply_overrides(config, ("invalid",))
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
@pytest.mark.os_agnostic
|
|
331
|
+
def test_apply_overrides_names_the_cli_as_the_source_of_an_overridden_key() -> None:
|
|
332
|
+
"""An overridden key reports the CLI as its origin, not the layer it replaced.
|
|
333
|
+
|
|
334
|
+
``Config.with_overrides`` returns the merged data with the ORIGINAL provenance
|
|
335
|
+
map by design, so without a rebuild ``config`` answers "where did this come
|
|
336
|
+
from" with the file holding the value that was just replaced.
|
|
337
|
+
"""
|
|
338
|
+
config = Config({"s": {"k": 1}}, {"s.k": {"layer": "file", "path": "/etc/app.toml", "key": "s.k"}})
|
|
339
|
+
|
|
340
|
+
result = apply_overrides(config, ("s.k=2",))
|
|
341
|
+
|
|
342
|
+
assert result["s"]["k"] == 2
|
|
343
|
+
assert result.origin("s.k") == {"layer": "cli", "path": None, "key": "s.k"}
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@pytest.mark.os_agnostic
|
|
347
|
+
def test_apply_overrides_leaves_an_untouched_key_with_its_own_source() -> None:
|
|
348
|
+
"""Only the keys ``--set`` supplied are relabelled; the rest keep their layer."""
|
|
349
|
+
config = Config(
|
|
350
|
+
{"s": {"k": 1, "other": "kept"}},
|
|
351
|
+
{
|
|
352
|
+
"s.k": {"layer": "file", "path": "/etc/app.toml", "key": "s.k"},
|
|
353
|
+
"s.other": {"layer": "env", "path": None, "key": "s.other"},
|
|
354
|
+
},
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
result = apply_overrides(config, ("s.k=2",))
|
|
358
|
+
|
|
359
|
+
assert result.origin("s.other") == {"layer": "env", "path": None, "key": "s.other"}
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_safe_console.py
RENAMED
|
@@ -81,6 +81,30 @@ class TestEchoOnAUtf8Console:
|
|
|
81
81
|
assert "✓" in buffer.getvalue().decode("utf-8")
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
class TestTheDefaultTargetFollowsTheStreamEchoWritesTo:
|
|
85
|
+
"""With no `file`, the encoding must come from the stream `echo` lands on.
|
|
86
|
+
|
|
87
|
+
click resolves that target itself from ``sys.stdout``/``sys.stderr``. Judge
|
|
88
|
+
the wrong stream and a legacy-codepage console gets exactly the crash this
|
|
89
|
+
module exists to prevent, while every test passing an explicit `file` stays
|
|
90
|
+
green and says nothing about it.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def test_a_cp1252_stdout_degrades_the_glyph(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
94
|
+
stream = _cp1252_stream()
|
|
95
|
+
monkeypatch.setattr(sys, "stdout", stream)
|
|
96
|
+
safe_console.echo("✓ deployed")
|
|
97
|
+
assert "[OK]" in _read_back(stream)
|
|
98
|
+
|
|
99
|
+
def test_err_is_judged_against_stderr_not_stdout(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
100
|
+
"""A stdout that could take the glyph must not excuse a cp1252 stderr."""
|
|
101
|
+
stream = _cp1252_stream()
|
|
102
|
+
monkeypatch.setattr(sys, "stdout", io.TextIOWrapper(io.BytesIO(), encoding="utf-8", newline=""))
|
|
103
|
+
monkeypatch.setattr(sys, "stderr", stream)
|
|
104
|
+
safe_console.echo("✓ deployed", err=True)
|
|
105
|
+
assert "[OK]" in _read_back(stream)
|
|
106
|
+
|
|
107
|
+
|
|
84
108
|
class TestSafeStreamProtectsRich:
|
|
85
109
|
"""Rich raises on a legacy codepage too; it renders through its own writer."""
|
|
86
110
|
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.devcontainer/devcontainer.json
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.devcontainer/settings.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/.github/workflows/codeql.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/notebooks/Quickstart.ipynb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cache_effectiveness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_env_file.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_exit_codes.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_overrides.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_cli_validation.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_deploy_permissions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_metadata_sync.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_module_entry.py
RENAMED
|
File without changes
|
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_property_email.py
RENAMED
|
File without changes
|
{bitranox_template_py_cli-1.7.1 → bitranox_template_py_cli-1.7.2}/tests/test_property_overrides.py
RENAMED
|
File without changes
|