Skip to main content

TOML configuration loader with include/merge/interpolation

Project description

tomlstack

tomlstack is a lightweight TOML config loader for Python 3.11+ with:

  • top-level include loading
  • include-tree inspection with raw and resolved paths
  • deterministic merge by include order
  • ${path} interpolation with cycle/undefined checks
  • node-level provenance (origin, history, dependencies)

tomlstack does not try to be a configuration framework. It addresses two missing pieces in TOML: file composition and safe interpolation, while keeping files self-contained and explainable.

Install

pip install tomlstack

Quick Start

main.toml:

include = [
    "./base.toml",
    "./prod.toml",
]

[db]
url = "postgres://${db.user}:${db.pass}@${db.host}:${db.port}"

base.toml:

[db]
user = "alice"
pass = "secret"
host = "localhost"
port = 5432

Python:

from tomlstack import TomlNode, load

cfg = load("main.toml")
print(cfg["db"]["url"].raw)    # raw interpolation string
print(cfg["db"]["url"].value)  # resolved value
print(cfg["db"]["url"].origin)
print(cfg["db"]["url"].history)
print(cfg["db"]["url"].dependencies)
print(cfg["db"]["url"].explain())
print(cfg.raw)                   # raw configuration snapshot
print(cfg.to_dict())             # resolved configuration snapshot

Include Semantics

  • top-level include only; nested include is treated as normal data
  • syntax: string or list of strings
  • valid include path forms:
    • ./... or ../...
    • @label/... (label from tomlstack.anchors)
    • absolute path
  • any other form raises an error with a path-format hint

Meta Include Directives

[tomlstack.anchors]
proj = "./shared"
  • anchors are local to the file that declares them
  • anchor path values must be absolute or start with ./ or ../

Merge Rules

Load order for current file:

  1. merge first include
  2. merge second include
  3. ...
  4. merge current file (highest priority)

Conflict behavior:

  • dict: recursive merge, later wins on key conflict
  • list: later value replaces whole list
  • scalar: later value replaces earlier

Interpolation Semantics

  • interpolation is resolved lazily by cfg.resolve(), cfg.to_dict(), or node.value
  • path syntax supports dot and list index: ${db.apps[0]}
  • full-string interpolation ("${db.port}") keeps source type
  • embedded interpolation ("postgres://${db.host}:${db.port}") allows only:
    • str, int, float, bool, date, time, datetime
  • formatting syntax: ${path:spec}
  • for date/time/datetime, formatting uses strftime
  • otherwise uses Python format(value, spec)
  • invalid interpolation syntax and formatting failures raise InterpolationError
  • undefined references raise InterpolationUndefinedError
  • interpolation cycles raise InterpolationCycleError

Invalid TOML raises TomlFormatError; invalid include paths and anchors raise IncludeError.

Public API

  • cfg = load("f.toml")
  • cfg.raw — raw configuration snapshot
  • cfg.resolve()
  • cfg.to_dict() — resolved configuration snapshot
  • cfg.include_treeIncludeNode load-occurrence tree
  • cfg.include_tree.render() — render raw include references
  • cfg.include_tree.render(absolute=True) — include references with resolved paths
  • node: TomlNode = cfg["proj"][0]["path"]["foo"]
  • node.raw
  • node.value
  • node.origin
  • node.history
  • node.dependencies — direct interpolation dependencies
  • node.explain() — transitive interpolation trace
  • node.preview()
  • cfg.to_toml() -> NotImplementedError

cfg.raw, cfg.to_dict(), node.raw, and node.value return independent data snapshots; mutating their dictionaries or lists does not modify the loaded configuration. TomlNode instances are created by configuration navigation and are not constructed directly.

History records definitions of the same data path from lowest to highest priority. When a list or value type is replaced, its old child paths are discarded. Resolving an interpolation does not change the history of the node containing the expression. Each history entry is a TomlFile with its raw reference and resolved absolute path.

Dependencies describe interpolation separately from merge history. A full replacement such as target = "${source}" leaves target.history at the file that defined target, while target.dependencies records the source path and its history.

Current Limitations

  • interpolation path parser supports unquoted dot keys and numeric list indices
  • no nested interpolation expressions
  • to_toml() is not implemented yet

Release To PyPI

Build package:

uv run --with build python -m build

Upload to TestPyPI first:

uv run --with twine python -m twine upload --repository testpypi dist/*

Verify install from TestPyPI:

python -m pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple tomlstack

Upload to PyPI:

uv run --with twine python -m twine upload dist/*

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

tomlstack-0.2.0.tar.gz (73.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tomlstack-0.2.0-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

Details for the file tomlstack-0.2.0.tar.gz.

File metadata

  • Download URL: tomlstack-0.2.0.tar.gz
  • Upload date:
  • Size: 73.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tomlstack-0.2.0.tar.gz
Algorithm Hash digest
SHA256 ec409daeeabb271a5f78aa712cd479b08ded83351932dbde5eb3579a8dab2ae8
MD5 713b6050e363ac8963d72afdff4d21b6
BLAKE2b-256 791dc8d8d46af32e43dbeb7fad4cbe8e769b585632f7b4dfbfc268930e8a3000

See more details on using hashes here.

Provenance

The following attestation bundles were made for tomlstack-0.2.0.tar.gz:

Publisher: publish-pypi.yml on WXZhao7/tomlstack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tomlstack-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: tomlstack-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tomlstack-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e197b04587eef5ad1bc36c377979db8b481c996b360a1c7817fe2f212a59c0ea
MD5 58595de10374bba909a1222c51066805
BLAKE2b-256 73d68189d0479f4b96fe222e011f0a4a201188e4e9f8ade9c7c8dd33497284f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for tomlstack-0.2.0-py3-none-any.whl:

Publisher: publish-pypi.yml on WXZhao7/tomlstack

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page