httk.store.storage_layout¶
Backend-neutral store declaration machinery shared by storage backends.
This module owns the logical entry-family declaration, its canonical JSON encoding, and trust-on-reopen validation. Physical names and backend-specific layout validation belong to each storage backend.
Attributes¶
The current backend-neutral declaration protocol. |
|
The reopen hint appended when an additive-only schema mismatch is not applied. |
Exceptions¶
A database does not exactly implement the current persisted store layout. |
|
A persisted application-owned layout needs explicit Python class bindings. |
Classes¶
Bind one stable store-local name to a concrete record class. |
|
Declare one application-owned entry family without global registration. |
|
One immutable configured entry family and its concrete records. |
|
The immutable normalized entry declaration of an initialized store. |
|
The nullable parent columns an additive fingerprint upgrade must add per table. |
Functions¶
|
Require entry-id fields on every backing of a defined entry family. |
|
Validate an explicit class declaration and replace it with stable registry names. |
|
Validate application-owned entry declarations and build a store layout. |
|
Serialize a normalized declaration in its exact deterministic persisted form. |
|
Serialize the resolved per-table schema of |
|
Diff a stored fingerprint against the current one, per differing table. |
|
Classify a fingerprint mismatch as an additive upgrade plan or a rejection. |
Module Contents¶
- httk.store.storage_layout.DECLARATION_PROTOCOL_VERSION: Final = '2'¶
The current backend-neutral declaration protocol.
The value is the major generation only, compared for strict equality on reopen and never parsed. Bump it to “3” solely on a breaking change to the declaration protocol that an existing store could not be reopened against.
- httk.store.storage_layout.ADDITIVE_UPGRADE_HINT: Final = 'the schema difference is purely additive (new nullable columns / lazily created tables); reopen...¶
The reopen hint appended when an additive-only schema mismatch is not applied.
- exception httk.store.storage_layout.StorageLayoutUpgradeRequiredError(diff, *, hint=None)¶
Bases:
RuntimeErrorA database does not exactly implement the current persisted store layout.
diffis immutable and JSON-shaped. Its top-level keys are stable categories (currentlyprotocol,declarationandschema), so a caller can present a precise upgrade diagnostic without parsing the human-readable exception message. Thedeclarationcategory maps named aspect keys (metadata_keys,store_timestamps,write_profile,entry_declaration) to their own diagnostics, so several independent declaration mismatches are reported together; the exception message names the mismatched aspects.- Parameters:
diff (collections.abc.Mapping[str, object]) – The immutable JSON-shaped category-keyed difference.
hint (str | None) – An optional remediation appended to the message and exposed as
hint(e.g. that a purely additive schema change can be applied withupgrade=True).
- diff: collections.abc.Mapping[str, object]¶
- exception httk.store.storage_layout.EntryLayoutBindingError¶
Bases:
ValueErrorA persisted application-owned layout needs explicit Python class bindings.
- class httk.store.storage_layout.EntryRecordDeclaration¶
Bind one stable store-local name to a concrete record class.
- Parameters:
name – Stable record identity persisted in the store declaration.
record – Concrete frozen dataclass used for storage and hydration.
definition_id – Optional entry-type definition IRI described by the record.
- class httk.store.storage_layout.EntryFamilyDeclaration¶
Declare one application-owned entry family without global registration.
Explicit declarations provide stable persistence identities directly to a store. They are intended for application-private families which should not participate in plugin discovery. The same declaration must be supplied whenever such a store is reopened.
- Parameters:
name – Stable family identity persisted in the store declaration.
family – Logical entry-family class exposed through
entry_layout.records – Ordered concrete record declarations belonging to the family.
definition_id – Optional entry-type definition IRI for the family.
- records: tuple[EntryRecordDeclaration, Ellipsis]¶
- class httk.store.storage_layout.EntryFamilyLayout¶
One immutable configured entry family and its concrete records.
- class httk.store.storage_layout.StorageLayout¶
The immutable normalized entry declaration of an initialized store.
- families: tuple[EntryFamilyLayout, Ellipsis]¶
- property entry_records: collections.abc.Mapping[type, tuple[type, Ellipsis]]¶
Configured family classes mapped to their ordered concrete record classes.
- property declaration: collections.abc.Mapping[str, tuple[str, Ellipsis]]¶
Configured stable family names mapped to their ordered stable record names.
- httk.store.storage_layout.validate_entry_id_fields(layout)¶
Require entry-id fields on every backing of a defined entry family.
- httk.store.storage_layout.normalize_entry_records(entry_records)¶
Validate an explicit class declaration and replace it with stable registry names.
Registry aliases are rejected rather than selected arbitrarily: a persistent declaration must have exactly one stable spelling for every supplied class.
- httk.store.storage_layout.normalize_entry_families(entry_families)¶
Validate application-owned entry declarations and build a store layout.
Unlike
normalize_entry_records(), this path does not require the family or record classes to be globally registered. Stable names and optional definition identities are supplied by the application itself.- Parameters:
entry_families (collections.abc.Sequence[EntryFamilyDeclaration]) – Explicit family declarations in any order.
- Returns:
The immutable normalized storage layout.
- Raises:
TypeError – If the declaration container or its members are invalid.
ValueError – If names, classes, definitions, or storage schemas conflict.
- Return type:
- httk.store.storage_layout.declaration_json(layout)¶
Serialize a normalized declaration in its exact deterministic persisted form.
- httk.store.storage_layout.schema_fingerprint_json(layout)¶
Serialize the resolved per-table schema of
layoutin deterministic form.The fingerprint covers every declared record class plus the transitive closure of referenced storable classes, resolved through
resolve_schema(). It captures what determines the on-disk layout, the stored value encoding, and the content identity of each table — the logical identity name, dedup policy, composite indexes, relationship links, and per-field roles, codecs, shapes, columns, child tables, identity participation, and list-vs-tuple container — so that reopening a store whose record classes changed is rejected up front.A code move or rename is safe only when the record pins an explicit
identity_name(every shipped httk record does); without a pin the qualified class name is the content identity, so the move changescontent_idand the store correctly refuses to open.clsandpython_typethemselves are excluded — the identity name and resolved columns capture everything the store depends on.- Parameters:
layout (StorageLayout) – The normalized storage layout to fingerprint.
- Returns:
A deterministic
sort_keysJSON document describing tables and definition-backed entry-id tables.- Return type:
- httk.store.storage_layout.schema_fingerprint_diff(stored, current)¶
Diff a stored fingerprint against the current one, per differing table.
The persisted fingerprint shape is versioned by the store protocol, so this only needs to survive a corrupt stored value gracefully.
- Parameters:
- Returns:
A mapping of table name to
{"expected", "actual"}for each table that differs;{}when the two fingerprints are byte-equal. A stored value that is not a parseable fingerprint yields a single"<fingerprint>"entry.- Return type:
- class httk.store.storage_layout.AdditiveUpgradePlan¶
The nullable parent columns an additive fingerprint upgrade must add per table.
- Parameters:
added_columns – Physical table name mapped to the ordered
ColumnSpecvalues newly present in the current fingerprint. New tables carry no entry (they are created whole); a table appears only when it already exists in the stored fingerprint and gained one or more nullable parent columns.
- added_columns: collections.abc.Mapping[str, tuple[httk.store.backend.schema.ColumnSpec, Ellipsis]]¶
- httk.store.storage_layout.classify_schema_upgrade(stored, current)¶
Classify a fingerprint mismatch as an additive upgrade plan or a rejection.
The whole diff must be additive. A table present only in the current fingerprint is a new table (additive; it is created whole). A table present in both is additive only when its
identity_name,dedup,composite_indexesandlinksare byte-equal, it carries no unrecognized top-level key, every stored field is present and byte-equal in the current fingerprint, and every added field is a non-child, non-derived, content-identity-excluded (IdentitySkip) field whose parent columns are all nullable. Identity participation is required so a pre-existing row’scontent_id(and therefore dedup, dispatch, and federation identity) is unchanged by the upgrade.- Parameters:
- Returns:
An
AdditiveUpgradePlanwhen fully additive, otherwise a human-readable rejection reason naming the offending table/field/column.- Return type: