Skip to content

Cookbook

Cookbook

Short, copy‑pasteable recipes. Each example is runnable; code is included from examples/.

Quickstart (load & resolve)

"""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()

Convert to Pydantic model

"""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()

Templates: env/file/config/yaml

"""Templates showcase: env, file, config, yaml.

Run:
    PYTHONPATH=src uv run python examples/templates/10_env_file_config_yaml.py

This uses shared YAML under examples/config/config.yaml which contains all template types.
"""

from __future__ import annotations

import os
from pathlib import Path

from coyaml import YSettings
from coyaml.sources.yaml import YamlFileSource


def main() -> None:
    # Prepare environment for env templates
    os.environ['DB_USER'] = 'templ_user'
    os.environ['DB_PASSWORD'] = 'templ_password'  # noqa: S105

    cfg = YSettings()
    cfg_path = Path(__file__).resolve().parents[1] / 'config' / 'config.yaml'
    cfg.add_source(YamlFileSource(cfg_path.as_posix()))
    cfg.resolve_templates()

    # env
    print('env user:', cfg['debug.db.user'])
    # file (reads tests/config/init.sql)
    print('file snippet length:', len(cfg['debug.db.init_script']))
    # config (builds db_url from other values)
    print('config db_url:', cfg['app.db_url'])
    # yaml (loads and merges external yaml)
    print('yaml feature:', cfg['app.extra_settings.feature_flags.enable_new_feature'])


if __name__ == '__main__':
    main()

Injection: explicit path

"""Injection by explicit dotted path using Annotated + YResource.

Run:
    PYTHONPATH=src uv run python examples/injection/20_inject_by_explicit_path.py
"""

from __future__ import annotations

from typing import Annotated

from coyaml import YRegistry, YResource, YSettings, coyaml
from coyaml.sources.yaml import YamlFileSource


def setup() -> None:
    cfg = YSettings()
    cfg.add_source(YamlFileSource('tests/config/config.yaml'))
    cfg.resolve_templates()
    YRegistry.set_config(cfg)


@coyaml
def handler(user: Annotated[str, YResource('debug.db.user')]) -> str:
    return user


def main() -> None:
    setup()
    print('user =', handler())


if __name__ == '__main__':
    main()

Injection: by name with mask

"""Injection by parameter name constrained by mask.

Run:
    PYTHONPATH=src uv run python examples/injection/22_inject_by_name_with_mask.py
"""

from __future__ import annotations

from typing import Annotated

from coyaml import YRegistry, YResource, YSettings, coyaml


def setup() -> None:
    cfg = YSettings({'debug': {'db': {'user': 'dev_user'}}, 'prod': {'db': {'user': 'prod_user'}}})
    YRegistry.set_config(cfg)


@coyaml(mask='debug.**')
def handler(user: Annotated[str | None, YResource()] = None) -> str | None:
    return user


def main() -> None:
    setup()
    print('user =', handler())


if __name__ == '__main__':
    main()