lacing.schema#
Body schema registry, JSON Schema export, and migrations.
Every annotation’s body is validated against the schema named by its
body_schema_uri (semver: annot://schema/<name>/v<major>). This
module implements:
register_body_schema()— register a Pydantic v2 model for a schema URI.validate()— validate an annotation’s body dict against its schema.json_schema()— get the JSON Schema for a registered URI.export_json_schemas()— write all JSON Schema artifacts to disk (underlacing/schema/<name>/v<N>.jsonby default), the upstream forjson-schema-to-zodcodegen.register_migration()— register a forward migration from version N to N+1 of a body schema.migrate()— upgrade a body dict (or whole annotation) through registered migrations.
See the lacing-schema-codegen skill and BACK-DOC §4.5.
Usage example:
from pydantic import BaseModel, Field
from lacing.schema import register_body_schema, register_migration
class WordBodyV1(BaseModel):
model_config = {"frozen": True, "extra": "forbid"}
text: str = Field(..., description="The word's surface form.")
register_body_schema("annot://schema/word/v1", WordBodyV1)
class WordBodyV2(BaseModel):
model_config = {"frozen": True, "extra": "forbid"}
text: str = Field(..., description="The word's surface form.")
normalized: str | None = Field(None, description="Normalized form.")
register_body_schema("annot://schema/word/v2", WordBodyV2)
@register_migration(schema_name="word", from_version=1, to_version=2)
def v1_to_v2(body: dict) -> dict:
return {**body, "normalized": None}
Functions
Drop every registered body schema and migration. |
|
|
Write every registered schema as JSON files under |
|
Look up the registered Pydantic model for |
|
|
|
Return the JSON Schema for the body model registered at |
|
Highest registered major version for |
|
Build a |
|
Migrate |
|
Convenience: migrate to the highest registered version of the schema. |
|
Split |
|
Register |
|
Register a forward migration from |
All currently registered |
|
|
Validate |
Exceptions
Raised when a body fails validation against its registered schema. |
|
Raised when an export would write an empty registry over real artifacts. |
|
Raised when a migration step is missing or fails. |
|
Raised when an annotation's body_schema_uri has no registered model. |
- exception lacing.schema.BodySchemaError[source]#
Bases:
ValueErrorRaised when a body fails validation against its registered schema.
- exception lacing.schema.EmptySchemaRegistryError[source]#
Bases:
RuntimeErrorRaised when an export would write an empty registry over real artifacts.
Almost always means the caller forgot
import lacing.bodies: the registry is populated by importing the body modules, so exporting without that import silently truncatesindex.jsonto{}and leaves the committedv<N>.jsonfiles orphaned.
- exception lacing.schema.MigrationError[source]#
Bases:
RuntimeErrorRaised when a migration step is missing or fails.
- exception lacing.schema.UnknownBodySchemaError[source]#
Bases:
KeyErrorRaised when an annotation’s body_schema_uri has no registered model.
- lacing.schema.clear_registry()[source]#
Drop every registered body schema and migration. For tests / repls.
- Return type:
- lacing.schema.export_json_schemas(target_dir, *, overwrite=True, include_meta=True, allow_empty=False)[source]#
Write every registered schema as JSON files under
target_dir.Layout:
<target_dir>/<name>/v<N>.json. Returns the list of paths written, in registration order.- Parameters:
target_dir (
str|Path) – Output directory. Created if missing.overwrite (
bool) – If False, refuse to write a file that already exists.include_meta (
bool) – If True, also write a<target_dir>/index.jsonmapping every URI to its file path and the Pydantic model’s qualified name (helps the codegen pipeline).allow_empty (
bool) – If True, permit an export from an empty registry. The default refuses, because the overwhelmingly likely cause is a missingimport lacing.bodiesand the write would destroy the committed artifacts.
- Raises:
EmptySchemaRegistryError – Nothing is registered and
allow_emptyis False.- Return type:
- lacing.schema.get_body_schema(uri)[source]#
Look up the registered Pydantic model for
uri.- Return type:
type[BaseModel]
- lacing.schema.json_schema(uri)[source]#
Return the JSON Schema for the body model registered at
uri.Pydantic’s
model_json_schema()output, plus adefaultfor every zero-argumentdefault_factoryfield (seelacing.json_schema.DefaultFactoryJsonSchema), whatever base class the registered model has.- Return type:
- lacing.schema.latest_version(schema_name)[source]#
Highest registered major version for
schema_name, or None.
- lacing.schema.make_uri(name, version)[source]#
Build a
body_schema_urifrom a name and major version.- Return type:
- lacing.schema.migrate(body, *, from_uri, to_uri)[source]#
Migrate
bodyfromfrom_uritoto_urivia registered steps.Composes single-step migrations. Raises
MigrationErrorif any step is missing.- Return type:
- lacing.schema.migrate_to_latest(body, *, from_uri)[source]#
Convenience: migrate to the highest registered version of the schema.
Returns
(migrated_body, target_uri).
- lacing.schema.parse_uri(uri)[source]#
Split
annot://schema/<name>/v<major>into(name, major).Raises
ValueErroron malformed input.
- lacing.schema.register_body_schema(uri, model)[source]#
Register
modelas the validator foruri. Returnsmodel.- Return type:
type[BaseModel]
- lacing.schema.register_migration(*, schema_name, from_version, to_version)[source]#
Register a forward migration from
v<from_version>tov<to_version>.Decorated function takes a body
dictand returns a new bodydict. Migrations must be one major-version step at a time (to_version == from_version + 1).Re-registering the same
(schema_name, from_version)pair replaces the previous entry — convenient in tests, intentional for hot-reload.
- lacing.schema.validate(body, uri)[source]#
Validate
bodyagainst the schema registered foruri.Returns the parsed Pydantic instance. Raises
BodySchemaErroron validation failure (wrapping the underlyingpydantic.ValidationError) orUnknownBodySchemaErrorif the URI isn’t registered.- Return type:
BaseModel