layerconf 0.1.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.
- layerconf-0.1.0/.github/workflows/ci.yml +64 -0
- layerconf-0.1.0/.github/workflows/docs.yml +31 -0
- layerconf-0.1.0/.github/workflows/release.yml +54 -0
- layerconf-0.1.0/.gitignore +18 -0
- layerconf-0.1.0/.python-version +1 -0
- layerconf-0.1.0/CHANGELOG.md +37 -0
- layerconf-0.1.0/CLAUDE.md +50 -0
- layerconf-0.1.0/PKG-INFO +496 -0
- layerconf-0.1.0/README.md +455 -0
- layerconf-0.1.0/docs/api/index.md +123 -0
- layerconf-0.1.0/docs/changelog.md +3 -0
- layerconf-0.1.0/docs/concepts.md +231 -0
- layerconf-0.1.0/docs/examples.md +236 -0
- layerconf-0.1.0/docs/getting-started.md +153 -0
- layerconf-0.1.0/docs/index.md +49 -0
- layerconf-0.1.0/docs/observability.md +186 -0
- layerconf-0.1.0/docs/providers.md +231 -0
- layerconf-0.1.0/docs/validation.md +250 -0
- layerconf-0.1.0/mkdocs.yml +73 -0
- layerconf-0.1.0/pyproject.toml +70 -0
- layerconf-0.1.0/src/layer/__init__.py +115 -0
- layerconf-0.1.0/src/layer/core.py +826 -0
- layerconf-0.1.0/src/layer/exceptions.py +60 -0
- layerconf-0.1.0/src/layer/exporters.py +208 -0
- layerconf-0.1.0/src/layer/interpolation.py +99 -0
- layerconf-0.1.0/src/layer/layering.py +8 -0
- layerconf-0.1.0/src/layer/observers.py +113 -0
- layerconf-0.1.0/src/layer/pipeline.py +292 -0
- layerconf-0.1.0/src/layer/providers/__init__.py +19 -0
- layerconf-0.1.0/src/layer/providers/base.py +34 -0
- layerconf-0.1.0/src/layer/providers/dotenv.py +51 -0
- layerconf-0.1.0/src/layer/providers/env.py +122 -0
- layerconf-0.1.0/src/layer/providers/etcd.py +96 -0
- layerconf-0.1.0/src/layer/providers/file.py +46 -0
- layerconf-0.1.0/src/layer/providers/ssm.py +91 -0
- layerconf-0.1.0/src/layer/providers/vault.py +53 -0
- layerconf-0.1.0/src/layer/solidify.py +349 -0
- layerconf-0.1.0/src/layer/sources.py +41 -0
- layerconf-0.1.0/src/layer/type_resolution.py +177 -0
- layerconf-0.1.0/src/layer/validation.py +355 -0
- layerconf-0.1.0/tests/conftest.py +33 -0
- layerconf-0.1.0/tests/test_aliasing.py +115 -0
- layerconf-0.1.0/tests/test_class_validators.py +257 -0
- layerconf-0.1.0/tests/test_computed_field.py +149 -0
- layerconf-0.1.0/tests/test_core.py +143 -0
- layerconf-0.1.0/tests/test_env_provider_unified.py +81 -0
- layerconf-0.1.0/tests/test_exporters.py +188 -0
- layerconf-0.1.0/tests/test_field_def.py +78 -0
- layerconf-0.1.0/tests/test_interpolation.py +45 -0
- layerconf-0.1.0/tests/test_nested.py +94 -0
- layerconf-0.1.0/tests/test_observers.py +198 -0
- layerconf-0.1.0/tests/test_pipeline.py +430 -0
- layerconf-0.1.0/tests/test_polish.py +285 -0
- layerconf-0.1.0/tests/test_providers.py +368 -0
- layerconf-0.1.0/tests/test_schema.py +81 -0
- layerconf-0.1.0/tests/test_solidify.py +65 -0
- layerconf-0.1.0/tests/test_solidify_mode.py +189 -0
- layerconf-0.1.0/tests/test_type_resolution.py +236 -0
- layerconf-0.1.0/tests/test_validation.py +67 -0
- layerconf-0.1.0/uv.lock +1122 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: ["**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_call:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
lint:
|
|
12
|
+
name: Lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
|
|
25
|
+
- name: Install dev dependencies
|
|
26
|
+
run: uv sync --extra dev
|
|
27
|
+
|
|
28
|
+
- name: ruff check
|
|
29
|
+
run: uv run ruff check src/
|
|
30
|
+
|
|
31
|
+
- name: ruff format check
|
|
32
|
+
run: uv run ruff format --check src/
|
|
33
|
+
|
|
34
|
+
test:
|
|
35
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
strategy:
|
|
38
|
+
fail-fast: false
|
|
39
|
+
matrix:
|
|
40
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- name: Install uv
|
|
46
|
+
uses: astral-sh/setup-uv@v4
|
|
47
|
+
|
|
48
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
49
|
+
uses: actions/setup-python@v5
|
|
50
|
+
with:
|
|
51
|
+
python-version: ${{ matrix.python-version }}
|
|
52
|
+
|
|
53
|
+
- name: Install package and dev dependencies
|
|
54
|
+
run: uv sync --extra dev
|
|
55
|
+
|
|
56
|
+
- name: Run tests with coverage
|
|
57
|
+
run: uv run pytest --cov=layer --cov-report=xml --cov-report=term-missing
|
|
58
|
+
|
|
59
|
+
- name: Upload coverage
|
|
60
|
+
uses: codecov/codecov-action@v4
|
|
61
|
+
if: matrix.python-version == '3.12'
|
|
62
|
+
with:
|
|
63
|
+
files: ./coverage.xml
|
|
64
|
+
fail_ci_if_error: false
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write # needed to push to gh-pages branch
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
deploy:
|
|
12
|
+
name: Build and deploy MkDocs
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0 # for git-revision-date plugin
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
|
|
27
|
+
- name: Install docs and dev dependencies
|
|
28
|
+
run: uv sync --extra docs --extra dev
|
|
29
|
+
|
|
30
|
+
- name: Build and deploy docs
|
|
31
|
+
run: uv run mkdocs gh-deploy --force
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
name: Run CI checks
|
|
10
|
+
uses: ./.github/workflows/ci.yml
|
|
11
|
+
|
|
12
|
+
release:
|
|
13
|
+
name: Semantic Release + PyPI
|
|
14
|
+
needs: ci
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
concurrency:
|
|
17
|
+
group: release
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write # PSR pushes version bump commit + tag
|
|
21
|
+
id-token: write # OIDC for PyPI Trusted Publishing
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0 # PSR needs full history to find the last version tag
|
|
27
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v4
|
|
31
|
+
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.12"
|
|
36
|
+
|
|
37
|
+
- name: Install python-semantic-release
|
|
38
|
+
run: pip install "python-semantic-release==9.*"
|
|
39
|
+
|
|
40
|
+
- name: Run semantic-release
|
|
41
|
+
id: semrel
|
|
42
|
+
env:
|
|
43
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
44
|
+
run: semantic-release version --push --changelog --vcs-release
|
|
45
|
+
|
|
46
|
+
- name: Build distribution
|
|
47
|
+
if: steps.semrel.outputs.released == 'true'
|
|
48
|
+
run: uv build
|
|
49
|
+
|
|
50
|
+
- name: Publish to PyPI (Trusted Publishing)
|
|
51
|
+
if: steps.semrel.outputs.released == 'true'
|
|
52
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
53
|
+
with:
|
|
54
|
+
packages-dir: dist/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.10
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## v0.1.0 (2026-03-24)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- Broken release workflow
|
|
9
|
+
([`e349cd0`](https://github.com/AncientPatata/layer/commit/e349cd0697f3cd7ef001359a0da2ca6995338fff))
|
|
10
|
+
|
|
11
|
+
- Package name
|
|
12
|
+
([`2f48964`](https://github.com/AncientPatata/layer/commit/2f489640834c20061f233cef91fd60ca3a37c72b))
|
|
13
|
+
|
|
14
|
+
- Ruff complaints
|
|
15
|
+
([`0dcff05`](https://github.com/AncientPatata/layer/commit/0dcff05000487cf69e1f145c2b35da06afaff11b))
|
|
16
|
+
|
|
17
|
+
- Trigger patch release
|
|
18
|
+
([`9af7b89`](https://github.com/AncientPatata/layer/commit/9af7b89bbb5981c250f8cec76e5a6349a5621b4e))
|
|
19
|
+
|
|
20
|
+
- Trigger patch release
|
|
21
|
+
([`856b2ce`](https://github.com/AncientPatata/layer/commit/856b2ce4b487eb50837caf3b4c0dc988c203b23d))
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- Improvements
|
|
26
|
+
([`2d4a7a4`](https://github.com/AncientPatata/layer/commit/2d4a7a440da2b7df2a02b848d4de9e9b77f93a2f))
|
|
27
|
+
|
|
28
|
+
- Initial docs
|
|
29
|
+
([`04a5557`](https://github.com/AncientPatata/layer/commit/04a555752c0bc886a9a178e6ac9c3865b48efc70))
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
- Etcd provider, schema binding and .env fix
|
|
34
|
+
([`4f58d80`](https://github.com/AncientPatata/layer/commit/4f58d80657a0e09bc8251dc7e22ee8cca1035cfa))
|
|
35
|
+
|
|
36
|
+
- Trigger release, dotenv now core dep.
|
|
37
|
+
([`70a5d2d`](https://github.com/AncientPatata/layer/commit/70a5d2dcea0ca8b303d1d8458f9a1a9f26b83e04))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
Layer is a Python library for deterministic, multi-source configuration management. It provides a decorator-based system (`@layer_obj`) for defining typed configuration schemas that support layered merging from multiple sources (files, env vars, dicts), categorical validation, variable interpolation, and full source history tracking.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Run all tests
|
|
13
|
+
uv run --with pytest pytest
|
|
14
|
+
|
|
15
|
+
# Run a single test file
|
|
16
|
+
uv run --with pytest pytest tests/test_solidify.py
|
|
17
|
+
|
|
18
|
+
# Run a single test
|
|
19
|
+
uv run --with pytest pytest tests/test_solidify.py::TestTypeCoercion::test_str_to_int
|
|
20
|
+
|
|
21
|
+
# Install in development mode (enables plain `pytest` after)
|
|
22
|
+
uv pip install -e ".[dev]"
|
|
23
|
+
|
|
24
|
+
# Lint
|
|
25
|
+
ruff check src/
|
|
26
|
+
|
|
27
|
+
# Build
|
|
28
|
+
hatchling build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
The intended data flow for configuration objects is: **Schema Definition → Source Loading → Layering → Interpolation → Validation → Freeze/Export**.
|
|
34
|
+
|
|
35
|
+
Key modules in `src/layer/`:
|
|
36
|
+
|
|
37
|
+
- **`core.py`** — The `@layer_obj` decorator and `field()` function. The decorator transforms a class into a configuration object with methods like `.layer()`, `.validate()`, `.resolve()`, `.freeze()`, `.explain()`, `.to_dict()`, `.diff()`, `.json_schema()`. This is the central module that ties everything together.
|
|
38
|
+
- **`solidify.py`** — Loading untyped data into typed `@layer_obj` instances. `solidify()` handles dicts, `solidify_file()` handles YAML/JSON/TOML files, `solidify_env()` handles environment variables with prefix conventions. Includes type coercion logic (str → int, bool, float, list, dict).
|
|
39
|
+
- **`validation.py`** — 14 single-field validators (e.g., `require`, `one_of`, `in_range`, `regex`) and 5 cross-field validators (e.g., `requires_if`, `mutually_exclusive`, `depends_on`). Validators follow the signature `(value, field_name, config) -> True | raise ValidationError`. Validation is organized by category so different rule sets run in different contexts.
|
|
40
|
+
- **`interpolation.py`** — Resolves `${field_name}` and `${nested.path}` variable references in string values, with circular reference detection.
|
|
41
|
+
- **`layering.py`** — `LayerRule` enum: OVERRIDE (default), PRESERVE, MERGE (dicts), APPEND (lists).
|
|
42
|
+
- **`sources.py`** — `SourceHistory` and `SourceEntry` dataclasses for tracking which source set each field value.
|
|
43
|
+
- **`exceptions.py`** — Exception hierarchy: `ConfigError` → `ValidationError`, `StructureError`, `LayeringError`, `InterpolationError`.
|
|
44
|
+
|
|
45
|
+
## Key Design Details
|
|
46
|
+
|
|
47
|
+
- `field()` returns a `FieldDef` storing type hints, defaults, validators (grouped by category), metadata, description, secret flag, and custom parser.
|
|
48
|
+
- The `@layer_obj` decorator adds `_field_defs`, `_sources`, and `_frozen` to instances. It replaces `FieldDef` class attributes with their default values on instantiation.
|
|
49
|
+
- Tests use a custom harness with global `passed`/`failed` counters (not pytest). The test file runs directly with `python test_features.py` and exits with code 1 on failure.
|
|
50
|
+
- Python >= 3.10.12 required. Uses UV as package manager.
|