Skip to content

Interface API

Historical execution context

See the dedicated Historical Context API reference for the generated signatures and the complete GraphQL directive contract.

Use general_manager.api.as_of(search_date) to make every supported read in an operation use one historical snapshot. The positional and explicit keyword forms are equivalent:

from general_manager.api import as_of, current_as_of_date

with as_of("2022-01-01") as search_date:
    assert current_as_of_date() == search_date

with as_of(search_date="2022-01-01"):
    project = Project(1)
    projects = Project.filter(status="active")

search_date accepts an ISO date or datetime string (including a trailing Z), a datetime.date, or a naive or timezone-aware datetime.datetime. Date-only values become midnight in Django's current timezone. Naive datetimes also use Django's current timezone; aware datetimes retain their timezone. current_as_of_date() returns the active aware datetime, or None outside an as-of context. Nesting is idempotent when both values represent the same instant, even when their timezones differ. Distinct instants during a daylight-saving fold still conflict. A different nested date, or a different explicit date resolved while a context is active, raises HistoricalContextConflictError without changing the outer context. The previous value is restored when the context exits, including when its body raises an exception.

Invalid or unsupported inputs raise InvalidSearchDateError. An explicit search_date passed to a manager or query inside the context must represent the same instant; it cannot override the operation snapshot. Managers and buckets bound to current data or another date likewise raise HistoricalContextConflictError when consumed in the context.

The context is strictly read-only. GeneralManager and direct interface create, update, and delete entry points raise HistoricalMutationError before permission checks, transports, signals, or database writes. ORM-backed interfaces provide historical reads and calculation interfaces propagate the snapshot through their dependencies. Request-backed and custom interfaces are fail-closed unless they explicitly declare supported behavior: their reads raise HistoricalReadNotSupportedError before external loading begins.

Historical many-to-many membership requires django-simple-history through tables. Generated DatabaseInterface models and auto-registered existing models include local many-to-many fields in history registration, but the resulting Historical<Model>_<field> tables must be deployed through the normal Django migration workflow. Only membership changes recorded after those tables are deployed can be reconstructed; scalar history cannot recover pre-rollout membership. If membership or target history is unavailable, a dated relation read fails closed instead of returning current relation data. Generated relations that name a custom through model by an unresolved string cannot be registered when the owner model is created; their historical reads also fail closed. Define and history-track such models explicitly when custom through history is required.

general_manager.interface.base_interface.InterfaceBase

Bases: ABC

Common base API for interfaces backing GeneralManager classes.

__init_subclass__

__init_subclass__(**kwargs)

Initialize capability-related class state for newly created subclasses.

This method resets per-subclass capability registries and configuration to a clean default, merges configured capability overrides into the class's capability_overrides mapping, and clears the flag that marks configured capabilities as applied. Keyword arguments are forwarded to the superclass implementation.

__init__

__init__(*args, **kwargs)

Initialize the interface using the provided identification inputs.

Positional arguments are mapped to the interface's declared input fields by position; keyword arguments are matched by name. Inputs are validated and normalized according to the interface's input field definitions and the resulting normalized identification is stored on the instance as self.identification.

Parameters:

Name Type Description Default
*args object

Positional identification values corresponding to the interface's input field order.

()
**kwargs object

Named identification values matching the interface's input field names.

{}

set_capability_selection classmethod

set_capability_selection(selection)

Attach a resolved capability selection to the interface and update its active capability names.

Parameters:

Name Type Description Default
selection CapabilitySelection

The resolved capability selection whose all set will become the interface's active capability names.

required

get_capabilities classmethod

get_capabilities()

Get the capability names attached to this interface class.

Returns:

Type Description
frozenset[CapabilityName]

frozenset[CapabilityName]: A frozenset of capability names registered on the interface class.

get_capability_handler classmethod

get_capability_handler(name)

Retrieve the capability instance associated with the given capability name.

Parameters:

Name Type Description Default
name CapabilityName

The capability identifier to look up.

required

Returns:

Type Description
'Capability | None'

Capability | None: The capability handler registered for name, or None if no handler is bound.

iter_capability_configs classmethod

iter_capability_configs()

Iterate configured capability entries declared on the interface.

Returns:

Type Description
Iterable[InterfaceCapabilityConfig]

Iterable[InterfaceCapabilityConfig]: An iterable of capability configuration entries registered on the interface.

require_capability classmethod

require_capability(name, *, expected_type=None)

Retrieve the configured capability handler for the interface by name.

Parameters:

Name Type Description Default
name CapabilityName

The capability identifier to look up.

required
expected_type type[Capability] | None

If provided, require the returned handler to be an instance of this type.

None

Returns:

Name Type Description
Capability 'Capability'

The capability handler instance corresponding to name.

Raises:

Type Description
NotImplementedError

If the interface has no capability configured under name.

TypeError

If expected_type is provided and the handler is not an instance of that type.

capability_selection classmethod

capability_selection()

Return the resolved capability selection associated with this interface.

@returns CapabilitySelection if a selection has been set, None otherwise.

parse_input_fields_to_identification

parse_input_fields_to_identification(*args, **kwargs)

Convert positional and keyword inputs into a validated identification mapping for the interface's input fields.

Positional values are assigned in input_fields declaration order before keyword validation. A keyword named <field>_id is accepted when <field> is a declared input; if both are supplied, the _id alias overwrites the canonical value. Positional overflow, duplicate positional-plus-keyword values, and unknown aliases surface as UnexpectedInputArgumentsError through the argument-normalization path.

Parameters:

Name Type Description Default
*args object

Positional arguments matched, in order, to the interface's defined input fields.

()
**kwargs object

Keyword arguments supplying input values by name.

{}

Returns:

Type Description
dict[str, object]

dict[str, object]: Mapping of input field names to their validated values.

Raises:

Type Description
UnexpectedInputArgumentsError

If extra keyword arguments are provided that do not match any input field (after allowing keys suffixed with "_id").

MissingInputArgumentsError

If one or more required input fields are not provided.

CircularInputDependencyError

If input fields declare dependencies that form a cycle and cannot be resolved.

InvalidInputTypeError

If a provided value does not match the declared type for an input.

InvalidInputConstraintError

If bounds validation or the configured validator rejects a value.

InvalidPossibleValuesTypeError

If an input's possible_values configuration is neither callable nor iterable.

InvalidInputValueError

If a provided value is not in the allowed set defined by an input's possible_values.

format_identification staticmethod

format_identification(identification)

Normalise identification data by replacing manager instances with their IDs.

Parameters:

Name Type Description Default
identification dict[str, object]

Raw identification mapping possibly containing manager instances.

required

Returns:

Type Description
dict[str, object]

dict[str, object]: Identification mapping with nested managers replaced by their identifications.

create classmethod

create(*args, **kwargs)

Create a new managed record in the underlying data store using the interface's inputs.

This base method is intentionally typed to the capability-level mutation result, currently a dictionary such as {"id": pk}. Capability handlers used with InterfaceBase.create() should return that mapping shape; higher manager layers may convert it to a manager instance.

Parameters:

Name Type Description Default
*args object

Positional input values corresponding to the interface's defined input fields.

()
**kwargs object

Input values provided by name; unexpected extra keywords will be rejected.

{}

Returns:

Type Description
dict[str, object]

The capability-level create result mapping.

update

update(*args, **kwargs)

Update the underlying managed record.

Positional and keyword arguments are forwarded unchanged to the configured update capability together with this interface instance. This base method does not combine payload values with identification and does not reject unexpected keywords itself; validation belongs to the update capability.

Returns:

Type Description
object

The updated record or a manager-specific result.

Raises:

Type Description
NotImplementedError

If this interface does not provide an update capability.

delete

delete(*args, **kwargs)

Delete the underlying record managed by this interface.

Delegates the deletion to the interface's configured delete capability and executes the operation with observability hooks. Positional and keyword arguments are forwarded unchanged together with this interface instance. This base method does not combine payload values with identification and does not reject unexpected keywords itself; validation belongs to the delete capability.

Returns:

Type Description
object

The result of the delete operation as returned by the delete capability.

Raises:

Type Description
NotImplementedError

If the interface does not provide a delete capability.

get_data

get_data()

Get the materialized data for this manager.

Returns:

Type Description
object

The materialized data for this manager (implementation-defined).

Raises:

Type Description
NotImplementedError

if reading is not supported for this manager.

get_attribute_types classmethod

get_attribute_types()

Retrieve metadata describing each attribute exposed by the manager.

This method delegates entirely to the read capability. It does not build fallback metadata from input_fields.

Returns:

Type Description
dict[str, AttributeTypedDict]

dict[str, AttributeTypedDict]: Mapping from attribute name to its metadata (keys include type, default, is_required, is_editable, and is_derived).

Raises:

Type Description
NotImplementedError

If the manager does not provide a read capability implementing get_attribute_types.

get_attributes classmethod

get_attributes()

Retrieve attribute values exposed by the interface.

This method delegates entirely to the read capability. It does not build fallback values from input_fields.

Returns:

Type Description
dict[str, object]

dict[str, object]: Mapping of attribute names to their current values.

Raises:

Type Description
NotImplementedError

If the interface does not provide a read capability implementing get_attributes.

get_graph_ql_properties classmethod

get_graph_ql_properties()

Collect GraphQLProperty descriptors declared on the interface's parent manager class.

Returns:

Type Description
dict[str, GraphQLProperty]

dict[str, GraphQLProperty]: Mapping from attribute name to the corresponding GraphQLProperty instance found on the parent manager class. Returns an empty dict if no parent class is set or none of its attributes are GraphQLProperty instances.

filter classmethod

filter(**kwargs)

Filter records through the query capability and return its Bucket of matches.

Parameters:

Name Type Description Default
**kwargs object

Lookup expressions mapping field lookups (e.g., "name__icontains") to values.

{}

Returns:

Type Description
'Bucket[GeneralManager]'

Bucket[GeneralManager]: Bucket returned by the query capability, containing records that match the lookup expressions.

Raises:

Type Description
NotImplementedError

If the interface's query capability does not implement filtering.

exclude classmethod

exclude(**kwargs)

Exclude records through the query capability and return its Bucket of matches.

Parameters:

Name Type Description Default
**kwargs object

Lookup expressions accepted by the query capability (e.g., field=value, field__lookup=value).

{}

Returns:

Type Description
'Bucket[GeneralManager]'

Bucket[GeneralManager]: Bucket returned by the query capability, containing records that do not match the provided lookup expressions.

Raises:

Type Description
NotImplementedError

If the interface's query capability does not implement an exclude operation.

all classmethod

all()

Retrieve all records through the query capability and return its Bucket.

Returns:

Type Description
'Bucket[GeneralManager]'

Bucket[GeneralManager]: Bucket returned by the query capability, containing every record accessible via this interface.

Raises:

Type Description
NotImplementedError

If the configured query capability does not implement all.

handle_interface classmethod

handle_interface()

Provide pre- and post-creation hooks for GeneralManager class construction derived from the interface's lifecycle capability.

Returns:

Type Description
tuple[classPreCreationMethod, classPostCreationMethod]

tuple[classPreCreationMethod, classPostCreationMethod]: - pre-create callable accepting (name, attrs, interface, base_model_class=None) and returning (attrs, interface_class, related_class). - post-create callable accepting (new_class, interface_class, model) and returning None.

Raises:

Type Description
NotImplementedError

If no lifecycle capability is declared, or if the configured lifecycle capability does not provide callable pre_create and post_create hooks.

Exception

Exceptions from lifecycle hooks propagate unchanged. Malformed hook return values are not validated here and fail in the caller that consumes the lifecycle tuple.

get_field_type classmethod

get_field_type(field_name)

Resolve the declared Python type for the named input field.

If a read capability implements get_field_type(), that capability owns the result. Otherwise this method falls back only to declared input_fields.

Parameters:

Name Type Description Default
field_name str

Name of the input field to look up.

required

Returns:

Name Type Description
type type

The Python type declared for the specified field.

Raises:

Type Description
KeyError

If no input field with the given name is defined.

InterfaceBase is the capability-driven base for custom interfaces. Subclasses declare input_fields as a mapping of names to Input[...] objects. Positional constructor arguments are mapped to input fields by declaration order, keyword arguments are matched by name, and <name>_id aliases are accepted for declared inputs when the canonical <name> was not already supplied. Positional overflow, duplicate positional-plus-keyword values, alias collisions, and unknown keyword or alias names raise UnexpectedInputArgumentsError. Required inputs that are missing raise MissingInputArgumentsError; circular input dependencies raise CircularInputDependencyError; invalid input types raise InvalidInputTypeError; failed bounds or validators raise InvalidInputConstraintError; invalid possible-values containers raise InvalidPossibleValuesTypeError; and failed possible-value membership raises InvalidInputValueError when possible-value validation is enabled. Possible-value membership is controlled by VALIDATE_INPUT_VALUES; if that setting is unset, membership validation follows settings.DEBUG.

create(), update(), delete(), get_data(), filter(), exclude(), and all() delegate to configured capability handlers. Base create() is typed to the capability-level result mapping, while update(), delete(), and get_data() preserve arbitrary capability results. Query capabilities must return Bucket instances from filter(), exclude(), and all(); manager classes preserve or narrow those bucket types. Missing capabilities raise NotImplementedError. get_attribute_types() and get_attributes() require a read capability and do not synthesize fallbacks from input_fields; get_field_type() delegates to the read capability when present and otherwise falls back only to declared inputs. The base observability executor calls before_operation, then the delegated operation, then after_operation; if before_operation raises the delegated operation is not called, and observer hook exceptions propagate. handle_interface() delegates class creation to the configured lifecycle capability's pre_create and post_create callables, passing only keyword arguments accepted by each callable's signature. Missing lifecycle hooks raise NotImplementedError; lifecycle exceptions and malformed lifecycle return values are not wrapped by InterfaceBase.

general_manager.interface.orm_interface.OrmInterfaceBase

Bases: InterfaceBase, Generic[HistoryModelT]

Common initialization and metadata for ORM-backed interfaces.

Subclasses provide ORM lifecycle capabilities and a Django model type. The base interface defines one required public input field, id, which is cast through Input(int) before becoming identification["id"]. During construction, the interface stores that value as pk, normalizes an optional historical search_date, and loads the current or historical ORM row into the internal _instance attribute through the configured lifecycle capability. Subclasses that override :attr:input_fields must keep an "id" field unless they also override initialization and row loading.

historical_lookup_buffer_seconds is consumed by ORM query support: a search_date must be at least this many seconds before timezone.now() before history tables are queried instead of the current row.

__init__

__init__(*args, search_date=None, **kwargs)

Initialize the ORM-backed interface for a primary key.

Positional and keyword inputs are parsed by :class:InterfaceBase using :attr:input_fields. The default shape accepts one id value. Naive search_date values are made timezone-aware with Django's current timezone before the row is loaded into the internal _instance cache. Subclasses overriding :attr:input_fields must preserve "id" unless they also replace this initializer.

Parameters:

Name Type Description Default
*args object

Raw input values consumed by InterfaceBase.

()
search_date SearchDateInput | None

Optional point-in-time lookup date.

None
**kwargs object

Raw named input values consumed by InterfaceBase.

{}

Raises:

Type Description
KeyError

If parsed identification does not contain "id".

DoesNotExist

Propagated from get_data when no live or historical row exists for the parsed primary key.

TypeError

Propagated from runtime values outside the typed datetime | None search_date contract or from capability lookup/configuration failures while loading ORM data.

Exception

Propagates history capability and Django ORM lookup errors raised by get_data without wrapping.

normalize_search_date staticmethod

normalize_search_date(search_date)

Return search_date as a timezone-aware datetime.

Naive values are converted with Django's current timezone. Aware values and None are returned unchanged.

Parameters:

Name Type Description Default
search_date SearchDateInput | None

Datetime to normalize, or None.

required

Returns:

Type Description
datetime | None

The timezone-aware datetime, existing aware datetime, or None.

handle_custom_fields classmethod

handle_custom_fields(model)

Return custom field names and generated ignore markers for model.

The result is delegated to the configured orm_lifecycle capability. The first list contains discovered custom field names. The second list contains generated ignore markers such as "<field>_value" and "<field>_unit".

Parameters:

Name Type Description Default
model type[Model] | Model

Model class or model instance to inspect.

required

Returns:

Type Description
tuple[list[str], list[str]]

(field_names, ignore_markers).

Raises:

Type Description
CapabilityNotAvailableError

If the ORM lifecycle capability is not configured.

TypeError

If the configured capability is not an OrmLifecycleCapability.

OrmInterfaceBase is the public base for Django ORM-backed interfaces. It inherits InterfaceBase, declares the default input_fields as {"id": Input(int)}, and loads a current or historical ORM row for that primary key into the internal _instance attribute during construction. Pass search_date=... to resolve a point-in-time row; naive datetimes are made timezone-aware with Django's current timezone before lookup. The historical_lookup_buffer_seconds class attribute controls how far in the past a search_date must be before ORM support reads from history tables instead of the current row.

Subclasses normally use DatabaseInterface, ExistingModelInterface, or ReadOnlyInterface rather than subclassing this base directly, but custom ORM interface types can reuse it when they provide the required lifecycle capability configuration. If a custom ORM interface overrides input_fields, preserve "id" unless you also replace initialization and row loading. The underscored helpers such as _from_trusted_orm_instance() and _default_base_model_class() are internal extension hooks for bucket hydration and class creation. Underscored helpers in ORM capability modules follow the same rule even if generated API pages render them; application code should prefer the documented manager, interface, and bucket methods.

handle_custom_fields(model) delegates to the configured ORM lifecycle capability and returns (field_names, ignore_markers), where ignore markers are the generated <field>_value and <field>_unit names. Missing or invalid lifecycle capabilities propagate the capability lookup/type errors.

general_manager.interface.interfaces.database.DatabaseInterface

Bases: OrmInterfaceBase[GeneralManagerModel]

CRUD-capable interface backed by a generated GeneralManager Django model.

Manager subclasses declare Django model fields on this interface. The ORM lifecycle capability turns those declarations into a concrete model and the configured writable ORM capabilities provide query, create, update, delete, history, validation, and observability behavior.

Construction uses OrmInterfaceBase inputs: the default public input is id, and search_date performs inherited point-in-time row lookup. Missing live or historical rows propagate the generated Django model's DoesNotExist exception. Write payload normalization can raise UnknownFieldError for unknown fields, InvalidFieldValueError when assignment raises ValueError, and InvalidFieldTypeError when assignment raises TypeError.

general_manager.interface.interfaces.existing_model.ExistingModelInterface

Bases: OrmInterfaceBase[ExistingModelT]

Writable ORM interface backed by a pre-existing Django model.

Subclasses declare model as either a Django model class or an app-label string accepted by django.apps.apps.get_model(), such as settings.AUTH_USER_MODEL. During manager class creation the existing_model_resolution lifecycle capability resolves that reference, caches the resolved model on the concrete interface, auto-registers database-aware history when needed, applies interface rules, and builds a factory for the legacy model. Auto-registration includes local many-to-many fields. A pre-registered tracker remains compatible on the default database; on a configured non-default alias, its generated history model must carry GeneralManager's database-aware marker or manager creation raises UnsafeHistoryConfigurationError. Interface rules are the optional Meta.rules sequence on the interface. Soft delete is enabled when the resolved model exposes an is_active attribute.

Construction and row loading are inherited from OrmInterfaceBase: the default public input is the wrapped row id parsed by Input(int) plus optional search_date: datetime | None. Naive search dates are made aware with Django's current timezone, and historical lookups follow OrmInterfaceBase.historical_lookup_buffer_seconds. Missing rows propagate the wrapped model's DoesNotExist exception. Invalid or missing model declarations raise the existing-model configuration errors from the resolution capability. Creation, update, delete, query, history, and factory APIs are inherited from the configured writable ORM capabilities and the owning GeneralManager class; this shell class only selects the existing-model lifecycle.

get_field_type classmethod

get_field_type(field_name)

Retrieve the effective type for a wrapped model attribute.

The method first ensures the legacy model has been resolved and cached on this interface class, then delegates to the inherited read-capability lookup. Resolution is class-local: subclasses that declare their own model do not reuse a parent interface's cached _model value. Stored Django fields return the Django field class. Managed relations are relation fields whose related model exposes _general_manager_class; those return that manager class. Generated descriptors are entries in ORM support's descriptor map, including custom fields and generated relation helpers; those return their descriptor metadata "type" value.

Parameters:

Name Type Description Default
field_name str

Name of the field or manager attribute to inspect.

required

Returns:

Type Description
type[object]

The effective field, manager, or descriptor type exposed for

type[object]

field_name.

Raises:

Type Description
MissingModelConfigurationError

If no model is configured.

InvalidModelReferenceError

If model is not a Django model class or resolvable app-label string.

FieldDoesNotExist

If neither the wrapped model nor generated descriptors can describe the field.

CapabilityNotAvailableError

If required capabilities are absent.

TypeError

If the configured resolution capability is not an ExistingModelResolutionCapability or the read capability is incompatible.

ExistingModelInterface is the writable ORM interface for wrapping a Django model that already exists outside GeneralManager. Direct subclasses set model to a Django model class or to an app-label string accepted by Django's app registry, such as settings.AUTH_USER_MODEL or "app_label.ModelName". The existing_model_resolution lifecycle capability resolves that reference during manager class creation, stores the resolved class on the concrete interface as _model and model, registers database-aware simple-history when needed, applies interface rules, and builds a factory for the existing table. Missing model declarations raise MissingModelConfigurationError; invalid strings, non-model classes, and other invalid references raise InvalidModelReferenceError. Auto-registration includes local many-to-many fields and routes base and relation history to the live row's database alias. A pre-existing tracker is accepted on the default alias. On a configured non-default alias its history model must carry GeneralManager's database-aware marker or manager creation raises UnsafeHistoryConfigurationError. Soft delete is enabled when the resolved model exposes an is_active attribute. The simple-history marker is model._meta.simple_history_manager_attribute; interface rules are the optional Meta.rules sequence on the interface. This shell class does not declare separate create/update/delete signatures. Those public operations are the inherited GeneralManager and writable ORM capability APIs documented in the core manager and existing-model guides; ExistingModelInterface selects the existing-model lifecycle for them.

Construction inherits the ORM input contract: pass the wrapped row id, parsed through the default Input(int), and optional search_date: datetime | None. Naive search dates are made aware with Django's current timezone, and history lookup uses historical_lookup_buffer_seconds from OrmInterfaceBase. Missing current or historical rows propagate the wrapped model's DoesNotExist exception. get_field_type(field_name) first lazily resolves this interface's own model, then delegates to ORM read support. Stored model fields return the Django field class, managed relations return the related model's _general_manager_class when present, and generated relation/custom descriptors return their metadata type; fields absent from both the model and descriptor map raise Django's FieldDoesNotExist. A managed relation means a Django relation whose related model has _general_manager_class; generated descriptors are ORM support descriptor-map entries for custom fields and generated relation helpers. The lazy cache is class-local, so a subclass that declares a different model resolves that declaration instead of reusing a parent interface's cached _model.

general_manager.interface.interfaces.read_only.ReadOnlyInterface

Bases: OrmInterfaceBase[GeneralManagerBasisModel]

Capability shell for read-only datasets mirrored into generated models.

Subclasses are declared as a manager's nested Interface and define the Django fields for a generated model. The parent manager, not this class, provides the _data payload as either a JSON string or a list of row dictionaries. The configured read-only lifecycle forces Meta.use_soft_delete = True, generates a model based on GeneralManagerBasisModel, and registers the created manager for startup schema checks and synchronization.

Construction and row loading are inherited from OrmInterfaceBase: the public input is the mirrored row id parsed by Input(int) plus optional search_date: datetime | None. Missing current or historical rows propagate the generated model's DoesNotExist exception. Read, query, history, validation, soft-delete, schema-check, and synchronization behavior comes from READ_ONLY_CAPABILITIES; this shell class does not define separate public mutation methods.

Read-only synchronization can raise the dedicated read-only configuration errors from the management capability when the parent manager is not bound, _data is missing or malformed, no unique row identity can be found, or relation lookups do not resolve exactly one row. Lifecycle and ORM errors propagate unchanged from the capability that raises them. The public manager surface inherited from GeneralManager is construction by id, attribute reads, all(), filter(), exclude(), and history access. Those successful reads and queries return manager instances or buckets of manager instances backed by generated model rows; history access returns the generated model's history queryset. Because no create, update, or delete capability is configured, inherited mutation entry points are not read-only data APIs.

Underscored attributes such as _interface_type and _parent_class are framework wiring, not application configuration. The parent manager's _data payload is the public read-only data source despite its legacy underscore name. Duplicate composite identities in _data are not rejected by the shell; the management capability falls back to full synchronization and processes rows in order for the same identity. Relation lookup dictionaries are flattened into Django __ lookups; zero or multiple matches raise ReadOnlyRelationLookupError, while malformed lookup keys or values propagate the Django query error. For many-to-many payloads, an omitted key leaves the relation unchanged, a present None clears it, and a present list replaces it.

ReadOnlyInterface is the capability shell for static or generated datasets mirrored into a generated Django model. Subclasses normally appear as a manager's nested Interface and declare Django model fields; the parent manager provides _data as either a JSON string or a list of row dictionaries. The read-only lifecycle forces Meta.use_soft_delete = True, generates the model with GeneralManagerBasisModel, and registers the created manager in the read-only startup registry so schema checks and data sync can run during startup.

Construction inherits the ORM input contract: pass the mirrored row id, parsed through default Input(int), and optional search_date: datetime | None. Missing current or historical rows propagate the generated model's DoesNotExist exception. The class itself does not define separate public mutation methods; read/query/history/validation, soft-delete, schema-check, and sync behavior come from READ_ONLY_CAPABILITIES and the owning GeneralManager API. Sync errors such as MissingReadOnlyBindingError, MissingReadOnlyDataError, InvalidReadOnlyDataTypeError, InvalidReadOnlyDataFormatError, MissingUniqueFieldError, and ReadOnlyRelationLookupError are raised by the read-only management capability when the parent/model binding, _data payload, unique row identity, or relation lookups are invalid. The successful public manager surface is construction by id, attribute reads, all(), filter(), exclude(), and history access. These return manager instances, buckets of manager instances, or the generated model's history queryset. READ_ONLY_CAPABILITIES intentionally omits create, update, and delete capabilities, so inherited mutation entry points are not read-only data APIs. _interface_type, _parent_class, and configured_capabilities are framework wiring; the parent manager's _data attribute is the public dataset source despite its legacy underscore name. Duplicate composite identities in _data are not rejected during full synchronization; rows for the same identity are processed in order, so later payload values can overwrite earlier values for that row. Relation lookup dictionaries are flattened into Django __ lookups; zero or multiple matches raise ReadOnlyRelationLookupError, while malformed lookup keys or values propagate the Django query error. For many-to-many fields, an omitted key leaves the relation unchanged, a present None clears it, and a present list replaces it.

general_manager.interface.interfaces.calculation.CalculationInterface

Bases: InterfaceBase

Interface shell for derived managers that expose typed inputs but no storage.

Subclasses normally declare input descriptors as class attributes (project = Input(Project)). During manager-class creation the calculation lifecycle capability scans the concrete interface class's own attributes, skips dunder names, collects values that are Input instances into a fresh input_fields dictionary, and assigns that dictionary to the generated interface subclass. Inherited descriptors and any manually assigned input_fields mapping are not merged by that lifecycle step. The generated interface receives a _parent_class backlink to the manager during post-create.

Resolved values are cached per interface instance in _resolved_input_values. The cache stores the cast result of each input, including manager wrappers for manager-typed inputs, and lives for the lifetime of that interface instance. Manager-typed inputs cache the resolved GeneralManager wrapper object returned by Input.cast(). There is no cross-instance, async, or thread-level invalidation contract for this cache. Query methods all(), filter(), and exclude() are provided by the configured calculation query capability and return CalculationBucket instances. The public get_data() method is backed by the calculation read capability and raises NotImplementedError("Calculations do not store data."). Managers still inherit create(), update(), and delete() from GeneralManager, but calculation interfaces configure no create, update, or delete capability, so those inherited mutation paths are unsupported and fail when they require the missing capability.

general_manager.interface.interfaces.request.RequestInterface

Bases: InterfaceBase

Base interface for request-backed resources with declarative operations.

Subclasses declare RequestField attributes on the interface and request filters, query operations, mutation operations, transports, auth providers, retry policies, serializers, and rules on Meta. Request fields are collected across the subclass MRO so derived interfaces can inherit or override field declarations. Legacy top-level request configuration raises RequestConfigurationError during subclass creation. Declared mutation operations automatically add the corresponding request mutation capabilities.

At subclass creation, Meta.filters, Meta.query_operations, Meta.default_query_operation, Meta.transport, Meta.transport_config, Meta.auth_provider, Meta.retry_policy, Meta.create_operation, Meta.update_operation, Meta.delete_operation, Meta.create_serializer, Meta.update_serializer, Meta.response_serializer, and Meta.rules are copied onto same-named interface class attributes. Omitted values use the class defaults declared below.

Request queries return lazy request buckets through the configured query capability. Instance field reads resolve values from the cached response payload and raise MissingRequestPayloadFieldError when a required declared field is absent.

__init__

__init__(*args, **kwargs)

Reject historical construction before parsing request inputs.

get_query_operation classmethod

get_query_operation(operation_name=None)

Return a named query operation, falling back to interface-level filters.

None and empty names resolve to default_query_operation. When that default operation is not explicitly declared, this method returns a synthetic operation with path="" and the interface-level filters. Declared operations whose own filters value is None inherit interface-level filters; declared operations with a filter mapping keep that operation-specific mapping.

Raises:

Type Description
UnknownRequestOperationError

If a non-default operation name is not declared.

query_operation classmethod

query_operation(operation_name, **kwargs)

Build a bucket for a named collection operation declared on the interface.

Parameters:

Name Type Description Default
operation_name str

Name of a configured RequestQueryOperation.

required
**kwargs object

Lookup values compiled by the request query capability.

{}

Returns:

Type Description
Bucket[GeneralManager]

A lazy request bucket for the interface's parent manager.

Raises:

Type Description
UnknownRequestOperationError

If the named operation is not declared.

NotImplementedError

If the configured query capability does not implement named request operations.

RequestConfigurationError

If request planning fails for the operation, filters, or transport setup.

Exception

Request planning errors from the active query capability, including unknown filters, invalid filter values, unsupported excludes, invalid request-fragment locations, and conflicting fragment keys, propagate unchanged.

set_request_payload_cache

set_request_payload_cache(payload)

Cache the raw response payload used to populate request-backed fields.

Passing None clears the cache. The method does not validate payload shape; individual field reads perform path resolution and required-field checks.

get_mutation_operation classmethod

get_mutation_operation(action)

Return the configured mutation operation for an action.

Parameters:

Name Type Description Default
action str

One of "create", "update", or "delete".

required

Raises:

Type Description
NotImplementedError

If the interface does not declare that mutation operation.

extract_identification classmethod

extract_identification(payload)

Extract manager identification values from a query payload.

Returns values for every field named in identification_fields, resolving declared request-field source paths where present.

Raises:

Type Description
MissingRequestPayloadFieldError

If a required identification value is absent from the payload.

resolve_payload_value classmethod

resolve_payload_value(payload, field_name)

Resolve a declared request field from a payload mapping.

Undeclared fields are resolved by their own name. Declared fields use the RequestField source path, return the field default when optional data is missing, and apply the field normalizer when one is configured.

Raises:

Type Description
MissingRequestPayloadFieldError

If a required value is missing.

execute_request_plan classmethod

execute_request_plan(plan)

Execute a compiled request plan and return normalized payload items.

The configured transport may return either a RequestQueryResult or a decoded request response accepted by default_request_response_normalizer. A callable response_serializer is applied to each normalized item and must return mapping-shaped payloads. Plans with create, update, or delete actions use the corresponding mutation operation; every other action string, including unknown or empty actions, uses the plan's operation_name to resolve a query operation. The plan's path_params are forwarded to the transport as request identification. Auth, retry, metrics, trace, and transport behavior is owned by the configured transport object; errors from those hooks propagate according to that transport implementation.

Raises:

Type Description
MissingRequestTransportError

If no transport is configured.

RequestSchemaError

If the response serializer returns non-mapping items or the default normalizer rejects the transport payload.

NotImplementedError

If a create, update, or delete plan targets an undeclared mutation operation.

UnknownRequestOperationError

If a non-mutation plan targets an undeclared query operation.

general_manager.interface.interfaces.remote_manager.RemoteManagerInterface

Bases: RequestInterface

Request-backed interface for a remote GeneralManager REST resource.

Direct subclasses read Meta.base_url, optional Meta.base_path, Meta.remote_manager, optional Meta.protocol_version, and optional Meta.websocket_invalidation_enabled when the class is defined. The interface validates that metadata, defaults base_path to /gm when it is omitted, defaults protocol_version to "v1", coerces websocket_invalidation_enabled with bool(...), normalizes base_path, installs the generated GET <base_path>/<remote_manager>/{id} detail query, POST <base_path>/<remote_manager>/query list query, and create/update/delete mutation operations, and configures response normalization for the remote-manager envelope. Generated operations include the X-General-Manager-Protocol-Version header. If a subclass already defines transport_config, its timeout, auth provider, retry policy, metrics backend, and trace backend are preserved while the validated Meta.base_url and response normalizer replace the transport's values.

Configuration errors are raised during direct subclass creation by validate_remote_manager_meta(...). Indirect subclasses are not reconfigured by this class hook. Query execution can additionally raise request operation, schema, transport, serializer, or validator errors from the underlying request interface.

get_websocket_invalidation_url classmethod

get_websocket_invalidation_url()

Return the websocket URL used for remote cache invalidation.

The URL is derived from base_url and the normalized base_path. Class creation validates base_url as http or https before this helper is available on a configured interface. https base URLs become wss and valid http base URLs become ws. A path prefix already present on base_url is stripped of trailing slashes and preserved before <base_path>/ws/<remote_manager>. Query and fragment components from base_url are not preserved; the protocol version is emitted as the version query parameter. This helper does not check websocket_invalidation_enabled by itself.

Returns:

Type Description
str

Absolute websocket URL for this interface's invalidation stream.

handle_invalidation_event classmethod

handle_invalidation_event(event)

Invalidate cached remote queries when a websocket event matches.

Parameters:

Name Type Description Default
event Mapping[str, object]

Decoded websocket payload. Only protocol_version, base_path, and resource_name are used for matching. action, identification, and event_id are intentionally ignored by the local request-query cache invalidation path.

required

Returns:

Type Description
bool

True when the event matches this interface and invalidation was

bool

requested for the parent manager; False for non-matching events.

Raises:

Type Description
AttributeError

If called before the interface is bound to a parent manager class.

Exception

Propagates cache invalidation backend errors.

RemoteManagerInterface is the generated-client interface for another GeneralManager service's RemoteAPI exposure. Direct subclasses read Meta.base_url, optional Meta.base_path, Meta.remote_manager, optional Meta.protocol_version, and optional Meta.websocket_invalidation_enabled at class creation time. Omitted Meta.base_path defaults to /gm, omitted Meta.protocol_version defaults to "v1", and Meta.websocket_invalidation_enabled is coerced with bool(...). Only direct subclasses are configured by this class hook; indirect subclasses inherit the already configured values unless they inherit directly from RemoteManagerInterface. The interface validates those values, creates standard detail/list/create/update/delete request operations, installs the protocol version header, and configures response normalization for RemoteAPI envelopes. If a subclass already declares transport_config, timeout, auth, retry, metrics, and trace settings are preserved while the base URL and response normalizer are replaced with the validated remote-manager settings.

get_websocket_invalidation_url() returns the websocket invalidation URL for the interface. Class creation validates base_url as HTTP(S). https base URLs become wss; http base URLs become ws; a path prefix in base_url is stripped of trailing slashes and preserved before <base_path>/ws/<remote_manager>; and protocol_version is emitted as the version query parameter. Query and fragment components from base_url are not preserved. The helper itself does not check websocket_invalidation_enabled; RemoteInvalidationClient performs that enabled check before opening connections. handle_invalidation_event(event) compares only protocol_version, base_path, and resource_name; matching events invalidate local remote-query caches for the parent manager and return True, while non-matching events return False. Cache invalidation errors propagate, and calling it before the interface is bound to a parent manager can raise AttributeError.

Capabilities

general_manager.interface.capabilities.base.CapabilityName module-attribute

CapabilityName = Literal[
    "read",
    "create",
    "update",
    "delete",
    "history",
    "validation",
    "query",
    "orm_support",
    "orm_mutation",
    "orm_lifecycle",
    "calculation_lifecycle",
    "notification",
    "scheduling",
    "access_control",
    "observability",
    "existing_model_resolution",
    "request_lifecycle",
    "read_only_management",
    "soft_delete",
]

Supported capability identifiers used by interface capability registries.

Capability names are stable string keys. Interfaces store active names in InterfaceBase._capabilities, map them to handler instances in InterfaceBase._capability_handlers, and may use them as override keys in capability_overrides.

general_manager.interface.capabilities.base.Capability

Bases: Protocol

Runtime-checkable protocol implemented by interface capability handlers.

A capability advertises one stable name and can attach or detach behavior from an interface class. Implementations mutate the supplied class in place and return None. Exceptions from concrete implementations propagate; this protocol does not define a normalization layer or idempotency guarantee.

setup

setup(interface_cls)

Attach this capability to the given interface class.

Implementations should modify or extend the provided interface class so that it exposes or enables the capability's behavior, for example by registering methods, attributes, or lifecycle hooks.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface class to mutate.

required

Returns:

Type Description
None

None.

Raises:

Type Description
Exception

Concrete capability implementations define their own validation and setup errors, which propagate unchanged.

teardown

teardown(interface_cls)

Detach this capability from the given interface class.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface class to mutate.

required

Returns:

Type Description
None

None.

Raises:

Type Description
Exception

Concrete capability implementations define their own teardown errors, which propagate unchanged.

general_manager.interface.capabilities.builtin.BaseCapability dataclass

Bases: Capability

Base implementation for capability validation and handler registration.

Subclasses publish a stable capability name and may list class attributes or methods required on the interface class in required_attributes. The dataclass has no instance fields or generated constructor parameters of its own. setup() validates those requirements, converts the interface class's current _capability_handlers mapping to a plain dict or starts from an empty plain dict when that attribute is absent, registers this capability instance under name, and writes the copied mapping back to the class. teardown() performs the inverse copy-and-remove operation with the same plain-dict conversion and also starts from an empty mapping when no registry exists yet.

The base implementation does not call the required attributes and does not validate their signatures; it only checks hasattr(interface_cls, attr). Repeated setup replaces the handler for the same name, and repeated teardown is a no-op once the handler is absent. Missing attributes raise :class:CapabilityBindingError; other attribute access or mapping-copy failures propagate unchanged.

setup

setup(interface_cls)

Validate and register this capability on an interface class.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

The interface class to mutate.

required

Returns:

Type Description
None

None. The supplied class is mutated in place.

Raises:

Type Description
CapabilityBindingError

If one or more names in required_attributes are missing from interface_cls. The reason lists missing names in alphabetical order.

Exception

Exceptions raised by hasattr() while checking required attributes, reading the existing class registry, converting _capability_handlers with dict(...), or assigning the updated registry are propagated unchanged.

teardown

teardown(interface_cls)

Remove this capability from an interface class registry.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

The interface class to mutate.

required

Returns:

Type Description
None

None. The supplied class is mutated in place.

Raises:

Type Description
Exception

Exceptions raised while reading, converting with dict(...), or assigning _capability_handlers are propagated unchanged.

general_manager.interface.capabilities.builtin.ReadCapability dataclass

Bases: BaseCapability

Register the read handler; requires get_data on the interface.

general_manager.interface.capabilities.builtin.CreateCapability dataclass

Bases: BaseCapability

Register the create handler; requires create on the interface.

general_manager.interface.capabilities.builtin.UpdateCapability dataclass

Bases: BaseCapability

Register the update handler; requires update on the interface.

general_manager.interface.capabilities.builtin.DeleteCapability dataclass

Bases: BaseCapability

Register the delete handler; requires delete on the interface.

general_manager.interface.capabilities.builtin.HistoryCapability dataclass

Bases: BaseCapability

Register the history handler; requires get_attribute_types.

general_manager.interface.capabilities.builtin.ValidationCapability dataclass

Bases: BaseCapability

Register the validation handler; requires get_attribute_types.

general_manager.interface.capabilities.builtin.NotificationCapability dataclass

Bases: BaseCapability

Register a notification marker handler without extra requirements.

general_manager.interface.capabilities.builtin.SchedulingCapability dataclass

Bases: BaseCapability

Register a scheduling marker handler without extra requirements.

general_manager.interface.capabilities.builtin.AccessControlCapability dataclass

Bases: BaseCapability

Register an access_control marker handler without extra requirements.

general_manager.interface.capabilities.builtin.ObservabilityCapability dataclass

Bases: BaseCapability

Register an observability marker handler without extra requirements.

general_manager.interface.capabilities.exceptions.CapabilityBindingError

Bases: RuntimeError

Raised when a capability cannot be attached to an interface class.

The error keeps the original capability name and failure reason as public attributes and formats str(error) as "Capability '<name>' could not be attached: <reason>". Empty reasons are preserved, including the trailing separator in the formatted message.

__init__

__init__(capability_name, reason)

Initialize the error with failed binding details.

Parameters:

Name Type Description Default
capability_name str

Name of the capability that could not be attached.

required
reason str

Explanation of why the attachment failed. The value is stored unchanged and may be an empty or multiline string.

required

Raises:

Type Description
Exception

Exceptions raised while formatting the message from non-string runtime values propagate if callers bypass static typing.

general_manager.interface.capabilities.configuration.InterfaceCapabilityConfig dataclass

Declarative entry describing one capability handler construction.

handler is the capability class to instantiate. options=None means no keyword arguments are supplied; a mapping value is converted to a plain dict immediately before construction and expanded as keyword arguments. The config object is immutable, but the original mapping is not copied until :meth:instantiate is called.

instantiate

instantiate()

Instantiate the configured capability handler.

Returns:

Type Description
Capability

Capability instance produced by calling handler. options=None

Capability

calls the handler with no keyword arguments; any supplied mapping,

Capability

including an empty or otherwise falsey mapping, is copied into a

Capability

mutable dict and expanded as keyword arguments.

Raises:

Type Description
TypeError

If handler rejects the supplied keyword arguments or is otherwise not constructible. Exceptions from mapping iteration while converting options with dict(...) propagate unchanged.

general_manager.interface.capabilities.configuration.CapabilitySet dataclass

Named immutable bundle of concrete capability configuration entries.

The constructor accepts any iterable of :class:InterfaceCapabilityConfig entries and stores it as a tuple. Entries are not copied deeply and are not validated beyond normal iteration; invalid values supplied at runtime remain invalid values in the tuple.

__init__

__init__(label, entries)

Store bundle entries as an immutable tuple.

Parameters:

Name Type Description Default
label str

Human-readable bundle label used for documentation and debugging.

required
entries Iterable[InterfaceCapabilityConfig]

Iterable of concrete capability configuration entries.

required

Raises:

Type Description
TypeError

If entries cannot be iterated.

general_manager.interface.capabilities.configuration.flatten_capability_entries

flatten_capability_entries(entries)

Expand capability bundles into a flat immutable tuple.

Parameters:

Name Type Description Default
entries Sequence[CapabilityConfigEntry] | Iterable[CapabilityConfigEntry]

Iterable of InterfaceCapabilityConfig values and CapabilitySet bundles. Bundles are expanded one level into their configured entries. The iterable is consumed once.

required

Returns:

Type Description
InterfaceCapabilityConfig

Tuple of concrete capability configurations in input order. Entries are

...

not deduplicated or validated; repeated capability handlers remain

tuple[InterfaceCapabilityConfig, ...]

repeated entries. Invalid non-CapabilitySet runtime values are

tuple[InterfaceCapabilityConfig, ...]

appended unchanged if callers bypass static typing.

Raises:

Type Description
TypeError

If entries cannot be iterated.

Exception

Exceptions raised while iterating entries propagate unchanged.

general_manager.interface.capabilities.configuration.iter_capability_entries

iter_capability_entries(entries)

Yield concrete capability configurations in order.

Parameters:

Name Type Description Default
entries Sequence[CapabilityConfigEntry] | Iterable[CapabilityConfigEntry]

Iterable of InterfaceCapabilityConfig values and CapabilitySet bundles. Bundles are expanded one level into their configured entries. Iteration stays lazy for the outer iterable.

required

Returns:

Type Description
Iterator[InterfaceCapabilityConfig]

Iterator over concrete capability configuration entries. Entries are not

Iterator[InterfaceCapabilityConfig]

deduplicated or validated. Invalid non-CapabilitySet runtime values

Iterator[InterfaceCapabilityConfig]

are yielded unchanged if callers bypass static typing.

Raises:

Type Description
TypeError

If entries cannot be iterated.

Exception

Exceptions raised while iterating entries propagate unchanged.

general_manager.interface.capabilities.factory.CAPABILITY_CLASS_MAP module-attribute

CAPABILITY_CLASS_MAP = {
    "read": ReadCapability,
    "create": CreateCapability,
    "update": UpdateCapability,
    "delete": DeleteCapability,
    "history": HistoryCapability,
    "validation": ValidationCapability,
    "notification": NotificationCapability,
    "scheduling": SchedulingCapability,
    "access_control": AccessControlCapability,
    "observability": ObservabilityCapability,
}

Default capability handler classes keyed by public capability name.

general_manager.interface.capabilities.factory.CapabilityOverride module-attribute

CapabilityOverride = (
    Callable[[], Capability] | type[Capability]
)

Per-name override accepted by :func:build_capabilities.

general_manager.interface.capabilities.factory.build_capabilities

build_capabilities(interface_cls, names, overrides)

Instantiate capability handlers for the supplied names.

Parameters:

Name Type Description Default
interface_cls type[object]

Interface class the capabilities will be associated with. This compatibility context is accepted for callers that already have an interface class available; the current implementation does not inspect or pass it to handlers.

required
names Iterable[CapabilityName]

Capability names to instantiate. The iterable is consumed once and order is preserved. Duplicate names create duplicate handler instances or call the override once per occurrence.

required
overrides Mapping[CapabilityName, CapabilityOverride]

Per-name overrides. When a name exists in this mapping and the value is not None at runtime, the override takes precedence over :data:CAPABILITY_CLASS_MAP. Override values are called with no arguments; class overrides are instantiated the same way as other zero-argument callables.

required

Returns:

Type Description
list[Capability]

A mutable list of capability instances in the same order as names.

Raises:

Type Description
KeyError

If a requested name has no non-None override and is absent from :data:CAPABILITY_CLASS_MAP.

Exception

Exceptions raised while iterating names, reading overrides, or calling the selected handler propagate unchanged.

general_manager.interface.capabilities.registry.CapabilityRegistry

In-memory registry mapping interface classes to capability declarations.

The registry stores declared capability names separately from concrete capability instances. It is process-local, has no locking, does not validate runtime values beyond normal iterable consumption, and returns defensive immutable views from read methods.

__init__

__init__()

Initialize empty declaration and instance registries.

_bindings maps interface classes to mutable internal sets of declared capability names. _instances maps interface classes to immutable tuples of concrete capability objects.

register

register(interface_cls, capabilities, *, replace=False)

Record declared capability names for an interface class.

The incoming iterable is consumed exactly once into a temporary set before internal state is changed. Duplicate names collapse. With replace=False the new names are merged into the existing binding; with replace=True the existing binding is replaced, including by an empty iterable. Runtime values are trusted if callers bypass static typing.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface receiving the capabilities.

required
capabilities Iterable[CapabilityName]

Iterable of capability names to register. Iteration order is not preserved because declaration reads return sets.

required
replace bool

Overwrite existing entries instead of merging when true.

False

Raises:

Type Description
Exception

Exceptions raised while iterating capabilities propagate unchanged before the registry is mutated.

get

get(interface_cls)

Retrieve the capability names registered for the given interface class.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface class to look up.

required

Returns:

Type Description
frozenset[CapabilityName]

A new frozenset of declared capability names, or an empty

frozenset[CapabilityName]

frozenset when the interface has no binding.

bind_instances

bind_instances(interface_cls, capabilities)

Record concrete capability instances for the given interface class.

The iterable is consumed once into a tuple before assignment. Instance bindings are independent of declared-name bindings: storing instances does not call register(), and replacing declared names does not remove stored instances.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface class to bind instances to.

required
capabilities Iterable['Capability']

Concrete capability objects to store, preserving iteration order. The tuple replaces any previous instance binding for the same interface.

required

Raises:

Type Description
Exception

Exceptions raised while iterating capabilities propagate unchanged before the instance binding is replaced.

instances

instances(interface_cls)

Retrieve the concrete capability objects associated with the given interface.

Parameters:

Name Type Description Default
interface_cls type['InterfaceBase']

Interface class to look up.

required

Returns:

Type Description
'Capability'

The stored capability tuple, or an empty tuple when no instances are

...

bound for the interface.

snapshot

snapshot()

Return a read-only snapshot of declared capability names.

The returned MappingProxyType wraps a new dictionary, and each value is a frozenset. Later registry mutations do not affect earlier snapshots. Concrete capability instances are not included.

Returns:

Type Description
Mapping[type['InterfaceBase'], frozenset[CapabilityName]]

A read-only mapping of interface classes to immutable declared-name

Mapping[type['InterfaceBase'], frozenset[CapabilityName]]

sets.

general_manager.interface.capabilities.orm_utils.payload_normalizer.PayloadNormalizer

Normalize keyword payloads for database-backed interface operations.

__init__

__init__(model)

Initialize the normalizer for a Django model and cache metadata used for payload normalization.

Parameters:

Name Type Description Default
model type[Model]

The Django model class whose attributes and fields will be inspected to validate and normalize payload keys and values.

required

normalize_filter_kwargs

normalize_filter_kwargs(kwargs)

Normalize filter keyword arguments by replacing any general-manager values with their unwrapped identifier or instance.

Returns a new mapping and does not mutate kwargs. Keys are preserved. A "general-manager value" is an actual GeneralManager instance. If prefer_instance resolution cannot find _interface._instance, the manager's identification["id"] is used; malformed manager state such as a missing "id" propagates the underlying exception.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of filter keyword names to values which may include general-manager wrappers.

required

Returns:

Type Description
PayloadMapping

A new dictionary with the same keys and values converted to their unwrapped manager form where applicable.

validate_keys

validate_keys(kwargs)

Validate that each key in the provided kwargs corresponds to a known attribute or field on the target model.

Known attributes are names present in vars(model), which includes descriptors, properties, methods, and other class attributes declared on the model class. Known fields are names from model._meta.get_fields(), including forward and reverse Django relations. The _list and _id_list aliases are accepted only when their base name is a real local many-to-many field; malformed aliases otherwise validate as their literal key and usually raise UnknownFieldError.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of payload keys to values; keys ending with "_id_list" will be validated by their base name (suffix removed).

required

Raises:

Type Description
UnknownFieldError

If any key's base name is not an attribute of the model instance and not a model field name.

split_many_to_many

split_many_to_many(kwargs)

Mutate a kwargs mapping by moving many-to-many related entries out of it.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of field lookups where keys for many-to-many relations are expected to end with _id_list.

required

Returns:

Name Type Description
tuple tuple[PayloadMapping, PayloadMapping]

A pair (remaining_kwargs, many_kwargs) where remaining_kwargs is the original kwargs mapping with many-to-many entries removed, and many_kwargs contains the removed entries whose base key (key with a trailing _id_list suffix stripped) corresponds to a many-to-many field.

Notes

This function mutates the kwargs argument by removing any entries moved into many_kwargs. The first returned mapping is the same object passed in. If both <relation>_list and <relation>_id_list are present, iteration order decides the last canonical value stored in many_kwargs.

split_many_to_many_non_mutating

split_many_to_many_non_mutating(kwargs)

Return separated many-to-many entries without mutating the input mapping.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of field lookups where keys for many-to-many relations may use either <relation>_list or <relation>_id_list.

required

Returns:

Name Type Description
tuple tuple[PayloadMapping, PayloadMapping]

A pair (remaining_kwargs, many_kwargs) where both mappings are new dictionaries. remaining_kwargs contains non-matching entries from kwargs, and many_kwargs contains matching many-to-many entries under canonical <relation>_id_list keys.

Notes

This is the non-mutating counterpart to split_many_to_many(). If both <relation>_list and <relation>_id_list are present, iteration order decides the last canonical value stored in many_kwargs.

normalize_simple_values

normalize_simple_values(kwargs)

Normalize simple (single-valued) payload entries by converting general-manager objects to their identifier form and adjusting keys.

For each key/value in kwargs, if value is recognized as a general-manager instance its identifier is used as the value; when the original key does not end with _id, the key is renamed to {key}_id. Non-manager values are kept unchanged. Returns a new mapping and does not mutate kwargs. Relation-key renaming applies only to forward ForeignKey and OneToOneField names cached from the model metadata. Reverse relations, generic relations, and many-to-many fields are not relation-renamed here. If both a relation key and its <relation>_id key appear, the later normalized key overwrites the earlier value according to input iteration order.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of field names to single values to normalize.

required

Returns:

Type Description
PayloadMapping

A new mapping with manager values replaced by their identifiers and keys suffixed with _id when appropriate.

normalize_many_values

normalize_many_values(kwargs)

Normalize values intended to represent multi-valued model fields into lists of underlying identifiers or preserved values.

For each key in kwargs: - Keys with value None or models.NOT_PROVIDED are omitted. - Iterable values (except str and bytes) are converted to lists where each item is resolved from manager-like objects to their identifier (or left unchanged if not resolvable). - Non-iterable values are wrapped into a single-item list after the same resolution. Returns a new mapping and preserves incoming keys exactly; it does not canonicalize <relation>_list to <relation>_id_list. Call split_many_to_many() first when canonical many-to-many keys are required. Dictionaries and generators are treated as iterables, so a dict normalizes its keys and a generator is consumed once.

Parameters:

Name Type Description Default
kwargs PayloadMapping

Mapping of field names to values which may be single items or iterables.

required

Returns:

Type Description
ManyValuePayload

A new mapping where each key maps to a list of resolved items suitable for multi-valued field assignment.

general_manager.interface.capabilities.core.utils.with_observability is a public helper for wrapping capability operations with optional observability hooks. Its full behavior is described in the Core Observability Utility section below.

general_manager.interface.bundles.calculation.CALCULATION_CORE_CAPABILITIES module-attribute

CALCULATION_CORE_CAPABILITIES = CapabilitySet(
    label="calculation_core",
    entries=(
        InterfaceCapabilityConfig(
            CalculationLifecycleCapability
        ),
        InterfaceCapabilityConfig(
            CalculationReadCapability
        ),
        InterfaceCapabilityConfig(
            CalculationQueryCapability
        ),
    ),
)

general_manager.interface.bundles.database.ORM_PERSISTENCE_CAPABILITIES module-attribute

ORM_PERSISTENCE_CAPABILITIES = CapabilitySet(
    label="orm_persistence_core",
    entries=(
        InterfaceCapabilityConfig(
            OrmPersistenceSupportCapability
        ),
        InterfaceCapabilityConfig(OrmLifecycleCapability),
        InterfaceCapabilityConfig(SoftDeleteCapability),
        InterfaceCapabilityConfig(OrmReadCapability),
        InterfaceCapabilityConfig(OrmValidationCapability),
        InterfaceCapabilityConfig(OrmHistoryCapability),
        InterfaceCapabilityConfig(OrmQueryCapability),
        InterfaceCapabilityConfig(
            LoggingObservabilityCapability
        ),
    ),
)

general_manager.interface.bundles.database.ORM_WRITABLE_CAPABILITIES module-attribute

ORM_WRITABLE_CAPABILITIES = CapabilitySet(
    label="orm_writable_core",
    entries=(
        *(entries),
        InterfaceCapabilityConfig(OrmMutationCapability),
        InterfaceCapabilityConfig(OrmCreateCapability),
        InterfaceCapabilityConfig(OrmUpdateCapability),
        InterfaceCapabilityConfig(OrmDeleteCapability),
    ),
)

general_manager.interface.bundles.database.EXISTING_MODEL_CAPABILITIES module-attribute

EXISTING_MODEL_CAPABILITIES = CapabilitySet(
    label="existing_model_core",
    entries=(
        *(entries),
        InterfaceCapabilityConfig(
            ExistingModelResolutionCapability
        ),
    ),
)

general_manager.interface.bundles.database.READ_ONLY_CAPABILITIES module-attribute

READ_ONLY_CAPABILITIES = CapabilitySet(
    label="read_only_core",
    entries=(
        InterfaceCapabilityConfig(
            OrmPersistenceSupportCapability
        ),
        InterfaceCapabilityConfig(
            ReadOnlyLifecycleCapability
        ),
        InterfaceCapabilityConfig(SoftDeleteCapability),
        InterfaceCapabilityConfig(OrmReadCapability),
        InterfaceCapabilityConfig(OrmValidationCapability),
        InterfaceCapabilityConfig(OrmHistoryCapability),
        InterfaceCapabilityConfig(OrmQueryCapability),
        InterfaceCapabilityConfig(
            LoggingObservabilityCapability
        ),
        InterfaceCapabilityConfig(
            ReadOnlyManagementCapability
        ),
    ),
)

general_manager.interface.bundles.remote_manager.REMOTE_MANAGER_CAPABILITIES module-attribute

REMOTE_MANAGER_CAPABILITIES = CapabilitySet(
    label="remote_manager",
    entries=(
        InterfaceCapabilityConfig(
            RequestLifecycleCapability
        ),
        InterfaceCapabilityConfig(RequestReadCapability),
        InterfaceCapabilityConfig(
            RequestValidationCapability
        ),
        InterfaceCapabilityConfig(
            RemoteManagerQueryCapability
        ),
        InterfaceCapabilityConfig(RequestCreateCapability),
        InterfaceCapabilityConfig(RequestUpdateCapability),
        InterfaceCapabilityConfig(RequestDeleteCapability),
        InterfaceCapabilityConfig(
            LoggingObservabilityCapability
        ),
    ),
)

general_manager.interface.bundles.request.REQUEST_CORE_CAPABILITIES module-attribute

REQUEST_CORE_CAPABILITIES = CapabilitySet(
    label="request_core",
    entries=(
        InterfaceCapabilityConfig(
            RequestLifecycleCapability
        ),
        InterfaceCapabilityConfig(RequestReadCapability),
        InterfaceCapabilityConfig(
            RequestValidationCapability
        ),
        InterfaceCapabilityConfig(RequestQueryCapability),
        InterfaceCapabilityConfig(
            LoggingObservabilityCapability
        ),
    ),
)

general_manager.interface.bundles.request.REQUEST_MUTATION_CAPABILITIES module-attribute

REQUEST_MUTATION_CAPABILITIES = CapabilitySet(
    label="request_mutation",
    entries=(
        InterfaceCapabilityConfig(RequestCreateCapability),
        InterfaceCapabilityConfig(RequestUpdateCapability),
        InterfaceCapabilityConfig(RequestDeleteCapability),
    ),
)

general_manager.interface.bundles.request.REQUEST_CAPABILITIES module-attribute

REQUEST_CAPABILITIES = REQUEST_CORE_CAPABILITIES

CapabilityName is the public literal set of supported capability identifiers. Interfaces use these stable string keys in _capabilities, _capability_handlers, capability_overrides, manifests, and capability registries. Capability is a runtime-checkable protocol for capability handler instances: a handler exposes a class-level name and implements setup(interface_cls) -> None and teardown(interface_cls) -> None. Both methods mutate the supplied interface class in place. Concrete implementations own their validation and error types; the protocol does not normalize exceptions and does not promise idempotency.

BaseCapability is the default base class for concrete capability handlers. It checks every name in required_attributes with hasattr(interface_cls, name); it does not call those attributes or validate their signatures. The dataclass has no instance fields or constructor options of its own. Successful setup() copies the interface class's current _capability_handlers mapping by converting it to a plain dict, or starts from an empty plain dict when no registry exists yet, registers the capability instance under its name, and writes the copied mapping back. teardown() uses the same plain-dict conversion, or starts from an empty mapping when no registry exists yet, removes that name if present, and writes the mapping back; repeated teardown is a no-op. Missing required attributes raise CapabilityBindingError with sorted missing names. The underlying missing-attribute formatter returns "missing required attributes: " for empty input, though setup() only calls it after at least one name is missing. Non-AttributeError failures from hasattr(), registry conversion, and class assignment propagate unchanged. Repeated setup replaces the handler currently stored for the same capability name. ReadCapability, CreateCapability, UpdateCapability, and DeleteCapability require get_data, create, update, and delete respectively. HistoryCapability and ValidationCapability both require get_attribute_types. NotificationCapability, SchedulingCapability, AccessControlCapability, and ObservabilityCapability are marker handlers with no additional requirements beyond registration.

CapabilityBindingError(capability_name, reason) is raised when a capability handler cannot attach to an interface class. The error subclasses RuntimeError, stores capability_name and reason unchanged as public attributes, and formats its message as Capability '<name>' could not be attached: <reason>. Empty and multiline reasons are preserved exactly in the attributes and formatted message. The exceptions module's public export list contains only CapabilityBindingError.

InterfaceCapabilityConfig(handler, options=None) is the public declarative entry used by Interface.configured_capabilities. handler is the capability class. options=None constructs it without keyword arguments; any supplied mapping, including an empty or otherwise falsey mapping, is copied to a plain dict at instantiate() time and expanded as keyword arguments. The config is frozen, but the original mapping is not copied until instantiation. Constructor errors and mapping-conversion errors propagate unchanged.

CapabilitySet(label, entries) names a reusable bundle of concrete InterfaceCapabilityConfig entries. The constructor accepts any iterable and stores entries as an immutable tuple attribute; it does not deep-copy or runtime-validate entry values beyond normal iteration. iter_capability_entries(entries) and flatten_capability_entries(entries) expand CapabilitySet values one level, preserve input order, do not deduplicate, and consume the supplied iterable once. iter_capability_entries() stays lazy for the outer iterable, while flatten_capability_entries() returns a tuple. They do not validate that handlers implement the capability protocol; invalid non-CapabilitySet runtime values are yielded or returned unchanged if callers bypass static typing. Iteration-time exceptions from the supplied iterable propagate unchanged. InterfaceBase performs capability protocol checks when it instantiates and binds configured capabilities. The configuration module's public export list is CapabilityConfigEntry, CapabilitySet, InterfaceCapabilityConfig, flatten_capability_entries, and iter_capability_entries.

CAPABILITY_CLASS_MAP is the default mapping from public CapabilityName values to built-in capability classes used by the legacy capability factory. CapabilityOverride is either a capability class or a zero-argument callable returning a capability instance. build_capabilities(interface_cls, names, overrides) consumes names once, preserves order, returns a mutable list, and creates duplicate instances for duplicate names. A non-None override value for a name takes precedence over CAPABILITY_CLASS_MAP, including for runtime names outside the static CapabilityName vocabulary. The current implementation accepts interface_cls for compatibility but does not inspect it or pass it to handlers. Unknown names without overrides raise KeyError("Unknown capability '<name>'"); iteration, mapping lookup, and handler construction errors propagate unchanged.

CapabilityRegistry is the in-memory registry used by manifest-driven capability builders to track resolved capability declarations and concrete capability instances per interface class. register(interface_cls, capabilities, replace=False) consumes capabilities exactly once into a temporary set before mutating internal state. Duplicate names collapse; replace=False merges into existing declarations; replace=True replaces the existing declaration, including with an empty set. Iteration errors propagate before the registry is changed. get(interface_cls) returns a defensive frozenset, or an empty frozenset for unregistered interfaces. bind_instances(interface_cls, capabilities) consumes concrete capability instances once into an ordered tuple before assignment and replaces only the instance binding for that interface. Declared names and concrete instances are independent: registering names does not clear instances, and binding instances does not register names. instances(interface_cls) returns the stored tuple or an empty tuple. snapshot() returns a MappingProxyType over a newly built mapping of interface classes to frozenset declarations; later registry mutations do not affect prior snapshots, and concrete instances are not included. The registry is process-local, has no locking, and trusts runtime values if callers bypass static typing.

general_manager.interface.manifests.capability_models.CapabilityPlan dataclass

Immutable manifest entry for one interface family.

CapabilityName is the public string-literal capability identifier type exported by general_manager.interface.capabilities. required and optional are normalized to frozenset values and duplicate capability names collapse. A capability may appear in both sets; manifest resolution and builder validation decide how to interpret that combination. flags maps runtime flag names to optional capability names, is copied to a plain dict, and is exposed through a read-only mapping proxy.

__post_init__

__post_init__()

Normalize required, optional, and flag mapping attributes.

Raises:

Type Description
TypeError

If required or optional cannot be iterated, if any capability name is unhashable, or if flags cannot be converted with dict(...).

general_manager.interface.manifests.capability_models.CapabilityConfig dataclass

Mutable runtime toggles for optional capability activation.

Capability names use the public CapabilityName string-literal type from general_manager.interface.capabilities. enabled and disabled are mutable sets consumed by ManifestCapabilityBuilder. enabled requests optional capabilities, while disabled removes optional capabilities after flag and manual enables have been validated. If the same optional name appears in both sets, disabled wins; manually enabling a non-optional name still raises in the builder even if that name is also disabled. flags stores arbitrary truth-tested values, not only booleans: is_flag_enabled() applies Python bool(...) coercion and treats missing flags as disabled.

__post_init__

__post_init__()

Normalize mutable containers owned by this config instance.

The config remains mutable after construction, but external set or mapping objects passed to the constructor are copied so later caller-side mutation does not affect builder resolution.

Raises:

Type Description
TypeError

If enabled or disabled cannot be iterated, if any capability name is unhashable, or if flags cannot be converted with dict(...).

is_flag_enabled

is_flag_enabled(flag_name)

Return whether flag_name is present with a truthy value.

Parameters:

Name Type Description Default
flag_name str

Flag key to check.

required

Returns:

Type Description
bool

True when the stored value is truthy, otherwise False. Missing

bool

flags return False.

general_manager.interface.manifests.capability_models.CapabilitySelection dataclass

Immutable result of resolving a plan against runtime config.

Capability names use the public CapabilityName string-literal type from general_manager.interface.capabilities. required, optional, and activated_optional are normalized to frozensets and duplicate capability names collapse. The model intentionally does not validate that activated optional names are present in optional; ManifestCapabilityBuilder owns that validation.

all property

all

Return required plus activated optional capability names.

Returns:

Type Description
frozenset[CapabilityName]

Fresh frozenset containing every required capability and every

frozenset[CapabilityName]

activated optional capability. Inactive optional names are excluded.

__post_init__

__post_init__()

Normalize all selection sets to immutable frozensets.

Raises:

Type Description
TypeError

If any field cannot be iterated or contains unhashable values.

CapabilityPlan(required=frozenset(), optional=frozenset(), flags={}) is the immutable manifest entry used by CapabilityManifest. required and optional are normalized to frozenset values, so duplicate capability names collapse. A name may appear in both sets; the model stores that state and leaves interpretation to manifest resolution and the builder. flags maps runtime flag names to capability names, is copied to a plain dict, and is exposed as a read-only mapping proxy. Iteration, hashing, and mapping-conversion errors propagate unchanged. All capability-name fields use the public CapabilityName string-literal type exported by general_manager.interface.capabilities.

CapabilityConfig(enabled=set(), disabled=set(), flags={}) is the mutable runtime toggle object passed to ManifestCapabilityBuilder.build(). The constructor copies supplied enabled/disabled sets and the flag mapping, then the instance remains mutable. Flag values are object-valued and truth-tested with Python bool(...); missing flags are disabled. enabled requests optional capabilities, while disabled removes optional capabilities after flag and manual enables have been validated. If the same optional name appears in both sets, disabled wins; manually enabling a non-optional name still raises in the builder even if the name is also disabled. CapabilitySelection(required, optional, activated_optional) is the immutable build result. It normalizes all three fields to frozenset values. Its all property returns required names plus activated optional names and excludes inactive optional names. The model does not validate that activated names are present in optional; the builder is the validation boundary.

general_manager.interface.manifests.capability_builder.ManifestCapabilityBuilder

Resolve and bind manifest-declared capabilities for interface classes.

The builder resolves a CapabilityManifest for one interface class, applies optional-capability configuration, creates handler instances in sorted capability-name order, binds them to the interface, and mirrors the final declaration plus concrete handlers into a CapabilityRegistry. It mutates the interface class by setting its capability selection, capability-name set, and handler mapping. If build fails during resolution, instantiation, attachment, or registry publication, the previous interface selection, names, and handlers are restored. Registry implementations own rollback for any registry-side state they mutate before raising.

registry property

registry

Return the registry receiving declarations and concrete handlers.

Returns:

Type Description
CapabilityRegistry

The CapabilityRegistry object supplied to the constructor, or the

CapabilityRegistry

fresh registry created by the builder.

__init__

__init__(*, manifest=None, registry=None)

Initialize the builder with manifest and registry dependencies.

Parameters:

Name Type Description Default
manifest CapabilityManifest | None

Manifest used to resolve interface classes. None selects the module default CAPABILITY_MANIFEST.

None
registry CapabilityRegistry | None

Registry that receives resolved declarations and concrete capability instances. None creates a fresh CapabilityRegistry for this builder.

None

build

build(interface_cls, *, config=None)

Resolve, instantiate, attach, and register capabilities.

The manifest is resolved for interface_cls, required capabilities are validated against the config, optional capabilities are activated by flags and manual enables, and disabled optional capabilities are removed. Capability instances are created from selection.all in sorted capability-name order using the interface's capability_overrides, then each handler is bound through InterfaceBase._bind_capability_handler. After successful binding, the registry replaces the interface's declared names and concrete handler tuple.

Parameters:

Name Type Description Default
interface_cls type[InterfaceBase]

Interface class to mutate and register.

required
config CapabilityConfig | None

Optional runtime configuration. None uses a default CapabilityConfig with no enabled, disabled, or flagged optional capabilities.

None

Returns:

Type Description
CapabilitySelection

The immutable selection that was attached to the interface.

Raises:

Type Description
ValueError

If a required capability is disabled, if a flag maps to a non-optional capability when enabled, or if a manual enable is not declared optional for the interface.

KeyError

If a selected capability has no default class and no override.

Exception

Exceptions from manifest resolution, config iterables or mappings, override lookup/call, capability construction, handler teardown/setup, startup-hook/system-check registration, or registry publication propagate unchanged. Failures restore the interface's prior capability selection, name set, and handler mapping. Registry implementations own rollback for registry-side state they mutate before raising.

ManifestCapabilityBuilder(manifest=None, registry=None) resolves a CapabilityManifest for one interface class and binds concrete capability handlers. manifest=None uses the module default manifest; registry=None creates a fresh CapabilityRegistry for the builder. The registry property returns that exact registry object.

build(interface_cls, config=None) resolves the manifest, rejects disabled required capabilities, activates optional capabilities from enabled flags and manual enables, removes disabled optional capabilities, creates handlers in sorted capability-name order using interface_cls.capability_overrides, binds each handler to the interface, then replaces the registry declaration and concrete handler tuple for that interface. A capability present in both enabled and disabled is disabled when it is optional; a non-optional manual enable still raises even if that name also appears in disabled. Unknown selected capability names raise KeyError; invalid optional selections raise ValueError; handler construction, setup/teardown, startup-hook registration, system-check registration, manifest, config, override, and registry errors propagate unchanged. If resolution, instantiation, or attachment fails before registry publication, or if registry publication itself raises, the builder restores the interface's previous selection, capability-name set, and handler mapping. Registry implementations own rollback for any registry-side state they mutate before raising.

with_observability(target, *, operation, payload, func) is the shared wrapper used by capability implementations that emit observability hooks. It is the only public export from general_manager.interface.capabilities.core.utils. The wrapper looks up target.get_capability_handler("observability") when that method exists. If the method is absent or returns None, func() is called directly and the payload is not copied. If a capability is present, the wrapper reads before_operation, after_operation, and on_error with getattr(..., None). Absent hook attributes and attributes set to None are ignored; non-None values are called as hooks, so non-callable values fail when called. It shallow-copies payload into one plain dict after capability lookup and hook-attribute lookup, then passes the same copy to every hook for that invocation. Hook order is before_operation, then func(), then after_operation on success, or on_error when func() raises. before_operation exceptions prevent func() from running; on_error exceptions replace the original func() exception; after_operation exceptions replace the successful result. Exceptions from capability lookup, hook-attribute lookup, payload conversion, hooks, and func() propagate unchanged.

CALCULATION_CORE_CAPABILITIES is the reusable bundle installed by CalculationInterface. Its label is "calculation_core" and its entries are CalculationLifecycleCapability, CalculationReadCapability, and CalculationQueryCapability, in that order. The lifecycle entry publishes the "calculation_lifecycle" capability name used by CalculationInterface.lifecycle_capability_name; the read capability backs attribute access and get_data(), and the query capability backs all(), filter(), and exclude(). The bundle intentionally does not include create, update, delete, or ORM capabilities.

ORM_PERSISTENCE_CAPABILITIES is the shared ORM persistence bundle. Its label is "orm_persistence_core" and its ordered entries install ORM support, ORM lifecycle, soft-delete handling, ORM read, validation, history, query, and logging observability capabilities. ORM_WRITABLE_CAPABILITIES has label "orm_writable_core", starts with the persistence entries in the same order, then adds mutation, create, update, and delete capabilities; this is the bundle installed by DatabaseInterface. EXISTING_MODEL_CAPABILITIES has label "existing_model_core", starts with the writable entries in the same order, then adds ExistingModelResolutionCapability; this is the bundle installed by ExistingModelInterface. READ_ONLY_CAPABILITIES has label "read_only_core" and installs ORM support, read-only lifecycle, soft-delete handling, ORM read, validation, history, query, logging observability, and read-only management capabilities, in that order. The read-only lifecycle capability intentionally publishes the shared "orm_lifecycle" capability name so OrmInterfaceBase lifecycle lookup continues to work. The bundle intentionally omits mutation, create, update, and delete capabilities.

REMOTE_MANAGER_CAPABILITIES is the bundle installed by RemoteManagerInterface. Its label is "remote_manager" and its ordered entries install request lifecycle, request read, request validation, remote manager query, request create, request update, request delete, and logging observability capabilities. RemoteManagerQueryCapability publishes the shared "query" capability name and is also present in RemoteManagerInterface.capability_overrides so request query behavior is replaced by the RemoteAPI-aware query capability.

REQUEST_CORE_CAPABILITIES is the bundle installed by RequestInterface. Its label is "request_core" and its ordered entries install request lifecycle, request read, request validation, request query, and logging observability capabilities. REQUEST_CAPABILITIES is an alias for REQUEST_CORE_CAPABILITIES kept for callers that need the default request-interface bundle. REQUEST_MUTATION_CAPABILITIES has label "request_mutation" and contains request create, request update, and request delete capabilities, in that order. RequestInterface does not install the mutation bundle wholesale by default; during subclass configuration it adds the matching create, update, and delete capability entries only when Meta.create_operation, Meta.update_operation, or Meta.delete_operation is declared and the handler is not already present.

general_manager.interface.capabilities.orm

ORM-backed capability implementations.

HistoryNotSupportedError

Bases: RuntimeError

Raised when historical lookups are requested but not supported.

The error message is "{interface_name} does not support historical queries.".

OrmHistoryCapability dataclass

Bases: BaseCapability

Lookup historical records for ORM-backed interfaces.

get_historical_record

get_historical_record(
    interface_cls, instance, search_date=None
)

Retrieve the latest historical record for instance at search_date.

The lookup prefers instance.history when the object exposes a django-simple-history manager. Otherwise it falls back to interface_cls._model.history and derives the primary key from instance.pk, then instance.id, then instance.identification["id"]. A configured database alias is applied before filtering.

Parameters:

Name Type Description Default
interface_cls type['OrmInterfaceBase[models.Model]']

ORM interface class used to resolve the model history manager and capability settings.

required
instance object

Model-like or manager-like object to identify in the history table.

required
search_date datetime | None

Optional cutoff date; when provided, only records with history_date <= search_date are considered.

None

Returns:

Type Description
Model | None

Historical model instance, or None when no identifier, history

Model | None

manager, or matching historical row is available.

get_history_queryset_for_manager

get_history_queryset_for_manager(interface_cls, manager)

Return the history queryset scoped to the manager instance's primary key.

The target identifier is derived from manager.pk, then manager.id, then mapping-like manager.identification["id"]. The lookup key defaults to "id" and uses the interface model primary-key field name when it is available as a string. A configured database alias is applied before the filtered queryset is returned.

Parameters:

Name Type Description Default
interface_cls type['OrmInterfaceBase[models.Model]']

ORM interface whose underlying model provides the history manager.

required
manager object

Manager-like object exposing pk, id, or identification["id"] for the target row.

required

Returns:

Type Description
QuerySet[Model]

History queryset limited to records for the target object.

Raises:

Type Description
HistoryNotSupportedError

If the interface does not expose a history manager or the manager cannot be scoped to a primary key.

get_historical_queryset

get_historical_queryset(interface_cls, search_date)

Retrieve a queryset representing the historical state as of the given date.

A configured database alias is applied before calling history.as_of(search_date).

Parameters:

Name Type Description Default
interface_cls type['OrmInterfaceBase[models.Model]']

ORM interface whose underlying model provides the historical manager.

required
search_date datetime

Cutoff datetime for historical snapshot lookup.

required

Returns:

Type Description
QuerySet[Model]

QuerySet representing the state at search_date.

Raises:

Type Description
HistoryNotSupportedError

If the model does not expose a history manager.

get_historical_record_by_pk

get_historical_record_by_pk(interface_cls, pk, search_date)

Retrieve the latest historical record for primary key pk at search_date.

The lookup uses the model's history manager, applies any configured database alias, filters by the model primary-key field and history_date <= search_date, orders by history_date, and returns the last row.

Parameters:

Name Type Description Default
interface_cls type['OrmInterfaceBase[models.Model]']

ORM interface whose underlying model provides the historical manager.

required
pk object

Primary key of the target model record.

required
search_date datetime | None

Cutoff datetime. If None, no history query is run.

required

Returns:

Type Description
Model | None

Historical model instance, or None when search_date is

Model | None

None, the model has no history manager, or no row matches.

OrmLifecycleCapability dataclass

Bases: BaseCapability

Handle creation and configuration of ORM-backed interfaces.

pre_create

pre_create(*, name, attrs, interface, base_model_class)

Prepare ORM model, concrete interface class, and factory before the parent class is created.

Creates a Django model class from fields discovered on the provided interface (applying any Meta configuration such as soft-delete and rules), finalizes its metadata, builds a concrete interface subclass bound to that model, and installs a Factory class and Interface class into the provided attrs mapping.

Parameters:

Name Type Description Default
name str

The name to use for the generated model and factory.

required
attrs dict[str, object]

The attribute dict for the class being created; will be updated with "Interface", "Factory", and "_interface_type".

required
interface type[OrmInterfaceBase[Model]]

The interface class that defines model fields and optional Meta/Factory configuration.

required
base_model_class type[GeneralManagerBasisModel]

Base model class to derive the generated model from (may be adjusted for soft-delete support).

required

Returns:

Type Description
tuple[dict[str, object], type['OrmInterfaceBase[models.Model]'], type[GeneralManagerBasisModel]]

tuple[dict[str, object], type[OrmInterfaceBase[models.Model]], type[GeneralManagerBasisModel]]: - The possibly-modified attrs mapping. - The concrete interface subclass bound to the generated model. - The generated Django model class.

Raises:

Type Description
Exception

Lifecycle setup errors are not wrapped. Invalid Django model bases or fields, invalid nested Meta attributes, invalid Factory definitions, rule setup errors, and custom field discovery errors propagate from Django, factory_boy, rule construction, or the custom field implementation that raised them.

post_create

post_create(*, new_class, interface_class, model)

Attach the created interface class and model to each other and assign ORM managers to the new class.

This function links the generated interface and model to the newly created class by setting the interface's parent class and the model's general manager class. It also obtains and assigns the default manager to new_class.objects, and if soft-delete is enabled for the interface, assigns an all_objects manager that includes inactive/soft-deleted records.

Parameters:

Name Type Description Default
new_class type

The class that was just created for the interface (the concrete manager/interface class).

required
interface_class type[OrmInterfaceBase]

The concrete interface subclass bound to the model.

required
model type[GeneralManagerBasisModel] | None

The ORM model class created for the interface, or None if no model was generated.

required

describe_custom_fields

describe_custom_fields(model)

List Django Field names declared on the given model and generate ignore markers for each field's value and unit.

Parameters:

Name Type Description Default
model type[Model] | Model

Model class or instance to inspect for attributes that are instances of Django models.Field.

required

Returns:

Name Type Description
field_names list[str]

Names of discovered model fields (uses the field's name attribute if present, otherwise the attribute name).

ignore list[str]

Generated ignore markers in the form <field_name>_value and <field_name>_unit for each discovered field.

OrmCreateCapability dataclass

Bases: BaseCapability

Create new ORM instances using capability-driven configuration.

create

create(interface_cls, *args, **kwargs)

Create a new ORM model instance from the provided payload and persist it with optional creator and history metadata.

Parameters:

Name Type Description Default
interface_cls OrmInterfaceClass

Interface class that defines the target model and capabilities.

required
*args object

Ignored positional arguments kept for manager/capability signature compatibility. Passing positional values has no effect.

()
**kwargs object

Field values used to construct the instance. Reserved metadata keys are creator_id and history_comment; all other keys are validated as model fields/attributes or many-to-many aliases such as <relation>_id_list.

{}

Returns:

Type Description
MutationResult

Capability-level result dictionary containing the new instance

MutationResult

primary key as {"id": pk}. The GeneralManager layer consumes this

MutationResult

result and returns the public manager instance from

MutationResult

Manager.create(...).

Raises:

Type Description
UnknownFieldError

If the normalized payload contains unknown keys.

InvalidFieldValueError

If field assignment raises ValueError.

InvalidFieldTypeError

If field assignment raises TypeError.

Exception

Validation, transaction, save, many-to-many, change-reason, history actor, and observability errors are not wrapped.

OrmDeleteCapability dataclass

Bases: BaseCapability

Delete (or deactivate) ORM instances.

delete

delete(interface_instance, *args, **kwargs)

Delete or deactivate the provided ORM interface instance according to the interface's deletion policy.

If soft-delete is enabled for the interface, the instance is marked inactive (requires the instance to implement SupportsActivation) and saved with an optional history comment indicating deactivation. If soft-delete is not enabled, the instance is hard-deleted inside a database transaction using the support-provided database alias when available; the function attempts to set changed_by_id from creator_id and attaches the provided history comment as the change reason before deletion.

Parameters:

Name Type Description Default
interface_instance OrmInterfaceInstance

The interface-wrapped model instance to remove.

required
*args object

Ignored positional arguments kept for manager/capability signature compatibility. Passing positional values has no effect.

()
**kwargs object

Reserved metadata keys are creator_id and history_comment; other keys are currently ignored by this capability.

{}

Returns:

Name Type Description
MutationResult MutationResult

Capability-level dictionary containing the primary key under the key "id". The GeneralManager layer consumes this result, invalidates the public manager instance for later field reads, and returns according to the manager-level delete contract.

Raises:

Type Description
MissingActivationSupportError

If soft-delete is enabled but the instance does not implement activation support.

Exception

Row lookup, history actor lookup, transaction, delete, cache invalidation, change-reason, save, and observability errors are not wrapped.

OrmMutationCapability dataclass

Bases: BaseCapability

Common utilities to modify ORM instances.

assign_simple_attributes

assign_simple_attributes(interface_cls, instance, kwargs)

Apply simple (non-relational) attribute updates to a Django model instance.

Parameters:

Name Type Description Default
instance Model

The model instance to modify.

required
kwargs MutationPayload

Mapping of field names to values; entries with the sentinel NOT_PROVIDED are ignored.

required

Returns:

Type Description
Model

models.Model: The same instance after attribute assignment.

Raises:

Type Description
InvalidFieldValueError

If assigning a value raises a ValueError for a field.

InvalidFieldTypeError

If assigning a value raises a TypeError for a field.

save_with_history

save_with_history(
    interface_cls, instance, *, creator_id, history_comment
)

Persist the model instance while recording creator metadata and an optional change reason.

Performs the save inside an atomic transaction using the interface's configured database alias when available, sets changed_by_id on the instance if the attribute exists, runs model validation, and attaches a change reason after a successful save when history_comment is provided.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The interface class used to resolve support capabilities and configuration.

required
instance Model

The Django model instance to validate and save.

required
creator_id int | None

Identifier of the user or process responsible for the change; assigned to instance.changed_by_id when supported.

required
history_comment str | None

Optional comment describing the change; attached as a change reason after save when provided.

required

Returns:

Name Type Description
object object

The primary key (pk) of the saved instance. Django primary keys may be non-integer values.

Raises:

Type Description
InvalidFieldValueError

From prior assignment helpers.

Exception

Database-alias lookup, history actor lookup, validation, transaction, save, change-reason, and observability errors are not wrapped.

apply_many_to_many

apply_many_to_many(
    interface_cls,
    instance,
    *,
    many_to_many_kwargs,
    history_comment
)

Apply many-to-many updates to a model instance's related fields.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

Interface class owning the model (used for observability).

required
instance Model

The model instance whose relationships will be updated.

required
many_to_many_kwargs ManyToManyPayload

Mapping of normalized many-to-many payload keys to related values. Keys are still expected to use <relation>_id_list; the suffix is removed to derive the relation manager name before calling .set(values).

required
history_comment str | None

Optional change reason to attach to the instance's history after updates.

required

Returns:

Type Description
Model

models.Model: The same model instance after its many-to-many relations have been updated.

Raises:

Type Description
AttributeError

If the derived relation manager does not exist.

Exception

Relation .set(), change-reason, and observability errors are not wrapped.

OrmUpdateCapability dataclass

Bases: BaseCapability

Update existing ORM instances.

update

update(interface_instance, *args, **kwargs)

Update the model instance referenced by the given interface instance with the provided payload, persisting changes and recording history and many-to-many updates.

Parameters:

Name Type Description Default
interface_instance OrmInterfaceBase

Interface wrapper whose pk identifies the target model instance to update.

required
*args object

Ignored positional arguments kept for manager/capability signature compatibility. Passing positional values has no effect.

()
**kwargs object

Field values to apply; reserved metadata keys are creator_id and history_comment. Other keys are validated as model fields/attributes or many-to-many aliases such as <relation>_id_list.

{}

Returns:

Name Type Description
MutationResult MutationResult

Capability-level mapping containing the saved primary key as {"id": pk}. The GeneralManager layer consumes this result, refreshes the public manager state, and returns the same manager instance from manager.update(...).

Raises:

Type Description
UnknownFieldError

If the normalized payload contains unknown keys.

InvalidFieldValueError

If field assignment raises ValueError.

InvalidFieldTypeError

If field assignment raises TypeError.

Exception

Row lookup, validation, transaction, save, many-to-many, cache invalidation, change-reason, history actor, and observability errors are not wrapped.

OrmValidationCapability dataclass

Bases: BaseCapability

Validate and normalize payloads used by mutation capabilities.

normalize_payload

normalize_payload(interface_cls, *, payload)

Normalize and split a mutation payload into simple field values and many-to-many relation values.

Parameters:

Name Type Description Default
interface_cls type

The interface class whose schema/normalizer should be used.

required
payload MutationPayload

Raw input payload to validate and normalize.

required

Returns:

Name Type Description
tuple tuple[MutationPayload, ManyToManyPayload]
  • MutationPayload: Normalized simple field values suitable for direct assignment.
  • ManyToManyPayload: Normalized many-to-many relation values keyed by <relation>_id_list.

Raises:

Type Description
UnknownFieldError

If a payload key is not a known model field or attribute.

Exception

Payload-normalizer and observability errors are not wrapped.

OrmPersistenceSupportCapability dataclass

Bases: BaseCapability

Expose shared helpers to work with Django ORM models.

get_database_alias

get_database_alias(interface_cls)

Retrieve the database alias declared on an ORM interface class.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The ORM interface class to inspect for a database attribute.

required

Returns:

Type Description
str | None

str | None: The value of the class attribute database if present, otherwise None.

get_manager

get_manager(interface_cls, *, only_active=True)

Obtain the Django manager for the interface's model, selecting between the active (soft-delete filtered) or all manager and honoring the interface's database alias.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

Interface class providing the Django model and optional metadata.

required
only_active bool

If True (default), return the active manager; if False, return the unfiltered/all manager.

True

Returns:

Type Description
Manager[Model]

django.db.models.Manager: The resolved manager for the interface's model.

Notes

This function also caches the resolved active manager onto interface_cls._active_manager.

get_queryset

get_queryset(interface_cls)

Retrieve an active queryset for the interface's model.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The interface class whose underlying Django model will be queried.

required

Returns:

Type Description
QuerySet[Model]

models.QuerySet: A Django QuerySet containing the model's active records.

get_payload_normalizer

get_payload_normalizer(interface_cls)

Return a PayloadNormalizer configured for the interface's Django model.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

Interface class providing the _model attribute.

required

Returns:

Name Type Description
PayloadNormalizer PayloadNormalizer

A normalizer instance bound to the interface's Django models.Model.

get_field_descriptors

get_field_descriptors(interface_cls)

Get or build cached field descriptors for the given ORM interface class.

If descriptors are not already present on the interface class, this populates and caches them on the class as _field_descriptors.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The ORM interface class to inspect.

required

Returns:

Type Description
dict[str, FieldDescriptor]

dict[str, FieldDescriptor]: Mapping of field names to their FieldDescriptor.

resolve_many_to_many

resolve_many_to_many(
    interface_instance, field_call, field_name
)

Resolve a many-to-many relationship for an interface instance and return a queryset of the related target records, using historical snapshots when applicable.

If the relation's through/model is a HistoricalChanges subclass, the function: - Locates the corresponding related attribute on the historical model and collects related IDs. - If the target model has no history support or the interface instance has no search date, returns the live target model queryset filtered by those IDs. - If the target model supports history and a search date is present, returns the historical snapshot queryset as of that date filtered by those IDs. If the target field or related attribute cannot be resolved, an empty queryset for the appropriate model is returned. Historical reads fail closed when either the through relation or target model has no usable history; live reads return the original related manager's queryset.

Parameters:

Name Type Description Default
interface_instance OrmInterfaceBase

The interface wrapper containing the model instance and optional search date.

required
field_call str

Attribute name on the instance to access the related manager (e.g., the many-to-many manager accessor).

required
field_name str

Field name on the interface's model corresponding to the relation target.

required

Returns:

Type Description
QuerySet[Model]

models.QuerySet[models.Model]: A queryset of the related target records or their historical snapshots when applicable.

Raises:

Type Description
AttributeError

If field_call is not a related-manager attribute on the wrapped ORM instance.

FieldDoesNotExist

If field_name is not a field on the interface model.

OrmQueryCapability dataclass

Bases: BaseCapability

Expose DatabaseBucket operations via the capability configuration.

filter

filter(interface_cls, **kwargs)

Builds a DatabaseBucket representing a queryset filtered by the provided lookup kwargs.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

Interface class whose model and configuration determine queryset construction.

required
**kwargs object

Lookup expressions passed through the payload normalizer; may include include_inactive to include inactive/soft-deleted records and search_date to scope results to a historical snapshot.

{}

Returns:

Name Type Description
DatabaseBucket DatabaseBucket['GeneralManager']

A container holding the resulting Django queryset (cast to the model's queryset type), the interface's parent class, and the normalized filter kwargs.

exclude

exclude(interface_cls, **kwargs)

Builds a DatabaseBucket representing a queryset that excludes records matching the provided filter criteria.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The ORM interface class whose model and metadata are used to construct the queryset.

required
**kwargs object

Filter lookup expressions to apply as exclusion criteria. May include include_inactive (bool) to control whether inactive/soft-deleted records are considered and search_date to scope results historically.

{}

Returns:

Name Type Description
DatabaseBucket DatabaseBucket['GeneralManager']

A container holding the resulting Django queryset, the interface's parent class, and the normalized filter dictionary used for the exclusion.

OrmReadCapability dataclass

Bases: BaseCapability

Fetch ORM instances (or historical snapshots) for interface instances.

get_data

get_data(interface_instance)

Retrieve the current model instance or a historical snapshot for the given ORM interface instance.

Parameters:

Name Type Description Default
interface_instance OrmInterfaceBase

Interface wrapper containing the primary key (pk) and optional _search_date used to request a historical snapshot.

required

Returns:

Type Description
Model

The live model instance or a historical record corresponding to interface_instance.pk (type depends on the model/history handler).

Raises:

Type Description
DoesNotExist

If no matching live instance or historical record exists.

get_attribute_types

get_attribute_types(interface_cls)

Return a mapping of field names to copies of their field descriptor metadata.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The ORM interface class whose field descriptors will be queried.

required

Returns:

Type Description
dict[str, AttributeTypedDict]

dict[str, AttributeTypedDict]: A dict mapping each field name to a shallow copy of that field's metadata dictionary.

get_attributes

get_attributes(interface_cls)

Return a mapping of field names to their accessor callables for the given ORM interface class.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The interface class whose model field descriptors will be used.

required

Returns:

Type Description
dict[str, Callable[[OrmInterfaceInstance], object]]

dict[str, Callable[[OrmInterfaceBase[models.Model]], object]]: A dictionary mapping each field name to a callable that, given an instance, returns that field's value.

get_field_type

get_field_type(interface_cls, field_name)

Determine the effective type associated with a model field.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

Interface class whose underlying Django model contains the field.

required
field_name str

Name of the field on the model.

required

Returns:

Name Type Description
type type[object]

The Django field class for stored model fields, the related

type[object]

model's _general_manager_class for managed relations, or the

type[object]

descriptor metadata "type" value for synthetic interface fields.

Raises:

Type Description
FieldDoesNotExist

If the field is not present on the model and no synthetic descriptor exists for field_name.

SoftDeleteCapability

Bases: BaseCapability

Track whether soft delete behavior should be applied.

__init__

__init__(enabled=False)

Initialize the soft-delete capability with a default enabled state.

Parameters:

Name Type Description Default
enabled bool

Initial enabled state for soft-delete; True to enable, False to disable.

False

setup

setup(interface_cls)

Initialize the capability's soft-delete state for the given interface class.

Determines the default enabled state in this order: 1) use interface_cls._soft_delete_default if present; 2) else use interface_cls._model._meta.use_soft_delete if available; 3) otherwise fall back to the capability's current enabled value. Sets self.enabled to the resulting boolean and then calls the base setup with the same interface class.

Parameters:

Name Type Description Default
interface_cls type[InterfaceBase]

The interface class being configured.

required

is_enabled

is_enabled()

Indicates whether soft-delete behavior is enabled for this capability.

Returns:

Name Type Description
bool bool

True if soft-delete is enabled, False otherwise.

set_state

set_state(enabled)

Set whether soft-delete is enabled for this capability.

Parameters:

Name Type Description Default
enabled bool

True to enable soft-delete behavior, False to disable it.

required

update_change_reason

update_change_reason(instance, reason)

Update the latest history row on the model instance's database alias.

get_support_capability

get_support_capability(interface_cls)

Resolve and return the "orm_support" capability instance for the given interface class.

Parameters:

Name Type Description Default
interface_cls type

The ORM interface class to query for the capability.

required

Returns:

Name Type Description
OrmPersistenceSupportCapability OrmPersistenceSupportCapability

The resolved persistence support capability instance.

is_soft_delete_enabled

is_soft_delete_enabled(interface_cls)

Determine whether soft-delete behavior is enabled for the given interface class.

Checks the interface's soft_delete capability first, then the model's _meta.use_soft_delete, and finally the interface's _soft_delete_default.

Parameters:

Name Type Description Default
interface_cls type[OrmInterfaceBase]

The interface class to evaluate.

required

Returns:

Name Type Description
bool bool

True if soft-delete is enabled for the interface class, False otherwise.

OrmLifecycleCapability is the class-creation capability behind generated ORM interfaces such as DatabaseInterface and read-only variants. Its pre_create(name=..., attrs=..., interface=..., base_model_class=...) hook collects Django models.Field attributes declared on the interface. The class creation path reaches that logic through OrmInterfaceBase.handle_custom_fields(); the lifecycle capability method that performs the inspection is describe_custom_fields(model). The hook extracts Meta.use_soft_delete and Meta.rules, builds a generated Django model class, builds a concrete interface subclass bound to that model, and installs attrs["Interface"], attrs["Factory"], and attrs["_interface_type"]. attrs["Factory"] may provide a custom factory definition; otherwise the nested interface.Factory definition is used. The returned tuple is the updated attrs mapping, the concrete OrmInterfaceBase[models.Model] subclass, and the generated model class. Extracting Meta.use_soft_delete and Meta.rules mutates the original nested Meta class by deleting those two attributes before the remaining Meta attributes are attached to the generated Django model.

post_create(new_class=..., interface_class=..., model=...) wires the created manager class back into the interface and model by setting interface_class._parent_class, model._general_manager_class, and the manager objects exposed as new_class.objects. When soft delete is enabled it also sets new_class.all_objects to a manager that includes inactive rows. A None model is a no-op for lifecycle compatibility.

OrmPersistenceSupportCapability centralizes ORM support helpers used by read, query, history, and mutation capabilities. get_database_alias() reads the interface database class attribute. get_manager(interface_cls, only_active=True) returns the selected Django manager, honoring the database alias and soft-delete state, and caches the active manager on the interface. get_queryset() returns get_manager(..., only_active=True).all(). get_payload_normalizer() binds a PayloadNormalizer to the interface model. get_field_descriptors() builds and caches descriptor metadata and accessors. Descriptor metadata is generated from concrete model fields, foreign keys, reverse one-to-one relations, many-to-many relations, and reverse one-to-many relations. Each descriptor contains metadata keys type, default, is_required, is_editable, and is_derived. Big-integer-like fields may add graphql_scalar. Direct and collection relations also add relation_kind="direct" or "collection" and filter_lookup when the relation can be used as a lookup root. Collection relations are exposed as <name>_list attributes and resolve to the related manager/queryset or to a filtered GeneralManager class when the related model has one. Collection descriptor names prefer the declared relation or related model name, then the Django accessor fallback, then relation-field-derived fallback names; if every candidate collides, DuplicateFieldNameError is raised. Descriptor construction expects the interface class to expose _model as a Django model class. A custom collection resolver is called with positional arguments (interface_instance, field_call, field_name), and resolver exceptions are not wrapped. GeneralManager-backed collection accessors raise MissingRelatedFieldsError only when no explicit relation lookup was supplied and no related field can be found at access time; multiple discovered related fields are all used as filter constraints. resolve_many_to_many() returns a related queryset for a many-to-many accessor; when the relation points through simple-history rows and the interface has a historical search_date, it returns the target history queryset as of that date, otherwise it returns live target rows filtered by related ids. Missing target relation metadata returns an empty queryset rather than raising. Invalid many-to-many accessor names raise AttributeError, and invalid interface model field names raise Django's FieldDoesNotExist. A dated relation read fails with HistoricalReadNotSupportedError (chained from HistoryNotSupportedError) when either membership history or target-row history is unavailable; it never falls back to current relation data. This remains true inside the scalar historical lookup buffer: a source row may be hydrated from the live table, but its many-to-many membership is resolved from the source history row at the effective date. Equal history_date values are broken by greatest history_id for both source and related rows.

Historical through-table columns are resolved from the concrete ManyToManyField source and reverse field metadata, including explicit through_fields; this preserves direction for asymmetric self-relations and custom through models with multiple foreign keys to the same model. Configured database aliases are applied independently to source membership and target history queries. When both querysets use the same alias, membership remains a lazy SQL subquery. A cross-alias relation instead materializes the membership ID list before querying target history because Django cannot execute a correct cross-database subquery.

Generated DatabaseInterface models register declared many-to-many fields with django-simple-history. Deployments must provision the resulting Historical<Model>_<field> through tables using the project's normal Django schema and migration workflow. Membership history is reliable only for changes recorded after that schema is rolled out: pre-rollout membership cannot be reconstructed or backfilled from scalar history alone. A generated relation whose custom through model is still an unresolved string during owner-model creation is not auto-registered for history; define and track that through model explicitly if its membership must support historical reads.

OrmReadCapability.get_data(interface_instance) returns the live model row for pk or, when search_date is older than the interface historical_lookup_buffer_seconds, the matching historical row. It caches reads inside the active calculation run using interface class, primary key, database alias, active/all manager choice, and search date. Missing rows propagate the generated model's DoesNotExist.

OrmHistoryCapability is the history helper used by ORM read/query support. get_historical_record(interface_cls, instance, search_date=None) resolves the primary key from instance.pk, then instance.id, then instance.identification["id"]; it prefers instance.history when present, otherwise falls back to interface_cls._model.history. When search_date is provided it filters with history_date__lte=search_date, orders by history_date and history_id, applies any configured database alias, and returns the latest historical model row or None. get_history_queryset_for_manager() returns the model history queryset scoped to a manager-like object's primary key and raises HistoryNotSupportedError when the model has no history manager or the manager cannot be identified; it applies any configured database alias before returning the filtered queryset. get_historical_queryset(interface_cls, search_date) applies any configured database alias and selects the latest non-deletion history row per object at or before search_date, using history_id to break same-timestamp ties. It raises HistoryNotSupportedError when history is unavailable. get_historical_record_by_pk() filters id=pk, history_date__lte=search_date and returns None when search_date is None, history is unavailable, or no row matches.

OrmQueryCapability.filter() and exclude() normalize payloads through the ORM payload normalizer, translate snake_case reverse-relation aliases, honor include_inactive, and accept search_date as either date or datetime. Dates are converted to midnight datetimes and then normalized through OrmInterfaceBase.normalize_search_date(). Invalid search_date inputs raise SearchDateInputError before normalization, and custom normalizers that return non-datetimes raise SearchDateNormalizationError. The visible InvalidSearchDateTypeError is a compatibility exception for custom validators that want to raise a message-bearing type; the built-in query path uses the two more specific errors above. Historical querysets require the history capability; otherwise HistoryNotSupportedError is raised. Ambiguous reverse aliases raise AmbiguousReverseFilterAliasError.

OrmReadCapability.get_field_type(name) returns a type object: the Django field class for stored fields, the related manager class for GeneralManager-backed relations, or the synthetic descriptor metadata "type" value. Unknown names raise Django's FieldDoesNotExist.

DjangoManagerSelector(model, database_alias, use_soft_delete, cached_active=None) is the public ORM utility that chooses Django managers for ORM-backed capability reads. active_manager() returns the model default manager when soft delete is disabled or when the model exposes an all_objects attribute by presence check; otherwise it reuses cached_active as-is or creates and caches a lightweight manager whose queryset filters is_active=True. all_manager() returns the all_objects attribute value only when soft delete is enabled and the attribute exists; otherwise it returns the default manager. The selector does not validate that all_objects or cached_active is a manager or belongs to model. A truthy database_alias rebinds the selected source manager through manager.db_manager(alias) on each call, while None and "" leave the original manager unchanged. The selector caches only the unaliased generated or caller-supplied active-manager source, not the aliased result. The generated active manager starts from the model default manager queryset and preserves aliases applied through db_manager(). The selector does not query the database by itself and has no global cache. Missing or malformed manager attributes and db_manager() failures propagate unchanged at the point the selector reads or uses them.

discard_orm_instance_cache(interface_cls, pk) clears cached ORM reads for one interface class and primary key inside the active calculation run. It is a no-op when no calculation run context is active and returns None.

OrmMutationCapability owns shared write helpers. assign_simple_attributes() sets normalized non-many-to-many values on a Django model instance, skips models.NOT_PROVIDED, wraps assignment ValueError as InvalidFieldValueError, and wraps assignment TypeError as InvalidFieldTypeError. save_with_history() sets _history_user for simple-history when the model does not expose changed_by, sets changed_by_id when the model has that field, runs full_clean(), saves inside an atomic transaction using the interface database alias when configured, returns the saved primary key, and applies history_comment with simple-history after the save. apply_many_to_many() expects normalized <relation>_id_list entries, strips the suffix to find the relation manager, calls .set(values), and applies the history comment again after relation updates.

OrmCreateCapability.create(interface_cls, **payload) is the capability-level implementation behind manager creation. Positional arguments are accepted only for signature compatibility and are ignored. The payload may contain reserved metadata keys creator_id and history_comment; other keys are validated as model fields/attributes or many-to-many aliases such as <relation>_id_list. The capability removes the metadata keys, validates and normalizes the remaining payload through the validation/support normalizer, creates the model instance, saves it, and applies many-to-many updates in one alias-aware transaction before returning {"id": pk}. Validation, save, history-reason, relation, and transaction errors propagate and roll back that unit. The GeneralManager layer consumes that result and returns the public manager instance from Manager.create(...).

OrmUpdateCapability.update() loads the target row by pk with inactive rows included, ignores positional arguments, applies the same normalization/save/many-to-many transaction, discards the run-scoped ORM read cache only after that transaction succeeds, and returns the capability result {"id": pk}. Inside a caller-owned transaction on the same alias, ORM reads bypass the run-scoped identity cache so uncommitted rows are not published into it. After rollback, callers should reconstruct any in-place-updated manager from its ID. The GeneralManager layer consumes that result, refreshes the public manager state, and returns the same manager instance from manager.update(...).

OrmDeleteCapability.delete() loads the row with inactive rows included and ignores positional arguments. It accepts only the reserved metadata keys creator_id and history_comment; other keyword arguments are currently ignored by this capability. With soft delete enabled it requires activation support, sets is_active=False, saves with a deactivation history comment, clears the read cache, and returns {"id": pk}. Without soft delete it sets history actor metadata, applies a deletion change reason, hard-deletes in an atomic transaction using the configured database alias, clears the read cache, and returns {"id": pk}. The GeneralManager layer consumes that result and invalidates the public manager instance for later field reads. Missing activation support raises MissingActivationSupportError; queryset .get(), validation, transaction, delete, many-to-many, history, cache invalidation, and observability errors propagate unchanged.

OrmValidationCapability.normalize_payload() validates payload keys, splits many-to-many values, normalizes manager-valued foreign keys to identifiers, and returns (simple_payload, many_to_many_payload). The many-to-many payload keeps <relation>_id_list keys after normalization; apply_many_to_many() strips that suffix before resolving the relation manager. MutationPayload is dict[str, object], ManyToManyPayload is dict[str, list[object]], and MutationResult is dict[str, object] because primary keys and payload values may be non-integer and heterogeneous. Unknown fields raise UnknownFieldError from the payload normalizer.

PayloadNormalizer is the model-bound helper used by ORM query and mutation capabilities. normalize_filter_kwargs(kwargs) returns a new mapping and unwraps manager-valued filter values to their underlying ORM instance when one is cached on the manager interface, otherwise to identification["id"]. Here "manager-valued" means an actual GeneralManager instance. If the manager has malformed identification state, such as a missing "id", the underlying exception propagates. validate_keys(kwargs) accepts model attributes from vars(model) (including descriptors, properties, methods, and other class attributes), names from model._meta.get_fields() (including forward and reverse Django relations), and many-to-many aliases. The canonical many-to-many write alias is <relation>_id_list; the GraphQL-facing <relation>_list spelling is also accepted only when the base relation is an actual local many-to-many field. Unknown keys raise UnknownFieldError.

split_many_to_many(kwargs) mutates and returns the provided mapping: matching many-to-many aliases are removed from the first returned mapping and placed in the second mapping under the canonical <relation>_id_list key. The first returned mapping is the same object passed in. Plain fields whose names merely end in _list are left untouched unless their base name is a real many-to-many relation. If both <relation>_list and <relation>_id_list are present, iteration order decides the last canonical value stored in the many-to-many mapping.

split_many_to_many_non_mutating(kwargs) returns new simple and many-to-many mappings without changing kwargs. It uses the same many-to-many alias recognition, canonical <relation>_id_list output keys, plain _list field preservation, and insertion-order collision behavior as the mutating split_many_to_many() helper.

normalize_simple_values(kwargs) returns a new mapping. It converts manager-valued foreign-key/one-to-one values to identifiers and renames unsuffixed relation keys to <relation>_id; raw non-model values for those forward ForeignKey and OneToOneField names are also sent to the <relation>_id key so Django receives an identifier assignment. Reverse relations, generic relations, and many-to-many fields are not renamed by this method. If both a relation key and its <relation>_id key appear, the later normalized key overwrites the earlier value according to input iteration order. normalize_many_values(kwargs) also returns a new mapping and preserves input keys exactly. It skips None and models.NOT_PROVIDED, treats strings and bytes as scalar one-item assignments, expands other iterables, consumes generators once, treats dictionaries as iterables over their keys, and resolves manager-like items to identification["id"] while preserving unrecognized values. Call split_many_to_many() or split_many_to_many_non_mutating() first when canonical many-to-many keys are required.

SoftDeleteCapability stores the effective soft-delete state for an interface. During setup it prefers _soft_delete_default, then _model._meta.use_soft_delete, and otherwise keeps the capability's configured default. is_soft_delete_enabled() checks the capability first, then model metadata, then _soft_delete_default.

The public custom-field helper exposed through OrmInterfaceBase returns two lists: discovered Django field names and ignore markers for the generated backing attributes, currently <field>_value and <field>_unit. Rules attached through Meta.rules are installed on the generated model metadata and used by the generated full_clean() hook. Lifecycle errors are intentionally not wrapped and GeneralManager does not promise stable lifecycle wrapper exception types here: invalid Django fields, invalid model bases, invalid nested Meta attributes, factory class construction errors, rule setup errors, custom-field-discovery errors, and support-capability lookup errors propagate from Django, factory_boy, rule construction, custom field code, or the support capability that raised them.

OrmInterfaceBase._from_trusted_orm_instance() is internal even though it is visible in generated API reference pages. It is only for framework-owned rows loaded by the interface's Django ORM query paths, not for API, GraphQL, import, factory, or other user payloads. When a subclass overrides __init__, trusted hydration calls that constructor as cls(pk) or cls(pk, search_date=...). For subclasses using the base initializer, the hook bypasses construction and installs the trusted row, {"id": pk} identification, primary key, and normalized search date directly.

general_manager.interface.capabilities.read_only

Public read-only capability exports.

The package-level surface is intentionally limited to capability classes and patchable observability hooks used by application setup and tests. Database transaction helpers stay private to the management implementation.

Exports

ReadOnlyLifecycleCapability: Lifecycle capability that configures read-only interfaces during manager class creation. ReadOnlyManagementCapability: Management capability that validates schema state and synchronizes bound read-only data. ReadOnlyLogger: Minimal logger protocol used by read-only management. ReadOnlyObservabilityHook: Callable protocol for replacing the package-level observability wrapper. ReadOnlyEnsureSchemaOperation: Literal operation for schema checks. ReadOnlySyncDataOperation: Literal operation for data sync. ReadOnlyObservabilityOperation: Stable read-only observability operation names. ReadOnlyEnsureSchemaObservabilityEvent: Paired schema operation and payload. ReadOnlySyncObservabilityEvent: Paired sync operation and payload. ReadOnlyObservabilityPayload: Union of read-only observability payload schemas. ReadOnlySchemaObservabilityPayload: Payload schema emitted by schema checks. ReadOnlySyncObservabilityPayload: Payload schema emitted by data sync. logger: Package-level ReadOnlyLogger patch point. Management resolves this name at log time, so replacing read_only.logger affects subsequent schema and synchronization logs. with_observability: Observability wrapper patch point used by read-only management. Management resolves this callable at runtime through the package, so replacing read_only.with_observability affects subsequent schema-check and sync calls.

ReadOnlyObservabilityTarget module-attribute

ReadOnlyObservabilityTarget = type[object]

Read-only interface class passed to observability hooks.

The alias stays broad so dynamic interface classes and test doubles can be used without importing ORM base classes into the package surface.

ReadOnlyLogger

Bases: Protocol

Minimal logger shape consumed by read-only management patches.

debug

debug(msg, *args, context=None, **kwargs)

Log diagnostic details with optional structured context.

info

info(msg, *args, context=None, **kwargs)

Log sync summaries with optional structured context.

warning

warning(msg, *args, context=None, **kwargs)

Log schema or sync warnings with optional structured context.

ReadOnlySchemaObservabilityPayload

Bases: TypedDict

Payload emitted for read_only.ensure_schema observability events.

ReadOnlySyncObservabilityPayload

Bases: TypedDict

Payload emitted for read_only.sync_data observability events.

ReadOnlyLifecycleCapability dataclass

Bases: OrmLifecycleCapability

Configure generated read-only managers for soft-delete synchronization.

pre_create

pre_create(*, name, attrs, interface, base_model_class)

Force read-only model generation onto the soft-delete base model.

Read-only synchronization uses inactive rows to represent payload rows that disappeared from _data. This hook creates a nested Meta class when the interface does not define one, overwrites Meta.use_soft_delete to True even when it was explicitly False, ignores the caller-supplied base_model_class, and delegates to the ORM lifecycle with GeneralManagerBasisModel.

Parameters:

Name Type Description Default
name str

Name used for the generated model, factory, and manager lifecycle artifacts.

required
attrs dict[str, object]

Class namespace for the new manager. This mapping is passed to the parent ORM lifecycle, which mutates and returns it with generated interface, factory, and interface-type entries.

required
interface type['OrmInterfaceBase[models.Model]']

ORM interface class to configure; for normal use this is a ReadOnlyInterface subclass.

required
base_model_class type[GeneralManagerBasisModel]

Ignored by this capability; read-only managers always delegate with GeneralManagerBasisModel.

required

Returns:

Type Description
dict[str, object]

The updated manager namespace, concrete interface subclass, and

type['OrmInterfaceBase[models.Model]']

generated read-only model class returned by the ORM lifecycle.

Raises:

Type Description
Exception

Specific exceptions are defined by the downstream component that raises them. Invalid interface attributes, Django model fields, Meta options, factory definitions, rule setup, support-capability lookup, or custom-field discovery errors propagate unchanged from the ORM lifecycle or the code that raised them.

post_create

post_create(*, new_class, interface_class, model)

Register the newly created manager class as a read-only class in GeneralManagerMeta.

Runs the ORM post-create lifecycle first so the manager, interface, and generated model are linked. It then appends new_class to GeneralManagerMeta.read_only_classes when the exact class object is not already present, which lets startup hooks discover read-only managers for schema checks and data synchronization. When model is None, the ORM post-create lifecycle returns without linking model state, but this capability still registers the class.

Parameters:

Name Type Description Default
new_class type['GeneralManager']

Newly created GeneralManager subclass to register.

required
interface_class type['OrmInterfaceBase[models.Model]']

Concrete ORM interface class, normally a read-only interface bound to the generated model.

required
model type['GeneralManagerBasisModel'] | None

Generated ORM model class, or None when no model was created by an upstream lifecycle.

required

Raises:

Type Description
Exception

Specific exceptions are defined by the downstream component that raises them. Errors from ORM post-create linking, manager lookup, or soft-delete manager setup propagate unchanged before registry mutation.

ReadOnlyObservabilityHook

Bases: Protocol

Callable shape expected for read_only.with_observability patches.

The default hook creates one shallow copy of payload for the event and passes that same copy to every callback. It calls before_operation before func; if that callback raises, func is not called. It calls on_error only when func raises; if on_error raises, that exception replaces the original func exception. It calls after_operation only after func succeeds; if after_operation raises, that exception replaces the successful return. Otherwise it returns func's result. Production replacement hooks should call func exactly once and return its result. Test hooks may intentionally skip, repeat, or fail the operation to simulate edge cases. Mutating a patched hook's received payload does not affect read-only management after the hook call because the payload is used only for that observability event. Async functions are not awaited; an awaitable returned by func is returned as-is.

Raises:

Type Description
Exception

Re-raises exceptions from func, observability callbacks, or the hook itself; the default hook does not suppress callback failures.

The general_manager.interface.capabilities.read_only package is the supported package-level import surface for read-only capability classes: ReadOnlyLifecycleCapability and ReadOnlyManagementCapability. It also exposes ReadOnlyLogger, ReadOnlyObservabilityHook, ReadOnlyEnsureSchemaOperation, ReadOnlySyncDataOperation, ReadOnlyObservabilityOperation, ReadOnlyEnsureSchemaObservabilityEvent, ReadOnlySyncObservabilityEvent, ReadOnlyObservabilityPayload, ReadOnlyObservabilityTarget, ReadOnlySchemaObservabilityPayload, ReadOnlySyncObservabilityPayload, logger, and with_observability through __all__ as patch points and type helpers for tests or advanced instrumentation. The private _compat.call_with_observability() helper exists only to make read-only management resolve the package-level hook at call time; import with_observability from the package instead.

ReadOnlyLifecycleCapability is the lifecycle hook behind ReadOnlyInterface. During class creation it adds a nested Meta class when needed, overwrites Meta.use_soft_delete = True even when a subclass set it to False, ignores any caller-supplied model base, and delegates model generation to the ORM lifecycle with GeneralManagerBasisModel. The class-creation namespace is passed through the ORM lifecycle, which mutates and returns it with the generated interface, factory, and interface-type entries. After class creation it runs the ORM post-create linking first, then registers the new manager in GeneralManagerMeta.read_only_classes when that exact class object is not already present, so startup hooks can find it for schema checks and synchronization. If the upstream lifecycle supplies model=None, ORM linking returns without attaching model state, but the read-only class is still registered. Lifecycle exceptions are not wrapped: invalid Django fields or Meta options, factory or rule construction errors, custom-field discovery failures, support-capability lookup failures, and ORM manager setup errors propagate from the component that raised them.

logger is a GeneralManagerLoggerAdapter. Test doubles can follow ReadOnlyLogger: a minimal protocol with debug(), info(), and warning() methods that accept a message, positional logging arguments, and an optional context mapping keyword. Read-only management resolves general_manager.interface.capabilities.read_only.logger at log time, so patching that package-level name affects subsequent schema and sync logs.

ReadOnlyObservabilityHook is the replacement protocol for with_observability: a synchronous callable accepting a target, keyword-only operation, payload, and func, and returning the result of func. ReadOnlyObservabilityTarget is type[object]; read-only management passes the read-only interface class, and the alias stays broad so dynamically generated interfaces and test doubles are accepted without importing ORM base classes into the package surface. Production replacement hooks should call func exactly once and return its result. Test hooks may intentionally skip, repeat, or fail the operation to simulate edge cases. The default hook creates one shallow copy of payload for the event and passes that same copy to every callback. It calls before_operation before func; if before_operation raises, func is not called. It calls on_error only when func raises; if on_error raises, that exception replaces the original func exception. It calls after_operation only after func succeeds; if after_operation raises, that exception replaces the successful return. Otherwise the hook returns func's result. A patched hook receives the management payload dictionary directly. It may mutate that per-event dictionary during the call, but should not retain it for later mutation; read-only management treats the payload as disposable after the hook returns and does not read it again. Async functions are not awaited by this wrapper; an awaitable returned by func is returned as-is. Read-only management resolves the hook from the package at call time, so patching general_manager.interface.capabilities.read_only.with_observability affects subsequent schema-check and sync calls.

Default observability callbacks have the same keyword shape used by the shared observability capability: before_operation(operation=..., target=..., payload=...), after_operation(operation=..., target=..., payload=..., result=...), and on_error(operation=..., target=..., payload=..., error=...).

general_manager.interface.capabilities.core.with_observability(target, operation=..., payload=..., func=...) is the shared wrapper used by capability packages. It accepts any mapping-shaped payload, copies it once to a dict for hook calls, and executes func directly when the target has no get_capability_handler() method or no observability capability. When a capability is present, it calls non-None optional hooks only: it calls before_operation before func, calls on_error only if func raises, re-raises the original exception unless the error hook raises, and calls after_operation only after successful completion. If before_operation raises, func is not called. Hook exceptions are not wrapped.

LoggingObservabilityCapability is registered as the "observability" capability and writes structured debug/error log events for interface operations through the "interface.observability" logger. The start, end, and error event messages are "interface operation start", "interface operation end", and "interface operation error". Each call passes the structured metadata as the logger keyword argument context=.... Context contains operation, the target name (target.__name__ when that attribute is a string, otherwise the target class name; AttributeError from __name__ lookup is treated as missing), sorted payload_keys, and selected payload metadata keys: service, method, path, status_code, retry_count, and request_id. Selected payload keys are included whenever the key is present, including when the value is None. End events add result_type as the simple runtime type name and copy status_code, retry_count, and request_id from result.metadata when that metadata is a collections.abc.Mapping; missing metadata attributes and non-mapping metadata values are ignored, and AttributeError from metadata lookup is treated as missing metadata. Result metadata keys are included whenever present, including None, and replace same-named payload values in the end-event context. Error events add error=repr(error), error_class=type(error).__name__, and status_code from error.status_code when that attribute exists, including when the value is None; missing status_code and AttributeError from status_code lookup are ignored. Logger construction, non-AttributeError target-name lookup failures, payload-key sorting, payload/result metadata access, non-AttributeError error status lookup failures, and logger call errors propagate unchanged.

Calculation capabilities use the same package-level replacement pattern for general_manager.interface.capabilities.calculation.with_observability. Query operations resolve that hook at call time with the calculation interface class as target, a payload dictionary, and one of these operation labels: "calculation.query.filter" with {"kwargs": dict(kwargs)}, "calculation.query.exclude" with {"kwargs": dict(kwargs)}, or "calculation.query.all" with {}. Lifecycle hooks emit "calculation.pre_create" with the user-declared interface class as target and {"interface": interface.__name__, "name": name}. They emit "calculation.post_create" with the generated interface class as target and {"interface": interface_class.__name__}. The default hook copies the payload before calling callbacks, executes func once, returns its result, and propagates callback or operation exceptions using the callback ordering described above.

ReadOnlyObservabilityOperation is the literal union "read_only.ensure_schema" | "read_only.sync_data", and ReadOnlyObservabilityPayload is the union of the two payload schemas below. ReadOnlyObservabilityHook overloads pair each operation literal with the matching payload schema for type checkers. Schema checks emit operation="read_only.ensure_schema" with ReadOnlySchemaObservabilityPayload: manager is the manager class name string and model is the Django model class name string. The paired event alias is ReadOnlyEnsureSchemaObservabilityEvent. Data sync emits operation="read_only.sync_data" with ReadOnlySyncObservabilityPayload: manager and model are the bound class name strings when present, otherwise None, and schema_validated is the boolean flag passed to sync_data(). The paired event alias is ReadOnlySyncObservabilityEvent.

from collections.abc import Callable
from typing import TypeVar

from general_manager.interface.capabilities.read_only import (
    ReadOnlyObservabilityOperation,
    ReadOnlySchemaObservabilityPayload,
    ReadOnlySyncObservabilityPayload,
)

ResultT = TypeVar("ResultT")


def traced_read_only_hook(
    target: type[object],
    *,
    operation: ReadOnlyObservabilityOperation,
    payload: ReadOnlySchemaObservabilityPayload | ReadOnlySyncObservabilityPayload,
    func: Callable[[], ResultT],
) -> ResultT:
    return func()

The read_only.management module below is documented as capability reference material. Its imported Django transaction module is not exported from read_only and is not package-level API. Patching general_manager.interface.capabilities.read_only.management.django_transaction is a private test escape hatch for replacing database transaction behavior, not a supported application extension point.

ReadOnlyManagementCapability.get_unique_fields(model) inspects Django model metadata to find the fields used to reconcile incoming _data rows with database rows. It includes fields marked unique=True, unique_together entries, and UniqueConstraint.fields, excluding the primary key named id. When a unique field is the concrete value column behind a MeasurementField, the method returns the public measurement descriptor name instead. If two measurement descriptors point at the same concrete value column, it raises ValueError; if the model has no _meta, it returns an empty set. The return value is intentionally a flat set. When several unique declarations exist, sync_data() uses the union of their fields as one composite identity and requires every field in that union on each payload row.

ensure_schema_is_up_to_date(interface_cls, manager_cls, model, *, connection=None) checks the bound model against the database table before read-only sync. It returns Django system-check Warning objects for missing model metadata, missing db_table, a missing database table, or mismatched local concrete column names. It compares column presence only: field types, nullability, defaults, indexes, generated columns, many-to-many through tables, and inherited fields outside the model's local concrete field list are not validated. A clean schema returns an empty list. Database introspection errors and read-only observability hook errors propagate unchanged.

sync_data(interface_cls, *, connection=None, transaction=None, integrity_error=None, json_module=None, logger_instance=None, unique_fields=None, schema_validated=False) synchronizes the parent manager's _data payload into the read-only model. _data may be a JSON string that decodes to a list or an in-memory list of row dictionaries. Unique fields are either supplied explicitly or discovered through get_unique_fields(). The sync creates missing rows, updates editable local fields, applies many-to-many assignments after save, reactivates matched soft-deleted rows, and sets previously active rows inactive when their unique identifier is absent from the payload. Omitted editable scalar fields are left unchanged on existing rows and excluded from create payloads. Omitted many-to-many fields are left unchanged; a present value of None clears the relation and a present list replaces it. Relation values may be lookup dictionaries; nested dictionaries are flattened into Django __ lookups and must match exactly one related row or ReadOnlyRelationLookupError is raised. Many-to-many relation payloads must be lists of lookup dictionaries or identifiers.

When schema_validated is false, sync_data() first calls ensure_schema_is_up_to_date() and logs then aborts without writes if warnings are returned. It also has a conservative fast path that fingerprints the active database rows and payload rows and skips the transaction when comparable local non-relation, non-measurement fields already match the payload fields present on each row. Related read-only interfaces sync before the local transaction, each through its own sync_data() call; recursive cycles are skipped by an in-progress stack. Public failures include MissingReadOnlyBindingError, MissingReadOnlyDataError, InvalidReadOnlyDataTypeError, InvalidReadOnlyDataFormatError, MissingUniqueFieldError, ReadOnlyRelationLookupError, the configured integrity error class, database errors, logger errors, and observability hook errors.

get_startup_hooks(interface_cls) returns a single startup callable when the interface is already bound to a parent manager and model. That callable runs sync_data() and suppresses only MissingReadOnlyBindingError, because binding metadata can become unavailable between hook registration and startup execution. When the interface is not bound at registration time, it returns an empty tuple instead of a no-op callable. get_system_checks(interface_cls) returns a callable that delegates to ensure_schema_is_up_to_date() when binding metadata is available and returns an empty list otherwise; observability and introspection errors propagate from the returned callable once binding is present. get_startup_hook_dependency_resolver(interface_cls) returns a resolver that orders read-only startup sync after direct read-only dependencies referenced by non-auto-created relation fields, including foreign-key, one-to-one, and many-to-many fields. The resolver inspects the class passed to the resolver; transitive dependencies and cycle handling are handled by the startup runner.

general_manager.interface.capabilities.read_only.management

Capabilities that power ReadOnlyInterface behavior.

ReadOnlyManagementCapability dataclass

Bases: BaseCapability

Provide schema verification and data-sync behavior for read-only interfaces.

get_startup_hook_dependency_resolver

get_startup_hook_dependency_resolver(interface_cls)

Return a resolver function that identifies read-only interfaces which must run before a given interface's startup hook.

The returned resolver inspects the interface class passed to the resolver, not the interface_cls argument captured here. It reports direct read-only dependencies referenced by non-auto-created relation fields, including foreign-key, one-to-one, and many-to-many fields. Transitive dependencies and cycle handling are left to the startup hook runner.

Parameters:

Name Type Description Default
interface_cls _ReadOnlyInterface

The interface class for which to obtain a startup-hook dependency resolver.

required

Returns:

Type Description
Callable[[type[object]], set[type[object]]]

A callable that, when invoked with an interface class, returns a set of read-only interface classes that should be executed prior to that interface's startup hook.

get_unique_fields

get_unique_fields(model)

Gather candidate unique field names declared on the Django model, remapping measurement-backed fields to their public attribute names.

Includes fields marked unique=True, fields listed in unique_together (or equivalent tuple/list/set entries), and fields referenced by UniqueConstraint definitions. Excludes the primary key named "id". If multiple unique declarations exist, the returned flat set is their union; sync_data() treats every returned field as part of one composite row identity. If the model has no _meta, returns an empty set.

Parameters:

Name Type Description Default
model type[Model]

Django model class whose unique declarations should be inspected.

required

Returns:

Type Description
set[str]

A set of unique field names with MeasurementField-backed value attributes remapped to their wrapper attribute names.

Raises:

Type Description
ValueError

If two MeasurementField descriptors map to the same concrete value_attr.

ensure_schema_is_up_to_date

ensure_schema_is_up_to_date(
    interface_cls, manager_cls, model, *, connection=None
)

Verify that the Django model's declared column names match the actual database table and return schema-related warnings.

Performs the following checks and returns corresponding Django Warning objects when applicable: - Model metadata (_meta) is missing. - db_table is not defined on the model meta. - The named database table does not exist. - The table's column names differ from the model's local concrete field column names (missing or extra columns).

Field types, nullability, defaults, indexes, generated columns, many-to-many through tables, and inherited fields outside the local concrete field list are not compared.

Parameters:

Name Type Description Default
interface_cls _ReadOnlyInterface

Read-only interface class passed to observability hooks.

required
manager_cls type['GeneralManager']

Manager class used in warning hints and observability payloads.

required
model type[Model]

Django model class whose database table should be checked.

required
connection _SchemaConnection | None

Database connection to use for introspection. If omitted, the default Django connection is used.

None

Returns:

Type Description
list[Warning]

A list of Django system-check Warning objects describing discovered mismatches; returns an empty list when no issues are found.

Raises:

Type Description
Exception

Propagates database introspection errors and read-only observability hook exceptions without wrapping.

sync_data

sync_data(
    interface_cls,
    *,
    connection=None,
    transaction=None,
    integrity_error=None,
    json_module=None,
    logger_instance=None,
    unique_fields=None,
    schema_validated=False
)

Synchronize the interface's bound read-only JSON data into the underlying Django model, creating, updating, and deactivating records to match the input.

Parses the read-only payload defined on the interface's parent class, enforces a set of unique identifying fields to match incoming items to existing rows, writes only model-editable fields that are present in each payload row, marks matched records active, creates missing records, and deactivates previously active records not present in the incoming data. If schema validation is enabled (or performed), aborts when schema warnings are detected.

When unique_fields is omitted, get_unique_fields() supplies a flat union of all unique declarations and every field in that union is required in each payload row. Omitted editable scalar fields are left unchanged on existing rows and are not included in create payloads. Omitted many-to-many fields are left unchanged; a present value of None clears the relation and a present list replaces it. Related read-only interfaces sync before the local transaction, each through its own sync_data() call, and recursive cycles are skipped by the in-progress guard.

Parameters:

Name Type Description Default
interface_cls _ReadOnlyInterface

Read-only interface class whose parent class must expose _data and model binding.

required
connection _SchemaConnection | None

Django DB connection to use instead of the default.

None
transaction _TransactionModule | None

Django transaction management object with an atomic() context manager.

None
integrity_error type[BaseException] | None

Exception class to treat as a DB integrity error (defaults to Django's IntegrityError).

None
json_module _JsonLoader | None

JSON-like parser with loads(str) support (defaults to the standard library json).

None
logger_instance ReadOnlyLogger | None

Logger to record sync results; falls back to the capability's resolved logger.

None
unique_fields set[str] | None

Explicit set of field names to use as the unique identifier for items; when omitted, the model's unique metadata is used.

None
schema_validated bool

When True, skip runtime schema validation; when False, ensure_schema_is_up_to_date is called before syncing and the sync is aborted if warnings are returned.

False

Raises:

Type Description
MissingReadOnlyBindingError

If the interface is not bound to both a parent manager and a model.

MissingReadOnlyDataError

If the parent manager has no _data attribute.

InvalidReadOnlyDataTypeError

If _data is neither a JSON string nor a list.

InvalidReadOnlyDataFormatError

If JSON does not decode to a list, many-to-many data is not a list, or an item misses a required unique field.

MissingUniqueFieldError

If no unique fields can be determined or supplied.

ReadOnlyRelationLookupError

If a relation lookup dictionary matches zero or multiple related records.

BaseException

Propagates the configured integrity_error, database errors, logger errors, and observability hook exceptions.

get_startup_hooks

get_startup_hooks(interface_cls)

Provide a startup hook that triggers read-only data synchronization for the given interface.

If the interface is not bound to both a parent manager and model when hooks are requested, no hook is registered and an empty tuple is returned. The registered hook catches MissingReadOnlyBindingError only to tolerate binding metadata becoming unavailable between registration and startup execution; other sync errors propagate.

Parameters:

Name Type Description Default
interface_cls _ReadOnlyInterface

Interface class used to derive the bound manager and model.

required

Returns:

Type Description
Callable[[], None]

A one-element tuple containing a callable that runs synchronization when invoked,

...

or an empty tuple if the interface lacks the necessary manager/model metadata. The callable invokes the capability's

tuple[Callable[[], None], ...]

sync logic and silently skips if the read-only binding is not yet available.

get_system_checks

get_system_checks(interface_cls)

Provide a system check function that validates the read-only model schema against the database.

Missing parent-manager or model binding is intentionally silent and returns an empty warning list from the check callable. Once binding is present, schema warnings and propagated introspection or observability errors follow ensure_schema_is_up_to_date().

Parameters:

Name Type Description Default
interface_cls _ReadOnlyInterface

The read-only interface class whose binding (parent manager and model) will be inspected.

required

Returns:

Type Description
tuple[Callable[[], list[Warning]], ...]

A tuple containing a single callable. When invoked, the callable returns a list of Warning objects produced by ensure_schema_is_up_to_date if both the parent manager and model are present; otherwise it returns an empty list.

general_manager.interface.capabilities.calculation.lifecycle

Capabilities tailored for calculation interfaces.

CalculationReadCapability dataclass

Bases: BaseCapability

Calculations expose inputs only and never persist data.

get_data

get_data(interface_instance)

Reject persisted-data access for calculation interface instances.

Parameters:

Name Type Description Default
interface_instance 'CalculationInterface'

Calculation interface instance whose stored data was requested. The value is accepted for capability compatibility and is not inspected.

required

Raises:

Type Description
NotImplementedError

Always raised because calculation managers are derived from their inputs and do not have backing storage.

get_attribute_types

get_attribute_types(interface_cls)

Build metadata for each declared calculation input.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface class whose collected input_fields mapping is inspected.

required

Returns:

Type Description
dict[str, dict[str, object]]

Mapping from input name to metadata rows with the exact keys

dict[str, dict[str, object]]

"type", "default", "is_editable", "is_required",

dict[str, dict[str, object]]

and "is_derived". Calculation inputs always report

dict[str, dict[str, object]]

default=None, is_editable=False, and is_derived=False;

dict[str, dict[str, object]]

is_required mirrors Input.required.

get_attributes

get_attributes(interface_cls)

Create lazy input accessors for a calculation interface.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface class whose input_fields mapping defines available input names, types, and dependencies.

required

Returns:

Type Description
dict[str, Callable[['CalculationInterface'], object]]

Mapping from input name to a callable. Each callable resolves

dict[str, Callable[['CalculationInterface'], object]]

declared dependencies first, casts the raw value from the instance's

dict[str, Callable[['CalculationInterface'], object]]

identification mapping, memoizes the cast result on that

dict[str, Callable[['CalculationInterface'], object]]

instance, and returns the typed value as object. Missing

dict[str, Callable[['CalculationInterface'], object]]

identification keys are passed to Input.cast() as None;

dict[str, Callable[['CalculationInterface'], object]]

required-input enforcement is handled by separate validation, not

dict[str, Callable[['CalculationInterface'], object]]

by this accessor.

Raises:

Type Description
KeyError

Propagated from missing dependency names or field names.

TypeError

Propagated from input casting callbacks with incompatible signatures or values.

ValueError

Propagated from input normalization/parsing failures.

get_field_type

get_field_type(interface_cls, field_name)

Return the declared Python type for one calculation input.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface class containing input_fields.

required
field_name str

Name of the input field to look up.

required

Returns:

Type Description
type[object]

The Python type declared on the input field.

Raises:

Type Description
KeyError

If field_name is absent from interface_cls.input_fields.

CalculationQueryCapability dataclass

Bases: BaseCapability

Expose CalculationBucket helpers via the generic query capability.

filter

filter(interface_cls, **kwargs)

Create a filtered calculation bucket for an interface.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface whose parent manager class is enumerated.

required
**kwargs object

Query filter parameters forwarded to CalculationBucket.filter.

{}

Returns:

Type Description
CalculationBucket[GeneralManager]

Bucket representing calculation input combinations that match the

CalculationBucket[GeneralManager]

provided filters.

Raises:

Type Description
InvalidCalculationInterfaceError

Propagated if the parent manager does not use a calculation interface.

KeyError

Propagated from missing dependency values.

TypeError

Propagated from invalid filter values, input domains, or callback signatures.

ValueError

Propagated from input parsing, normalization, or filter value failures.

exclude

exclude(interface_cls, **kwargs)

Create a calculation bucket with matching combinations excluded.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface whose parent manager class is enumerated.

required
**kwargs object

Exclusion criteria forwarded to CalculationBucket.exclude.

{}

Returns:

Type Description
CalculationBucket[GeneralManager]

Bucket representing calculation input combinations after matching

CalculationBucket[GeneralManager]

combinations are removed.

Raises:

Type Description
InvalidCalculationInterfaceError

Propagated if the parent manager does not use a calculation interface.

KeyError

Propagated from missing dependency values.

TypeError

Propagated from invalid exclusion values, input domains, or callback signatures.

ValueError

Propagated from input parsing, normalization, or filter value failures.

all

all(interface_cls)

Create a bucket for all calculation input combinations.

Parameters:

Name Type Description Default
interface_cls type['CalculationInterface']

Calculation interface whose parent manager class is enumerated.

required

Returns:

Type Description
CalculationBucket[GeneralManager]

Bucket representing every possible calculation input combination.

Raises:

Type Description
InvalidCalculationInterfaceError

Propagated if the parent manager does not use a calculation interface.

KeyError

Propagated from missing dependency values.

TypeError

Propagated from invalid input domain definitions or callback signatures.

ValueError

Propagated from input parsing or normalization failures.

CalculationLifecycleCapability dataclass

Bases: BaseCapability

Manage calculation interface pre/post creation hooks.

pre_create

pre_create(*, name, attrs, interface)

Collect calculation inputs and attach the generated interface class.

Parameters:

Name Type Description Default
name str

Declared manager class name, used only for observability payloads.

required
attrs dict[str, object]

Mutable manager-class attribute mapping. This method sets "_interface_type" and "Interface".

required
interface type['CalculationInterface']

User-declared calculation interface class. Only its own Input class attributes are collected; inherited descriptors and pre-existing input_fields values are not merged.

required

Returns:

Type Description
dict[str, object]

Tuple of updated attrs, generated calculation interface subclass,

type['CalculationInterface']

and None for lifecycle hook compatibility.

post_create

post_create(*, new_class, interface_class, model=None)

Attach the concrete manager class to the generated interface.

Parameters:

Name Type Description Default
new_class type[GeneralManager]

Concrete manager class just created.

required
interface_class type['CalculationInterface']

Generated calculation interface class whose _parent_class backlink will be updated.

required
model None

Reserved for lifecycle compatibility and ignored.

None

ExistingModelResolutionCapability is the lifecycle capability behind ExistingModelInterface. resolve_model(interface_cls) reads interface_cls.model, accepts either a Django model class or an app-label string accepted by django.apps.apps.get_model() such as "app_label.ModelName" or settings.AUTH_USER_MODEL, stores the resolved class on interface_cls._model and interface_cls.model, and enables the soft-delete capability by default when the model exposes is_active. None, empty strings, unresolved lazy references, malformed strings, and non-model objects are invalid. Missing model configuration raises MissingModelConfigurationError; invalid strings or non-model references raise InvalidModelReferenceError.

ensure_history(model, interface_cls=None) registers database-aware django-simple-history for an untracked model and includes local many-to-many field names. A pre-existing tracker is accepted for the default alias. For a non-default interface alias, its generated history model must have GeneralManager's database-aware marker; otherwise UnsafeHistoryConfigurationError(model_name, interface_name, alias) is raised. The exception message is <model> must use DatabaseAwareHistoricalRecords before <interface> configures non-default database alias '<alias>'.. The records class and exception currently live in implementation modules and are not stable exports from general_manager.interface; this is a compatibility limitation of 0.63.1, not a promise of those direct import paths. Other registration errors from django-simple-history propagate. apply_rules(interface_cls, model) appends interface_cls.Meta.rules after any existing model._meta.rules and replaces model.full_clean with the GeneralManager rules-aware implementation. If no interface rules are declared, the method is a no-op. ensure_history() is idempotent once simple-history metadata exists; apply_rules() is not a deduplication boundary, so repeated calls append the interface rules again and repatch full_clean().

pre_create(name=..., attrs=..., interface=...) resolves the model, ensures history, applies rules, creates the concrete interface subclass, resets cached field descriptors, writes attrs["_interface_type"], attrs["Interface"], and attrs["Factory"], and returns (attrs, concrete_interface, model). A Factory class supplied on the manager attrs takes precedence over the interface Factory; public attributes from that definition and its nested Meta are copied into the generated AutoFactory, while Meta.model is always set to the resolved model. "Public attributes" means directly declared non-dunder attributes except Meta; inherited attributes are not copied, and descriptors, callables, and annotations present in the prototype __dict__ are copied as ordinary values. pre_create() repeats resolution, history, rule, and factory work each time it is called according to those helper contracts. post_create(new_class=..., interface_class=..., model=...) wires the generated manager class onto the interface and Django model, assigns new_class.objects, and when soft delete is enabled also exposes new_class.all_objects from ORM support with only_active=False. If the legacy model does not already expose an unfiltered all_objects, GeneralManager falls back to Django's _default_manager; that fallback mirrors the legacy model's default manager and is not guaranteed to include inactive rows when the legacy default manager filters them. A None model is a no-op for lifecycle compatibility. Errors from history registration, rule application, factory construction, class creation, manager wiring, ORM support lookup, and observability hooks propagate unchanged.

general_manager.interface.capabilities.existing_model.resolution

Capabilities specialized for ExistingModelInterface.

ExistingModelResolutionCapability dataclass

Bases: BaseCapability

Resolve and configure the Django model used by ExistingModelInterface.

resolve_model

resolve_model(interface_cls)

Resolve and bind the Django model referenced by an ExistingModelInterface subclass.

Parameters:

Name Type Description Default
interface_cls ExistingInterfaceClass

The interface class whose model attribute should be resolved and attached. model must be either a Django model class or a string accepted by django.apps.apps.get_model(), such as "app_label.ModelName" or settings.AUTH_USER_MODEL. None, empty strings, unresolved lazy references, and non-model objects are invalid.

required

Returns:

Type Description
type[Model]

type[models.Model]: The resolved Django model class.

Raises:

Type Description
MissingModelConfigurationError

If the interface has no model attribute set.

InvalidModelReferenceError

If the model attribute is neither a valid model class nor a resolvable app label string.

Exception

Exceptions raised by the observability hook are not wrapped.

ensure_history

ensure_history(model, interface_cls=None)

Register simple history tracking for the given Django model if it is not already registered.

Parameters:

Name Type Description Default
model type[Model]

The Django model class to enable history tracking on.

required
interface_cls type['ExistingModelInterface'] | None

Optional interface class associated with the model; when provided, the registration is attributed to that interface.

None

Raises:

Type Description
Exception

Registration and observability hook exceptions are not wrapped.

apply_rules

apply_rules(interface_cls, model)

Apply the interface's Meta.rules to the Django model and wire a compatible full_clean method.

If the interface defines a Meta.rules sequence, this function appends those rules to any existing rules on model._meta and assigns the combined list back to model._meta.rules. It then replaces model.full_clean with a full-clean helper appropriate for the model. If no rules are defined on the interface, the model is left unchanged. Repeated calls append the interface rules again and replace full_clean again; the method is not a deduplication boundary.

Parameters:

Name Type Description Default
interface_cls type[ExistingModelInterface]

The interface class whose Meta.rules will be applied.

required
model type[Model]

The Django model to receive combined rules and a patched full_clean.

required

Raises:

Type Description
Exception

Invalid rule containers, full_clean patching errors, and observability hook exceptions are not wrapped.

pre_create

pre_create(*, name, attrs, interface)

Prepare and return attributes and types needed to create a concrete interface class tied to an existing Django model.

Parameters:

Name Type Description Default
name str

The name to use for the generated concrete interface and its factory.

required
attrs AttributeMap

Attribute mapping for the class being created; this mapping will be updated with keys such as "_interface_type", "Interface", and "Factory".

required
interface type[ExistingModelInterface]

The ExistingModelInterface subclass that defines the model reference and optional Factory to base the concrete interface on.

required

Returns:

Type Description
tuple[AttributeMap, ExistingInterfaceClass, type[Model]]

tuple[AttributeMap, ExistingInterfaceClass, type[models.Model]]: A tuple containing the (possibly mutated) attrs dict to use when creating the class, the generated concrete interface type (with its model wired), and the resolved Django model class.

Raises:

Type Description
MissingModelConfigurationError

If model resolution finds no model configuration.

InvalidModelReferenceError

If model resolution receives an invalid reference.

Exception

History registration, rule application, factory construction, class creation, and observability hook exceptions are not wrapped. Repeated calls repeat history/rule/factory work according to the helper methods' contracts.

post_create

post_create(*, new_class, interface_class, model)

Finalize wiring between the newly created concrete class, its interface, and the Django model.

Parameters:

Name Type Description Default
new_class type

The newly created concrete manager/class that will be attached to the interface and model.

required
interface_class type[ExistingModelInterface]

The interface class from which the concrete class was created.

required
model type[Model] | None

The resolved Django model associated with the interface, or None if no model is configured.

required
Description

If a model is provided, attaches new_class as the interface's _parent_class and the model's _general_manager_class, assigns new_class.objects using the ORM persistence capability for the interface, and if soft-delete support is enabled, ensures the model exposes all_objects (falling back to _default_manager if missing) and assigns new_class.all_objects from the ORM support capability with only_active=False. If the legacy model does not already expose an unfiltered all_objects, the fallback mirrors Django's _default_manager; GeneralManager cannot guarantee that fallback is unfiltered when the legacy model's default manager filters rows.

Raises:

Type Description
Exception

ORM support lookup, manager construction, generated class wiring, and observability hook exceptions are not wrapped.

build_factory

build_factory(
    *, name, interface_cls, model, factory_definition=None
)

Create a concrete AutoFactory subclass configured for the given interface and Django model.

Parameters:

Name Type Description Default
name str

Base name used to derive the generated factory class name (result will be "{name}Factory").

required
interface_cls type[ExistingModelInterface]

The interface type the factory will produce instances for.

required
model type[Model]

The Django model that the factory's Meta.model should reference.

required
factory_definition type[object] | None

Optional prototype class whose directly declared non-dunder attributes are copied into the generated factory, except Meta. Inherited attributes are not copied from the prototype __dict__; descriptors, callables, and annotations present in that dict are copied as ordinary values. Attributes generated by this method (interface and Meta) override any copied value with the same name.

None

Returns:

Type Description
type[AutoFactory[Model]]

type[AutoFactory]: A newly created AutoFactory subclass named "{name}Factory" with its interface attribute set to the given interface and a Meta class pointing to the provided model.

Raises:

Type Description
Exception

Invalid factory definitions, invalid nested Meta values, class creation errors, and AutoFactory metaclass errors are not wrapped.

general_manager.interface.utils.errors.InvalidFieldValueError

Bases: ValueError

Raised when model-field assignment rejects a value.

Used by writable ORM capabilities after Django/model assignment raises ValueError for a payload field.

__init__

__init__(field_name, value)

Build an error message for an invalid field value.

Parameters:

Name Type Description Default
field_name str

Payload/model field name that rejected the value.

required
value object

Rejected value included in the message with str(value).

required
Message

Invalid value for {field_name}: {value}.

general_manager.interface.utils.errors.InvalidFieldTypeError

Bases: TypeError

Raised when model-field assignment rejects a value type.

Used by writable ORM capabilities after Django/model assignment raises TypeError for a payload field.

__init__

__init__(field_name, error)

Build an error message for a field type failure.

Parameters:

Name Type Description Default
field_name str

Payload/model field name that rejected the value.

required
error TypeError

Original TypeError; its message is embedded unchanged.

required
Message

Type error for {field_name}: {error}.

general_manager.interface.utils.errors.UnknownFieldError

Bases: ValueError

Raised when write payloads reference fields absent from the model.

__init__

__init__(field_name, model_name)

Build an error message for an unknown model field.

Parameters:

Name Type Description Default
field_name str

Payload field name that was not recognized.

required
model_name str

Name of the Django model checked for that field.

required
Message

{field_name} does not exist in {model_name}.

general_manager.interface.utils.errors.DuplicateFieldNameError

Bases: ValueError

Raised when generated interface descriptors collide on one name.

__init__

__init__()

Build the fixed Field name already exists. message.

general_manager.interface.utils.errors.MissingActivationSupportError

Bases: TypeError

Raised when soft delete needs model is_active support.

__init__

__init__(model_name)

Build an error message for missing soft-delete support.

Parameters:

Name Type Description Default
model_name str

Name of the model class missing is_active.

required
Message

{model_name} must define an 'is_active' attribute.

general_manager.interface.utils.errors.MissingReadOnlyDataError

Bases: ValueError

Raised when a read-only manager lacks its _data source.

__init__

__init__(interface_name)

Build an error message for missing read-only data.

Parameters:

Name Type Description Default
interface_name str

Name of the read-only manager/interface owner.

required
Message

ReadOnlyInterface '{interface_name}' must define a '_data' attribute.

general_manager.interface.utils.errors.MissingUniqueFieldError

Bases: ValueError

Raised when read-only sync cannot determine a row identity.

__init__

__init__(interface_name)

Build an error message for missing unique field metadata.

Parameters:

Name Type Description Default
interface_name str

Name of the read-only manager/interface owner.

required
Message

ReadOnlyInterface '{interface_name}' must declare at least one unique field.

general_manager.interface.utils.errors.ReadOnlyRelationLookupError

Bases: ValueError

Raised when read-only sync resolves zero or multiple related rows.

__init__

__init__(interface_name, field_name, matches, lookup)

Build an error message for an ambiguous relation lookup.

Parameters:

Name Type Description Default
interface_name str

Name of the read-only manager/interface owner.

required
field_name str

Relation field being resolved.

required
matches int

Number of matching rows; exactly one is required.

required
lookup object

Lookup payload included in the message with repr(lookup).

required
Message

ReadOnlyInterface '{interface_name}' could not resolve relation '{field_name}' (expected 1 match, found {matches}) for lookup {lookup!r}.

general_manager.interface.utils.errors.InvalidReadOnlyDataFormatError

Bases: TypeError

Raised when read-only _data has an invalid row/list shape.

__init__

__init__()

Build the fixed _data JSON must decode to a list of dictionaries. message.

general_manager.interface.utils.errors.InvalidReadOnlyDataTypeError

Bases: TypeError

Raised when read-only _data is neither a JSON string nor a list.

__init__

__init__()

Build the fixed _data must be a JSON string or a list of dictionaries. message.

general_manager.interface.utils.errors.MissingReadOnlyBindingError

Bases: RuntimeError

Raised when read-only sync runs before lifecycle binding completes.

__init__

__init__(interface_name)

Build an error message for missing manager/model binding.

Parameters:

Name Type Description Default
interface_name str

Name of the unbound read-only interface class.

required
Message

ReadOnlyInterface '{interface_name}' must be bound to a manager and model before syncing.

general_manager.interface.utils.errors.MissingModelConfigurationError

Bases: ValueError

Raised when an ExistingModelInterface does not declare model.

__init__

__init__(interface_name)

Build an error message for missing existing-model configuration.

Parameters:

Name Type Description Default
interface_name str

Name of the interface class missing model.

required
Message

{interface_name} must define a 'model' attribute.

general_manager.interface.utils.errors.UnsafeHistoryConfigurationError

Bases: ValueError

Raised when pre-registered history cannot follow an interface alias.

__init__

__init__(model_name, interface_name, alias)

Build guidance for replacing an unsafe simple-history tracker.

general_manager.interface.utils.errors.InvalidModelReferenceError

Bases: TypeError

Raised when an existing-model reference cannot be resolved.

__init__

__init__(reference)

Build an error message for an invalid model reference.

Parameters:

Name Type Description Default
reference object

Invalid value from ExistingModelInterface.model; its string form is included in the message.

required
Message

Invalid model reference '{reference}'.

general_manager.interface.utils.errors contains public exception classes shared by the interface implementations. Writable ORM create/update paths raise UnknownFieldError for unknown payload fields, InvalidFieldValueError when field assignment raises ValueError, and InvalidFieldTypeError when assignment raises TypeError. Descriptor generation raises DuplicateFieldNameError when generated attribute names collide, and soft delete raises MissingActivationSupportError when an active/inactive model does not expose is_active.

Read-only synchronization raises MissingReadOnlyBindingError before lifecycle binding, MissingReadOnlyDataError when the parent manager does not provide _data, InvalidReadOnlyDataTypeError when _data is neither a JSON string nor a list, InvalidReadOnlyDataFormatError for malformed decoded payloads, many-to-many values, or missing required unique fields, MissingUniqueFieldError when row identity cannot be determined, and ReadOnlyRelationLookupError when a relation lookup dictionary resolves zero or multiple rows. Existing-model resolution raises MissingModelConfigurationError for a missing model declaration and InvalidModelReferenceError for unresolved or non-model declarations. These exceptions preserve their constructor inputs only in the formatted message; they do not expose additional public attributes.

The message formats are stable:

  • InvalidFieldValueError(field_name, value): Invalid value for {field_name}: {value}.
  • InvalidFieldTypeError(field_name, error): Type error for {field_name}: {error}.
  • UnknownFieldError(field_name, model_name): {field_name} does not exist in {model_name}.
  • DuplicateFieldNameError(): Field name already exists.
  • MissingActivationSupportError(model_name): {model_name} must define an 'is_active' attribute.
  • MissingReadOnlyDataError(interface_name): ReadOnlyInterface '{interface_name}' must define a '_data' attribute.
  • MissingUniqueFieldError(interface_name): ReadOnlyInterface '{interface_name}' must declare at least one unique field.
  • ReadOnlyRelationLookupError(interface_name, field_name, matches, lookup): ReadOnlyInterface '{interface_name}' could not resolve relation '{field_name}' (expected 1 match, found {matches}) for lookup {lookup!r}.
  • InvalidReadOnlyDataFormatError(): _data JSON must decode to a list of dictionaries.
  • InvalidReadOnlyDataTypeError(): _data must be a JSON string or a list of dictionaries.
  • MissingReadOnlyBindingError(interface_name): ReadOnlyInterface '{interface_name}' must be bound to a manager and model before syncing.
  • MissingModelConfigurationError(interface_name): {interface_name} must define a 'model' attribute.
  • InvalidModelReferenceError(reference): Invalid model reference '{reference}'.

general_manager.interface.utils.database_interface_protocols.SupportsHistoryQuery

Bases: Protocol

Protocol for the query object returned by django-simple-history managers.

as_of

as_of(search_date)

Scope the history query to the state at a given date.

Parameters:

Name Type Description Default
search_date object | None

Date-like cutoff value accepted by the underlying history manager, or None for the full history.

required

Returns:

Type Description
'SupportsHistoryQuery'

History query limited to the specified search_date, or full

'SupportsHistoryQuery'

history when search_date is None.

using

using(alias)

Return a history query scoped to the given database/router alias.

Parameters:

Name Type Description Default
alias str

Database/router alias to target for the returned query.

required

Returns:

Type Description
'SupportsHistoryQuery'

A history query object configured to operate against the specified alias.

filter

filter(**kwargs)

Filter the history query using the provided lookup expressions.

Parameters:

Name Type Description Default
**kwargs object

Lookup expressions to filter history records.

{}

Returns:

Type Description
'SupportsHistoryQuery'

A SupportsHistoryQuery representing the filtered history results.

last

last()

Retrieve the last item from the history query results.

Returns:

Type Description
object

Final object in the query result set, or None when the query is

object

empty.

general_manager.interface.utils.database_interface_protocols.SupportsHistory

Bases: Protocol

Protocol for models exposing a django-simple-history manager.

general_manager.interface.utils.database_interface_protocols.SupportsActivation

Bases: Protocol

Protocol for models that can be activated/deactivated.

general_manager.interface.utils.database_interface_protocols.SupportsWrite

Bases: Protocol

Protocol for models supporting full_clean/save operations.

full_clean

full_clean(*args, **kwargs)

Validate the model's fields and run model- and field-level validation.

Parameters:

Name Type Description Default
*args object

Positional arguments forwarded to Django's Model.full_clean.

()
**kwargs object

Keyword arguments forwarded to Django's Model.full_clean.

{}

Raises:

Type Description
ValidationError

If validation fails.

save

save(*args, **kwargs)

Persist the model instance using its implementation-defined save behavior.

Parameters:

Name Type Description Default
*args object

Positional arguments forwarded to the underlying save method.

()
**kwargs object

Keyword arguments forwarded to the underlying save method.

{}

Returns:

Type Description
object

Result of the underlying save operation.

The database-interface protocols are structural helper types used by ORM capabilities. SupportsHistoryQuery models the small django-simple-history query surface GeneralManager calls: as_of(...), using(...), filter(...), and last(). Date cutoffs, lookup values, primary keys, and Django save return values are typed as object because they are forwarded to Django or django-simple-history without local interpretation. SupportsHistory, SupportsActivation, and SupportsWrite are runtime-checkable protocols for history managers, is_active soft-delete support, and writable model behavior.

Request Interfaces

Application authors normally use RequestField, RequestFilter, RequestQueryOperation, RequestMutationOperation, RequestTransportConfig, and the built-in auth/transport helpers. Transport authors usually implement SharedRequestTransport.send() or the hook protocols below.

RequestQueryOperation is an alias of RequestOperation. Prefer the alias in read/query declarations for readability; use RequestMutationOperation for create/update/delete declarations.

RequestQueryPlan is an alias of RequestPlan. It exists for readability and backward compatibility with earlier query-only request interfaces.

RequestAction is the literal action vocabulary used in plans and local predicates: all, create, delete, detail, exclude, filter, and update.

RequestLocation is the literal request-fragment location vocabulary: query, headers, path, and body.

RequestPayload is Mapping[str, object]; RequestHeaders is Mapping[str, str]; RequestResponse is one payload mapping or a list of payload mappings.

RequestInterface.input_fields is a dict[str, Input[type[object]]]. Request interfaces usually receive that mapping from the inherited lifecycle machinery; custom subclasses that override it should provide real Input descriptors, not plain metadata objects.

Request interface subclasses copy request configuration from Interface.Meta to same-named class attributes during subclass creation. Public Meta names are filters, query_operations, default_query_operation, transport, transport_config, auth_provider, retry_policy, create_operation, update_operation, delete_operation, create_serializer, update_serializer, response_serializer, and rules. Omitted values use the class defaults: empty filter and query-operation mappings, default_query_operation="list", no transport/auth/retry/serializer hooks, no mutation operations, and an empty rule list.

RequestSerializer receives one resolved value and returns the serialized value. RequestValidator receives one lookup value and should raise an exception when the value is invalid. RequestResponseNormalizer receives a raw transport response plus interface, operation, and plan, and must return a RequestQueryResult.

RequestOperation(name, path, ...) requires name and path. Optional constructor fields are method="GET", collection=False, filters={}, metadata={}, static_query_params={}, static_headers={}, static_body=None, and timeout=None. For request interfaces, pass filters=None when a declared operation should inherit the interface-level filter mapping; an explicit mapping, including {}, is operation-specific. Operations do not own serializer or response-normalizer hooks: mutation serializers such as create_serializer live on Interface.Meta, and response normalization lives on RequestTransportConfig.

Request capability internals use the same public types. Validation requires fields, a detail operation, callable serializers/auth hooks, valid retry policy settings, valid filter keys, and non-overlapping operation-local filters. Retry policies require max_attempts >= 1, non-negative base backoff, positive multiplier, bounded jitter, optional max backoff no lower than base backoff, and idempotency header/factory configured together. Query capabilities compile object-valued lookup maps into immutable RequestQueryPlan instances, track a request_query dependency, and defer execution to RequestBucket. Operation-local filters take precedence for their operation; inherited interface filters apply only when an operation declares filters=None. Unsupported local-only filters, excludes without remote support or fallback, invalid fragment locations, and conflicting duplicate fragment keys raise the documented request planning errors unchanged from the active query capability; RequestInterface.query_operation() does not wrap them. Attribute reads execute the detail plan only when no payload cache is present, require exactly one returned item, cache that mapping on the interface instance, and emit request.read.detail. Query execution emits request.query.execute; lifecycle cloning emits request.pre_create and _parent_class assignment emits request.post_create. Create/update/delete accept creator_id and history_comment for manager API compatibility but do not send those values to the remote service. RequestInterface.execute_request_plan() treats only create, update, and delete as mutation actions; every other action string resolves a query operation using plan.operation_name. Missing mutation operations raise NotImplementedError, undeclared non-default query operations raise UnknownRequestOperationError, and auth, retry, metrics, trace, transport, and normalization errors propagate according to the configured transport and normalizer implementations.

general_manager.interface.requests.RequestField dataclass

Describe a manager attribute exposed by a request-backed interface.

source may be a dotted path or tuple path inside the remote payload. default is used by higher-level interface code when an optional value is absent, and normalizer can convert the resolved value before assignment.

value_path

value_path(field_name)

Return the payload path used to resolve this field's value.

general_manager.interface.requests.RequestFilter dataclass

Declare how one manager lookup compiles into a remote request fragment.

location chooses whether the compiled value is written to query params, headers, path params, or body. compiler receives a RequestFilterBinding and may return a custom fragment. Filters without remote output must enable allow_local_fallback so matching happens against returned items.

param property

param

Return the legacy name for remote_name.

allow_exclude property

allow_exclude

Return the legacy name for supports_exclude.

exclude_param property

exclude_param

Return the legacy name for exclude_remote_name.

local_fallback property

local_fallback

Return the legacy name for allow_local_fallback.

remote property

remote

Return whether this filter writes a remote request parameter.

applies_to_operation

applies_to_operation(operation_name)

Return whether this filter may be used with the named operation.

validate_value

validate_value(filter_key, value)

Validate a lookup value and raise when its type or validator rejects it.

general_manager.interface.requests.RequestFilterBinding dataclass

Context passed into custom request filter compilers.

general_manager.interface.requests.RequestPlanFragment dataclass

A partial request-plan contribution produced by one filter mapping.

general_manager.interface.requests.RequestOperation dataclass

Describe a named remote request operation used by a request interface.

The path can contain {name} placeholders populated from RequestPlan.path_params. Static request parts are merged with the plan at execution time and conflicting duplicate keys raise RequestPlanConflictError. filters=None is a request-interface sentinel meaning "inherit the interface-level filter mapping"; an explicit mapping, including an empty mapping, is operation-specific.

general_manager.interface.requests.RequestMutationOperation dataclass

Bases: RequestOperation

Describe a named create, update, or delete operation for a request interface.

general_manager.interface.requests.RequestPlan dataclass

Normalized request plan produced from declarative request operations.

Transports consume this immutable value object. query_params, headers, path_params, and body are outbound request fragments; filters and excludes retain original manager lookup values for local fallback and introspection.

local_filters property

local_filters

Return local filter predicates keyed by lookup name.

__reduce__

__reduce__()

Return pickle state that restores immutable mapping proxies as mappings.

general_manager.interface.requests.RequestQueryResult dataclass

Normalized output returned by request query execution hooks.

items contains zero or more mapping payloads after response normalization. Single-object responses are represented as a one-item tuple.

general_manager.interface.requests.SharedRequestTransport

Bases: ABC

Base transport that builds and executes a request from a request plan.

execute() performs request construction, idempotency-key injection, auth, retry handling, metrics, tracing, and response normalization. Subclasses implement only send() for adapter-specific I/O.

execute

execute(
    *, interface_cls, operation, plan, identification=None
)

Execute a plan and return normalized query results.

send abstractmethod

send(
    request,
    *,
    interface_cls,
    operation,
    plan,
    identification
)

Send a normalized request and return a transport response.

general_manager.interface.requests.UrllibRequestTransport

Bases: SharedRequestTransport

First-party JSON transport backed by Python's stdlib HTTP client.

The transport supports absolute HTTP(S) URLs, JSON request bodies, decoded JSON object/list responses, operation-level timeout overrides, and HTTP status mapping through RequestTransportStatusError.

send

send(
    request,
    *,
    interface_cls,
    operation,
    plan,
    identification
)

Send a normalized HTTP request and return a decoded response.

general_manager.interface.requests.RequestTransportConfig dataclass

Static configuration used by a shared request transport.

base_url must be an absolute HTTP(S) origin, optionally with a base path; operation paths are joined with one slash. timeout is expressed in seconds and may be overridden per operation.

general_manager.interface.requests.RequestRetryPolicy dataclass

Framework retry/backoff policy for shared request transports.

By default only idempotent HTTP methods are retried. Set retry_non_idempotent_methods with an idempotency-key header/factory when retrying mutation methods such as POST or PATCH.

allows_method

allows_method(method)

Return whether this policy permits retrying the HTTP method.

compute_backoff_seconds

compute_backoff_seconds(*, retry_count, random_factor=None)

Return the 1-based retry delay in seconds after optional jitter.

build_idempotency_key

build_idempotency_key()

Return a caller-supplied idempotency key or generate a UUID string.

general_manager.interface.requests.RequestTransportRequest dataclass

Normalized outbound request passed to auth providers and transports.

url is the absolute base URL joined with the formatted operation path, while path keeps the formatted path alone for tracing and adapters. The mappings are copied into immutable mapping proxies during initialization.

general_manager.interface.requests.RequestTransportResponse dataclass

Decoded transport response before conversion into RequestQueryResult.

payload must already be decoded into either one mapping or a list of mappings. Use metadata for adapter-specific values that should survive response normalization.

general_manager.interface.requests.RequestAuthProvider

Bases: Protocol

Protocol for applying authentication to an outbound transport request.

apply

apply(request, *, interface_cls, operation, plan)

Return a request copy with authentication data applied.

general_manager.interface.requests.BearerTokenAuthProvider dataclass

Apply a bearer token to the Authorization header.

apply

apply(request, *, interface_cls, operation, plan)

Return a request copy with a Bearer <token> header.

general_manager.interface.requests.HeaderApiKeyAuthProvider dataclass

Apply an API key to a configured request header.

apply

apply(request, *, interface_cls, operation, plan)

Return a request copy with the configured header set to the API key.

general_manager.interface.requests.QueryApiKeyAuthProvider dataclass

Apply an API key to a configured query-string parameter.

apply

apply(request, *, interface_cls, operation, plan)

Return a request copy with the configured query parameter set.

general_manager.interface.requests.BasicAuthProvider dataclass

Apply HTTP basic auth to the Authorization header.

apply

apply(request, *, interface_cls, operation, plan)

Return a request copy with an RFC 7617-style Basic auth header.

general_manager.interface.requests.FieldMappingSerializer dataclass

Map one dictionary shape into another using declared key names.

The mapping is {target_key: source_key}. Missing source keys raise KeyError; extra payload keys are ignored.

__call__

__call__(payload)

Return a new payload containing only mapped target keys.

general_manager.interface.requests.RequestMetricsBackend

Bases: Protocol

Protocol for recording request-interface metrics.

record_request

record_request(
    *,
    service,
    operation,
    method,
    status_code,
    outcome,
    duration,
    retry_count
)

Record one completed transport execution in seconds.

record_error

record_error(
    *,
    service,
    operation,
    method,
    error_class,
    status_code,
    retry_count
)

Record one failed transport execution after retries stop.

general_manager.interface.requests.NoopRequestMetricsBackend

Default metrics backend used when request metrics are not configured.

record_request

record_request(
    *,
    service,
    operation,
    method,
    status_code,
    outcome,
    duration,
    retry_count
)

Accept a successful request metric without recording it.

record_error

record_error(
    *,
    service,
    operation,
    method,
    error_class,
    status_code,
    retry_count
)

Accept an error metric without recording it.

general_manager.interface.requests.RequestTraceBackend

Bases: Protocol

Protocol for optional request tracing hooks.

on_request_start

on_request_start(*, service, operation, method, path)

Start tracing for the overall request execution and return context.

on_request_end

on_request_end(
    *,
    trace_context,
    service,
    operation,
    method,
    path,
    status_code,
    request_id,
    retry_count
)

Finish tracing for a successful request execution.

on_request_error

on_request_error(
    *,
    trace_context,
    service,
    operation,
    method,
    path,
    error,
    status_code,
    retry_count
)

Finish tracing for a failed request execution.

general_manager.interface.requests.NoopRequestTraceBackend

Default tracing backend used when request tracing is not configured.

on_request_start

on_request_start(*, service, operation, method, path)

Return an inert trace context for a request start event.

on_request_end

on_request_end(
    *,
    trace_context,
    service,
    operation,
    method,
    path,
    status_code,
    request_id,
    retry_count
)

Ignore a successful request end event.

on_request_error

on_request_error(
    *,
    trace_context,
    service,
    operation,
    method,
    path,
    error,
    status_code,
    retry_count
)

Ignore a failed request end event.

Request Errors

general_manager.interface.requests.RequestRemoteError

Bases: RequestInterfaceError

Base class for transport or upstream-service request failures.

general_manager.interface.requests.RequestTransportError

Bases: RequestRemoteError

Raised when request execution fails before a usable upstream response exists.

general_manager.interface.requests.RequestTransportStatusError

Bases: RequestTransportError

Raised by transports when an upstream HTTP-style status indicates failure.

__init__

__init__(
    *, status_code, request, payload=None, headers=None
)

Store the failed request, decoded payload, response headers, and status.

general_manager.interface.requests.RequestAuthenticationError

Bases: RequestRemoteError

Raised when the upstream service rejects request authentication.

general_manager.interface.requests.RequestAuthorizationError

Bases: RequestRemoteError

Raised when the upstream service denies access to the request.

general_manager.interface.requests.RequestNotFoundError

Bases: RequestRemoteError

Raised when the upstream service reports that a resource was not found.

general_manager.interface.requests.RequestConflictError

Bases: RequestRemoteError

Raised when the upstream service reports a conflicting request.

general_manager.interface.requests.RequestRateLimitedError

Bases: RequestRemoteError

Raised when the upstream service rate-limits the request.

general_manager.interface.requests.RequestSchemaError

Bases: RequestInterfaceError

Raised when a request payload or serializer returns an invalid schema.

serializer_must_return_mappings classmethod

serializer_must_return_mappings(interface_name)

Return an error for serializers that produce non-mapping payloads.

non_mapping_payload classmethod

non_mapping_payload(interface_name, operation_name)

Return an error for operation payloads that are not mappings.

non_mapping_json_list classmethod

non_mapping_json_list()

Return an error for JSON arrays containing non-object items.

non_object_json_payload classmethod

non_object_json_payload()

Return an error for decoded JSON that is not an object or object list.

unsupported_url_scheme classmethod

unsupported_url_scheme(url)

Return an error for transports asked to call non-HTTP(S) URLs.

general_manager.interface.requests.RequestPlanConflictError

Bases: ValueError

Raised when multiple filters try to write incompatible request fragments.

general_manager.interface.requests.MissingRequestPayloadFieldError

Bases: KeyError

Raised when a required field is missing from a remote payload.

general_manager.interface.requests.RequestServerError

Bases: RequestRemoteError

Raised when the upstream service returns a server-side error.

Interface Infrastructure

general_manager.interface.infrastructure.startup_hooks.register_startup_hook

register_startup_hook(
    interface_cls, hook, *, dependency_resolver=None
)

Register a startup hook associated with an interface type.

Registrations are kept in insertion order per interface. If the same hook object is already registered for the same interface with the same dependency resolver object, the second registration is ignored. The function only records the hook; exceptions from the hook or resolver can occur later when callers run the registered hooks.

Parameters:

Name Type Description Default
interface_cls InterfaceType

The interface type the hook applies to.

required
hook StartupHook

Callable invoked at startup for implementations of the interface.

required
dependency_resolver DependencyResolver | None

Optional callable that returns the interface types interface_cls depends on. Hooks registered with the same resolver are grouped and ordered together by the startup runner.

None

general_manager.interface.infrastructure.startup_hooks.iter_interface_startup_hooks

iter_interface_startup_hooks()

Yield registered interface/hook pairs without dependency ordering.

This iterator preserves the registry's insertion order: interfaces appear in the order they were first registered and hooks appear in per-interface registration order. It intentionally omits dependency-resolver metadata; use registered_startup_hook_entries() when runner-like dependency grouping is required.

Returns:

Type Description
Iterator[tuple[InterfaceType, StartupHook]]

Iterator of (interface_cls, hook) tuples.

general_manager.interface.infrastructure.startup_hooks.registered_startup_hooks

registered_startup_hooks()

Return a detached registry snapshot keyed by interface type.

Returns:

Type Description
dict[InterfaceType, tuple[StartupHook, ...]]

Mapping from each interface class to its startup hook callables. The

dict[InterfaceType, tuple[StartupHook, ...]]

returned dictionary is detached from the registry and each hook sequence

dict[InterfaceType, tuple[StartupHook, ...]]

is a tuple preserving per-interface registration order.

general_manager.interface.infrastructure.startup_hooks.registered_startup_hook_entries

registered_startup_hook_entries()

Return a detached snapshot including dependency resolvers.

Returns:

Type Description
dict[InterfaceType, tuple[StartupHookEntry, ...]]

Mapping from each interface class to immutable StartupHookEntry

dict[InterfaceType, tuple[StartupHookEntry, ...]]

records. The returned dictionary is detached from the registry and the

dict[InterfaceType, tuple[StartupHookEntry, ...]]

tuple preserves per-interface registration order.

general_manager.interface.infrastructure.startup_hooks.clear_startup_hooks

clear_startup_hooks()

Clear every registered startup hook.

This is intended for tests and bootstrap reset flows. It mutates only the process-local registry and does not affect previously returned snapshot dictionaries.

general_manager.interface.infrastructure.startup_hooks.order_interfaces_by_dependency

order_interfaces_by_dependency(
    interfaces, dependency_resolver
)

Order interface classes so dependencies appear before dependents.

When dependency_resolver is None, the input order is returned unchanged. Otherwise, the resolver is called once for each input interface class and may return any set-like collection of interface classes. Dependencies not present in interfaces are ignored. Cycles and self-dependencies do not raise; affected interfaces are appended after the acyclic ordered portion in their original relative order. Resolver exceptions propagate to the caller.

Parameters:

Name Type Description Default
interfaces Sequence[InterfaceType]

Interface classes to order. The original order is used as a stable tie-breaker and as the fallback order for unresolved cycles.

required
dependency_resolver DependencyResolver | None

Optional callable that returns the interface classes each input interface depends on.

required

Returns:

Type Description
list[InterfaceType]

Ordered list of interface classes. With a resolver, repeated interface

list[InterfaceType]

classes collapse to the first ordered occurrence because dependency

list[InterfaceType]

tracking is keyed by interface class.

general_manager.interface.infrastructure.system_checks.register_system_check

register_system_check(interface_cls, hook)

Register a system-check hook for an interface type.

Parameters:

Name Type Description Default
interface_cls InterfaceType

The interface class to associate the hook with.

required
hook SystemCheckHook

No-argument callable that returns a list of Django system-check result objects.

required
Notes

If the same hook is already registered for the interface, this function leaves registrations unchanged.

general_manager.interface.infrastructure.system_checks.iter_interface_system_checks

iter_interface_system_checks()

Iterate over all registered system-check hooks, yielding an (interface, hook) pair for each.

Returns:

Name Type Description
iterator Iterator[tuple[InterfaceType, SystemCheckHook]]

An iterator that yields (interface_cls, hook) pairs for every hook currently registered in the module registry.

general_manager.interface.infrastructure.system_checks.registered_system_checks

registered_system_checks()

Map interface types to tuples of their registered system-check hooks.

Returns:

Type Description
dict[InterfaceType, tuple[SystemCheckHook, ...]]

A detached snapshot mapping each interface class to a tuple of its

dict[InterfaceType, tuple[SystemCheckHook, ...]]

registered system-check hooks. Mutating the returned dict is harmless

dict[InterfaceType, tuple[SystemCheckHook, ...]]

and does not mutate the registry; subsequent registry changes do not

dict[InterfaceType, tuple[SystemCheckHook, ...]]

affect the returned tuples.

general_manager.interface.infrastructure.system_checks.clear_system_checks

clear_system_checks()

Remove all registered system checks, primarily for test isolation.