Skip to content

Core Primitives

Use this page when you want the main configuration building blocks:

  • BaseConfig and ConfigMeta for defining config containers.
  • Field, field(), Group, and group() for declaring config attributes.
  • Var for direct access to the bound ContextVar wrapper.

liblaf.conf.BaseConfig

Group related configuration variables behind a singleton object.

Subclasses declare Field descriptors for scalar values and group descriptors for nested configuration sections. Instances expose helpers for loading environment variables, applying temporary overrides, and serializing the current state.

Methods:

  • load_env

    Refresh every field from its configured environment variable.

  • override

    Temporarily override one or more values within a context manager.

  • set

    Update fields or groups from a mapping and keyword arguments.

  • to_dict

    Serialize the current config tree to nested dictionaries.

  • to_namespace

    Serialize the current config tree to nested namespaces.

Attributes:

env_prefix class-attribute

env_prefix: str

name class-attribute

name: str

load_env

load_env() -> None

Refresh every field from its configured environment variable.

Source code in src/liblaf/conf/_config.py
def load_env(self) -> None:
    """Refresh every field from its configured environment variable."""
    for name in self._fields:
        var: Var[Any] = self._get_field(name)
        var.load_env()
    for name in self._groups:
        group: BaseConfig = self._get_group(name)
        group.load_env()

override

override(
    changes: Mapping[str, Any] | None = None,
    /,
    **kwargs: Any,
) -> Generator[None]

Temporarily override one or more values within a context manager.

Parameters:

  • changes (Mapping[str, Any] | None, default: None ) –

    Optional mapping of names to temporary values.

  • **kwargs (Any, default: {} ) –

    Additional name-to-value overrides.

Yields:

  • Generator[None]

    None while the overrides are active.

Source code in src/liblaf/conf/_config.py
@contextlib.contextmanager
def override(
    self, changes: Mapping[str, Any] | None = None, /, **kwargs: Any
) -> Generator[None]:
    """Temporarily override one or more values within a context manager.

    Args:
        changes: Optional mapping of names to temporary values.
        **kwargs: Additional name-to-value overrides.

    Yields:
        `None` while the overrides are active.
    """
    if changes is not None:
        kwargs.update(changes)
    with contextlib.ExitStack() as stack:
        for name, value in kwargs.items():
            var: BaseConfig | Var[Any] = self._get_field_or_group(name)
            stack.enter_context(var.override(value))
        yield

set

set(
    changes: Mapping[str, Any] | None = None,
    /,
    **kwargs: Any,
) -> None

Update fields or groups from a mapping and keyword arguments.

Nested groups accept mapping values and forward them to the nested config's own set() method.

Source code in src/liblaf/conf/_config.py
def set(self, changes: Mapping[str, Any] | None = None, /, **kwargs: Any) -> None:
    """Update fields or groups from a mapping and keyword arguments.

    Nested groups accept mapping values and forward them to the nested
    config's own `set()` method.
    """
    if changes is not None:
        kwargs.update(changes)
    for name, value in kwargs.items():
        var: BaseConfig | Var[Any] = self._get_field_or_group(name)
        var.set(value)

to_dict

to_dict() -> dict[str, Any]

Serialize the current config tree to nested dictionaries.

Source code in src/liblaf/conf/_config.py
def to_dict(self) -> dict[str, Any]:
    """Serialize the current config tree to nested dictionaries."""
    result: dict[str, Any] = {}
    for name in self._fields:
        result[name] = self._get_field(name).get()
    for name in self._groups:
        result[name] = self._get_group(name).to_dict()
    return result

to_namespace

to_namespace() -> SimpleNamespace

Serialize the current config tree to nested namespaces.

Source code in src/liblaf/conf/_config.py
def to_namespace(self) -> types.SimpleNamespace:
    """Serialize the current config tree to nested namespaces."""
    result: types.SimpleNamespace = types.SimpleNamespace()
    for name in self._fields:
        setattr(result, name, self._get_field(name).get())
    for name in self._groups:
        setattr(result, name, self._get_group(name).to_namespace())
    return result

liblaf.conf.ConfigMeta

Bases: type


              flowchart TD
              liblaf.conf.ConfigMeta[ConfigMeta]

              

              click liblaf.conf.ConfigMeta href "" "liblaf.conf.ConfigMeta"
            

Build config classes and cache a singleton instance per subclass.

Methods:

  • __call__

    Return the cached config instance, creating it on first access.

  • __new__

    Create a config class with derived metadata and descriptor maps.

__call__

__call__[T: BaseConfig](*args, **kwargs) -> T

Return the cached config instance, creating it on first access.

Source code in src/liblaf/conf/_config.py
def __call__[T: BaseConfig](cls: type[T], *args, **kwargs) -> T:
    """Return the cached config instance, creating it on first access."""
    instance: T | None = cls.__dict__.get("_instance")
    if instance is None:
        instance = super().__call__(*args, **kwargs)  # ty:ignore[invalid-super-argument]
        cls._instance = instance
    return instance

__new__

__new__(
    mcs,
    name: str,
    bases: tuple[type, ...],
    namespace: dict[str, Any],
    /,
    **_kwargs: Any,
) -> type

Create a config class with derived metadata and descriptor maps.

Source code in src/liblaf/conf/_config.py
def __new__(
    mcs,
    name: str,
    bases: tuple[type, ...],
    namespace: dict[str, Any],
    /,
    **_kwargs: Any,
) -> type:
    """Create a config class with derived metadata and descriptor maps."""
    if "name" not in namespace:
        namespace["name"] = alias_generators.to_snake(name).removesuffix("_config")
    if "env_prefix" not in namespace:
        namespace["env_prefix"] = namespace["name"].upper() + "_"
    cls: type[BaseConfig] = cast(
        "type[BaseConfig]", super().__new__(mcs, name, bases, namespace)
    )
    fields: dict[str, Field[Any]] = {}
    groups: dict[str, Group[Any]] = {}
    for base in reversed(cls.__mro__[1:]):
        fields.update(getattr(base, "_fields", {}))
        groups.update(getattr(base, "_groups", {}))
    for key, value in namespace.items():
        match value:
            case Field():
                groups.pop(key, None)
                fields[key] = value
            case Group():
                fields.pop(key, None)
                groups[key] = value
            case _:
                fields.pop(key, None)
                groups.pop(key, None)
    cls._fields = fields
    cls._groups = groups
    return cls

liblaf.conf.Field dataclass

Field(
    env: str | None = None,
    default: T | MissingType = MISSING,
    factory: Factory[T] | None = None,
    converter: Converter[T] = identity,
)

Describe a config value and lazily bind it to a Var.

The descriptor stores the environment-variable name, default value, optional factory, and string converter used when it creates a bound variable for a config instance.

Parameters:

  • env (str | None, default: None ) –
  • default (T | MissingType, default: <MissingType.MISSING: 1> ) –
  • factory (T | None, default: None ) –
  • converter (T, default: <function identity at 0x7fe03ade6c40> ) –

Attributes:

Methods:

  • __get__

    Return the descriptor on the class or a cached bound variable.

  • __set_name__

    Record the attribute name assigned by the owning config class.

converter class-attribute instance-attribute

converter: Converter[T] = identity

default class-attribute instance-attribute

default: T | MissingType = MISSING

env class-attribute instance-attribute

env: str | None = None

factory class-attribute instance-attribute

factory: Factory[T] | None = None

name class-attribute instance-attribute

name: str = field(init=False)

__get__

__get__(instance: None, owner: type | None = None) -> Self
__get__(
    instance: object, owner: type | None = None
) -> Var[T]

Return the descriptor on the class or a cached bound variable.

Source code in src/liblaf/conf/_field.py
def __get__(
    self, instance: ConfigProtocol | None, owner: type | None = None
) -> Self | Var[T]:
    """Return the descriptor on the class or a cached bound variable."""
    if instance is None:
        return self
    if self.name not in instance.__dict__:
        instance.__dict__[self.name] = self._bind(instance)
    return instance.__dict__[self.name]

__set_name__

__set_name__(owner: type, name: str) -> None

Record the attribute name assigned by the owning config class.

Source code in src/liblaf/conf/_field.py
def __set_name__(self, owner: type, name: str) -> None:
    """Record the attribute name assigned by the owning config class."""
    object.__setattr__(self, "name", name)

liblaf.conf.field

field[T](
    *,
    env: str | None = None,
    default: T | MissingType = MISSING,
    factory: Factory[T] | None = None,
    converter: Converter[T] = identity,
) -> Field[T]

Create a Field descriptor for a config attribute.

Source code in src/liblaf/conf/_field.py
def field[T](
    *,
    env: str | None = None,
    default: T | MissingType = MISSING,
    factory: Factory[T] | None = None,
    converter: Converter[T] = converters.identity,
) -> Field[T]:
    """Create a `Field` descriptor for a config attribute."""
    return Field(env=env, default=default, factory=factory, converter=converter)

liblaf.conf.Group dataclass

Group(factory: Callable[[], T])

Cache a nested config or computed object per owning instance.

Parameters:

Attributes:

Methods:

  • __get__

    Return the descriptor on the class or the cached group value.

  • __set_name__

    Record the attribute name assigned by the owning class.

factory instance-attribute

factory: Callable[[], T]

name class-attribute instance-attribute

name: str = field(init=False)

__get__

__get__(instance: None, owner: type | None = None) -> Self
__get__(instance: object, owner: type | None = None) -> T

Return the descriptor on the class or the cached group value.

Source code in src/liblaf/conf/_group.py
def __get__(self, instance: object | None, owner: type | None = None) -> Self | T:
    """Return the descriptor on the class or the cached group value."""
    if instance is None:
        return self
    if self.name not in instance.__dict__:
        instance.__dict__[self.name] = self.factory()
    return instance.__dict__[self.name]

__set_name__

__set_name__(owner: type, name: str) -> None

Record the attribute name assigned by the owning class.

Source code in src/liblaf/conf/_group.py
def __set_name__(self, owner: type, name: str) -> None:
    """Record the attribute name assigned by the owning class."""
    object.__setattr__(self, "name", name)

liblaf.conf.group

group[T](factory: type[T]) -> Group[T]
group[T](factory: Callable[[], T]) -> Group[T]

Wrap a config subclass or zero-argument callable as a group descriptor.

Source code in src/liblaf/conf/_group.py
def group[T](factory: Callable[[], T]) -> Group[T]:
    """Wrap a config subclass or zero-argument callable as a group descriptor."""
    return Group(factory)

liblaf.conf.Var dataclass

Var(
    name: str,
    default: T | MissingType = MISSING,
    factory: Factory[T] | None = None,
    env: str | None = None,
    converter: Converter[T] | None = None,
)

Store one typed configuration value in a ContextVar.

Values can be seeded from a default, a factory, or an environment variable. Temporary overrides use normal ContextVar semantics, so they are scoped to the active context.

Parameters:

  • env (str | None) –
  • converter (T) –

Methods:

  • __hash__

    Hash the wrapped context variable.

  • get

    Return the current value or a caller-provided fallback.

  • load_env

    Reload the current value from the configured environment variable.

  • override

    Temporarily set a value for the duration of a context manager.

  • reset

    Restore the value captured by set().

  • set

    Set the current value and return the reset token.

Attributes:

Source code in src/liblaf/conf/_var.py
def __init__(
    self,
    name: str,
    default: T | MissingType = MISSING,
    factory: Factory[T] | None = None,
    env: str | None = None,
    converter: Converter[T] | None = None,
) -> None:
    """Initialize a variable and eagerly apply any environment value."""
    if converter is None:
        converter: Converter[T] = converters.identity
    if env is not None:
        value: str | None = os.getenv(env)
        if value is not None:
            default: T = cast("T", converter(value))
    if default is MISSING and factory is not None:
        default: T = factory()
    if default is MISSING:
        var: contextvars.ContextVar[T] = contextvars.ContextVar(name)
    else:
        var: contextvars.ContextVar[T] = contextvars.ContextVar(
            name, default=default
        )
    object.__setattr__(self, "_var", var)
    object.__setattr__(self, "env", env)
    object.__setattr__(self, "converter", converter)

converter instance-attribute

converter: Converter[T]

env instance-attribute

env: str | None

name property

name: str

Return the ContextVar name.

__hash__

__hash__() -> int

Hash the wrapped context variable.

Source code in src/liblaf/conf/_var.py
def __hash__(self) -> int:
    """Hash the wrapped context variable."""
    return hash(self._var)

get

get() -> T
get(default: T) -> T
get[D](default: D) -> D | T

Return the current value or a caller-provided fallback.

Source code in src/liblaf/conf/_var.py
def get(self, default: Any = MISSING) -> T:
    """Return the current value or a caller-provided fallback."""
    if default is MISSING:
        return self._var.get()
    return self._var.get(default)

load_env

load_env() -> None

Reload the current value from the configured environment variable.

Source code in src/liblaf/conf/_var.py
def load_env(self) -> None:
    """Reload the current value from the configured environment variable."""
    if self.env is None:
        return
    value: str | None = os.getenv(self.env)
    if value is None:
        return
    if self.converter is None:
        self.set(cast("T", value))
    else:
        self.set(self.converter(value))

override

override(value: T) -> Generator[None]

Temporarily set a value for the duration of a context manager.

Parameters:

  • value (T) –

    Temporary value to expose inside the context.

Yields:

  • Generator[None]

    None while the override is active.

Source code in src/liblaf/conf/_var.py
@contextlib.contextmanager
def override(self, value: T) -> Generator[None]:
    """Temporarily set a value for the duration of a context manager.

    Args:
        value: Temporary value to expose inside the context.

    Yields:
        `None` while the override is active.
    """
    token: contextvars.Token[T] = self._var.set(value)
    try:
        yield
    finally:
        self._var.reset(token)

reset

reset(token: Token[T]) -> None

Restore the value captured by set().

Source code in src/liblaf/conf/_var.py
def reset(self, token: contextvars.Token[T]) -> None:
    """Restore the value captured by `set()`."""
    self._var.reset(token)

set

set(value: T) -> Token[T]

Set the current value and return the reset token.

Source code in src/liblaf/conf/_var.py
def set(self, value: T) -> contextvars.Token[T]:
    """Set the current value and return the reset token."""
    return self._var.set(value)