Basic usage
Basic usage
This tutorial covers the essentials: creating settings, loading YAML, resolving templates, and reading values.
Quickstart
Code (excerpt) from the runnable example:
"""Quickstart: load YAML, resolve templates, and read values.
How to run locally:
PYTHONPATH=src uv run python examples/basic/01_quickstart.py
This example intentionally uses the shared config file under examples/config.
"""
from __future__ import annotations
import os
from pathlib import Path
from coyaml import YSettings
from coyaml.sources.yaml import YamlFileSource
def main() -> None:
# Set environment variables required by the example templates.
# Note: never do this in production code; prefer a real environment or .env.
os.environ['DB_USER'] = 'quick_user'
os.environ['DB_PASSWORD'] = 'quick_password' # noqa: S105
# Initialize settings and load YAML from the examples folder.
cfg = YSettings()
cfg_path = Path(__file__).resolve().parents[1] / 'config' / 'config.yaml'
cfg.add_source(YamlFileSource(cfg_path.as_posix()))
# Resolve all templates (env, file, config, yaml) after loading.
cfg.resolve_templates()
# Read values using attribute access (dot notation) and dotted keys.
print('index =', cfg.index)
print('llm =', cfg['llm'])
print('db_url =', cfg['debug.db.url'])
print('db_user =', cfg.debug.db.user)
if __name__ == '__main__':
main()
Dot access and setting values
"""Dot access vs dotted keys; setting values and nested creation.
Run:
PYTHONPATH=src uv run python examples/basic/02_dot_access_and_set.py
"""
from __future__ import annotations
from coyaml import YNode, YSettings
def main() -> None:
cfg = YSettings()
# Assign flat values via attributes and dotted keys.
cfg.index = 1
cfg['llm'] = 'gpt'
# Create nested structure with a dotted key; intermediate dicts are created automatically.
cfg['debug.db.url'] = 'sqlite:///example.db'
# Nested dictionaries are wrapped as YNode for convenient attribute access.
assert isinstance(cfg.debug, YNode) # noqa: S101
assert cfg.debug.db.url == 'sqlite:///example.db' # noqa: S101
print('index =', cfg.index)
print('llm =', cfg['llm'])
print('db_url =', cfg.debug.db.url)
if __name__ == '__main__':
main()
Converting to Pydantic models
"""Converting configuration (or subtrees) to Pydantic models using .to().
Run:
PYTHONPATH=src uv run python examples/basic/03_pydantic_to_method.py
"""
from __future__ import annotations
from pathlib import Path
from pydantic import BaseModel
from coyaml import YSettings
from coyaml.sources.yaml import YamlFileSource
class DatabaseConfig(BaseModel):
url: str
class DebugConfig(BaseModel):
db: DatabaseConfig
def main() -> None:
cfg = YSettings()
cfg_path = Path(__file__).resolve().parents[1] / 'config' / 'config.yaml'
cfg.add_source(YamlFileSource(cfg_path.as_posix()))
# Convert a subtree to a Pydantic model
debug: DebugConfig = cfg.debug.to(DebugConfig)
print('debug.db.url =', debug.db.url)
# Convert the whole tree to a Pydantic model
full: DebugConfig = cfg.to(DebugConfig)
# Note: this will fail unless the top-level shape matches DebugConfig.
# It is here to demonstrate that .to() can be called at any level.
_ = full
if __name__ == '__main__':
main()
Run it locally:
PYTHONPATH=src uv run python examples/base.py