Settings

The didactic-settings distribution. See Guides > Settings for the composition ladder, config groups, union descent, interpolation and provenance.

Composition

didactic.settings.compose

compose(
    path: Path | str | None = None,
    *,
    schema: type[M],
    base: Mapping[str, ConfigValue] | None = None,
    groups: Mapping[str, str | None] | None = None,
    profile: str | Mapping[str, ConfigValue] | None = None,
    overlays: Sequence[
        Path | str | Mapping[str, ConfigValue]
    ] = (),
    overrides: Sequence[Override] = (),
    search_path: Sequence[Path | str] = (),
    resolvers: Mapping[str, ResolverFn] | None = None,
) -> M

Compose a validated model from files, fragments, overlays and overrides.

PARAMETER DESCRIPTION
path

The primary document. Its defaults: list selects root fragments and config-group fragments; its parent directory is the first search root.

TYPE: Path | str | None DEFAULT: None

schema

The model to validate against; every layer is checked against it at every depth.

TYPE: type[M]

base

A mapping merged below everything else.

TYPE: Mapping[str, ConfigValue] | None DEFAULT: None

groups

Config-group selections by slot, applied after the file's defaults: entries; None deselects a slot.

TYPE: Mapping[str, str | None] | None DEFAULT: None

profile

A profile name (loaded as profiles/<name> from the search roots) or a mapping used as given.

TYPE: str | Mapping[str, ConfigValue] | None DEFAULT: None

overlays

Documents merged above the profile: file paths or mappings.

TYPE: Sequence[Path | str | Mapping[str, ConfigValue]] DEFAULT: ()

overrides

key=value strings (text decoded by the leaf annotation) or (key, value) pairs (typed). A key containing / selects a config group instead.

TYPE: Sequence[Override] DEFAULT: ()

search_path

Directories searched, after the primary file's parent, for fragments and profiles.

TYPE: Sequence[Path | str] DEFAULT: ()

resolvers

Interpolation resolvers consulted before the registry, for this call only.

TYPE: Mapping[str, ResolverFn] | None DEFAULT: None

RETURNS DESCRIPTION
M

The validated instance; :func:~didactic.settings.provenance_of reads its record.

RAISES DESCRIPTION
ConfigError

For any refusal at any depth: an unknown key, an unknown or missing variant, a missing fragment or profile, a malformed override, text the leaf annotation cannot read.

InterpolationError

For an expression that cannot be resolved.

ValidationError

When the resolved tree fails the model's own validation.

didactic.settings.compose_traced

compose_traced(
    path: Path | str | None = None,
    *,
    schema: type[M],
    base: Mapping[str, ConfigValue] | None = None,
    groups: Mapping[str, str | None] | None = None,
    profile: str | Mapping[str, ConfigValue] | None = None,
    overlays: Sequence[
        Path | str | Mapping[str, ConfigValue]
    ] = (),
    overrides: Sequence[Override] = (),
    search_path: Sequence[Path | str] = (),
    resolvers: Mapping[str, ResolverFn] | None = None,
) -> Composed[M]

Compose like :func:compose and return the value with its record.

Parameters are those of :func:compose.

didactic.settings.compose_layers

compose_layers(
    *,
    schema: type[M],
    layers: Sequence[Layer],
    resolvers: Mapping[str, ResolverFn] | None = None,
) -> Composed[M]

Merge an assembled ladder, settle, interpolate, validate and record.

PARAMETER DESCRIPTION
schema

The model to validate against.

TYPE: type[M]

layers

The layers, lowest precedence first.

TYPE: Sequence[Layer]

resolvers

Interpolation resolvers consulted before the registry, for this call only.

TYPE: Mapping[str, ResolverFn] | None DEFAULT: None

RAISES DESCRIPTION
ConfigError

For a refusal during the merge, the settle pass or the check of the resolved tree, or when the schema declares __slots__ and cannot carry the record.

didactic.settings.Composed dataclass

Composed(
    value: M,
    tree: dict[str, ConfigValue],
    provenance: Provenance,
    layers: tuple[Layer, ...],
)

The result of a traced composition.

PARAMETER DESCRIPTION
value

The validated model, with the provenance attached as __provenance__.

TYPE: M

tree

The merged, settled and interpolated document: what model_validate received.

TYPE: dict[str, ConfigValue]

provenance

Exactly one origin per leaf of value.model_dump_json().

TYPE: Provenance

layers

Every layer applied, lowest precedence first.

TYPE: tuple[Layer, ...]

didactic.settings.Layer dataclass

Layer(
    origin: Origin,
    document: Mapping[str, ConfigValue],
    textual: bool = False,
)

One document to merge, tagged with its origin.

PARAMETER DESCRIPTION
origin

The origin every leaf the document sets will carry.

TYPE: Origin

document

The nested document, already mounted at the root (a group fragment is wrapped under its slot path before it becomes a layer).

TYPE: Mapping[str, ConfigValue]

textual

Whether string leaves are text to decode by the leaf's annotation before the write (environment variables, dotenv lines, CLI arguments, key=value override strings) rather than typed values.

TYPE: bool DEFAULT: False

didactic.settings.strict_merge

strict_merge(
    base: Mapping[str, ConfigValue],
    overlay: Mapping[str, ConfigValue],
    *,
    schema: type[Model],
    origin: Origin | None = None,
    provenance: dict[KeyPath, Origin] | None = None,
) -> dict[str, ConfigValue]

Merge one mapping over another under a schema.

A convenience over :func:merge_layer for callers holding two documents: the overlay becomes a typed layer with origin (Origin("overlay") when omitted) and its leaves are recorded in provenance when one is given.

Class-based settings

didactic.settings.Settings

Settings(**kwargs: FieldValue | JsonValue)

Bases: Model

Base class for application settings.

Subclasses declare fields like any didactic.api.Model, plus a class-level __sources__ tuple. Call Settings.load to compose an instance from a primary file, its config groups, a profile, overlays, the sources and overrides.

Examples:

>>> import didactic.api as dx
>>> from didactic.settings import Settings, EnvSource
>>>
>>> class App(Settings):
...     debug: bool = False
...     port: int = 8080
...
...     __sources__ = (EnvSource(prefix="APP_"),)
ATTRIBUTE DESCRIPTION
__sources__

The sources consulted in declaration order; later sources win. Their names must be distinct.

TYPE: tuple[Source, ...]

__search_path__

Directories searched for fragments and profiles, after the primary file's parent and the first FileSource's parent.

TYPE: tuple[str, ...]

__provenance__

The Provenance of an instance built by load: one origin per leaf.

TYPE: Provenance

RAISES DESCRIPTION
TypeError

At class creation, when a field is named after one of load's keywords or two sources share a name.

load classmethod

load(
    path: Path | str | None = None,
    *,
    profile: str | Mapping[str, ConfigValue] | None = None,
    groups: Mapping[str, str | None] | None = None,
    overlays: Sequence[
        Path | str | Mapping[str, ConfigValue]
    ] = (),
    overrides: Sequence[Override] = (),
    search_path: Sequence[Path | str] | None = None,
    resolvers: Mapping[str, ResolverFn] | None = None,
    **values: ConfigValue,
) -> Self

Compose an instance from the file, groups, profile, sources and overrides.

PARAMETER DESCRIPTION
path

The primary document; its defaults: list is honoured and its parent is the first search root.

TYPE: Path | str | None DEFAULT: None

profile

A profile name or mapping.

TYPE: str | Mapping[str, ConfigValue] | None DEFAULT: None

groups

Config-group selections by slot.

TYPE: Mapping[str, str | None] | None DEFAULT: None

overlays

File paths or mappings merged above the profile.

TYPE: Sequence[Path | str | Mapping[str, ConfigValue]] DEFAULT: ()

overrides

key=value strings or (key, value) pairs, applied above the sources.

TYPE: Sequence[Override] DEFAULT: ()

search_path

Directories searched for fragments and profiles; __search_path__ when omitted.

TYPE: Sequence[Path | str] | None DEFAULT: None

resolvers

Interpolation resolvers for this call.

TYPE: Mapping[str, ResolverFn] | None DEFAULT: None

**values

Typed overrides applied last, keyed by dotted path with __ as the separator: model__type_encoder__num_heads=8.

TYPE: ConfigValue DEFAULT: {}

RETURNS DESCRIPTION
Settings

The validated instance with __provenance__ attached.

load_traced classmethod

load_traced(
    path: Path | str | None = None,
    *,
    profile: str | Mapping[str, ConfigValue] | None = None,
    groups: Mapping[str, str | None] | None = None,
    overlays: Sequence[
        Path | str | Mapping[str, ConfigValue]
    ] = (),
    overrides: Sequence[Override] = (),
    search_path: Sequence[Path | str] | None = None,
    resolvers: Mapping[str, ResolverFn] | None = None,
    **values: ConfigValue,
) -> Composed[Self]

Load like :meth:load and return the value with its record and layers.

Parameters are those of :meth:load.

didactic.settings.Source

Base class of every settings source.

Subclasses are frozen dataclasses that declare their own parameters and a name (recorded as Origin.name on every leaf the source sets; distinct within one Settings class) and implement :meth:layer.

layer

layer(schema: type[Model]) -> Layer | None

Return the layer this source contributes, or None when empty.

PARAMETER DESCRIPTION
schema

The settings class being loaded; textual sources enumerate its settable paths.

TYPE: type[Model]

didactic.settings.EnvSource dataclass

EnvSource(
    prefix: str = "",
    *,
    separator: str = "__",
    name: str = "env",
)

Bases: Source

Read settings from environment variables.

Every settable path of the schema (each leaf, and each model, union and map slot) is looked up as prefix plus the path segments joined by separator, upper-cased: EnvSource(prefix="APP_") reads trainer.epochs from APP_TRAINER__EPOCHS and the whole model.type_encoder slot from APP_MODEL__TYPE_ENCODER (JSON object text). Below a map slot, variables continuing the slot's name set entries: APP_PATHS__DATA_DIR sets paths["data_dir"] (the key is lower-cased, since variable names are upper-cased) and the segments after the key address the entry's own fields. Variables that name no path are never read.

PARAMETER DESCRIPTION
prefix

Text prepended to every variable name.

TYPE: str DEFAULT: ''

separator

Text joining the path segments.

TYPE: str DEFAULT: '__'

name

The source name for provenance.

TYPE: str DEFAULT: 'env'

layer

layer(schema: type[Model]) -> Layer | None

Return the layer of every set variable, or None when none is.

didactic.settings.DotEnvSource dataclass

DotEnvSource(
    path: str | Path = ".env",
    prefix: str = "",
    *,
    separator: str = "__",
    name: str = "dotenv",
)

Bases: Source

Read settings from a dotenv file.

Lines are KEY=value, optionally prefixed by export; blank lines and # comments are skipped; a value wrapped in matching single or double quotes is unquoted. Keys are looked up exactly as :class:EnvSource looks up variables. A missing file contributes nothing.

PARAMETER DESCRIPTION
path

The dotenv file.

TYPE: str | Path DEFAULT: '.env'

prefix

Text prepended to every key.

TYPE: str DEFAULT: ''

separator

Text joining the path segments.

TYPE: str DEFAULT: '__'

name

The source name for provenance.

TYPE: str DEFAULT: 'dotenv'

layer

layer(schema: type[Model]) -> Layer | None

Return the layer of every key the file sets, or None.

didactic.settings.FileSource dataclass

FileSource(
    path: str | Path = "config.toml",
    *,
    name: str = "file",
    required: bool = False,
)

Bases: Source

Read settings from a JSON, TOML or YAML file.

The whole document is the layer, checked against the schema at every depth like any other file; the file's defaults key is an ordinary key here, since only the primary path of Settings.load carries a selection list.

PARAMETER DESCRIPTION
path

The file; its suffix selects the reader.

TYPE: str | Path DEFAULT: 'config.toml'

name

The source name for provenance.

TYPE: str DEFAULT: 'file'

required

Whether a missing file is an error rather than an empty source.

TYPE: bool DEFAULT: False

layer

layer(schema: type[Model]) -> Layer | None

Return the document as a layer, or None when the file is absent.

RAISES DESCRIPTION
FileNotFoundError

When the file is absent and required is set.

didactic.settings.CliSource dataclass

CliSource(
    args: Namespace
    | Mapping[str, ConfigValue]
    | None = None,
    *,
    name: str = "cli",
)

Bases: Source

Read settings from parsed command-line arguments.

Keys are dotted paths or paths joined by __; a None value means the argument was not given and is skipped. String values are decoded by the leaf annotation; typed values pass through.

PARAMETER DESCRIPTION
args

An argparse.Namespace or a mapping of argument values.

TYPE: Namespace | Mapping[str, ConfigValue] | None DEFAULT: None

name

The source name for provenance.

TYPE: str DEFAULT: 'cli'

layer

layer(schema: type[Model]) -> Layer | None

Return the layer of every argument that was given, or None.

Provenance

didactic.settings.Provenance

Provenance(entries: Mapping[str, Origin])

Bases: Mapping[str, Origin]

Which layer wrote each leaf of a composed model.

An immutable mapping from dotted leaf path to :class:Origin that iterates in sorted path order and compares by value, so two compositions from the same layers give equal records. It covers exactly the leaves of value.model_dump_json(): every leaf no layer wrote is labelled default. Map keys are recorded verbatim as path segments, so a key containing . makes its path ambiguous. A list is one leaf: the elements of a tuple[T, ...] field are checked against the schema but not attributed individually, so the record stops at the list boundary.

paths property

paths: tuple[str, ...]

Every recorded leaf path, sorted.

source_of

source_of(path: str) -> Origin

Return the origin of one leaf.

RAISES DESCRIPTION
ConfigError

When no leaf has that path; the message lists the leaves.

under

under(prefix: str) -> Provenance

Return the entries at or below a dotted prefix, keys kept absolute.

by_layer

by_layer() -> dict[str, tuple[str, ...]]

Group the leaf paths by Origin.label.

The answer to "what did the profile change": each label maps to the sorted paths it wrote.

to_dict

to_dict() -> dict[str, dict[str, str | None]]

Render the record as JSON-shaped dicts, for a sidecar file.

didactic.settings.Origin dataclass

Origin(
    kind: OriginKind,
    name: str = "",
    path: str | None = None,
    expression: str | None = None,
)

Where a leaf's value came from.

PARAMETER DESCRIPTION
kind

The precedence rung.

TYPE: OriginKind

name

What within the rung: the profile name, slot=name for a group fragment, the defaults entry text for a root fragment, the override text, the file basename, a settings source's name, or #<index> for an in-process overlay mapping. Empty when the rung has one anonymous member (default, base, a mapping profile).

TYPE: str DEFAULT: ''

path

The on-disk file the value was read from, for file-backed layers.

TYPE: str | None DEFAULT: None

expression

The leaf's source text when it contained ${...}; the value recorded on the tree is the resolved one.

TYPE: str | None DEFAULT: None

label property

label: str

kind when name is empty, else kind:name.

didactic.settings.OriginKind

OriginKind = Literal[
    "default",
    "base",
    "group",
    "defaults",
    "file",
    "profile",
    "overlay",
    "source",
    "override",
]

The closed set of precedence rungs, lowest first.

default is written only by provenance completion and by the settle pass for an injected discriminator; the others name the layer kinds compose and Settings.load apply.

didactic.settings.provenance_of

provenance_of(model: Model) -> Provenance

Read the record attached to an instance built by the engine.

RAISES DESCRIPTION
ConfigError

When the instance was constructed directly or through Model.with_(), neither of which carries a record.

Interpolation

didactic.settings.resolve

resolve(
    node: ConfigValue,
    *,
    root: Mapping[str, ConfigValue],
    here: tuple[str | int, ...] = (),
    resolvers: Mapping[str, ResolverFn] | None = None,
) -> ConfigValue

Resolve every interpolation in node, returning a new value.

Strings are parsed and evaluated; dicts and lists are descended with here extended by the key or index. A string that is exactly one expression substitutes the typed value (resolving "${a.b}" where a.b is an int gives an int); a substring substitution coerces to str.

PARAMETER DESCRIPTION
node

The value to resolve.

TYPE: ConfigValue

root

The tree references resolve against.

TYPE: Mapping[str, ConfigValue]

here

Path of node within root, for relative references.

TYPE: tuple[str | int, ...] DEFAULT: ()

resolvers

Resolvers consulted before the process-wide registry, for this call only.

TYPE: Mapping[str, ResolverFn] | None DEFAULT: None

RAISES DESCRIPTION
InterpolationError

For an unresolved reference, an unknown resolver, a resolver that raised, a cycle or a syntax error. The error's path names the leaf whose text was being resolved.

didactic.settings.resolve_traced

resolve_traced(
    document: Mapping[str, ConfigValue],
    *,
    root: Mapping[str, ConfigValue] | None = None,
    resolvers: Mapping[str, ResolverFn] | None = None,
) -> tuple[dict[str, ConfigValue], dict[KeyPath, str]]

Resolve a whole document and report which leaves held expressions.

PARAMETER DESCRIPTION
document

The document whose leaves are resolved.

TYPE: Mapping[str, ConfigValue]

root

The tree references resolve against; document itself when omitted. The composition engine passes the document backed by the schema's defaults, so a reference to a field no layer set reads the model's default.

TYPE: Mapping[str, ConfigValue] | None DEFAULT: None

resolvers

Resolvers consulted before the process-wide registry, for this call only.

TYPE: Mapping[str, ResolverFn] | None DEFAULT: None

RETURNS DESCRIPTION
tuple

The resolved document, and {path: text} for every dict-keyed leaf whose source text contained ${: the string itself for a string leaf, the JSON rendering of the list as written for a list leaf any of whose elements contained ${.

didactic.settings.register_resolver

register_resolver(
    name: str, fn: ResolverFn, *, replace: bool = False
) -> None

Register a resolver under name in the process-wide registry.

PARAMETER DESCRIPTION
name

Resolver name as it appears in ${name:args}.

TYPE: str

fn

Function called with the interpolated string arguments. Its return value is substituted in place.

TYPE: ResolverFn

replace

Whether re-registration of an existing name is allowed. Off by default so accidental shadowing is loud.

TYPE: bool DEFAULT: False

RAISES DESCRIPTION
ValueError

When name is already registered and replace is false.

didactic.settings.unregister_resolver

unregister_resolver(name: str) -> None

Remove a registered resolver; a no-op when the name is absent.

didactic.settings.list_resolvers

list_resolvers() -> tuple[str, ...]

Return the names of every registered resolver, sorted.

didactic.settings.lookup

lookup(path: str) -> ConfigValue

Evaluate a dotted path inside the active evaluation.

Integer segments index lists; the value found is itself interpolated before it is returned. Because the lookup runs inside the evaluation state of the enclosing :func:resolve call, a reference cycle that passes through a resolver is reported as a cycle.

RAISES DESCRIPTION
InterpolationError

When called outside an active :func:resolve, or when the path does not resolve.

didactic.settings.active_root

active_root() -> Mapping[str, ConfigValue] | None

Return the tree currently being interpolated, or None.

Resolvers that read other parts of the tree should prefer :func:lookup, which shares cycle detection with the evaluation in progress; this accessor exposes the raw tree for resolvers that inspect its shape.

didactic.settings.ResolverFn module-attribute

ResolverFn = Callable[..., ConfigValue]

A resolver: called with the interpolated string arguments, returns a value.

Arguments are strings; the return value is substituted in place, typed when the expression is the whole leaf. A resolver may call :func:lookup to read other parts of the tree being interpolated.

Documents, overrides and scalars

didactic.settings.load_document

load_document(path: Path | str) -> dict[str, ConfigValue]

Load one JSON, TOML or YAML file as a document.

PARAMETER DESCRIPTION
path

The file; its suffix selects the reader.

TYPE: Path | str

RETURNS DESCRIPTION
dict[str, ConfigValue]

The document. An empty file gives an empty document.

RAISES DESCRIPTION
FileNotFoundError

When path does not exist.

ConfigError

When the suffix is unsupported, when a YAML file is opened without PyYAML installed, or when the top-level value is not a mapping.

didactic.settings.nest_override

nest_override(
    dotted_key: str, value: ConfigValue
) -> dict[str, ConfigValue]

Wrap a value under a dotted key, one nested dict per segment.

nest_override("model.type_encoder.num_heads", 8) gives {"model": {"type_encoder": {"num_heads": 8}}}. The key's syntax is validated by :func:~didactic.settings.parse_override; this function only builds the tree.

didactic.settings.parse_override

parse_override(expr: str) -> tuple[str, str]

Split a key=value override into its key and raw value text.

The key is validated: it must be non-empty, every dotted segment must be non-empty, and no segment may be an integer (lists are set whole, as tags=[...]). The value text is returned untouched; the leaf annotation decides how it is read.

RAISES DESCRIPTION
OverrideSyntaxError

When = is absent or the key is malformed.

didactic.settings.parse_scalar

parse_scalar(text: str) -> ConfigValue

Read text with the schema-free grammar.

Surrounding whitespace is ignored. null, ~ and the empty string give None; true and false (any case) give booleans; an integer literal without a leading zero gives an int; a float literal (1.5, 1e-3, inf, nan) gives a float; text starting with [ or { is JSON; a single- or double-quoted string gives its contents; anything else is the text itself.

RAISES DESCRIPTION
OverrideSyntaxError

When text starting with [ or { is not valid JSON.

didactic.settings.decode_text

decode_text(
    text: str,
    annotation: object,
    *,
    path: str,
    origin: Origin | None = None,
) -> ConfigValue

Read text for a leaf annotation.

PARAMETER DESCRIPTION
text

The text as it arrived from the environment, a dotenv file, the command line or an override string.

TYPE: str

annotation

The leaf's annotation (FieldSpec.annotation, or the value type of a dict[str, T] entry). Annotated[T, ...] unwraps to T and T | None reads null, ~ and the empty string as None before decoding T.

TYPE: object

path

Dotted path of the leaf, for the error message.

TYPE: str

origin

The layer that supplied the text, for the error message.

TYPE: Origin | None DEFAULT: None

RETURNS DESCRIPTION
ConfigValue

str keeps the text verbatim. bool accepts 1, 0, true, false, yes, no, on and off in any case. int and float use the constructors. Literal[...] matches the text against str() of each member and returns the member. An Enum is matched by member name, then by value, and the member's value is returned. tuple[T, ...] and frozenset[T] read JSON when the text starts with [ and otherwise split on commas outside brackets, braces and quotes, decoding each item as T. A map or model slot requires JSON object text. Any other annotation falls back to :func:parse_scalar. Text holding a ${...} expression is returned as it is, whatever the annotation, so interpolation can resolve it; the resolved value is checked against the annotation afterwards.

RAISES DESCRIPTION
CoercionError

When the text cannot be read for the annotation.

didactic.settings.ConfigValue

ConfigValue = (
    str
    | int
    | float
    | bool
    | None
    | Sequence[ConfigValue]
    | Mapping[str, ConfigValue]
)

A JSON-shaped config value: scalars, None, lists and string-keyed dicts.

The container arms are spelled with the covariant Sequence and Mapping so a narrowly inferred literal ({"a": {"b": "x"}}, typed dict[str, dict[str, str]]) is accepted wherever a ConfigValue is expected. At runtime the engine builds and checks for list and dict.

didactic.settings.KeyPath

KeyPath = tuple[str, ...]

A path of dict keys from the document root to a node.

Errors

didactic.settings.ConfigError

ConfigError(message: str, *, path: str | None = None)

Bases: ValueError

A configuration is malformed or fails the engine's checks.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

path

Dotted path of the offending leaf, or None when the error is not about one leaf (a malformed defaults list, an unsupported file suffix, a missing config directory).

TYPE: str | None DEFAULT: None

didactic.settings.UnknownKeyError

UnknownKeyError(
    message: str,
    *,
    path: str,
    allowed: tuple[str, ...] = (),
    declared_by: tuple[object, ...] = (),
    set_by: Origin | None = None,
)

Bases: ConfigError

A layer sets a key the schema does not declare at that path.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

path

Dotted path of the unknown key.

TYPE: str

allowed

Sorted field names accepted at the enclosing node.

TYPE: tuple[str, ...] DEFAULT: ()

declared_by

Primary tags of the union variants that declare the key, as the live discriminator values; empty when no variant does, or when the node is a plain model.

TYPE: tuple[object, ...] DEFAULT: ()

set_by

The origin of the layer that set the key.

TYPE: Origin | None DEFAULT: None

didactic.settings.UnknownVariantError

UnknownVariantError(
    message: str,
    *,
    path: str,
    value: object,
    registered: tuple[object, ...] = (),
)

Bases: ConfigError

A discriminator names no registered variant, or is not a literal.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

path

Dotted path of the discriminator leaf.

TYPE: str

value

The discriminator value as it arrived.

TYPE: object

registered

The registered tags as the live discriminator values, sorted by type and then by value.

TYPE: tuple[object, ...] DEFAULT: ()

didactic.settings.MissingFragmentError

MissingFragmentError(
    message: str,
    *,
    group: str,
    name: str,
    tried: tuple[Path, ...],
    available: tuple[str, ...] = (),
)

Bases: ConfigError

A named fragment, root fragment or profile exists in no search root.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

group

The dotted slot of the config group; the empty string for a root-mounted defaults entry; "profiles" for a profile.

TYPE: str

name

The fragment name that was looked for.

TYPE: str

tried

Every path tried, in the order tried.

TYPE: tuple[Path, ...]

available

Sorted names that do exist for the group, across every root.

TYPE: tuple[str, ...] DEFAULT: ()

didactic.settings.OverrideSyntaxError

OverrideSyntaxError(
    message: str, *, path: str | None = None
)

Bases: ConfigError

A key=value override, or its value text, cannot be parsed.

didactic.settings.CoercionError

CoercionError(
    message: str, *, path: str, expected: str, text: str
)

Bases: ConfigError

Text from a textual layer cannot be decoded for the leaf's annotation.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

path

Dotted path of the leaf.

TYPE: str

expected

A rendering of the annotation the text had to satisfy.

TYPE: str

text

The text that was refused.

TYPE: str

didactic.settings.InterpolationError

InterpolationError(
    message: str,
    *,
    path: tuple[str | int, ...] | None = None,
)

Bases: ValueError

An interpolation expression cannot be resolved.

Raised for a reference to a path that does not exist in the composed tree, a call to an unregistered resolver, a resolver that raised, a cycle between references, or a syntax error in the expression.

PARAMETER DESCRIPTION
message

The rendered error text.

TYPE: str

path

Path of the leaf whose text was being resolved when the error was raised; None when no leaf was being resolved (a direct call to :func:~didactic.settings.lookup outside an evaluation, a bare string passed to :func:~didactic.settings.resolve).

TYPE: tuple[str | int, ...] | None DEFAULT: None