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.
Files changed (60) hide show
  1. layerconf-0.1.0/.github/workflows/ci.yml +64 -0
  2. layerconf-0.1.0/.github/workflows/docs.yml +31 -0
  3. layerconf-0.1.0/.github/workflows/release.yml +54 -0
  4. layerconf-0.1.0/.gitignore +18 -0
  5. layerconf-0.1.0/.python-version +1 -0
  6. layerconf-0.1.0/CHANGELOG.md +37 -0
  7. layerconf-0.1.0/CLAUDE.md +50 -0
  8. layerconf-0.1.0/PKG-INFO +496 -0
  9. layerconf-0.1.0/README.md +455 -0
  10. layerconf-0.1.0/docs/api/index.md +123 -0
  11. layerconf-0.1.0/docs/changelog.md +3 -0
  12. layerconf-0.1.0/docs/concepts.md +231 -0
  13. layerconf-0.1.0/docs/examples.md +236 -0
  14. layerconf-0.1.0/docs/getting-started.md +153 -0
  15. layerconf-0.1.0/docs/index.md +49 -0
  16. layerconf-0.1.0/docs/observability.md +186 -0
  17. layerconf-0.1.0/docs/providers.md +231 -0
  18. layerconf-0.1.0/docs/validation.md +250 -0
  19. layerconf-0.1.0/mkdocs.yml +73 -0
  20. layerconf-0.1.0/pyproject.toml +70 -0
  21. layerconf-0.1.0/src/layer/__init__.py +115 -0
  22. layerconf-0.1.0/src/layer/core.py +826 -0
  23. layerconf-0.1.0/src/layer/exceptions.py +60 -0
  24. layerconf-0.1.0/src/layer/exporters.py +208 -0
  25. layerconf-0.1.0/src/layer/interpolation.py +99 -0
  26. layerconf-0.1.0/src/layer/layering.py +8 -0
  27. layerconf-0.1.0/src/layer/observers.py +113 -0
  28. layerconf-0.1.0/src/layer/pipeline.py +292 -0
  29. layerconf-0.1.0/src/layer/providers/__init__.py +19 -0
  30. layerconf-0.1.0/src/layer/providers/base.py +34 -0
  31. layerconf-0.1.0/src/layer/providers/dotenv.py +51 -0
  32. layerconf-0.1.0/src/layer/providers/env.py +122 -0
  33. layerconf-0.1.0/src/layer/providers/etcd.py +96 -0
  34. layerconf-0.1.0/src/layer/providers/file.py +46 -0
  35. layerconf-0.1.0/src/layer/providers/ssm.py +91 -0
  36. layerconf-0.1.0/src/layer/providers/vault.py +53 -0
  37. layerconf-0.1.0/src/layer/solidify.py +349 -0
  38. layerconf-0.1.0/src/layer/sources.py +41 -0
  39. layerconf-0.1.0/src/layer/type_resolution.py +177 -0
  40. layerconf-0.1.0/src/layer/validation.py +355 -0
  41. layerconf-0.1.0/tests/conftest.py +33 -0
  42. layerconf-0.1.0/tests/test_aliasing.py +115 -0
  43. layerconf-0.1.0/tests/test_class_validators.py +257 -0
  44. layerconf-0.1.0/tests/test_computed_field.py +149 -0
  45. layerconf-0.1.0/tests/test_core.py +143 -0
  46. layerconf-0.1.0/tests/test_env_provider_unified.py +81 -0
  47. layerconf-0.1.0/tests/test_exporters.py +188 -0
  48. layerconf-0.1.0/tests/test_field_def.py +78 -0
  49. layerconf-0.1.0/tests/test_interpolation.py +45 -0
  50. layerconf-0.1.0/tests/test_nested.py +94 -0
  51. layerconf-0.1.0/tests/test_observers.py +198 -0
  52. layerconf-0.1.0/tests/test_pipeline.py +430 -0
  53. layerconf-0.1.0/tests/test_polish.py +285 -0
  54. layerconf-0.1.0/tests/test_providers.py +368 -0
  55. layerconf-0.1.0/tests/test_schema.py +81 -0
  56. layerconf-0.1.0/tests/test_solidify.py +65 -0
  57. layerconf-0.1.0/tests/test_solidify_mode.py +189 -0
  58. layerconf-0.1.0/tests/test_type_resolution.py +236 -0
  59. layerconf-0.1.0/tests/test_validation.py +67 -0
  60. 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,18 @@
1
+ .vscode/
2
+
3
+ # Python-generated files
4
+ __pycache__/
5
+ *.py[oc]
6
+ build/
7
+ dist/
8
+ wheels/
9
+ *.egg-info
10
+
11
+ # Virtual environments
12
+ .venv
13
+
14
+ # Planning
15
+ planning_docs/
16
+
17
+ # docs
18
+ site/
@@ -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.