Models¶
A dx.Model subclass is a frozen, type-checked record. The metaclass
walks the declared annotations once at class-creation time and builds
a FieldSpec per field. Subsequent operations
(construction, attribute access, serialisation) work off those specs.
Declaration¶
import didactic.api as dx
class User(dx.Model):
"""A user record."""
id: str
email: str
nickname: str = ""
The class docstring becomes the description in JSON Schema and other schema-format exports.
Construction¶
User accepts keyword arguments. Required fields must be supplied;
optional fields take their declared default.
A construction call validates each value against its annotation, runs
any @validates methods, and evaluates any
axioms. Failures raise
didactic.api.ValidationError with one
ValidationErrorEntry per failure.
Immutability¶
Every Model instance is frozen. Direct attribute assignment raises:
To produce a modified copy, use Model.with_:
with_ validates the new fields, so the result is always a
well-formed Model.
Equality and hashing¶
Two Models compare equal when their classes are identical and every field has an equal value. Models hash on the same key.
Inheritance¶
Subclassing extends the field set. The parent's fields appear before the child's in the canonical iteration order:
Theory derivation handles single inheritance transparently; multi inheritance triggers a panproto colimit. See Inheritance.
Generic Models¶
PEP 695 generics work directly:
The base Box[T] is abstract: constructing it directly raises a
TypeError with a message that says the class is generic and must
be parameterised first.
Inspecting a class¶
Every Model exposes: