confease 1.0.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.
@@ -0,0 +1,51 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ pages: write
12
+ id-token: write
13
+
14
+ concurrency:
15
+ group: pages
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ deploy:
20
+ name: Build and deploy documentation
21
+ runs-on: ubuntu-latest
22
+ environment:
23
+ name: github-pages
24
+ url: ${{ steps.deployment.outputs.page_url }}
25
+
26
+ steps:
27
+ - name: Check out repository
28
+ uses: actions/checkout@v6
29
+
30
+ - name: Set up Python
31
+ uses: actions/setup-python@v6
32
+ with:
33
+ python-version: "3.11"
34
+
35
+ - name: Install Hatch
36
+ run: python -m pip install --upgrade hatch
37
+
38
+ - name: Build docs
39
+ run: hatch run docs:build
40
+
41
+ - name: Configure Pages
42
+ uses: actions/configure-pages@v5
43
+
44
+ - name: Upload Pages artifact
45
+ uses: actions/upload-pages-artifact@v4
46
+ with:
47
+ path: docs/_build/html
48
+
49
+ - name: Deploy to GitHub Pages
50
+ id: deployment
51
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,51 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+ id-token: write
12
+
13
+ jobs:
14
+ build:
15
+ name: Build and publish distribution packages
16
+ runs-on: ubuntu-latest
17
+ environment:
18
+ name: pypi
19
+ url: https://pypi.org/p/confease
20
+
21
+ steps:
22
+ - name: Check out repository
23
+ uses: actions/checkout@v6
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v6
27
+ with:
28
+ python-version: "3.11"
29
+
30
+ - name: Install release tooling
31
+ run: python -m pip install --upgrade hatch twine
32
+
33
+ - name: Build sdist and wheel
34
+ run: hatch build
35
+
36
+ - name: Check distribution metadata
37
+ run: twine check dist/*
38
+
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
41
+ with:
42
+ skip-existing: true
43
+
44
+ - name: Generate SHA256 checksums
45
+ run: sha256sum dist/* > dist/checksums.txt
46
+
47
+ - name: Upload artifacts to GitHub Release
48
+ uses: softprops/action-gh-release@v3
49
+ with:
50
+ files: dist/*
51
+ generate_release_notes: true
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ .pytest_cache/
3
+ .mypy_cache/
4
+ .ruff_cache/
5
+
6
+ build/
7
+ dist/
8
+ *.egg-info/
9
+
10
+ docs/_build/
@@ -0,0 +1,20 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff-check
5
+ name: ruff check
6
+ entry: hatch run ruff check .
7
+ language: system
8
+ pass_filenames: false
9
+
10
+ - id: mypy
11
+ name: mypy
12
+ entry: hatch run mypy src
13
+ language: system
14
+ pass_filenames: false
15
+
16
+ - id: pytest
17
+ name: pytest
18
+ entry: hatch run pytest
19
+ language: system
20
+ pass_filenames: false
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.0.0] - 2026-08-13
11
+
12
+ ### Added
13
+
14
+ - Add the `Confease` configuration container with defaults, user/system files, environment variables, and `argparse.Namespace` source loading.
15
+ - Add configurable source precedence with CLI, environment, system, user, and default origins.
16
+ - Add typed configuration persistence for YAML, JSON, TOML, CSV, INI-family formats, and XML.
17
+ - Add one-level nested configuration keys with dotted leaf access and section snapshots.
18
+ - Add indexed access and assignment through `conf[key]` and `conf[key] = value`.
19
+ - Add safe config-file editing through a blocking `TextEditor` and `Confease.edit_file()` draft-validation workflow.
20
+ - Add release, documentation deployment, and pre-commit automation for package maintenance.
21
+
22
+ ### Changed
23
+
24
+ - Preserve original Python value types instead of stringifying `Confitem.value`.
25
+ - Store CSV and INI-family scalar values as YAML text so common Python values round-trip across flat formats.
26
+ - Keep defaults memory-only unless callers explicitly save the full effective configuration with `save(user_only=False)`.
27
+ - Treat nested-capable parsers as nested mappings while CSV persists flat dotted keys with a `key,value` header.
28
+
29
+ ### Documentation
30
+
31
+ - Add practical README guidance for installation, quickstart usage, precedence, nested keys, environment variables, supported file formats, and editor workflows.
32
+ - Add Sphinx documentation with user guides, parser/file-format guidance, troubleshooting notes, and autodoc-based API reference pages.
33
+
34
+ ### Tests
35
+
36
+ - Add focused coverage for core configuration behavior, parser round-tripping, source precedence, persistence, indexed access, and editor safety.
confease-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 souppot contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.5
2
+ Name: confease
3
+ Version: 1.0.0
4
+ Summary: Small Python configuration helper with predictable source precedence
5
+ Project-URL: Repository, https://github.com/octanima-labs/confease
6
+ Project-URL: Documentation, https://octanima-labs.github.io/confease
7
+ Project-URL: Issues, https://github.com/octanima-labs/confease/issues
8
+ Author-email: octanima-labs <34071457+octanima-labs@users.noreply.github.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: 2ning
21
+ Requires-Dist: pyyaml
22
+ Requires-Dist: tomli-w
23
+ Description-Content-Type: text/markdown
24
+
25
+ # confease
26
+
27
+ `confease` is a small Python configuration helper for applications that need predictable precedence across defaults, configuration files, environment variables, and CLI arguments.
28
+
29
+ Use it when you want one shared configuration object that can load user and system config files, accept `argparse` overrides, read typed environment values, and persist user preferences without building a full settings framework.
30
+
31
+ > Status: `confease` is an alpha prototype. The public API is intentionally small, but behavior may still change before a stable release.
32
+
33
+ ## Installation
34
+
35
+ When published, install from PyPI:
36
+
37
+ ```bash
38
+ pip install confease
39
+ ```
40
+
41
+ For local development from this repository:
42
+
43
+ ```bash
44
+ git clone https://github.com/octanima-labs/confease.git
45
+ cd confease
46
+ hatch run pytest
47
+ ```
48
+
49
+ The package requires Python 3.11 or newer.
50
+
51
+ ## Quickstart
52
+
53
+ Create one shared configuration object near your application entry point:
54
+
55
+ ```python
56
+ from argparse import ArgumentParser
57
+
58
+ from confease import Confease
59
+
60
+ parser = ArgumentParser()
61
+ parser.add_argument("--debug", dest="DEBUG", action="store_true")
62
+ parser.add_argument("--database-host", dest="database", action="store_const", const={"host": "db.internal"})
63
+ args = parser.parse_args()
64
+
65
+ conf = Confease(
66
+ "~/.config/my-app/conf.yaml",
67
+ APP_DIR="~/Apps",
68
+ DEBUG=False,
69
+ database={"host": "localhost", "port": 5432},
70
+ )
71
+
72
+ conf.load_sources(args, "/etc/my-app/conf.yaml")
73
+ ```
74
+
75
+ Read values with `get()` or indexed access:
76
+
77
+ ```python
78
+ conf.get("APP_DIR") # "~/Apps"
79
+ conf["APP_DIR"] # "~/Apps"
80
+ conf.get("MISSING") # None
81
+ conf["MISSING"] # None
82
+ conf.get("DEBUG", cast=bool) # False
83
+ ```
84
+
85
+ Update values with `set()` or indexed assignment:
86
+
87
+ ```python
88
+ conf.set("DEBUG", True)
89
+ conf["APP_DIR"] = "/srv/app"
90
+ conf.save()
91
+ ```
92
+
93
+ By default, `save()` writes only user-origin values. Use `save(user_only=False)` when you want to persist the full effective configuration, including defaults and overrides.
94
+
95
+ ## Nested Keys
96
+
97
+ `Confease` supports one nested level. Internally, nested leaves are stored as dotted keys:
98
+
99
+ ```python
100
+ conf.set("database", {"host": "localhost", "port": 5432})
101
+
102
+ conf.get("database.host") # "localhost"
103
+ conf["database.host"] # "localhost"
104
+ conf.get("database") # {"host": "localhost", "port": 5432}
105
+ conf["database"]["host"] # "localhost"
106
+ ```
107
+
108
+ Section access returns a plain snapshot dictionary. Missing subkeys raise `KeyError`, so write nested values through dotted keys or `set()`:
109
+
110
+ ```python
111
+ conf["database.port"] = 5433
112
+ ```
113
+
114
+ ## Source Precedence
115
+
116
+ By default, sources are resolved in this order:
117
+
118
+ ```text
119
+ CLI > ENV > SYS > USR > DEF
120
+ ```
121
+
122
+ Origins mean:
123
+
124
+ - `CLI`: values from an `argparse.Namespace` passed to `load_sources()` or `reload_cli()`.
125
+ - `ENV`: known environment variables loaded by `reload_env()`.
126
+ - `SYS`: config files outside the current user home directory.
127
+ - `USR`: config files inside the current user home directory and values assigned with `set()`.
128
+ - `DEF`: defaults passed as keyword arguments to `Confease(...)`.
129
+
130
+ Customize precedence with `preference`:
131
+
132
+ ```python
133
+ conf = Confease("conf.yaml", preference=["env", "cli", "user", "default"])
134
+ conf.load_sources(args, "conf.yaml", preference=["cli", "env", "user", "default"])
135
+ ```
136
+
137
+ Omitted origins are appended after the origins you provide.
138
+
139
+ ## Environment Variables
140
+
141
+ `reload_env()` only imports environment variables whose keys are already known from defaults or loaded files. Values are parsed with `yaml.safe_load`, so common scalar text recovers Python types:
142
+
143
+ ```bash
144
+ export DEBUG=true
145
+ export PORT=5432
146
+ ```
147
+
148
+ ```python
149
+ conf = Confease(DEBUG=False, PORT=8000)
150
+ conf.reload_env()
151
+
152
+ conf["DEBUG"] # True
153
+ conf["PORT"] # 5432
154
+ ```
155
+
156
+ ## File Formats
157
+
158
+ The parser is inferred from the path suffix when `parser=None` is used, or you can pass a parser class explicitly.
159
+
160
+ Supported suffixes:
161
+
162
+ - `.yaml`, `.yml`
163
+ - `.json`
164
+ - `.toml`
165
+ - `.ini`, `.cfg`, `.conf`, `.config`
166
+ - `.xml`
167
+ - `.csv`
168
+
169
+ ```python
170
+ from confease import Confease, Json
171
+
172
+ yaml_conf = Confease("conf.yaml", parser=None)
173
+ json_conf = Confease("conf.json", parser=Json)
174
+ ```
175
+
176
+ YAML, JSON, TOML, INI, and XML persist one-level nested sections. CSV persists flat dotted keys with a `key,value` header.
177
+
178
+ ## Edit Config Files
179
+
180
+ `edit_file()` opens a temporary draft in a blocking text editor, validates the edited content with the active parser, and only then replaces the real config file:
181
+
182
+ ```python
183
+ from confease import TextEditor
184
+
185
+ conf.editor = TextEditor("code")
186
+ conf.edit_file(user_only=True)
187
+ ```
188
+
189
+ Invalid edited content raises an error and leaves the previous file and in-memory values unchanged.
190
+
191
+ ## Documentation
192
+
193
+ - Documentation: <https://octanima-labs.github.io/confease>
194
+ - Repository: <https://github.com/octanima-labs/confease>
195
+ - Issues: <https://github.com/octanima-labs/confease/issues>
196
+
197
+ ## License
198
+
199
+ MIT
@@ -0,0 +1,175 @@
1
+ # confease
2
+
3
+ `confease` is a small Python configuration helper for applications that need predictable precedence across defaults, configuration files, environment variables, and CLI arguments.
4
+
5
+ Use it when you want one shared configuration object that can load user and system config files, accept `argparse` overrides, read typed environment values, and persist user preferences without building a full settings framework.
6
+
7
+ > Status: `confease` is an alpha prototype. The public API is intentionally small, but behavior may still change before a stable release.
8
+
9
+ ## Installation
10
+
11
+ When published, install from PyPI:
12
+
13
+ ```bash
14
+ pip install confease
15
+ ```
16
+
17
+ For local development from this repository:
18
+
19
+ ```bash
20
+ git clone https://github.com/octanima-labs/confease.git
21
+ cd confease
22
+ hatch run pytest
23
+ ```
24
+
25
+ The package requires Python 3.11 or newer.
26
+
27
+ ## Quickstart
28
+
29
+ Create one shared configuration object near your application entry point:
30
+
31
+ ```python
32
+ from argparse import ArgumentParser
33
+
34
+ from confease import Confease
35
+
36
+ parser = ArgumentParser()
37
+ parser.add_argument("--debug", dest="DEBUG", action="store_true")
38
+ parser.add_argument("--database-host", dest="database", action="store_const", const={"host": "db.internal"})
39
+ args = parser.parse_args()
40
+
41
+ conf = Confease(
42
+ "~/.config/my-app/conf.yaml",
43
+ APP_DIR="~/Apps",
44
+ DEBUG=False,
45
+ database={"host": "localhost", "port": 5432},
46
+ )
47
+
48
+ conf.load_sources(args, "/etc/my-app/conf.yaml")
49
+ ```
50
+
51
+ Read values with `get()` or indexed access:
52
+
53
+ ```python
54
+ conf.get("APP_DIR") # "~/Apps"
55
+ conf["APP_DIR"] # "~/Apps"
56
+ conf.get("MISSING") # None
57
+ conf["MISSING"] # None
58
+ conf.get("DEBUG", cast=bool) # False
59
+ ```
60
+
61
+ Update values with `set()` or indexed assignment:
62
+
63
+ ```python
64
+ conf.set("DEBUG", True)
65
+ conf["APP_DIR"] = "/srv/app"
66
+ conf.save()
67
+ ```
68
+
69
+ By default, `save()` writes only user-origin values. Use `save(user_only=False)` when you want to persist the full effective configuration, including defaults and overrides.
70
+
71
+ ## Nested Keys
72
+
73
+ `Confease` supports one nested level. Internally, nested leaves are stored as dotted keys:
74
+
75
+ ```python
76
+ conf.set("database", {"host": "localhost", "port": 5432})
77
+
78
+ conf.get("database.host") # "localhost"
79
+ conf["database.host"] # "localhost"
80
+ conf.get("database") # {"host": "localhost", "port": 5432}
81
+ conf["database"]["host"] # "localhost"
82
+ ```
83
+
84
+ Section access returns a plain snapshot dictionary. Missing subkeys raise `KeyError`, so write nested values through dotted keys or `set()`:
85
+
86
+ ```python
87
+ conf["database.port"] = 5433
88
+ ```
89
+
90
+ ## Source Precedence
91
+
92
+ By default, sources are resolved in this order:
93
+
94
+ ```text
95
+ CLI > ENV > SYS > USR > DEF
96
+ ```
97
+
98
+ Origins mean:
99
+
100
+ - `CLI`: values from an `argparse.Namespace` passed to `load_sources()` or `reload_cli()`.
101
+ - `ENV`: known environment variables loaded by `reload_env()`.
102
+ - `SYS`: config files outside the current user home directory.
103
+ - `USR`: config files inside the current user home directory and values assigned with `set()`.
104
+ - `DEF`: defaults passed as keyword arguments to `Confease(...)`.
105
+
106
+ Customize precedence with `preference`:
107
+
108
+ ```python
109
+ conf = Confease("conf.yaml", preference=["env", "cli", "user", "default"])
110
+ conf.load_sources(args, "conf.yaml", preference=["cli", "env", "user", "default"])
111
+ ```
112
+
113
+ Omitted origins are appended after the origins you provide.
114
+
115
+ ## Environment Variables
116
+
117
+ `reload_env()` only imports environment variables whose keys are already known from defaults or loaded files. Values are parsed with `yaml.safe_load`, so common scalar text recovers Python types:
118
+
119
+ ```bash
120
+ export DEBUG=true
121
+ export PORT=5432
122
+ ```
123
+
124
+ ```python
125
+ conf = Confease(DEBUG=False, PORT=8000)
126
+ conf.reload_env()
127
+
128
+ conf["DEBUG"] # True
129
+ conf["PORT"] # 5432
130
+ ```
131
+
132
+ ## File Formats
133
+
134
+ The parser is inferred from the path suffix when `parser=None` is used, or you can pass a parser class explicitly.
135
+
136
+ Supported suffixes:
137
+
138
+ - `.yaml`, `.yml`
139
+ - `.json`
140
+ - `.toml`
141
+ - `.ini`, `.cfg`, `.conf`, `.config`
142
+ - `.xml`
143
+ - `.csv`
144
+
145
+ ```python
146
+ from confease import Confease, Json
147
+
148
+ yaml_conf = Confease("conf.yaml", parser=None)
149
+ json_conf = Confease("conf.json", parser=Json)
150
+ ```
151
+
152
+ YAML, JSON, TOML, INI, and XML persist one-level nested sections. CSV persists flat dotted keys with a `key,value` header.
153
+
154
+ ## Edit Config Files
155
+
156
+ `edit_file()` opens a temporary draft in a blocking text editor, validates the edited content with the active parser, and only then replaces the real config file:
157
+
158
+ ```python
159
+ from confease import TextEditor
160
+
161
+ conf.editor = TextEditor("code")
162
+ conf.edit_file(user_only=True)
163
+ ```
164
+
165
+ Invalid edited content raises an error and leaves the previous file and in-memory values unchanged.
166
+
167
+ ## Documentation
168
+
169
+ - Documentation: <https://octanima-labs.github.io/confease>
170
+ - Repository: <https://github.com/octanima-labs/confease>
171
+ - Issues: <https://github.com/octanima-labs/confease/issues>
172
+
173
+ ## License
174
+
175
+ MIT
@@ -0,0 +1,49 @@
1
+ Core API
2
+ ========
3
+
4
+ .. currentmodule:: confease
5
+
6
+ The core API is centered on :class:`Confease`, a configuration container that stores :class:`Confitem` values with an origin and resolves conflicts through configurable precedence.
7
+
8
+ Origins
9
+ -------
10
+
11
+ .. data:: CLI
12
+
13
+ Origin name for values loaded from command-line arguments.
14
+
15
+ .. data:: ENV
16
+
17
+ Origin name for values loaded from environment variables.
18
+
19
+ .. data:: SYS
20
+
21
+ Origin name for values loaded from configuration files outside the current user's home directory.
22
+
23
+ .. data:: USR
24
+
25
+ Origin name for values loaded from user configuration files or assigned through :meth:`Confease.set`.
26
+
27
+ .. data:: DEF
28
+
29
+ Origin name for defaults passed to :class:`Confease`.
30
+
31
+ .. data:: ORIGINS
32
+
33
+ Ordered list of all supported origin names.
34
+
35
+ Confease
36
+ --------
37
+
38
+ .. autoclass:: Confease
39
+ :members:
40
+ :special-members: __getitem__, __setitem__
41
+ :exclude-members: __weakref__
42
+
43
+ Confitem
44
+ --------
45
+
46
+ .. autoclass:: Confitem
47
+ :members:
48
+ :special-members: __eq__, __repr__, __str__
49
+ :exclude-members: __weakref__
@@ -0,0 +1,12 @@
1
+ API Reference
2
+ =============
3
+
4
+ This reference documents the public ``confease`` API and the parser classes exposed by the package.
5
+
6
+ API descriptions are generated from source docstrings with Sphinx autodoc, Napoleon, and ``sphinx-autodoc-typehints``. Treat the docstrings in ``src/confease/`` as the canonical API comments, and keep this section focused on navigation and high-level grouping.
7
+
8
+ .. toctree::
9
+ :maxdepth: 2
10
+
11
+ core
12
+ parsers