A small, schema-driven YAML object merger and validator
Project description
config-cascade-merge
A small, schema-driven YAML object merger and validator written in Python. It loads a base schema and validates ordered overlay operations against it.
Installation
config-cascade-merge requires Python 3.10 or newer.
python -m pip install config-cascade-merge
You can also install the latest development version directly from GitHub:
python -m pip install git+https://github.com/149segolte/config-cascade-merge.git
Quick start
config-cascade-merge --base_config base.yaml --overlays_dir overlays/
The executable also supports short options:
config-cascade-merge -b base.yaml -o overlays/
The module form is equivalent:
python -m config_cascade_merge -b base.yaml -o overlays/
Base schema
The base file describes the allowed configuration shape rather than containing configuration values.
# base.yaml
type: object
keys:
profile:
type: object
keys:
name:
type: string
active:
type: boolean
packages:
type: list
id: name
value:
type: object
keys:
name:
type: string
version:
type: integer
labels:
type: map
value:
type: string
Schema types
| Type | Purpose | Main fields |
|---|---|---|
string, integer, float, boolean, any |
Primitive value | - |
object |
Fixed-key mapping | keys, optional merge, optional id |
map |
Arbitrary-key mapping with uniform values | value, optional merge, optional id |
list |
Ordered values with a uniform item schema | value, optional merge, optional id |
union |
Value matching one of at least two schemas | value (list of schemas) |
tagged_union |
Object selected by a discriminator field | keys, tag.name, tag.options |
The merge policy is either append (default) or override. An id identifies values for identity-based merging. These policies are normalized and validated now; merge execution is not yet implemented.
Example tagged union:
type: tagged_union
keys:
label:
type: string
tag:
name: kind
options:
file:
path:
type: string
service:
port:
type: integer
disabled: null
Overlays
Each overlay has a non-empty name and an ordered list of operations. Paths start with .; . addresses the schema root.
# overlays/10-workstation.yaml
name: workstation
operations:
- action: set
path: .profile
data:
name: Ada
active: true
- action: merge
path: .packages
data:
- name: ruff
version: 1
- action: test
path: .profile.name
data: Ada
on_fail: warn
message: unexpected profile
- action: remove
path: .labels.legacy
- action: clear
path: .packages
Operations
| Action | Behavior | Required fields |
|---|---|---|
set |
Creates or replaces a value; data must fully match the target schema | path, data |
merge |
Validates a recursive merge into an object, map, or list | path, data |
remove |
Nulls a fixed object field or deletes a dynamic map entry | path |
test |
Checks equality before later execution | path, data; optional on_fail, message |
clear |
Removes all entries from a map or list | path |
test.on_fail accepts:
error— stop execution (default)warn— report the optional message and continueskip— keep prior operations from this overlay and skip the remainderdrop— discard all operations from this overlay
These failure behaviors are represented by normalized operations but are not executed yet.
Validation and errors
The validator rejects malformed YAML, invalid schemas, unknown paths or fields, incompatible values, and unsupported operations. Errors include source filenames and line numbers when available:
overlays/10-workstation.yaml:8: Data at '.packages[0].version' must be integer, got str
The CLI exits with status 1 for invalid paths, schemas, or overlays. An empty base file exits successfully without processing overlays.
Development
Clone the repository, install development dependencies, and run the test suite:
git clone https://github.com/149segolte/config-cascade-merge.git
cd config-cascade-merge
uv sync --dev
uv run pytest
Build both source and wheel distributions:
uv build
Project layout:
src/config_cascade_merge/cli.py CLI entry point
src/config_cascade_merge/schema.py schema parsing and normalization
src/config_cascade_merge/overlay.py overlay loading and validation
src/config_cascade_merge/yaml_loader.py YAML loading with source locations
tests/ pytest test suite
See CONTRIBUTING.md for the contribution and release process.
License
Licensed under the Mozilla Public License 2.0.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file config_cascade_merge-0.6.1.tar.gz.
File metadata
- Download URL: config_cascade_merge-0.6.1.tar.gz
- Upload date:
- Size: 21.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
318dfbebe47a21bd23af0f3d367e52f798b9bed4d70434092a52479510bdbe96
|
|
| MD5 |
873101c0f0ba826ff1a83a9fac705e2d
|
|
| BLAKE2b-256 |
df91ef7c54651a6e4b4278c96a352a63c96c8bc9308907b41398efffae1c1ef0
|
File details
Details for the file config_cascade_merge-0.6.1-py3-none-any.whl.
File metadata
- Download URL: config_cascade_merge-0.6.1-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c796b4fa21838b24f9f2c43ebd044c44e632d8bef5eb2790d7e89d3c2b5910b6
|
|
| MD5 |
68aeb0f51092a71424a58172fbdb4899
|
|
| BLAKE2b-256 |
2c33a0348e1499c3b157031bdb64e499d51b9c91f859ba5189b0fc3562a5da20
|