cottax.core.frozen

The value layer every class stands on: Frozen, the frozen dataclass base with its abstract variables and its checks (base.py), OrderedMap, the mapping a value stores (ordered_map.py), Violation, what a check yields and how a refusal is raised or collected, checked, a function declaring its checks as a class does, name_of and dotted, a callable or a class named in a message (violation.py), and how a feature’s class gets into a consumer: an Answer registered with answers and found by answer, or a Choice, its finals marked choice (answer.py).

class AbstractClassVar[T][source]

Bases: Generic[T]

Annotation only, on a level: fn: AbstractClassVar[Callable]. A class variable

class AbstractVar[T][source]

Bases: Generic[T]

Annotation only, on a level: fn: AbstractVar[Callable].

class Frozen[source]

Bases: ABC

Every subclass is a frozen dataclass whose checks, each level’s added to its ancestors’, run at post-init.

checks: PerLevel[tuple[Callable[[Any], object], ...]] = ()

Callable [self] -> iterable of violations, which are raised at construction unless skipped (see unchecked).

classmethod per_level(name: str, derived_first: bool = False)[source]

Get the attribute name from each level in the MRO, in order from base to implementation, or the reverse. name is one a level declared PerLevel.

Return type:

Iterator[Callable]

class PerLevel[T][source]

Bases: Generic[T]

Annotation only, on the level that declares it: checks: PerLevel[tuple] = (). A class variable each level binds for itself, read with per_level, which accumulates them root first – so a level adds and never replaces.

unchecked(*skipped: Callable[[Any], object])[source]

Disable Frozen checks for the scope of with: the callables in skipped, matched by identity, or all if skipped is empty.

class OrderedMap[K: Hashable, V](entries: Mapping[K, V] | Iterable[tuple[K, V]] = ())[source]

Bases: Mapping[K, V], Generic[K, V]

A frozen mapping in the order it was written. Two tuples; the lookup table is built on first use and cached, the hash on first call.

keys()[source]
Return type:

tuple[K, ...]

values()[source]
Return type:

tuple[V, ...]

items()[source]
Return type:

tuple[tuple[K, V], ...]

classmethod trusted(keys: tuple[K, ...], values: Iterable[V])[source]

Built without the duplicate check, keys already distinct: a dict’s, or a flatten’s.

Return type:

OrderedMap[K, V]

class Answer[source]

Bases: Frozen

The one right answer per node or place class. A level directly under Answer is a consumer’s interface, saying what it is answered per (about); the owner of a class it is about writes a final and registers it with @answers(*classes): a feature for its own, a consumer for its own and for core’s. A final holds no field: the registry builds it, cls().

about: AbstractClassVar[Any]

a class, a type alias of one, a protocol, or a tuple of those. @answers refuses a class that is none; a protocol is met by shape, which a class cannot be asked.

Type:

What the interface is answered per, bound by the interface

checks_answer: PerLevel[tuple[Callable[[Any, tuple[Any, ...]], Iterable[Violation]], ...]] = ()

why answer is refused beside the answers already registered for its interface (a word two would share).

Type:

check(answer, registered)

class Choice[source]

Bases: ABC

Several fit, so none is registered: a study names one in a slot, which the interface class’s docstring states in a Handed in as: block, an example of the call. Never an Answer as well.

answer[A: Answer](interface: type[A], obj: object, default: Any = _REFUSE)[source]

The interface answer registered for the class of obj (answer_for_class).

Return type:

A

answer_for_class[A: Answer](interface: type[A], cls: type, default: Any = _REFUSE)[source]

The interface answer registered for cls, looked up along its ancestry, most specific first. With none: default, or else refused.

Return type:

A

answered()[source]

What has been answered: per interface, the answer registered for each class.

Return type:

dict[type[Answer], dict[type, Answer]]

answers[A: type[Answer]](*classes: type)[source]

Register an Answer final for each of classes. A class is answered once per interface: a second answer is refused, so nothing depends on import order, unless it has the first’s module and qualified name (a module reloaded), when it replaces it.

Return type:

Callable[[A], A]

choice[C: type](interface: type)[source]

Mark a final as one a study may name for the Choice interface. Nothing is registered and the class is returned as it is: only that it is a final of interface is checked, so every choice on offer is found by searching for the mark.

Return type:

Callable[[C], C]

class Violation[source]

Bases: Frozen

Violation: can raise or used to debug.

error: AbstractClassVar[type[Exception]]

Exception raised for this violation

template: AbstractClassVar[str]

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

property where: dict[str, object]

places, node names, or tuples of either.

Type:

The fields, by role

property message: str
property raised: Exception

The exception a caller expects for this violation, carrying it as violation, so a refusal caught is still data.

checked[F: Callable](*checks: Callable[..., Iterable[Violation]])[source]

A function declaring its checks as a class does: each is called with the function’s arguments as it receives them, and the first violation is raised before the body runs.

Return type:

Callable[[F], F]

first(violations: Iterable[Violation])[source]

Raise the first violation, if any – the boundary between rules-as-data and the exceptions a constructor owes its caller.

Return type:

None

violations(cls: type[Frozen] | Callable, *args, skip: Collection[Callable] = (), **kwargs)[source]

Every case cls(*args, **kwargs) breaks, as data: built with the checks skipped, then each rule down the hierarchy asked and everything it yields collected (wherever possible; some checks cannot be run on totally invalid data (e.g. a nesting check for a nesting not in the graph)). A checked function’s checks are asked of its arguments, and its body never runs.

Return type:

Iterator[Violation]

name_of(implementation: object)[source]

A callable’s name, or its type’s, for a message.

Return type:

str

dotted(cls: type)[source]

A class’s module and qualified name, for a message.

Return type:

str

Submodules