conclude 1.0.0__tar.gz → 1.0.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.
- {conclude-1.0.0 → conclude-1.0.2}/.gitignore +6 -0
- conclude-1.0.2/CHANGELOG.md +67 -0
- {conclude-1.0.0 → conclude-1.0.2}/PKG-INFO +18 -18
- {conclude-1.0.0 → conclude-1.0.2}/README.md +14 -14
- conclude-1.0.2/RELEASING.md +56 -0
- {conclude-1.0.0 → conclude-1.0.2}/docs/comparison.md +1 -1
- conclude-1.0.2/docs/concept.md +401 -0
- conclude-1.0.2/hatch_build.py +33 -0
- {conclude-1.0.0 → conclude-1.0.2}/pyproject.toml +24 -3
- conclude-1.0.2/spec/README.md +72 -0
- conclude-1.0.2/spec/casters.json +438 -0
- conclude-1.0.2/spec/config_layers.json +571 -0
- conclude-1.0.2/spec/config_tables.json +221 -0
- conclude-1.0.2/spec/dotenv.json +239 -0
- conclude-1.0.2/spec/gitignore.json +189 -0
- conclude-1.0.2/spec/guard.json +273 -0
- conclude-1.0.2/spec/invocation.json +1241 -0
- conclude-1.0.2/spec/merge.json +1076 -0
- conclude-1.0.2/spec/naming.json +94 -0
- conclude-1.0.2/spec/sources.json +315 -0
- conclude-1.0.2/spec/templates.json +603 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/__init__.py +1 -1
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/env.py +5 -1
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_comparison.py +15 -7
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_docs.py +22 -7
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_env.py +59 -0
- conclude-1.0.2/test/test_repo_hygiene.py +413 -0
- conclude-1.0.2/test/test_spec.py +473 -0
- conclude-1.0.0/.github/dependabot.yml +0 -10
- conclude-1.0.0/.github/workflows/ci.yml +0 -109
- conclude-1.0.0/.github/workflows/publish.yml +0 -125
- conclude-1.0.0/CHANGELOG.md +0 -7
- conclude-1.0.0/tests/test_repo_hygiene.py +0 -190
- conclude-1.0.0/uv.lock +0 -948
- {conclude-1.0.0 → conclude-1.0.2}/LICENSE +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/docs/guide.md +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/docs/reference.md +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/app.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/casters.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/developer.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/files.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/formatters.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/guard.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/infer.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/merge.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/naming.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/paths.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/py.typed +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/templates.py +0 -0
- {conclude-1.0.0 → conclude-1.0.2}/src/conclude/tomlwrite.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_app.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_casters.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_developer.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_dotenv_guard.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_files.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_formatters.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_guard.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_infer.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_merge.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_naming.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_templates.py +0 -0
- {conclude-1.0.0/tests → conclude-1.0.2/test}/test_tomlwrite_and_paths.py +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file. The
|
|
4
|
+
format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
|
+
and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [1.0.2] - 2026-09-26
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Python tree is now under `python/` to match `node/` tree.
|
|
12
|
+
|
|
13
|
+
## [1.0.1] - 2026-09-20
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `.env` files, and dotenv-format developer files, are now read as UTF-8 on
|
|
18
|
+
every platform, and a leading byte-order mark is ignored. Previously the
|
|
19
|
+
platform's default text encoding was used, which garbled non-ASCII values
|
|
20
|
+
on Windows, and a byte-order mark (which some Windows editors add) made
|
|
21
|
+
the first variable silently disappear.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- The package's OS classifier is now `Operating System :: Unix` rather than
|
|
26
|
+
`OS Independent`: the tests run on Linux, and the paths conclude uses
|
|
27
|
+
(`~/.config`, `/etc`) are Unix conventions.
|
|
28
|
+
- The source distribution no longer includes `uv.lock` or `.github/`.
|
|
29
|
+
|
|
30
|
+
## [1.0.0] - 2026-09-20
|
|
31
|
+
|
|
32
|
+
First public release.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- **Inference from one dict.** `App(name, defaults)` infers each setting's
|
|
37
|
+
environment variable, config-file key, CLI flag, caster and formatter
|
|
38
|
+
from its name, type and default. `opt(type)` declares a typed setting
|
|
39
|
+
that starts out unset.
|
|
40
|
+
- **Layered resolution:** `defaults < system < user < project < env <
|
|
41
|
+
developer < CLI`, with per-key casting at every layer.
|
|
42
|
+
- **Config files:** user (`~/.config/<name>/config.toml`) and project
|
|
43
|
+
(`./.config.toml`, plus `.config.*.toml` siblings, configurable or
|
|
44
|
+
disabled with `config_cwd_aux_pattern`) files; an opt-in system-wide
|
|
45
|
+
`/etc/<name>/config.toml`; two-level `[PARENT]` / `[PARENT.CHILD]`
|
|
46
|
+
tables; a positional shorthand that picks a table.
|
|
47
|
+
- **`.env` fallback** beneath real environment variables (opt-in).
|
|
48
|
+
`dotenv_require_gitignored=True` holds it to the developer file's
|
|
49
|
+
gitignore guard, and `App.dotenv_status()` reports its state.
|
|
50
|
+
- **Developer config layer** (opt-in via `pyproject_path`): a private,
|
|
51
|
+
gitignored, project-local file named by `pyproject.toml`'s
|
|
52
|
+
`tool.conclude.developer.config` that beats ambient environment
|
|
53
|
+
variables and loses to the CLI. The file is TOML if its name ends in
|
|
54
|
+
`.toml` and dotenv otherwise (say `.env.local`, keyed by the app's
|
|
55
|
+
environment variable names, so it can be shared with docker compose or
|
|
56
|
+
direnv). It is applied only when the file exists, sits in a git working
|
|
57
|
+
tree, and is covered by its ignore rules, checked with the optional
|
|
58
|
+
`pathspec` extra: `pip install 'conclude[gitignore]'`.
|
|
59
|
+
`<NAME>_DEVELOPER_CONFIG=off` is a kill switch, and
|
|
60
|
+
`App.developer_status()` reports the layer's state and reason as data.
|
|
61
|
+
- **`describe_sources()`** for `--help`, listing every source and, for the
|
|
62
|
+
developer layer and a strict `.env`, whether it is active and why not.
|
|
63
|
+
- **Generated templates and docs:** `format_env()`, `format_toml()` and
|
|
64
|
+
`format_cli()` render every setting next to its default.
|
|
65
|
+
- **`--print-invocation`** and `format_invocation()`: reproduce a resolved
|
|
66
|
+
configuration as a command line.
|
|
67
|
+
- Standard library only; fully typed (`py.typed`); Python 3.11 and newer.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: conclude
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Set up your defaults; conclude infers the env vars, config-file keys, and CLI flags, and resolves them all into one settings object.
|
|
5
5
|
Project-URL: Homepage, https://github.com/tanakapayam/conclude
|
|
6
|
-
Project-URL: Documentation, https://github.com/tanakapayam/conclude/blob/main/docs/guide.md
|
|
6
|
+
Project-URL: Documentation, https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md
|
|
7
7
|
Project-URL: Repository, https://github.com/tanakapayam/conclude
|
|
8
8
|
Project-URL: Issues, https://github.com/tanakapayam/conclude/issues
|
|
9
|
-
Project-URL: Changelog, https://github.com/tanakapayam/conclude/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Changelog, https://github.com/tanakapayam/conclude/blob/main/python/CHANGELOG.md
|
|
10
10
|
Author: Payam Tanaka
|
|
11
11
|
License-Expression: MIT
|
|
12
12
|
License-File: LICENSE
|
|
@@ -14,7 +14,7 @@ Keywords: cli,config,configuration,dotenv,environment-variables,settings,toml
|
|
|
14
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
15
15
|
Classifier: Environment :: Console
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: Operating System ::
|
|
17
|
+
Classifier: Operating System :: Unix
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -92,7 +92,7 @@ conclude deliberately does not do schema validation (values are cast,
|
|
|
92
92
|
not validated), secret-manager backends, YAML or JSON files, or named
|
|
93
93
|
environments; the table says where to look for those. For a dated,
|
|
94
94
|
feature-by-feature comparison, see
|
|
95
|
-
[How conclude compares](https://github.com/tanakapayam/conclude/blob/main/docs/comparison.md).
|
|
95
|
+
[How conclude compares](https://github.com/tanakapayam/conclude/blob/main/docs/python/comparison.md).
|
|
96
96
|
|
|
97
97
|
## Design principles
|
|
98
98
|
|
|
@@ -195,28 +195,28 @@ app = conclude.App(
|
|
|
195
195
|
The developer file is always guarded, and `.env` is when you ask: the
|
|
196
196
|
file is used only if it exists, sits in a git working tree, and is
|
|
197
197
|
gitignored. Otherwise it is skipped quietly, and `describe_sources()`
|
|
198
|
-
says why. Details: [the `.env` file](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#6-local-development-a-env-file), [the developer file](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#8-a-private-developer-config-file).
|
|
198
|
+
says why. Details: [the `.env` file](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#6-local-development-a-env-file), [the developer file](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#8-a-private-developer-config-file).
|
|
199
199
|
|
|
200
200
|
## What's in it
|
|
201
201
|
|
|
202
202
|
- **Inference** of casters, formatters, CLI flags, env var names and
|
|
203
203
|
config keys from the defaults alone; `opt(type)` for a setting that
|
|
204
|
-
starts out unset ([guide, section 1](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#1-the-bare-minimum), [section 3](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#3-when-inference-isnt-quite-enough-casters-and-formatters)).
|
|
204
|
+
starts out unset ([guide, section 1](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#1-the-bare-minimum), [section 3](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#3-when-inference-isnt-quite-enough-casters-and-formatters)).
|
|
205
205
|
- **Config-file tables**, including a positional shorthand that picks a
|
|
206
|
-
table per recipient/deck/profile ([section 4](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#4-a-positional-shorthand--per-recipient-config-tables)).
|
|
206
|
+
table per recipient/deck/profile ([section 4](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#4-a-positional-shorthand--per-recipient-config-tables)).
|
|
207
207
|
- **`--print-invocation`** and `App.format_invocation()`: print the
|
|
208
208
|
command line that reproduces a resolved configuration
|
|
209
|
-
([section 5](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#5-debugging-and-documentation---print-invocation)).
|
|
209
|
+
([section 5](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#5-debugging-and-documentation---print-invocation)).
|
|
210
210
|
- **A `.env` fallback**, optionally required to be gitignored, sitting
|
|
211
|
-
beneath real environment variables ([section 6](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#6-local-development-a-env-file)).
|
|
212
|
-
- **A system-wide config file**, the lowest-priority file ([section 7](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#7-machine-wide-defaults-a-system-config-file)).
|
|
211
|
+
beneath real environment variables ([section 6](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#6-local-development-a-env-file)).
|
|
212
|
+
- **A system-wide config file**, the lowest-priority file ([section 7](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#7-machine-wide-defaults-a-system-config-file)).
|
|
213
213
|
- **A private developer file**, TOML or dotenv, that beats ambient
|
|
214
|
-
environment variables ([section 8](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#8-a-private-developer-config-file)).
|
|
214
|
+
environment variables ([section 8](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#8-a-private-developer-config-file)).
|
|
215
215
|
- **`describe_sources()`** for `--help`: which sources are in play, and
|
|
216
|
-
why a given one isn't ([section 9](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#9-turning-off-a-source-and-telling-the-user)).
|
|
216
|
+
why a given one isn't ([section 9](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#9-turning-off-a-source-and-telling-the-user)).
|
|
217
217
|
- **Templates and docs generated from your defaults**:
|
|
218
218
|
`format_env()`, `format_toml()`, `format_cli()`
|
|
219
|
-
([section 10](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#10-generating-docs-and-templates)).
|
|
219
|
+
([section 10](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#10-generating-docs-and-templates)).
|
|
220
220
|
- Standard library only, fully typed (`py.typed`), Python 3.11+. The
|
|
221
221
|
gitignore check (developer file, strict `.env`) uses the optional
|
|
222
222
|
`pathspec` package.
|
|
@@ -237,16 +237,16 @@ pip install 'conclude[gitignore]'
|
|
|
237
237
|
|
|
238
238
|
## Documentation
|
|
239
239
|
|
|
240
|
-
- [Guide](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md) -- builds a small CLI, `remind`, one
|
|
240
|
+
- [Guide](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md) -- builds a small CLI, `remind`, one
|
|
241
241
|
idea at a time.
|
|
242
|
-
- [Reference](https://github.com/tanakapayam/conclude/blob/main/docs/reference.md) -- every class, method, and
|
|
242
|
+
- [Reference](https://github.com/tanakapayam/conclude/blob/main/docs/python/reference.md) -- every class, method, and
|
|
243
243
|
module.
|
|
244
|
-
- [Changelog](https://github.com/tanakapayam/conclude/blob/main/CHANGELOG.md).
|
|
244
|
+
- [Changelog](https://github.com/tanakapayam/conclude/blob/main/python/CHANGELOG.md).
|
|
245
245
|
|
|
246
246
|
## Development
|
|
247
247
|
|
|
248
248
|
```
|
|
249
|
-
uv sync
|
|
249
|
+
uv sync --locked # fails if uv.lock is out of date; `uv lock` refreshes it
|
|
250
250
|
uv run pytest
|
|
251
251
|
uv run ruff check . && uv run ruff format --check .
|
|
252
252
|
uv run mypy
|
|
@@ -61,7 +61,7 @@ conclude deliberately does not do schema validation (values are cast,
|
|
|
61
61
|
not validated), secret-manager backends, YAML or JSON files, or named
|
|
62
62
|
environments; the table says where to look for those. For a dated,
|
|
63
63
|
feature-by-feature comparison, see
|
|
64
|
-
[How conclude compares](https://github.com/tanakapayam/conclude/blob/main/docs/comparison.md).
|
|
64
|
+
[How conclude compares](https://github.com/tanakapayam/conclude/blob/main/docs/python/comparison.md).
|
|
65
65
|
|
|
66
66
|
## Design principles
|
|
67
67
|
|
|
@@ -164,28 +164,28 @@ app = conclude.App(
|
|
|
164
164
|
The developer file is always guarded, and `.env` is when you ask: the
|
|
165
165
|
file is used only if it exists, sits in a git working tree, and is
|
|
166
166
|
gitignored. Otherwise it is skipped quietly, and `describe_sources()`
|
|
167
|
-
says why. Details: [the `.env` file](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#6-local-development-a-env-file), [the developer file](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#8-a-private-developer-config-file).
|
|
167
|
+
says why. Details: [the `.env` file](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#6-local-development-a-env-file), [the developer file](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#8-a-private-developer-config-file).
|
|
168
168
|
|
|
169
169
|
## What's in it
|
|
170
170
|
|
|
171
171
|
- **Inference** of casters, formatters, CLI flags, env var names and
|
|
172
172
|
config keys from the defaults alone; `opt(type)` for a setting that
|
|
173
|
-
starts out unset ([guide, section 1](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#1-the-bare-minimum), [section 3](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#3-when-inference-isnt-quite-enough-casters-and-formatters)).
|
|
173
|
+
starts out unset ([guide, section 1](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#1-the-bare-minimum), [section 3](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#3-when-inference-isnt-quite-enough-casters-and-formatters)).
|
|
174
174
|
- **Config-file tables**, including a positional shorthand that picks a
|
|
175
|
-
table per recipient/deck/profile ([section 4](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#4-a-positional-shorthand--per-recipient-config-tables)).
|
|
175
|
+
table per recipient/deck/profile ([section 4](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#4-a-positional-shorthand--per-recipient-config-tables)).
|
|
176
176
|
- **`--print-invocation`** and `App.format_invocation()`: print the
|
|
177
177
|
command line that reproduces a resolved configuration
|
|
178
|
-
([section 5](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#5-debugging-and-documentation---print-invocation)).
|
|
178
|
+
([section 5](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#5-debugging-and-documentation---print-invocation)).
|
|
179
179
|
- **A `.env` fallback**, optionally required to be gitignored, sitting
|
|
180
|
-
beneath real environment variables ([section 6](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#6-local-development-a-env-file)).
|
|
181
|
-
- **A system-wide config file**, the lowest-priority file ([section 7](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#7-machine-wide-defaults-a-system-config-file)).
|
|
180
|
+
beneath real environment variables ([section 6](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#6-local-development-a-env-file)).
|
|
181
|
+
- **A system-wide config file**, the lowest-priority file ([section 7](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#7-machine-wide-defaults-a-system-config-file)).
|
|
182
182
|
- **A private developer file**, TOML or dotenv, that beats ambient
|
|
183
|
-
environment variables ([section 8](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#8-a-private-developer-config-file)).
|
|
183
|
+
environment variables ([section 8](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#8-a-private-developer-config-file)).
|
|
184
184
|
- **`describe_sources()`** for `--help`: which sources are in play, and
|
|
185
|
-
why a given one isn't ([section 9](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#9-turning-off-a-source-and-telling-the-user)).
|
|
185
|
+
why a given one isn't ([section 9](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#9-turning-off-a-source-and-telling-the-user)).
|
|
186
186
|
- **Templates and docs generated from your defaults**:
|
|
187
187
|
`format_env()`, `format_toml()`, `format_cli()`
|
|
188
|
-
([section 10](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md#10-generating-docs-and-templates)).
|
|
188
|
+
([section 10](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md#10-generating-docs-and-templates)).
|
|
189
189
|
- Standard library only, fully typed (`py.typed`), Python 3.11+. The
|
|
190
190
|
gitignore check (developer file, strict `.env`) uses the optional
|
|
191
191
|
`pathspec` package.
|
|
@@ -206,16 +206,16 @@ pip install 'conclude[gitignore]'
|
|
|
206
206
|
|
|
207
207
|
## Documentation
|
|
208
208
|
|
|
209
|
-
- [Guide](https://github.com/tanakapayam/conclude/blob/main/docs/guide.md) -- builds a small CLI, `remind`, one
|
|
209
|
+
- [Guide](https://github.com/tanakapayam/conclude/blob/main/docs/python/guide.md) -- builds a small CLI, `remind`, one
|
|
210
210
|
idea at a time.
|
|
211
|
-
- [Reference](https://github.com/tanakapayam/conclude/blob/main/docs/reference.md) -- every class, method, and
|
|
211
|
+
- [Reference](https://github.com/tanakapayam/conclude/blob/main/docs/python/reference.md) -- every class, method, and
|
|
212
212
|
module.
|
|
213
|
-
- [Changelog](https://github.com/tanakapayam/conclude/blob/main/CHANGELOG.md).
|
|
213
|
+
- [Changelog](https://github.com/tanakapayam/conclude/blob/main/python/CHANGELOG.md).
|
|
214
214
|
|
|
215
215
|
## Development
|
|
216
216
|
|
|
217
217
|
```
|
|
218
|
-
uv sync
|
|
218
|
+
uv sync --locked # fails if uv.lock is out of date; `uv lock` refreshes it
|
|
219
219
|
uv run pytest
|
|
220
220
|
uv run ruff check . && uv run ruff format --check .
|
|
221
221
|
uv run mypy
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Releasing conclude (Python)
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
release published (tag python-v<version>)
|
|
5
|
+
|
|
|
6
|
+
v
|
|
7
|
+
ci ---> build ---> publish-testpypi (workflow_dispatch, target testpypi: a dry run)
|
|
8
|
+
| |
|
|
9
|
+
| +-> publish-pypi waits for a reviewer to approve the `pypi`
|
|
10
|
+
| environment, then publishes with trusted
|
|
11
|
+
| publishing (no stored token)
|
|
12
|
+
|
|
|
13
|
+
+-- one sdist + wheel, built once, uploaded as an artifact and promoted unchanged
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
TestPyPI is the dry run here (there is no separate staging registry, unlike the Node
|
|
17
|
+
package's GitHub Packages stage): `workflow_dispatch` with `target: testpypi` builds,
|
|
18
|
+
checks, and publishes to TestPyPI, and installs nothing back automatically -- try it
|
|
19
|
+
yourself with `pip install -i https://test.pypi.org/simple/ conclude`. A real release
|
|
20
|
+
(`target: pypi`, or a published GitHub Release) is checked, gated behind a required
|
|
21
|
+
reviewer on the `pypi` environment, then published to PyPI.
|
|
22
|
+
|
|
23
|
+
## One-time setup
|
|
24
|
+
|
|
25
|
+
1. **Environments** (repository Settings, Environments):
|
|
26
|
+
- `testpypi`: no protection needed.
|
|
27
|
+
- `pypi`: add yourself (or a team) under *Required reviewers*; that is the approval
|
|
28
|
+
gate.
|
|
29
|
+
2. **Trusted publisher**, on both <https://pypi.org> and <https://test.pypi.org>, for the
|
|
30
|
+
project `conclude`: this repository, workflow **`python-publish.yml`**, environment
|
|
31
|
+
`pypi` (`testpypi` on TestPyPI). For a project that does not exist yet, use
|
|
32
|
+
"Publishing" -> "Add a new pending publisher".
|
|
33
|
+
3. Nothing to store: publishing uses OIDC. No PyPI token exists.
|
|
34
|
+
|
|
35
|
+
> **If this workflow was ever registered under a different filename** (for example the
|
|
36
|
+
> project's original `publish.yml`, before this repository moved every language into its
|
|
37
|
+
> own top-level directory): trusted publishing is matched by *workflow filename*, so the
|
|
38
|
+
> existing entries on PyPI and TestPyPI must be updated to `python-publish.yml` -- edit
|
|
39
|
+
> them under "Publishing" on each site -- or the next release fails with a permission
|
|
40
|
+
> error, not a helpful one.
|
|
41
|
+
|
|
42
|
+
## Releasing
|
|
43
|
+
|
|
44
|
+
1. Bump `__version__` in `src/conclude/__init__.py` (the single source of truth; see
|
|
45
|
+
`[tool.hatch.version]` in `pyproject.toml`), and the version in
|
|
46
|
+
`docs/python/comparison.md`'s "Verified" line if it's stale. Put a dated entry in
|
|
47
|
+
`CHANGELOG.md` (the release is refused while it says *Unreleased*).
|
|
48
|
+
2. Merge to `main`.
|
|
49
|
+
3. Create a GitHub Release from a new tag `python-v<version>` on `main`.
|
|
50
|
+
4. `publish-pypi` waits for a reviewer to **approve the `pypi` deployment**; approve it
|
|
51
|
+
when you are happy.
|
|
52
|
+
|
|
53
|
+
## Rehearsing
|
|
54
|
+
|
|
55
|
+
Actions, Publish, Run workflow, target `testpypi` -- builds, checks, and publishes to
|
|
56
|
+
TestPyPI without touching the `pypi` environment or a real version on PyPI.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A feature-by-feature comparison with five libraries people often reach
|
|
4
4
|
for instead. **Verified 2026-09-19** against each project's
|
|
5
5
|
documentation and its PyPI metadata; the versions checked are
|
|
6
|
-
conclude 1.0.
|
|
6
|
+
conclude 1.0.2, ConfigArgParse 1.7.7, jsonargparse 4.52.0,
|
|
7
7
|
pydantic-settings 2.15.0, Dynaconf 3.3.5 and python-decouple 3.8.
|
|
8
8
|
|
|
9
9
|
A dash (--) means no built-in support that the project's documentation
|