Skip to content

Core API

general_manager.manager.general_manager.GeneralManager

identification property

identification

Return the identification dictionary used to fetch the managed object.

history property

history

Return the history queryset scoped to this manager instance.

__init__

__init__(*args, **kwargs)

Create a manager by constructing its Interface and record the resulting identification.

Parameters:

Name Type Description Default
*args object

Positional arguments forwarded to the Interface constructor.

()
**kwargs object

Keyword arguments forwarded to the Interface constructor.

{}

__str__

__str__()

Return a user-friendly representation showing the identification.

__repr__

__repr__()

Return a detailed representation of the manager instance.

__getattr__

__getattr__(attribute_name)

Lazily install descriptors for declared fields on late-imported managers.

Manager classes imported after Django app startup are registered but have not yet had descriptor properties attached. Falling back here lets interactive and test-only managers behave like startup-loaded managers while preserving normal AttributeError behavior for unknown names. The fallback calls GeneralManagerMeta.ensure_attributes_initialized(self.__class__, attribute_name); a truthy result means descriptors were installed and the attribute is returned through object.__getattribute__. A falsey result raises AttributeError(attribute_name).

__reduce__

__reduce__()

Provide snapshot-preserving pickling support for this manager.

__or__

__or__(other)

Combine this manager with another manager or a Bucket into a Bucket representing their union.

Parameters:

Name Type Description Default
other Self | Bucket[Self]

A manager of the same class or a Bucket to union with.

required

Returns:

Type Description
Bucket[Self]

Bucket[Self]: A Bucket containing the union of the managed objects represented by this manager and other.

Raises:

Type Description
UnsupportedUnionOperandError

If other is not a Bucket and not a GeneralManager instance of the same class.

__eq__

__eq__(other)

Determine whether another object represents the same managed entity.

Returns:

Type Description
bool

true if other is a GeneralManager whose identification equals this manager's, false otherwise.

__iter__

__iter__()

Iterate over attribute names and resolved values for the managed object.

Callable entries in _attributes are invoked with self._interface. The synthetic history property and generated relation descriptors are skipped. GraphQLProperty and normal property class attributes are yielded by reading them through getattr(self, name).

create classmethod

create(
    creator_id=None,
    history_comment=None,
    ignore_permission=False,
    **kwargs
)

Create a new managed object through the interface.

Parameters:

Name Type Description Default
creator_id int | None

Optional identifier of the creating user.

None
history_comment str | None

Audit comment stored with the change.

None
ignore_permission bool

When True, skip permission validation.

False
**kwargs object

Additional fields forwarded to the interface create method.

{}

Returns:

Name Type Description
Self Self

Manager instance representing the created object.

Raises:

Type Description
PermissionError

Propagated if the permission check fails.

update

update(
    creator_id=None,
    history_comment=None,
    ignore_permission=False,
    **kwargs
)

Update the managed object, refresh this manager in place, and return it.

Parameters:

Name Type Description Default
creator_id int | None

Optional identifier of the user performing the update.

None
history_comment str | None

Optional audit comment recorded with the update.

None
ignore_permission bool

If True, skip permission validation.

False
**kwargs object

Field updates forwarded to the interface.

{}

Returns:

Name Type Description
Self Self

This manager instance after reloading its backing interface state.

Raises:

Type Description
PermissionError

If the permission check fails when ignore_permission is False.

delete

delete(
    creator_id=None,
    history_comment=None,
    ignore_permission=False,
)

Delete the managed object; performs a soft delete when the underlying interface is configured accordingly.

Parameters:

Name Type Description Default
creator_id int | None

Optional identifier of the user performing the action.

None
history_comment str | None

Audit comment recorded with the deletion.

None
ignore_permission bool

When True, skip permission validation.

False

Raises:

Type Description
PermissionError

If permission validation fails.

filter classmethod

filter(**kwargs)

Get a Bucket of managers matching the provided lookup expressions.

Lookup expressions may include GeneralManager instances, or lists/tuples containing them. Single-field manager identifications are replaced with their id value only when the identification mapping has exactly the one key "id". Empty mappings, single-key non-"id" mappings, and multi-key mappings are replaced with a copied identification mapping before the lookups are forwarded to the interface. Normalization is shallow: only top-level lookup values and direct list/tuple items are inspected. Non-manager values, including nested containers, are forwarded unchanged. When no manager values are present, the original kwargs mapping is delegated. The method returns the interface result typed as Bucket[Self] and does not wrap identification, mapping-copy, interface, or bucket errors.

Parameters:

Name Type Description Default
**kwargs object

Lookup expressions used to filter managers.

{}

Returns:

Type Description
Bucket[Self]

Bucket[Self]: Bucket containing manager instances that match the lookups.

get classmethod

get(**kwargs)

Return the single manager matching the provided lookup expressions.

This is a convenience wrapper around filter(...).get() and preserves the underlying bucket's single-item exception behavior.

exclude classmethod

exclude(**kwargs)

Return a bucket excluding managers that match the provided lookups.

Lookup normalization, return typing, and error propagation match filter(...).

Parameters:

Name Type Description Default
**kwargs object

Lookup expressions forwarded to the interface as exclusions.

{}

Returns:

Type Description
Bucket[Self]

Bucket[Self]: Bucket of manager instances that do not satisfy the lookups.

all classmethod

all()

Return a bucket containing every managed object of this class.

__parse_identification staticmethod

__parse_identification(kwargs)

Replace manager instances within a filter mapping by lookup identifiers.

Parameters:

Name Type Description Default
kwargs dict[str, object]

Mapping containing potential manager instances.

required

Returns:

Type Description
dict[str, object] | None

Mapping with managers substituted by lookup identifiers, or

dict[str, object] | None

None if no substitutions occurred.

__lookup_identifier staticmethod

__lookup_identifier(manager)

Return the scalar id for normal managers, or a copy for composite ids.

GeneralManager(*args, **kwargs) constructs the configured Interface, stores its identification mapping, and tracks an identification dependency. Public constructor inputs are the interface inputs for that manager; constructor validation and input-specific errors come from the interface. identification returns the stored mapping, and str(manager)/repr(manager) render ClassName(**identification). Iterating a manager yields declared attributes and GraphQL/property values after checking that the manager state is still valid. Callable entries in _attributes are invoked with self._interface; the synthetic history property and generated relation descriptors are skipped. Managers start valid after construction or trusted hydration. _reload_interface_state() reconstructs Interface(**identification), marks the manager valid, and clears the invalidation reason. _invalidate_manager_state(reason) marks the manager invalid and stores the reason. Reading or mutating a manager after delete() raises InvalidManagerStateError.

GeneralManager.create(creator_id=None, history_comment=None, ignore_permission=False, **fields) checks create permission unless ignore_permission is true, delegates to Interface.create(...), logs the created identification, and returns a new manager constructed from that identification. manager.update(...) checks that the manager is still valid, checks update permission unless skipped, delegates to the interface, reloads the backing interface in place, preserves request payload cache when available, and returns the same manager instance. manager.delete(...) checks delete permission unless skipped, delegates to the interface, invalidates the manager for later field reads, and returns None.

For writable ORM interfaces as of GeneralManager 0.63.1, ordinary create()/update() calls commit the row save, history actor/reason, and many-to-many <relation>_id_list changes in one transaction on the configured database alias. Validation, save, history, relation, and transaction exceptions propagate and roll back that complete unit. Upload-aware writes retain their separate atomic upload/finalization contract. After a caller-owned transaction rolls back, discard an in-place-updated manager and reconstruct it from its ID; materialized values on that Python object may reflect the failed transaction. The ORM transaction guide shows the pattern.

GeneralManager.filter(**lookups) and exclude(**lookups) forward lookup expressions to the interface and return Bucket[Self]. Lookup values may be manager instances or lists/tuples containing manager instances; those values are replaced with their scalar identification["id"] value for normal single-id managers, or with a copied identification mapping for composite identifiers, before the interface call. Scalar normalization applies only when the identification mapping has exactly the one key "id". Empty mappings, single-key non-"id" mappings, and multi-key mappings are forwarded as copied identification mappings. Normalization is shallow: only top-level lookup values and direct list/tuple items are inspected. Nested containers and non-manager values are forwarded unchanged. Calls without manager values delegate the original lookup mapping. These methods return the interface result typed as Bucket[Self] and do not wrap identification access, mapping-copy, interface, or bucket errors. GeneralManager.get(**lookups) is filter(**lookups).get() and preserves the bucket's single-item behavior. GeneralManager.all() returns Interface.filter() as a bucket of the concrete manager class.

manager.history delegates to the configured history capability's get_history_queryset_for_manager(Interface, manager) and returns that queryset object. Missing history capability support raises HistoryNotSupportedError. Late descriptor fallback calls GeneralManagerMeta.ensure_attributes_initialized(cls, name); when it returns true, the attribute is read normally, and otherwise AttributeError(name) is raised.

GeneralManager.__or__(other) combines a manager instance with either a compatible Bucket or another manager instance of the exact same class. Bucket operands handle the union themselves; same-class manager operands call filter(id__in=[left.identification, right.identification]). Other operands raise UnsupportedUnionOperandError.

GeneralManager._from_trusted_orm_instance(row, *, search_date=None) is an internal trusted hydration hook for framework-owned ORM rows. It bypasses public input validation and should only be used with Django rows already loaded by the owning ORM interface. Managers that use the base constructor hydrate by calling the interface's trusted ORM hook directly, store the hydrated interface and its identification, mark state valid, and track the identification dependency. Managers with a custom __init__ are reconstructed with cls(row.pk) or cls(row.pk, search_date=search_date) so their custom construction contract still runs. ORM interfaces normalize search_date while building the trusted interface or constructor path. Interfaces without a trusted hydration hook raise TrustedOrmHydrationNotSupportedError.

UnsupportedUnionOperandError(type_) renders Unsupported type for union: {type_}.. TrustedOrmHydrationNotSupportedError(interface_name) renders {interface_name} does not support trusted ORM hydration..

general_manager.manager.general_manager.UnsupportedUnionOperandError

Bases: TypeError

Raised when attempting to union a manager with an incompatible operand.

The public message is "Unsupported type for union: {operand_type}.".

__init__

__init__(operand_type)

Exception raised when attempting to perform a union with an unsupported operand type.

Parameters:

Name Type Description Default
operand_type type

The operand type that is not supported for the union; its representation is included in the exception message.

required

general_manager.manager.general_manager.TrustedOrmHydrationNotSupportedError

Bases: TypeError

Raised when trusted ORM hydration is requested for a non-ORM interface.

The public message is "{interface_name} does not support trusted ORM hydration.".

general_manager.utils.public_api.MissingExportError

Bases: AttributeError

Raised when a requested export is not defined in the public API.

__init__

__init__(module_name, attribute)

Initialize the MissingExportError with the originating module name and the missing attribute.

Constructs the exception message "module 'module_name' has no attribute 'attribute'".

Parameters:

Name Type Description Default
module_name str

Name of the module where the attribute was expected.

required
attribute str

Name of the missing attribute.

required

Package-level imports such as from general_manager import GeneralManager and from general_manager.interface import DatabaseInterface are resolved lazily from the public API registry. A package __getattr__(name) returns the resolved export object, caches it in that package module, and raises MissingExportError for names not listed in that package's __all__. dir(package) includes both currently loaded module globals and registered lazy exports. Successful lazy resolutions are debug-logged with module, export, target module, and target attribute context. Missing public exports are warning-logged with module and export context.

general_manager.models is the root Django models module for this app. It re-exports SearchIndexState, WorkflowEventRecord, WorkflowOutbox, WorkflowExecutionRecord, and WorkflowDeliveryAttempt from their canonical search/workflow modules for Django discovery and stable root-module imports. The module defines no helper callables, accepts no application input, returns no application output, and does not wrap import or Django app-registry errors. Detailed field and model behavior is documented in the Search and Workflow API pages.

general_manager.apps.GeneralmanagerConfig

Bases: AppConfig

Django application configuration for GeneralManager startup hooks.

ready

ready()

Coordinate all startup phases for the general_manager app.

The startup sequence installs hook runners and system checks, imports optional app managers modules, initializes pending manager classes, configures remote APIs, observability, search, workflow, and warm-up schedulers, and finally builds GraphQL when AUTOCREATE_GRAPHQL is enabled.

Raises:

Type Description
Exception

Startup errors from imported managers modules, initialization, settings-backed configurators, remote API wiring, or GraphQL bootstrap propagate unchanged.

install_startup_hook_runner staticmethod

install_startup_hook_runner()

Install the startup hook runner through the bootstrap module.

register_system_checks staticmethod

register_system_checks()

Register GeneralManager system checks through the bootstrap module.

initialize_general_manager_classes staticmethod

initialize_general_manager_classes(
    pending_attribute_initialization, all_classes
)

Initialize pending manager classes through the bootstrap module.

Parameters:

Name Type Description Default
pending_attribute_initialization list[type[GeneralManager]]

Manager classes whose generated attributes still need initialization.

required
all_classes list[type[GeneralManager]]

Registry of all known manager classes used for initialization and permission validation.

required

Raises:

Type Description
Exception

Propagates errors from bootstrap initialization, including invalid permission-class configuration.

check_permission_class staticmethod

check_permission_class(general_manager_class)

Validate a manager permission class through the bootstrap module.

Parameters:

Name Type Description Default
general_manager_class type[GeneralManager]

Manager class whose nested permission class should be checked.

required

Raises:

Type Description
InvalidPermissionClassError

If the configured permission class is not a BasePermission subclass.

handle_graph_ql staticmethod

handle_graph_ql(pending_graphql_interfaces)

Build GraphQL integration for pending manager interfaces.

Parameters:

Name Type Description Default
pending_graphql_interfaces list[type[GeneralManager]]

Manager classes queued for GraphQL interface and mutation generation.

required

Raises:

Type Description
Exception

Propagates GraphQL schema, URLConf, and ASGI wiring errors from bootstrap.

handle_remote_api staticmethod

handle_remote_api(manager_classes)

Register remote API integration for manager classes.

Parameters:

Name Type Description Default
manager_classes list[type[GeneralManager]]

Manager classes inspected for remote API exposure.

required

Raises:

Type Description
Exception

Propagates errors from remote API registration.

add_graphql_url staticmethod

add_graphql_url(schema)

Add the generated GraphQL URL to the configured URLConf.

Parameters:

Name Type Description Default
schema Schema

Graphene schema served by the generated GraphQL view.

required

Raises:

Type Description
MissingRootUrlconfError

If Django has no ROOT_URLCONF setting.

Exception

Propagates import, URLConf mutation, middleware, view, or ASGI route wiring errors from bootstrap.

GeneralmanagerConfig.ready() is the Django startup entry point for the package. It installs the management-command startup-hook runner and registers system checks before importing optional <app>.managers modules and initializing pending manager classes. Installing the runner does not execute registered startup hooks immediately; the patched management-command runner executes them before supported commands run. After manager initialization, ready() registers remote APIs, configures audit logging, search, workflow, search reconciliation, and GraphQL warm-up schedules, and builds the GraphQL schema only when AUTOCREATE_GRAPHQL is enabled. Startup failures from manager imports, initialization, settings-backed configurators, remote API wiring, or GraphQL bootstrap propagate through Django's app-loading path.

The static methods on GeneralmanagerConfig are compatibility wrappers around general_manager.bootstrap helpers. They keep older imports and tests working: install_startup_hook_runner(), register_system_checks(), initialize_general_manager_classes(...), check_permission_class(...), handle_graph_ql(...), handle_remote_api(...), add_graphql_url(schema), and _ensure_asgi_subscription_route(graphql_url). add_graphql_url(schema) requires a Graphene schema and raises MissingRootUrlconfError when Django has no ROOT_URLCONF. Other wrapper errors propagate from the bootstrap helper they call. register_system_checks() is process-idempotent by module-qualified interface class identity, so repeated app setup skips already-registered hooks without suppressing different interface classes that share the same bare class name.

general_manager.manager.meta.GeneralManagerMeta

Bases: type

Metaclass responsible for wiring GeneralManager interfaces and registries.

The metaclass validates declared Interface classes, lets interface lifecycle hooks alter class creation, tracks manager classes for startup initialization and GraphQL generation, and lazily installs descriptor-backed fields for managers imported after startup. The process-global registries are append-only for class creation; this class does not deduplicate entries or lock registry mutation outside descriptor initialization.

__getattribute__

__getattribute__(attribute_name)

Initialize late-imported field descriptors before class attribute lookup.

__getattr__ is only reached for missing names, so inherited GeneralManager attributes must pass through here to let declared fields override inherited names the same way bootstrap initialization does. Once a manager class has completed descriptor initialization, attributes already present on that class use normal type lookup without rechecking initialization. Missing names and inherited public names still pass through initialization so late-discovered fields keep the existing override behavior. "Non-private" means the requested name does not start with "_" and is not exactly "Interface". Probing an unknown public name may call Interface.get_attributes(), but it installs descriptors only when the probed name is declared by the interface.

Parameters:

Name Type Description Default
attribute_name str

Class attribute being read.

required

Returns:

Type Description
object

The attribute returned by type.__getattribute__ after optional

object

descriptor initialization.

Raises:

Type Description
AttributeError

Propagated from normal class attribute lookup.

Exception

Exceptions from Interface.get_attributes() other than NotImplementedError propagate unchanged.

__getattr__

__getattr__(attribute_name)

Lazily install field descriptors for manager classes imported after startup.

Django app initialization wires descriptors for managers known at startup. Managers defined later, for example in an interactive shell or a test scratch module, still register with this metaclass but have not had descriptors attached yet. If the missing class attribute is a declared manager field, initialize the class and retry the lookup. Unknown names may call the interface attribute provider, but they do not cache _attributes or install descriptors unless the name is declared.

Parameters:

Name Type Description Default
attribute_name str

Missing class attribute being resolved.

required

Returns:

Type Description
object

The descriptor-backed attribute value after initialization.

Raises:

Type Description
AttributeError

If the name is not an interface-backed field.

Exception

Exceptions from Interface.get_attributes() other than NotImplementedError propagate unchanged.

ensure_attributes_initialized staticmethod

ensure_attributes_initialized(
    manager_class, attribute_name=None
)

Ensure descriptor-backed fields are installed for manager_class.

Returns True when the class exposes attribute_name after initialization, or when no specific attribute was requested and descriptors were installed. Returns False for unknown attributes or classes that do not expose interface-backed fields. The class-level manager_class._attributes cache stores the dict[str, object] interface attribute mapping used to build descriptors; manager instances also store resolved per-instance values on instance._attributes. This shared attribute name is intentional compatibility behavior. Attribute mapping key order is preserved when descriptors are installed, empty mappings still count as successful initialization when no specific attribute_name was requested, and non-string keys are not validated here but are incompatible with normal descriptor installation.

Parameters:

Name Type Description Default
manager_class type['GeneralManager']

Manager class whose descriptors should be installed.

required
attribute_name str | None

Optional single field name to validate before installing descriptors.

None

Returns:

Type Description
bool

True when descriptors were already present or successfully

bool

installed for the requested field; otherwise False. A missing

bool

get_attributes method or a NotImplementedError from that

bool

method returns False.

Raises:

Type Description
Exception

Exceptions from Interface.get_attributes() other than NotImplementedError propagate unchanged.

ensure_manager_is_valid staticmethod

ensure_manager_is_valid(instance, attribute_name=None)

Raise when descriptor-backed field access targets an invalidated manager.

Missing _manager_state_valid is treated as valid. Missing _manager_state_reason falls back to "manager state is invalid" when the manager is marked invalid.

Parameters:

Name Type Description Default
instance 'GeneralManager'

Manager instance being accessed.

required
attribute_name str | None

Field name being read, or None for a whole manager validity check.

None

Raises:

Type Description
InvalidManagerStateError

If the manager carries an invalidated state flag.

__new__

__new__(mcs, name, bases, attrs)

Create a GeneralManager subclass, integrate any declared Interface hooks, and register the class for pending initialization and GraphQL processing.

If the class body directly defines an Interface key in attrs, validates it is a subclass of InterfaceBase, calls interface.handle_interface() on that class object, invokes the returned pre-creation hook to allow modification of the class namespace, creates the class, then invokes the returned post-creation hook and registers the class for attribute initialization and global tracking. Inherited Interface attributes are not treated as declared by this creation path; subclasses that should be managers must declare their own Interface class body entry. InterfaceBase itself satisfies the subclass check, but its default lifecycle path raises NotImplementedError unless a lifecycle capability or override is available. handle_interface() is a classmethod on InterfaceBase; concrete interfaces may inherit the capability-driven implementation or override it. It must return (pre_creation, post_creation) callables. pre_creation is called with (name, attrs, interface) and must return (attrs, interface_cls, model) where attrs is a dict[str, object] namespace passed to type.__new__, interface_cls is a type[InterfaceBase] used for post-creation and capability selection, and model is a Django Model subclass or None passed to post_creation. The metaclass does not separately assign new_class.Interface = interface_cls; the returned attrs mapping must contain the final "Interface" entry when the created class should expose that interface. post_creation is called with (new_class, interface_cls, model) and returns None. model is lifecycle pass-through owned by the interface capability; the metaclass does not store or validate it except by passing it to post_creation. Return values are not type-validated beyond tuple unpacking and the later calls that consume them. If Interface is not defined directly in attrs, creates the class directly. If settings.AUTOCREATE_GRAPHQL is true, registers the created class for GraphQL interface processing, including plain classes without an interface; later GraphQL bootstrap owns any filtering or failure behavior. If class creation or any interface-backed setup step raises before the settings check, pending_graphql_interfaces is not appended.

Capability selection is the interface capability manifest chosen by ManifestCapabilityBuilder for the returned interface_cls. It is built by ManifestCapabilityBuilder.build(interface_cls) and stored by interface_cls.set_capability_selection(selection) for later capability-handler lookup. This metaclass does not append to read_only_classes; the read-only lifecycle capability owns that registry.

Parameters:

Name Type Description Default
mcs type

The metaclass creating the class.

required
name str

Name of the class being created.

required
bases tuple[type, ...]

Base classes for the new class.

required
attrs dict[str, object]

Class namespace supplied during creation.

required

Returns:

Name Type Description
type type

The newly created subclass, possibly modified by Interface hooks.

Raises:

Type Description
InvalidInterfaceTypeError

If a declared Interface is not an InterfaceBase subclass.

NotImplementedError

Propagated from interfaces that cannot provide lifecycle hooks through handle_interface().

TypeError

Propagated from malformed hook call signatures, invalid class namespace values passed to type.__new__, invalid returned interface classes consumed by capability setup, or descriptor/class creation operations.

ValueError

Propagated from malformed lifecycle hook return unpacking.

NotImplementedError

Propagated from interfaces that cannot provide lifecycle hooks through handle_interface().

Exception

Other exceptions from interface pre/post creation hooks, capability selection, or setting the capability selection propagate unchanged.

create_at_properties_for_attributes staticmethod

create_at_properties_for_attributes(attributes, new_class)

Attach descriptor properties to new_class for each name in attributes.

Each generated descriptor returns the interface field type when accessed on the class and resolves the corresponding value from instance._attributes when accessed on an instance. Existing attributes with the same names are overwritten unconditionally, matching bootstrap descriptor installation. Generated descriptors implement only __get__; assignment to the same name on the class replaces the descriptor, and instance assignment follows normal non-data-descriptor shadowing rules. Descriptor reads cache resolved values on the manager instance and replay dependency tracking when returning a cached manager value. Duplicate names are processed in order, so later duplicates overwrite earlier descriptors. Non-string names or iterables that raise during iteration propagate their original exception and may leave descriptors from earlier names installed. If called through ensure_attributes_initialized(), those failures can occur after manager_class._attributes is cached and before pending-initialization removal. If the stored value is callable it is always treated as a deferred evaluator and invoked with instance._interface; expose literal callables by wrapping them in a non-callable container or by using a custom descriptor path. A missing stored key raises MissingAttributeError, but a missing instance._attributes mapping or missing instance._interface attribute raises the normal AttributeError. A present but malformed _interface is passed to the callable unchanged; callable failures are wrapped in AttributeEvaluationError.

Parameters:

Name Type Description Default
attributes Iterable[str]

Names of attributes for which descriptors will be created.

required
new_class type[GeneralManager]

Class that will receive the generated descriptor attributes.

required

Raises:

Type Description
MissingAttributeError

Later raised by generated descriptors when an instance does not contain the requested attribute.

AttributeEvaluationError

Later raised by generated descriptors when a callable attribute value fails.

InvalidManagerStateError

Later raised by generated descriptors when reading an invalidated manager.

GeneralManagerMeta is the metaclass behind every GeneralManager subclass. When a class body directly declares an Interface key in attrs, the metaclass validates that it is an InterfaceBase subclass, calls interface.handle_interface() on that class object, then calls the returned lifecycle pre-creation hook with (name, attrs, interface) and expects (attrs, interface_cls, model) back. Inherited Interface attributes are not treated as declarations by this class-creation path; subclasses that should be registered managers must declare their own Interface class body entry. InterfaceBase itself passes the subclass check, but its default lifecycle path raises NotImplementedError unless a lifecycle capability or override supplies hooks. InterfaceBase.handle_interface() is a classmethod; concrete interfaces may inherit its capability-driven implementation or override it. It must return (pre_creation, post_creation) callables. pre_creation(name, attrs, interface) returns (attrs, interface_cls, model): attrs is a dict[str, object] namespace passed to type.__new__, interface_cls is a type[InterfaceBase] used for post-creation and capability selection, and model is a Django Model subclass or None. The metaclass does not separately assign new_class.Interface = interface_cls; the returned attrs mapping must contain the final "Interface" entry when the created class should expose that interface. post_creation(new_class, interface_cls, model) returns None. model is lifecycle pass-through owned by the interface capability; the metaclass does not store or validate it except by passing it to post_creation. Return values are not type-validated beyond tuple unpacking and the later calls that consume them. After class creation the metaclass calls the post hook, builds capability selection from ManifestCapabilityBuilder.build(interface_cls), stores it with interface_cls.set_capability_selection(selection) for later capability-handler lookup, and appends the new class to all_classes and pending_attribute_initialization. Capability selection is the interface capability manifest chosen for the returned interface class. Invalid interface declarations raise InvalidInterfaceTypeError. Malformed hook call signatures, invalid class namespace values passed to type.__new__, invalid returned interface classes consumed by capability setup, and descriptor/class creation operations may raise TypeError; malformed lifecycle hook return unpacking may raise ValueError; unsupported lifecycle hooks raise NotImplementedError; other lifecycle hook errors, capability-selection errors, and selection-storage errors propagate from their source. Classes without an Interface are still created normally but are not added to the manager registries. When AUTOCREATE_GRAPHQL is enabled, pending_graphql_interfaces append happens after class creation and, for interface-backed managers, after pre-hook, post-hook, capability selection, pending_attribute_initialization, and all_classes registration. Every class created by the metaclass is appended, including plain classes without an Interface; downstream GraphQL bootstrap owns later filtering or failure behavior. If class creation or any interface-backed setup step raises before the settings check, pending_graphql_interfaces is not appended. read_only_classes is a sibling registry populated by the read-only lifecycle capability, not by GeneralManagerMeta.__new__; read-only lifecycle creation appends generated read-only manager classes there and normal tests or bootstrap cleanup may replace the list when restoring process state.

ensure_attributes_initialized(manager_class, attribute_name=None) installs descriptor-backed fields from manager_class.Interface.get_attributes(). Supplying attribute_name limits the success condition to that declared field: unknown names, managers without an Interface, interfaces without get_attributes, and interfaces whose read attributes raise NotImplementedError return False. Other errors from get_attributes() propagate. Probing an unknown public name may call get_attributes(), but it does not cache attributes or install descriptors unless the name is declared. Successful initialization stores the dict[str, object] interface attribute mapping on the class-level manager_class._attributes, creates descriptors for all declared fields, and removes the class from pending_attribute_initialization when present. Mapping key order is preserved when descriptors are installed. Empty mappings count as successful initialization when no specific attribute_name was requested. Non-string keys are not validated before descriptor installation; if setattr() rejects a key, the original exception propagates, _attributes may already be cached, descriptors from earlier keys may already be installed, and pending-initializer removal is skipped because execution stops before that step. A later ensure_attributes_initialized(manager_class) call sees the cached _attributes mapping and retries descriptor creation for all keys; a targeted call for a declared key also retries descriptor creation for all keys before returning True. Manager instances also use instance._attributes for resolved values; the shared attribute name is intentional compatibility behavior.

Generated descriptors return Interface.get_field_type(name) when read on the class. When read on an instance, they first call ensure_manager_is_valid(instance, name), then read instance._attributes[name]. Callable attribute values are invoked with instance._interface and are always treated as deferred evaluators; literal callables must be wrapped in a non-callable container or exposed by a custom descriptor path. Callable failures are wrapped in AttributeEvaluationError whose message starts with Error calling attribute {name}:, with the original exception chained as __cause__. Missing stored keys raise MissingAttributeError, but missing instance._attributes or instance._interface raises normal AttributeError. Invalidated managers raise InvalidManagerStateError, and class-level field type lookup errors propagate from the interface. Missing _manager_state_valid is treated as valid; a missing invalidation reason falls back to manager state is invalid. Invalid attribute reads render Cannot access attribute {attribute_name!r} on invalidated {ManagerName}: {reason}.; whole-manager checks render Cannot access invalidated {ManagerName}: {reason}..

GeneralManagerMeta.__getattribute__ performs lazy descriptor installation before class attribute reads whose names do not start with _, excluding Interface, so a declared field can override inherited manager methods such as create. __getattr__ performs the same lazy installation for genuinely missing class attributes and raises AttributeError(name) when the name is not an interface-backed field. Descriptor installation overwrites existing attributes with the same names, including explicit class attributes and inherited methods. Generated descriptors implement only __get__: assigning the same name on the class replaces the descriptor, assigning on an instance follows normal non-data-descriptor shadowing rules, and descriptor reads do not cache resolved values. Duplicate names are processed in order, so later duplicates overwrite earlier descriptors. Non-string names or attribute iterables that fail partway through propagate their original exception and may leave descriptors for earlier names installed. A present but malformed _interface is passed to callable attribute values unchanged; errors raised by that callable are wrapped as AttributeEvaluationError. Normal GeneralManager construction creates instance._interface from self.Interface(*args, **kwargs), and trusted ORM hydration creates it through the interface's trusted hydration hook. The descriptor does not check that the current instance._interface is an instance of new_class.Interface; it passes the value currently stored on the instance.

The class registries are process-local mutable lists used by bootstrap, search, GraphQL, tests, and read-only lifecycle wiring. Application code should treat them as framework-owned; replacement or clearing is tolerated for tests and advanced bootstrap integrations that restore process state afterward. Class creation appends without deduplication. Descriptor initialization holds one metaclass-level lock around checking/caching _attributes, calling get_attributes(), installing descriptors, and removing the class from pending_attribute_initialization; under that lock, get_attributes() is called at most once for a class whose attributes are successfully cached. Other registry mutation is not locked. Concurrent external clearing or replacement of the registry lists while classes are being created or descriptors are being initialized has no stronger guarantee than normal Python list assignment and mutation semantics.

An empty attribute mapping means the interface has no descriptor-backed fields to install. That still counts as initialized for bulk startup work because the class no longer needs pending descriptor processing; targeted initialization for a named field still returns False when the name is absent.

general_manager.manager.group_manager.GroupManager

Bases: Generic[GeneralManagerType]

Represent aggregated results for grouped GeneralManager records.

__init__

__init__(manager_class, group_by_value, data)

Initialise a grouped manager with the underlying bucket and grouping keys.

Parameters:

Name Type Description Default
manager_class type[GeneralManagerType]

Manager subclass whose records were grouped.

required
group_by_value dict[str, object]

Grouping key values describing this group.

required
data Bucket[GeneralManagerType]

Bucket of records belonging to the group.

required

Returns:

Type Description
None

None

__hash__

__hash__()

Return a hash based on the manager class, group keys, and grouped data.

Manager instances, mappings, lists, tuples, and sets are recursively frozen before hashing. Mapping entries are sorted by their frozen key/value tuples; sets become frozenset values. The resulting hash follows normal Python hash stability rules: it is suitable for the lifetime of unchanged group state, but it is not a cross-process persistent identifier and can change if mutable grouped data changes after construction.

Returns:

Name Type Description
int int

Hash value combining class, keys, and data.

__eq__

__eq__(other)

Compare grouped managers by manager class, keys, and grouped data.

Parameters:

Name Type Description Default
other object

Object to compare against.

required

Returns:

Name Type Description
bool bool

True when both grouped managers describe the same data.

__repr__

__repr__()

Return a debug representation showing grouped keys and data.

Returns:

Type Description
str

Debug string in the form

str

"GroupManager(<manager_class>, <group_by_value>, <data>)".

__iter__

__iter__()

Iterate over attribute names and their aggregated values.

Yields:

Type Description
str

Attribute name and aggregated value pairs. Interface attributes are

object

the keys returned by manager_class.Interface.get_attributes() and

tuple[str, object]

are yielded in that mapping's iteration order. GraphQLProperty

tuple[str, object]

values declared directly on the manager class are yielded after

tuple[str, object]

interface attributes in class __dict__ order. Duplicate names are

tuple[str, object]

not filtered.

__getattr__

__getattr__(item)

Lazily compute aggregated attribute values when accessed.

Parameters:

Name Type Description Default
item str

Attribute name requested by the caller.

required

Returns:

Type Description
object

Group-by key value or cached aggregate for the requested attribute.

object

Cached aggregate values are stored in the private _grouped_data

object

dictionary under the requested attribute name and are not

object

invalidated if the underlying bucket or group_by_value mapping is

object

mutated after first access.

Raises:

Type Description
MissingGroupAttributeError

If the attribute cannot be resolved from group metadata or a GraphQLProperty return annotation.

Exception

Exceptions raised while iterating the underlying bucket or reading grouped record attributes propagate unchanged.

combine_value

combine_value(item)

Aggregate the values of a named attribute across all records in the group.

Parameters:

Name Type Description Default
item str

Attribute name to aggregate from each grouped record.

required

Returns:

Type Description
object

Aggregated value for item: group "id", empty buckets, and

object

all-None values return None; bucket/manager values are unioned

object

with |; lists are concatenated; dicts are merged with later values

object

overwriting earlier keys; strings are deduplicated in encounter

object

order and joined by ", "; booleans use any() before numeric

object

handling; numeric and Measurement values are summed;

object

datetime/date/time values use max(). The aggregation branch is

object

selected from interface metadata or a concrete GraphQLProperty

object

return annotation, not from each runtime value, so mixed runtime

object

values follow the selected branch and may raise from that operation.

Raises:

Type Description
MissingGroupAttributeError

If the attribute does not exist or its type cannot be determined on the manager. GraphQLProperty annotations use the first typing.get_args() entry when present, otherwise the annotation object itself; unsupported non-class annotations raise this error.

Exception

Exceptions raised while reading grouped record attributes, unioning bucket/manager values, merging containers, summing values, or comparing date/time values propagate unchanged.

GroupManager is the per-group object yielded by GroupBucket. Attribute access first returns group-by key values, then lazily aggregates values from the group's underlying bucket and caches the result. Cached aggregates are not invalidated if the underlying bucket or group-key mapping is mutated later; they are stored in the private _grouped_data dictionary under the requested attribute name. Iteration yields keys from manager_class.Interface.get_attributes() first in that mapping's order, then GraphQLProperty values declared directly on the manager class in class-__dict__ order; duplicate names are not filtered.

id, empty buckets, and all-None inputs aggregate to None. Bucket and manager values are combined with |, lists are concatenated, dicts are merged with later values overwriting earlier keys, strings are de-duplicated in encounter order and joined by ", ", booleans use any() before numeric handling, numeric and Measurement values are summed, and date/time values use max(). The aggregation branch is chosen from interface metadata or a concrete GraphQLProperty return annotation, not from every runtime value, so mixed runtime values follow the selected branch and may raise from that operation. GraphQL property annotations use the first typing.get_args() entry when present, otherwise the annotation object itself; unsupported non-class annotations raise MissingGroupAttributeError. hash(group) recursively freezes manager instances, mappings, lists, tuples, and sets before hashing. Mapping entries are sorted by their frozen key/value tuples, sets become frozenset values, and the final hash is suitable only for unchanged in-process group state, not as a persistent cross-process identifier. Missing metadata or unsupported return annotations raise MissingGroupAttributeError; errors from bucket iteration, attribute access, unioning, summing, merging, or comparison propagate unchanged.

general_manager.manager.input.Input

Bases: Generic[INPUT_TYPE]

Describe an interface input's type, constraints, and dependency metadata.

Input instances are attached to Interface classes and consumed by GeneralManager interfaces when casting raw values, enumerating calculation combinations, or exposing GraphQL input metadata. The descriptor stores the expected Python class, optional allowed values, scalar bounds, dependency names, and optional validation/normalization callbacks. It does not validate that static possible_values match type during construction.

__init__

__init__(
    type,
    possible_values=None,
    depends_on=None,
    *,
    required=True,
    min_value=None,
    max_value=None,
    validator=None,
    normalizer=None
)

Create an Input specification with type information, constraints, and dependency metadata.

Parameters:

Name Type Description Default
type INPUT_TYPE

Expected Python class for the input value.

required
possible_values PossibleValues | None

Allowed values as a domain, iterable, bucket, or callable returning one.

None
depends_on list[str] | None

Names of other inputs required for dynamic constraints.

None
required bool

Whether callers must provide a value for this input.

True
min_value ScalarConstraint | None

Inclusive lower bound for scalar values.

None
max_value ScalarConstraint | None

Inclusive upper bound for scalar values.

None
validator Validator | None

Extra validation callback returning True/False or None.

None
normalizer Normalizer | None

Optional callback used to canonicalize values after casting.

None

Raises:

Type Description
TypeError

If type is not a class accepted by issubclass.

date_range classmethod

date_range(
    *,
    start,
    end,
    frequency="day",
    step=1,
    depends_on=None,
    required=True
)

Create a date input backed by a structured date range domain.

start and end may be dates or callbacks that accept declared dependency values. Dependency names are inferred from callback parameter names unless depends_on is supplied. The generated input normalizes non-daily frequencies to their canonical date before returning values from :meth:cast.

Raises:

Type Description
InvalidDateRangeError

If bounds, frequency, or step are invalid after dependency callbacks have been resolved.

TypeError

If a dependency callback cannot be invoked with the available dependency values.

KeyError

If a dependent domain is resolved without a required dependency value.

monthly_date classmethod

monthly_date(
    *,
    start,
    end,
    anchor="month_end",
    step=1,
    depends_on=None,
    required=True
)

Create a date input constrained to canonical monthly dates.

anchor accepts "start"/"month_start" and "end"/"month_end". Other values are forwarded as date-range frequencies and invalid values raise InvalidDateRangeError when the domain is built.

yearly_date classmethod

yearly_date(
    *,
    start,
    end,
    anchor="year_end",
    step=1,
    depends_on=None,
    required=True
)

Create a date input constrained to canonical yearly dates.

anchor accepts "start"/"year_start" and "end"/"year_end". Other values are forwarded as date-range frequencies and invalid values raise InvalidDateRangeError when the domain is built.

from_manager_query classmethod

from_manager_query(
    manager_type,
    *,
    query=None,
    depends_on=None,
    required=True
)

Create a manager input whose possible values come from a manager query.

With no query, possible values come from manager_type.all(). Mapping queries are passed to manager_type.filter(**query); callable queries receive dependency values and may return either a mapping or an already resolved iterable/bucket/domain.

Raises:

Type Description
AttributeError

If manager_type does not provide the required all or filter class method for the selected query form.

TypeError

If a query callback cannot be invoked with the available dependency values.

KeyError

If dependency values are missing when possible values are resolved.

resolve_possible_values

resolve_possible_values(
    identification=None, *, cache_context=None
)

Resolve possible values for the current dependency context.

Static values are returned unchanged. Callable providers receive only declared dependency values, raising KeyError when a dependency is missing. When called inside a calculation run with cache_context, provider results are cached by owner class, field name, and declared dependency values; one-shot iterators are materialized before caching. Unhashable dependency values skip the cache and call the provider.

normalize

normalize(
    value, identification=None, *, cache_context=None
)

Canonicalize a cast value using domain or explicit normalization rules.

If possible_values is a static InputDomain, domain normalization runs even when no custom normalizer is configured. Dynamic possible values are resolved only when a custom normalizer exists; if that resolved value is an InputDomain, dynamic-domain normalization runs before the custom normalizer. Custom normalizers receive the converted value first, then positional dependency values, a domain keyword containing the resolved possible-values object or None, and named dependency values. Unsupported callback signatures raise the normal Python TypeError from invocation.

validate_bounds

validate_bounds(value)

Return whether a value satisfies configured scalar bounds.

None is valid only for non-required inputs. For non-None values, Python comparison errors from incompatible value/bound types propagate.

validate_with_callable

validate_with_callable(value, identification=None)

Return whether a value satisfies the configured validator callback.

None values bypass custom validators. Validator callbacks receive the candidate value first, followed by declared dependency values selected from identification. A None return is treated as a successful validation and callback exceptions propagate unchanged.

cast

cast(value, identification=None, *, cache_context=None)

Convert a raw value to the configured input type and normalize it.

cast does not apply scalar bounds, possible-value membership checks, or the validator callback. Interface validation calls :meth:validate_bounds, possible-value membership, and :meth:validate_with_callable as separate steps.

Parameters:

Name Type Description Default
value object

Raw value supplied by the caller.

required
identification dict[str, object] | None

Mapping of dependency input names to their current values, used by dynamic possible values, normalizers, and validators.

None

Returns:

Type Description
object

Value converted to the target type, or None when value is

object

None.

Raises:

Type Description
ValueError

If date, datetime, measurement, or fallback constructor conversion rejects the value.

TypeError

If the configured type constructor or a callback cannot accept the supplied value/dependencies.

KeyError

If normalization needs a declared dependency that is missing from identification.

Input(type, possible_values=None, depends_on=None, *, required=True, min_value=None, max_value=None, validator=None, normalizer=None) is the public descriptor used on calculation and custom interfaces. It stores the expected Python class, optional static or callable allowed values, scalar bounds, dependency names, and optional validation/normalization callbacks. Construction does not check that static possible_values match type; value casting and interface validation perform the runtime checks. Unless this section says a detail belongs to an owning interface, the behavior described here is the public contract for the exported Input and domain classes. Supported type values are Python class objects that issubclass(type, GeneralManager) and isinstance(value, type) can inspect. Manager-typed inputs declare a GeneralManager subclass; manager instances are instances of that declared manager class.

Input.cast(value, identification=None, *, cache_context=None) converts raw values to the configured type and then normalizes them. None is returned unchanged. date and datetime inputs accept native values and ISO strings; date inputs convert native datetime values to .date(), while datetime inputs convert native date values with datetime.combine(value, datetime.min.time()). ISO strings are parsed by Python's date.fromisoformat() or datetime.fromisoformat() exactly, including their normal timezone-aware datetime behavior. Manager-typed inputs accept either a mapping used as constructor keywords or a single value passed as id; existing manager instances skip construction but still pass through normalization. The id path constructs manager_type(id=value) and does not perform a query by itself. Mappings, including mappings with an id key, are passed as manager_type(**mapping); invalid keywords and manager constructors that do not accept id fail through the constructor's normal exception. For every other type, already-matching values pass through normalization and non-matching values are converted with type(value). Constructor errors propagate unchanged. Measurement inputs accept the strings documented for Measurement.from_string(). cast() does not apply scalar bounds, possible-value membership checks, or the validator callback; interface validation calls validate_bounds(), membership validation, and validate_with_callable() separately. Conversion ValueErrors, constructor/callback TypeErrors, and missing dependency KeyErrors propagate. identification is the current input-value mapping keyed by dependency input name; Input only reads the dependency names declared on that input.

Callable possible_values, validators, and normalizers receive only declared dependency values. Dependency names are supplied explicitly through depends_on or inferred from non-variadic callback parameters. resolve_possible_values() returns static values unchanged, invokes providers for the current dependency context, and uses run-scoped caching only when a cache context and active calculation run are present. Cache keys include the owner class, input field name, and frozen declared dependency values; there is no cross-run invalidation. Unhashable dependency values skip the run cache. Static possible values are returned as the original object, not copied or materialized. The cache lives only for the active CalculationRunContext; leaving that run ends the cache lifetime.

Callback invocation follows each callback's signature. Dependency names are inferred from callable possible_values in Input(...), from start/end callbacks in Input.date_range(...), and from callable query in Input.from_manager_query(...). Validator and normalizer callbacks do not infer dependencies by themselves; pass depends_on when they need other input values. Names such as value or domain are not reserved during inference. Dependency values are available as both positional values in declared dependency order and named keyword values. Positional-only parameters consume positional values; positional-or-keyword parameters consume positional values first and then named values; keyword-only parameters consume named values; *args receives remaining positional values; **kwargs receives remaining named values. Defaults are left for Python to apply when no dependency value is supplied for that parameter. Normalizers also receive the converted value before dependency values and may accept a domain keyword containing the resolved possible values or None. For example, with depends_on=["project"], a validator lambda value, project: ... gets the candidate first and the project second; a normalizer lambda value, project, domain=None: ... gets the converted value, project, and resolved possible-values object. Avoid naming dependencies value or domain for normalizers unless you intentionally want Python-style positional binding to win over the same keyword name.

normalize(value, ...) first applies static InputDomain normalization. Dynamic possible values are resolved only when a custom normalizer exists; if the resolved object is an InputDomain, dynamic-domain normalization then runs before the custom normalizer. The domain keyword receives the resolved possible-values object itself, including non-domain iterables or buckets, or None when there are no possible values. A callable possible-values provider that returns an InputDomain does not normalize values during cast() unless a custom normalizer is present; this is intentional compatibility behavior.

validate_bounds(value) returns True for None only when required=False. For non-None values it compares the value directly with configured scalar bounds, so incompatible mixed types raise ordinary Python comparison errors. validate_with_callable(value, identification=None) skips None, treats a validator result of None as success, and propagates validator exceptions. Validators receive the candidate value first, followed by declared dependency values from identification. On Input itself, validate_bounds(None) is the requiredness check; owning interfaces may combine it with their own input-shape validation before calling the rest of the pipeline.

Input.date_range(...), Input.monthly_date(...), and Input.yearly_date(...) build date inputs backed by DateRangeDomain; Input.from_manager_query(...) builds manager inputs whose possible values come from .all() or .filter(**query). These helpers are stable public API. Input does not define a public membership-validation helper for plain iterables, buckets, or callable results; that validation belongs to the owning interface. Static possible values that do not match the declared type therefore fail only when an owning interface validates membership or a configured normalizer/domain operation rejects them.

general_manager.manager.input.InputDomain dataclass

Bases: Generic[VALUE_TYPE]

Structured description of an input domain.

The base domain stores a kind string, returns identity values from :meth:normalize, reports {"kind": kind} from :meth:metadata, and implements contains(value) as a safe membership check. Direct in checks call :meth:__contains__, which iterates over :meth:__iter__. On the base class that raises DomainIterationError because subclasses are responsible for finite iteration; call :meth:contains when callers need a false result instead of that eager-iteration error.

InputDomain is the base class for structured possible-value domains. It provides contains(value), normalize(value), metadata(), and iteration. The base class is intentionally not eagerly iterable and raises DomainIterationError; use concrete domains or custom subclasses for finite choices. The base normalize() is identity, base metadata() returns only {"kind": kind}, contains(value) catches TypeError from membership and returns False, and direct value in domain calls __contains__ and can propagate DomainIterationError from the base iterator or iteration errors from subclasses.

general_manager.manager.input.NumericRangeDomain dataclass

Bases: InputDomain[int | float | Decimal]

Inclusive finite numeric range with optional stepping.

Values are valid only when they fall on the generated step sequence. If any bound, step, or candidate is a Decimal, membership and iteration use Decimal arithmetic and iteration yields Decimal values. Otherwise, if any bound, step, or candidate is a float, they use float arithmetic and iteration yields float values. Pure integer ranges yield int values. bool is not a documented numeric input type even though Python may treat it as an integer at runtime. Floating-point checks use max(1e-12, abs(step) * 1e-9) tolerance and decimal checks use the equivalent Decimal tolerance so endpoint and step comparisons remain stable for common decimal fractions.

NumericRangeDomain(min_value, max_value, step=1) represents an inclusive finite numeric range for int, float, or Decimal values. It raises InvalidNumericRangeError when step <= 0 or min_value > max_value. Float membership uses max(1e-12, abs(step) * 1e-9) tolerance, and decimal membership uses max(Decimal("1e-12"), abs(Decimal(str(step))) * Decimal("1e-9")), so stepped ranges such as 0.0 to 0.3 by 0.1 behave predictably. Values inside the bounds but not on the step sequence are rejected. If any bound, step, or candidate is a Decimal, checks use decimal arithmetic and iteration yields Decimal values. Otherwise, if any bound, step, or candidate is a float, checks use float arithmetic and iteration yields floats. Pure integer ranges yield integers. bool is not a documented numeric input type even though Python may treat it as an integer at runtime; callers should not rely on bool-specific behavior as part of this API.

general_manager.manager.input.DateRangeDomain dataclass

Bases: InputDomain[date]

Inclusive finite date domain backed by a frequency and step.

Non-daily frequencies normalize candidate dates to the configured anchor before membership checks. week_end anchors to Sunday. Month and year steps advance by calendar months or years from the current anchored date; quarter steps advance by three-month intervals. Iteration starts at normalize(start) and stops once the next generated date would be greater than the raw end value, so unaligned starts may anchor before or after the supplied start date and unaligned ends are upper bounds rather than additional anchors. datetime values are accepted by membership checks and converted to their date component first; :meth:normalize itself is typed for date inputs.

DateRangeDomain(start, end, *, frequency="day", step=1) represents an inclusive finite date range. Supported frequencies are day, week_end, month_start, month_end, quarter_end, year_start, and year_end. Invalid bounds, non-positive steps, and unsupported frequencies raise InvalidDateRangeError. Membership checks convert datetime values to their date component, normalize non-daily candidates to the configured anchor, and then require that anchored date to appear in the generated range. week_end anchors to Sunday. Month and year steps advance by calendar months or years from the current anchored date; quarter steps advance by three-month intervals. Iteration starts at normalize(start) and stops when the next generated date would be greater than the raw end, so unaligned starts may anchor before or after the supplied start date and unaligned ends act as upper bounds. Examples: month_start normalizes 2024-02-15 to 2024-02-01; month_end normalizes it to 2024-02-29; quarter_end normalizes it to 2024-03-31; year_start normalizes it to 2024-01-01; year_end normalizes it to 2024-12-31.

general_manager.bucket.base_bucket.Bucket

Bases: ABC, Generic[GeneralManagerType]

Abstract interface for lazily evaluated GeneralManager collections.

Concrete buckets provide their own storage type and reconstruction behavior. The base class stores only the manager class plus object-shaped lookup metadata so shared helpers such as grouping and run-scoped indexes can work across database, request, and calculation-backed collections.

__init__

__init__(manager_class)

Create a bucket bound to a specific manager class.

Parameters:

Name Type Description Default
manager_class type[GeneralManagerType]

GeneralManager subclass whose instances this bucket represents.

required

Returns:

Type Description
None

None

__eq__

__eq__(other)

Compare two buckets for equality.

Parameters:

Name Type Description Default
other object

Object tested for equality with this bucket.

required

Returns:

Name Type Description
bool bool

True when the buckets share the same class, manager class, and data payload.

__reduce__

__reduce__()

Provide fallback pickling support by returning constructor arguments.

Subclasses with additional constructor requirements override this method. The fallback shape is kept for older bucket implementations that accepted (data, manager_class, filters, excludes).

Returns:

Type Description
str | tuple[object, ...]

tuple[object, ...]: Reconstruction data for compatible subclasses.

__or__ abstractmethod

__or__(other)

Return a bucket containing the union of this bucket and another input.

Parameters:

Name Type Description Default
other Bucket[GeneralManagerType] | GeneralManagerType

Bucket or single manager instance to merge.

required

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: New bucket with the combined contents.

__iter__ abstractmethod

__iter__()

Iterate over items in the bucket.

Yields:

Name Type Description
GeneralManagerType GeneralManagerType

Items stored in the bucket.

filter abstractmethod

filter(**kwargs)

Return a bucket reduced to items matching the provided filters.

Parameters:

Name Type Description Default
**kwargs object

Field lookups applied to the underlying query.

{}

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: Filtered bucket instance.

exclude abstractmethod

exclude(**kwargs)

Return a bucket that excludes items matching the provided filters.

Parameters:

Name Type Description Default
**kwargs object

Field lookups specifying records to remove from the result.

{}

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: Bucket with the specified records excluded.

first abstractmethod

first()

Return the first item contained in the bucket.

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: First entry if present, otherwise None.

last abstractmethod

last()

Return the last item contained in the bucket.

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: Last entry if present, otherwise None.

count abstractmethod

count()

Return the number of items represented by the bucket.

Returns:

Name Type Description
int int

Count of items.

all abstractmethod

all()

Return a bucket encompassing every item managed by this instance.

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: Bucket without filters or exclusions.

get abstractmethod

get(**kwargs)

Retrieve a single item matching the provided criteria.

Parameters:

Name Type Description Default
**kwargs object

Field lookups identifying the target record.

{}

Returns:

Name Type Description
GeneralManagerType GeneralManagerType

Matching item.

__getitem__ abstractmethod

__getitem__(item)

Retrieve an item or slice from the bucket.

Parameters:

Name Type Description Default
item int | slice

Index or slice specifying the desired record(s).

required

Returns:

Type Description
GeneralManagerType | Bucket[GeneralManagerType]

GeneralManagerType | Bucket[GeneralManagerType]: Resulting item or bucket slice.

__len__ abstractmethod

__len__()

Return the number of items contained in the bucket.

Returns:

Name Type Description
int int

Count of elements.

__contains__ abstractmethod

__contains__(item)

Checks whether the specified item is present in the bucket.

Parameters:

Name Type Description Default
item GeneralManagerType

Manager instance evaluated for membership.

required

Returns:

Name Type Description
bool bool

True if the bucket contains the provided instance.

sort abstractmethod

sort(key, reverse=False)

Return a sorted bucket.

Parameters:

Name Type Description Default
key str | tuple[str, ...]

Attribute name(s) used for sorting.

required
reverse bool

Whether to sort in descending order.

False

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: Sorted bucket instance.

group_by

group_by(*group_by_keys)

Materialise a grouped view of the bucket.

Parameters:

Name Type Description Default
*group_by_keys str

Attribute names used to form groups.

()

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: Bucket grouping items by the provided keys.

index_by

index_by(key_spec, *, max_rows=1000)

Build or reuse a unique run-scoped index over this bucket.

Duplicate frozen keys raise an error because each key must identify one row. The result is cached only for the active calculation run and is separated by bucket object, key spec, unique-vs-many mode, and max_rows. If no run is active, the method creates a temporary run for this call, so there is no reuse across separate calls. Cached hits return the same mutable dictionary object stored for the run; treat it as read-only because mutations are visible to later same-run hits. Failed index construction does not store a cache entry, so later same-run calls retry the build. Validation order is max_rows, then key_spec, then bucket iteration. During iteration, the row guardrail is checked before key resolution for each row.

Parameters:

Name Type Description Default
key_spec BucketIndexKeySpec

One field name, or a non-empty tuple of field names for a composite key. Empty strings are accepted and passed to attribute lookup unchanged; mapping keys are not read unless the row also exposes them as attributes.

required
max_rows int | None

Maximum number of source rows to read before failing, or None to disable the guardrail. Non-positive limits are allowed but fail as soon as any row is read. Runtime callers must pass an integer or None; booleans and other values raise TypeError.

1000

Returns:

Type Description
dict[Hashable, GeneralManagerType]

A dictionary mapping each frozen key to the single matching manager.

dict[Hashable, GeneralManagerType]

Empty buckets return an empty dictionary.

dict[Hashable, GeneralManagerType]

Frozen keys preserve already-hashable scalar values and normalize

dict[Hashable, GeneralManagerType]

managers and containers into hashable identities suitable for lookup

dict[Hashable, GeneralManagerType]

during the same process.

Raises:

Type Description
BucketIndexTooLargeError

If more than max_rows rows are read.

DuplicateBucketIndexKeyError

If two rows resolve to the same key.

MissingBucketIndexKeyError

If a row lacks a requested key field.

UnsupportedBucketIndexKeySpecError

If key_spec is not a string or a non-empty tuple containing only strings.

TypeError

If max_rows is not an integer or None.

UnhashableBucketIndexKeyError

If a key value cannot be frozen.

Exception

Exceptions raised while iterating the bucket propagates unchanged.

index_many

index_many(key_spec, *, max_rows=1000)

Build or reuse a run-scoped index that groups rows by key.

Values are tuples preserving source iteration order, and the cached result is scoped to the active calculation run. Cache entries are separated by bucket object, key spec, unique-vs-many mode, and max_rows. If no run is active, the method creates a temporary run for this call, so there is no reuse across separate calls. Cached hits return the same mutable dictionary object stored for the run; treat it as read-only because mutations are visible to later same-run hits. Failed index construction does not store a cache entry, so later same-run calls retry the build. Validation order is max_rows, then key_spec, then bucket iteration. During iteration, the row guardrail is checked before key resolution for each row.

Parameters:

Name Type Description Default
key_spec BucketIndexKeySpec

One field name, or a non-empty tuple of field names for a composite key. Empty strings are accepted and passed to attribute lookup unchanged; mapping keys are not read unless the row also exposes them as attributes.

required
max_rows int | None

Maximum number of source rows to read before failing, or None to disable the guardrail. Non-positive limits are allowed but fail as soon as any row is read. Runtime callers must pass an integer or None; booleans and other values raise TypeError.

1000

Returns:

Type Description
dict[Hashable, tuple[GeneralManagerType, ...]]

A dictionary mapping each frozen key to matching managers in source

dict[Hashable, tuple[GeneralManagerType, ...]]

order. Empty buckets return an empty dictionary. Frozen keys

dict[Hashable, tuple[GeneralManagerType, ...]]

preserve already-hashable scalar values and normalize managers and

dict[Hashable, tuple[GeneralManagerType, ...]]

containers into hashable identities suitable for lookup during the

dict[Hashable, tuple[GeneralManagerType, ...]]

same process.

Raises:

Type Description
BucketIndexTooLargeError

If more than max_rows rows are read.

MissingBucketIndexKeyError

If a row lacks a requested key field.

UnsupportedBucketIndexKeySpecError

If key_spec is not a string or a non-empty tuple containing only strings.

TypeError

If max_rows is not an integer or None.

UnhashableBucketIndexKeyError

If a key value cannot be frozen.

Exception

Exceptions raised while iterating the bucket propagates unchanged.

none

none()

Return an empty bucket instance.

Returns:

Type Description
Bucket[GeneralManagerType]

Bucket[GeneralManagerType]: Empty bucket.

Raises:

Type Description
NotImplementedError

Always raised by the base implementation; subclasses must provide a concrete version.

general_manager.bucket.database_bucket.DatabaseBucket

Bases: Bucket[GeneralManagerType]

Bucket implementation backed by Django ORM querysets.

__init__

__init__(
    data,
    manager_class,
    filter_definitions=None,
    exclude_definitions=None,
    *,
    search_date=None,
    sort_keys=None,
    sort_reverse=False,
    run_scoped_cacheable=True
)

Instantiate a database-backed bucket with optional filter state.

Filter and exclude definitions are copied into bucket-owned dictionaries, so later mutations to caller-provided mappings do not change this bucket. Pickle reconstruction restores through primary-key snapshots rather than by serializing the queryset object.

Parameters:

Name Type Description Default
data QuerySet[Model]

Queryset providing the underlying data.

required
manager_class type[GeneralManagerType]

GeneralManager subclass used to wrap rows.

required
filter_definitions FilterDefinitions | None

Pre-existing filter expressions captured from parent buckets.

None
exclude_definitions FilterDefinitions | None

Pre-existing exclusion expressions captured from parent buckets.

None
search_date datetime | date | None

Optional timestamp applied when instantiating manager instances.

None
sort_keys tuple[str, ...] | None

Property names used by a previous bucket sort operation.

None
sort_reverse bool

Whether sorted keys should be interpreted in descending order for dependency tracking.

False
run_scoped_cacheable bool

Whether terminal results from this bucket are safe to reuse inside the active calculation run.

True

Returns:

Type Description
None

None

__eq__

__eq__(other)

Compare buckets only after validating their effective dates.

__reduce__

__reduce__()

Preserve a result snapshot without serializing the queryset object.

Reducing a bucket records the effective filter/exclude dependencies, materializes primary keys in queryset order, rejects duplicate primary keys with DuplicateDatabaseBucketSnapshotError, and restores through the original model default manager on the original database alias by filtering those primary keys and preserving the snapshot order.

__iter__

__iter__()

Iterate over manager instances corresponding to the queryset rows.

Safe run-scoped row snapshots are reused when present. Otherwise cached primary-key snapshots are reused when available, and the queryset is iterated as trusted ORM rows when possible. Rows are trusted only when they match the interface model, are not deferred, and historical buckets expose history state. Untrusted rows fall back to primary-key manager construction. search_date is passed through when managers are built from primary keys or trusted rows.

Yields:

Name Type Description
GeneralManagerType GeneralManagerType

Manager instance for each primary key in the queryset.

__or__

__or__(other)

Produce a new DatabaseBucket representing the union of this bucket with another DatabaseBucket or a GeneralManager instance of the same manager class.

Parameters:

Name Type Description Default
other Bucket[GeneralManagerType] | GeneralManagerType

The bucket or manager instance to merge with this bucket.

required

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: A new bucket containing the combined items from both operands.

Raises:

Type Description
DatabaseBucketTypeMismatchError

If other is not a DatabaseBucket of the same class and not a compatible GeneralManager.

DatabaseBucketManagerMismatchError

If other is a DatabaseBucket but uses a different manager class.

DatabaseBucketSearchDateMismatchError

If both buckets target the same manager but have different search dates.

__merge_filter_definitions

__merge_filter_definitions(basis, **kwargs)

Merge stored filter definitions with additional lookup values.

Parameters:

Name Type Description Default
basis FilterDefinitions

Existing lookup definitions copied into the result.

required
**kwargs LookupValue

New lookups whose values are appended to the result mapping.

{}

Returns:

Name Type Description
FilterDefinitions FilterDefinitions

Combined mapping of lookups to value lists.

__parse_filter_definitions

__parse_filter_definitions(**kwargs)

Split provided filter kwargs into three parts: query annotations required by properties, ORM-compatible lookup mappings, and Python-evaluated filter specifications.

Parameters:

Name Type Description Default
**kwargs LookupValue

Filter lookups supplied to filter or exclude.

{}

Returns:

Name Type Description
tuple tuple[dict[str, QueryAnnotation], LookupMapping, list[PythonFilterDefinition]]
  • annotations (dict[str, object]): Mapping from property name to its query_annotation (callable or annotation object) for properties that require ORM annotations.
  • orm_kwargs (dict[str, object]): Mapping of ORM lookup strings (e.g., "field__lookup") to their values to be passed to the queryset.
  • python_filters (list[tuple[str, object, str]]): List of tuples (lookup, value, root_property_name) for properties that must be evaluated in Python.

Raises:

Type Description
NonFilterablePropertyError

If a lookup targets a property that is not allowed to be filtered.

__parse_python_filters

__parse_python_filters(query_set, python_filters)

Evaluate Python-only filters and return the primary keys that satisfy them.

Parameters:

Name Type Description Default
query_set QuerySet[Model]

Queryset to inspect.

required
python_filters list[tuple[str, object, str]]

Filters requiring Python evaluation, each containing the lookup, value, and property root.

required

Returns:

Type Description
list[object]

list[object]: Primary keys of rows that meet all Python-evaluated filters.

filter

filter(**kwargs)

Return a new DatabaseBucket refined by the given Django-style lookup expressions.

search_date is a reserved kwarg consumed by the bucket and preserved on the returned bucket. Remaining kwargs are split between ORM lookups, query-annotated properties, and Python-only property filters. Python-only property filters evaluate the candidate rows in Python and narrow the queryset by the matching primary keys. Stored filter definitions are copied before the new lookups are appended, so parent and child buckets do not share nested lookup lists.

Parameters:

Name Type Description Default
**kwargs object

Django-style lookup expressions to apply to the underlying queryset, plus optional reserved search_date.

{}

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: New bucket containing items matching the existing state combined with the provided lookups.

Raises:

Type Description
NonFilterablePropertyError

If a provided property is not filterable for this manager.

InvalidQueryAnnotationTypeError

If a query-annotation callback returns a non-QuerySet.

QuerysetFilteringError

If Django raises FieldError, TypeError, or ValueError while applying ORM filters.

exclude

exclude(**kwargs)

Produce a bucket that excludes rows matching the provided Django-style lookup expressions.

Accepts ORM lookups, query annotation entries, and Python-only filters; annotation callables will be applied to the underlying queryset as needed. search_date is a reserved kwarg consumed by the bucket and preserved on the returned bucket. Python-only property filters evaluate candidate rows in Python and then exclude the matching primary keys. Stored exclude definitions are copied before new lookups are appended, so parent and child buckets do not share nested lookup lists.

Parameters:

Name Type Description Default
**kwargs object

Django-style lookup expressions, annotation entries, or property-based filters used to identify records to exclude.

{}

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: A new bucket whose queryset omits rows matching the provided lookups.

Raises:

Type Description
NonFilterablePropertyError

If a provided property is not filterable for this manager.

InvalidQueryAnnotationTypeError

If an annotation callable is applied and does not return a Django QuerySet.

QuerysetFilteringError

If Django raises FieldError, TypeError, or ValueError while applying ORM excludes.

first

first()

Return the first row in the queryset as a manager instance.

Reuses safe cached row snapshots or primary-key snapshots when present; otherwise delegates to queryset first().

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: First manager instance if available.

last

last()

Return the last row in the queryset as a manager instance.

Reuses safe cached row snapshots or primary-key snapshots when present; otherwise delegates to queryset last().

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: Last manager instance if available.

count

count()

Count the number of rows represented by the bucket.

A safe run-scoped primary-key snapshot is reused when present; otherwise this delegates to the queryset count.

Returns:

Name Type Description
int int

Number of represented rows.

all

all()

Return a new lazy bucket wrapping self._data.all().

Filter definitions, exclusion definitions, search date, sort metadata, and run-scoped cacheability are preserved on the returned bucket.

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: Bucket encapsulating self._data.all().

get

get(**kwargs)

Retrieve a single manager instance matching the provided lookups.

When a run-scoped row or primary-key snapshot is already available and the lookup is exactly one pk or id value, the snapshot is used before falling back to queryset get(). Snapshot lookups preserve the queryset's DoesNotExist and MultipleObjectsReturned behavior.

Parameters:

Name Type Description Default
**kwargs object

Field lookups resolved via QuerySet.get.

{}

Returns:

Name Type Description
GeneralManagerType GeneralManagerType

Manager instance wrapping the matched model.

Raises:

Type Description
ObjectDoesNotExist

Propagated from the underlying queryset when no row matches.

MultipleObjectsReturned

Propagated when multiple rows satisfy the lookup.

__getitem__

__getitem__(item)

Access manager instances by index or obtain a sliced bucket.

Slices return a lazy DatabaseBucket. Scalar indexes return a manager instance; when a run-scoped snapshot path is used, negative scalar indexes raise ValueError. Otherwise normal Django queryset indexing exceptions propagate.

Parameters:

Name Type Description Default
item int | slice

Index of the desired row or slice object describing a range.

required

Returns:

Type Description
GeneralManagerType | DatabaseBucket[GeneralManagerType]

GeneralManagerType | DatabaseBucket[GeneralManagerType]: Manager instance for single indices or bucket wrapping the sliced queryset.

__bool__

__bool__()

Return whether the bucket contains at least one row without counting all rows.

Truthiness is an existence check, not a cardinality request. Reuse any active run-context snapshot first, then cache a queryset exists() result for equivalent trusted querysets in the same calculation run.

__len__

__len__()

Return the number of rows represented by the bucket.

Delegates to count() so dependency tracking, run-scoped snapshots, and queryset fallback behavior stay aligned between both cardinality paths.

Returns:

Name Type Description
int int

Number of represented rows.

__str__

__str__()

Return a user-friendly representation of the bucket.

Returns:

Name Type Description
str str

Human-readable description of the queryset and manager class.

__repr__

__repr__()

Return a debug representation of the bucket.

Returns:

Name Type Description
str str

Detailed description including queryset, manager class, filters, and excludes.

group_by

group_by(*group_by_keys)

Group only when this bucket matches the active historical instant.

__contains__

__contains__(item)

Determine whether the provided instance belongs to the bucket.

Manager instances are matched by identification["id"] and Django models by pk. Missing identifiers return False. A safe run-scoped primary-key snapshot is used when present; otherwise the bucket performs a targeted queryset exists() lookup.

Parameters:

Name Type Description Default
item GeneralManagerType | Model

Manager or model instance whose primary key is checked.

required

Returns:

Name Type Description
bool bool

True when the primary key exists in the queryset.

sort

sort(key, reverse=False)

Return a new DatabaseBucket ordered by the given property name(s).

Accepts a single property name or a tuple of property names. Properties with ORM annotations are applied at the database level; properties without ORM annotations are evaluated in Python and the resulting records are re-ordered while preserving a queryset result. Python-only sorts materialize candidate rows, sort them in memory, then preserve that materialized order with a Django Case annotation. Stable ordering and preservation of manager wrapping are maintained.

Parameters:

Name Type Description Default
key str | tuple[str, ...]

Property name or sequence of property names to sort by, applied in order of appearance.

required
reverse bool

If True, sort each specified key in descending order.

False

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: A new bucket whose underlying queryset is ordered according to the requested keys.

Raises:

Type Description
NonSortablePropertyError

If any requested property is not marked as sortable on the manager's GraphQL properties.

InvalidQueryAnnotationTypeError

If a property query annotation callable returns a non-QuerySet value.

QuerysetOrderingError

If the ORM rejects the constructed ordering (e.g., invalid field or incompatible ordering expression).

none

none()

Return an empty bucket sharing the same manager class.

Preserves copied filter/exclude state, search date, sort metadata, and run-scoped cacheability from all() before replacing the queryset with QuerySet.none().

Returns:

Type Description
DatabaseBucket[GeneralManagerType]

DatabaseBucket[GeneralManagerType]: Empty bucket retaining manager and query context.

DatabaseBucket is the ORM-backed collection returned by database and existing-model managers. It keeps Django queryset laziness for builder methods such as filter(), exclude(), all(), sort(), and slicing, then wraps model rows as the configured manager class when terminal operations evaluate the query. The constructor accepts a Django QuerySet, the manager class, optional filter/exclude snapshots, optional search_date, sort metadata, and the run-scoped cache flag. Those lookup snapshots are copied into bucket-owned dictionaries, so mutating the original mappings after construction does not change the bucket.

Common cookbook patterns:

active = Project.filter(status="active")
first = active.sort("name").first()
total = active.count()

if first is not None and first in active:
    visible_names = [project.name for project in active[0:10]]

count() and len(bucket) return the queryset count unless a safe run-scoped snapshot already exists. first(), last(), scalar indexing, iteration, and membership checks record the effective dependency before reading rows; membership uses the candidate manager's identification["id"] or a model instance's primary key and returns False for unsaved objects. Python-only @graph_ql_property filters and sorts are supported only when the property is marked filterable or sortable; non-filterable properties raise NonFilterablePropertyError, non-sortable properties raise NonSortablePropertyError, invalid query annotations raise InvalidQueryAnnotationTypeError, and rejected ORM filter/order expressions are wrapped as QuerysetFilteringError or QuerysetOrderingError.

Run-scoped reuse is conservative. Database buckets bypass snapshot reuse for select-for-update, combined, distinct, prefetch-related, deferred-field, invalid, or oversized queryset shapes. When a safe row snapshot exists, terminal helpers reuse trusted ORM rows; otherwise they can reuse cached primary keys or evaluate the queryset normally. Historical buckets pass search_date into constructed managers and only trust ORM rows that expose history state. Pickled bucket snapshots store primary keys in queryset order, reject duplicate primary keys, and restore by filtering those primary keys through the original model/database alias while preserving the snapshot order. filter() and exclude() copy their stored lookup snapshots before appending new lookups, and get() only answers cached snapshots for single-key pk or id lookups. Python-only property sorts materialize candidate rows, sort them in memory, then preserve the materialized order with a Django Case annotation. Combining database buckets with | requires the same bucket type, manager class, and search_date; union buckets disable run-scoped result reuse. none() keeps the same manager, filter/exclude snapshots, search date, sort metadata, and cache flag while replacing the queryset with an empty queryset.

general_manager.bucket.group_bucket.GroupBucket

Bases: Generic[GeneralManagerType]

Bucket variant that groups managers by specified attributes.

__init__

__init__(manager_class, group_by_keys, data)

Build a grouping bucket from the provided base data.

Parameters:

Name Type Description Default
manager_class type[GeneralManagerType]

GeneralManager subclass represented by the bucket.

required
group_by_keys tuple[str, ...]

Attribute names used to define each group.

required
data Bucket[GeneralManagerType]

Source bucket whose entries are grouped.

required

Returns:

Type Description
None

None

Raises:

Type Description
TypeError

If a group-by key is not a string.

ValueError

If a group-by key is not a valid manager attribute.

__eq__

__eq__(other)

Compare by unordered group set, manager class, and grouping keys.

Parameters:

Name Type Description Default
other object

Object compared against the current bucket.

required

Returns:

Name Type Description
bool bool

True when both buckets contain the same set of groups and use the same manager class and grouping-key tuple. Group order is not part of equality.

__check_group_by_arguments

__check_group_by_arguments(group_by_keys)

Validate that each provided group-by key is a string and is exposed by the manager interface.

Parameters:

Name Type Description Default
group_by_keys tuple[str, ...]

Attribute names to use for grouping.

required

Raises:

Type Description
InvalidGroupByKeyTypeError

If any element of group_by_keys is not a string.

UnknownGroupByKeyError

If any key is not listed in the manager class's interface attributes.

__build_grouped_manager

__build_grouped_manager(data)

Builds a GroupManager for each distinct combination of configured group-by attribute values.

Parameters:

Name Type Description Default
data Bucket[GeneralManagerType]

Source bucket whose entries are partitioned by the bucket's configured group-by keys.

required

Returns:

Type Description
list[GroupManager[GeneralManagerType]]

list[GroupManager[GeneralManagerType]]: A list of GroupManager objects, one per unique tuple of group-by key values; groups are produced in order sorted by the string representation of their key tuples.

__or__

__or__(other)

Return a new GroupBucket representing the union of this bucket and another compatible GroupBucket.

Parameters:

Name Type Description Default
other GroupBucket

The grouping bucket to merge with this one.

required

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: A GroupBucket with the same manager class and grouping keys whose basis data is the union of both inputs.

Raises:

Type Description
GroupBucketTypeMismatchError

If other is not a GroupBucket of the same class.

GroupBucketManagerMismatchError

If other tracks a different manager class.

GroupBucketKeysMismatchError

If other uses different grouping keys.

__reduce__

__reduce__()

Provide pickling support with constructor and current basis data.

Returns:

Type Description
str | tuple[object, ...]

tuple[object, ...]: (GroupBucket, (manager_class, group_by_keys, basis_data)), allowing unpickling to rebuild groups from the stored basis bucket.

__iter__

__iter__()

Iterate over the grouped managers produced by this bucket.

Yields:

Type Description
GroupManager[GeneralManagerType]

GroupManager[GeneralManagerType]: Individual group manager instances.

filter

filter(**kwargs)

Return a grouped bucket filtered by the provided lookups.

Parameters:

Name Type Description Default
**kwargs object

Field lookups evaluated against the underlying bucket.

{}

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: Grouped bucket containing only matching records.

exclude

exclude(**kwargs)

Return a grouped bucket that excludes records matching the provided lookups.

Parameters:

Name Type Description Default
**kwargs object

Field lookups whose matches should be removed from the underlying bucket.

{}

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: Grouped bucket built from the filtered base data.

first

first()

Return the first grouped manager in the collection.

Returns:

Type Description
GroupManager[GeneralManagerType] | None

GroupManager[GeneralManagerType] | None: First group when available.

last

last()

Return the last grouped manager in the collection.

Returns:

Type Description
GroupManager[GeneralManagerType] | None

GroupManager[GeneralManagerType] | None: Last group when available.

count

count()

Count the number of grouped managers in the bucket.

Returns:

Name Type Description
int int

Number of groups.

all

all()

Return the current grouping bucket.

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: This instance.

get

get(**kwargs)

Retrieve the first GroupManager matching the provided lookups.

Parameters:

Name Type Description Default
**kwargs object

Field lookups used to filter the grouped managers.

{}

Returns:

Type Description
GroupManager[GeneralManagerType]

The first matching GroupManager.

Raises:

Type Description
GroupItemNotFoundError

If no grouped manager matches the filters.

__getitem__

__getitem__(item)

Retrieve a single grouped manager by index or construct a new GroupBucket from a slice of groups.

Parameters:

Name Type Description Default
item int | slice

Integer index to select a single GroupManager, or a slice to select a subsequence of groups.

required

Returns:

Type Description
GroupManager[GeneralManagerType] | GroupBucket[GeneralManagerType]

GroupManager[GeneralManagerType] if item is an int, otherwise a GroupBucket[GeneralManagerType] built from the selected groups.

Raises:

Type Description
EmptyGroupBucketSliceError

If the slice selects no groups.

InvalidGroupBucketIndexError

If item is not an int or slice.

__len__

__len__()

Return the number of grouped managers.

Returns:

Name Type Description
int int

Number of groups.

__contains__

__contains__(item)

Determine whether the given manager instance exists in the underlying data.

Parameters:

Name Type Description Default
item GeneralManagerType

Manager instance checked for membership.

required

Returns:

Name Type Description
bool bool

True if the instance is present in the basis data.

sort

sort(key, reverse=False)

Return a new GroupBucket sorted by the specified attributes.

Parameters:

Name Type Description Default
key str | tuple[str, ...]

Attribute name(s) used for sorting.

required
reverse bool

Whether to apply descending order.

False

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: Sorted grouping bucket.

group_by

group_by(*group_by_keys)

Extend the grouping with additional attribute keys.

Parameters:

Name Type Description Default
*group_by_keys str

Attribute names appended to the current grouping.

()

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: New bucket grouped by the combined key set.

none

none()

Produce an empty grouping bucket that preserves the current configuration.

Returns:

Type Description
GroupBucket[GeneralManagerType]

GroupBucket[GeneralManagerType]: Empty grouping bucket with identical manager class and grouping keys.

GroupBucket is the grouped view returned by bucket.group_by(...). It materializes one GroupManager per distinct tuple of group-by values from the source bucket. Group keys must be strings listed by the manager interface's attributes; non-string keys raise InvalidGroupByKeyTypeError, and unknown keys raise UnknownGroupByKeyError. Group values are frozen into hashable identities so manager-valued keys compare by manager class plus sorted identification items, lists and tuples compare by element identities, sets compare as frozensets, mapping values compare by recursively frozen key/value pairs sorted by repr, and other values use their raw hashable value. Groups are emitted in str(group_by_value) sort order. Equality ignores that order and compares the set of groups plus manager class and grouping-key tuple. Pickle reconstruction uses (GroupBucket, (manager_class, group_by_keys, basis_data)), rebuilding groups from the stored basis bucket.

For manager-valued group keys, the source bucket slice is rebuilt with relation lookups derived from the grouped manager identification. Attribute metadata filter_lookup is used when present; otherwise the group key name is used. filter(**lookups) and exclude(**lookups) delegate to the underlying basis bucket and then rebuild the grouped view. get(**lookups) returns the first matching group after that filtering step and raises GroupItemNotFoundError when no group remains; it does not enforce uniqueness. first() and last() return a group or None, while count() and len(bucket) count groups.

Scalar indexing returns a GroupManager. Slicing unions the selected groups' underlying basis buckets and returns a new GroupBucket; an empty slice raises EmptyGroupBucketSliceError, and non-int/non-slice indexes raise InvalidGroupBucketIndexError. all() returns self. none() returns a new empty grouped bucket with the same manager class and grouping keys. Membership checks test whether the supplied manager instance is present in the underlying basis bucket, not whether a matching group key exists.

sort(key, reverse=False) sorts the current groups in memory by one attribute name or a tuple of attribute names, returning a new grouped bucket with the same basis bucket and sorted group list. Missing sort attributes propagate AttributeError, and incomparable values propagate Python TypeError. The | operator combines compatible grouped buckets by unioning their basis buckets and regrouping; operands must be GroupBucket instances of the same concrete class, manager class, and grouping-key tuple. Mismatches raise GroupBucketTypeMismatchError, GroupBucketManagerMismatchError, or GroupBucketKeysMismatchError.

general_manager.bucket.calculation_bucket.CalculationBucket

Bases: Bucket[GeneralManagerType]

Bucket that builds cartesian products of calculation input fields.

__init__

__init__(
    manager_class,
    filter_definitions=None,
    exclude_definitions=None,
    sort_key=None,
    reverse=False,
)

Initialize a CalculationBucket configured to enumerate all valid input combinations for a manager.

Parameters:

Name Type Description Default
manager_class type[GeneralManagerType]

Manager subclass whose Interface must inherit from CalculationInterface.

required
filter_definitions dict[str, dict] | None

Mapping of input/property filter constraints to apply to generated combinations.

None
exclude_definitions dict[str, dict] | None

Mapping of input/property exclude constraints to remove generated combinations.

None
sort_key str | tuple[str] | None

Key name or tuple of key names used to order generated manager combinations.

None
reverse bool

If True, reverse the ordering defined by sort_key.

False

Raises:

Type Description
InvalidCalculationInterfaceError

If the manager_class.Interface does not inherit from CalculationInterface.

__eq__

__eq__(other)

Compare two calculation buckets for structural equality.

Parameters:

Name Type Description Default
other object

Candidate bucket.

required

Returns:

Name Type Description
bool bool

True when both buckets share the same manager class and identical filter/exclude state.

__reduce__

__reduce__()

Provide pickling support for calculation buckets.

Returns:

Type Description
generalManagerClassName | tuple[object, ...]

tuple[object, ...]: Reconstruction data representing the class, arguments, and state.

__setstate__

__setstate__(state)

Restore the bucket after unpickling.

Parameters:

Name Type Description Default
state dict[str, object]

Pickled state containing cached combination data.

required

Returns:

Type Description
None

None

__or__

__or__(other)

Build a bucket from constraints common to this bucket and another operand.

Parameters:

Name Type Description Default
other Bucket[GeneralManagerType] | GeneralManagerType

A CalculationBucket or a GeneralManager instance to combine. If a same-class manager instance is given, it is first converted into an id__in=[identification] filter bucket.

required

Returns:

Type Description
CalculationBucket[GeneralManagerType]

A new CalculationBucket containing only filter and exclude

CalculationBucket[GeneralManagerType]

definitions that are present with equal values on both bucket

CalculationBucket[GeneralManagerType]

operands. This is a compatibility-preserving common-constraint

CalculationBucket[GeneralManagerType]

merge, not a set union of materialized calculation results.

Raises:

Type Description
IncompatibleBucketTypeError

If other is neither a CalculationBucket nor a compatible manager instance.

IncompatibleBucketManagerError

If other is a CalculationBucket for a different manager class.

__str__

__str__()

Return a compact preview of generated combinations.

Cached buckets include the exact combination count. Uncached buckets avoid materializing all combinations for string formatting; when more than the preview limit exists, the count is reported as a lower-bound label.

Returns:

Name Type Description
str str

Human-readable summary of up to five combinations.

__repr__

__repr__()

Return a detailed representation of the bucket configuration.

Returns:

Name Type Description
str str

Debug string listing filters, excludes, sort key, and ordering.

transform_properties_to_input_fields staticmethod

transform_properties_to_input_fields(
    properties, input_fields
)

Derive input-field definitions for GraphQL properties without explicit inputs.

This helper is a framework hook used by calculation filtering and sorting. It treats list, tuple, set, union, and optional property type hints as their concrete element/member type when possible and falls back to object when the hint cannot be resolved to a class.

Parameters:

Name Type Description Default
properties dict[str, GraphQLProperty]

GraphQL properties declared on the manager.

required
input_fields dict[str, Input]

Existing input field definitions.

required

Returns:

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

dict[str, Input]: Combined mapping of input field names to Input definitions.

filter

filter(**kwargs)

Add additional filters and return a new calculation bucket.

Lookup keys use the shared calculation filter grammar: field or field__lookup for input and property values. Supported Python lookup operators are exact, lt, lte, gt, gte, contains, startswith, endswith, and in. For manager-typed inputs, field=value filters by the manager id, field_id is an id alias, and suffixes such as field__name__startswith are forwarded to the nested manager bucket. Unknown fields raise UnknownInputFieldError from the filter parser.

Parameters:

Name Type Description Default
**kwargs object

Filter expressions applied to generated combinations.

{}

Returns:

Type Description
CalculationBucket[GeneralManagerType]

CalculationBucket[GeneralManagerType]: Bucket reflecting the updated filter definitions.

Raises:

Type Description
UnknownInputFieldError

If a filter key references no input or derived GraphQL property.

TypeError

Propagated from invalid input casts or downstream manager-bucket filtering.

ValueError

Propagated from input parsing or normalization.

exclude

exclude(**kwargs)

Add additional exclusion rules and return a new calculation bucket.

Exclusion keys use the same lookup grammar and error behavior as :meth:filter; matching combinations are removed rather than kept.

Parameters:

Name Type Description Default
**kwargs object

Exclusion expressions removing combinations from the result.

{}

Returns:

Type Description
CalculationBucket[GeneralManagerType]

CalculationBucket[GeneralManagerType]: Bucket reflecting the updated exclusion definitions.

Raises:

Type Description
UnknownInputFieldError

If an exclude key references no input or derived GraphQL property.

TypeError

Propagated from invalid input casts or downstream manager-bucket filtering.

ValueError

Propagated from input parsing or normalization.

all

all()

Return a deep copy of this calculation bucket.

Returns:

Type Description
CalculationBucket[GeneralManagerType]

CalculationBucket[GeneralManagerType]: Independent copy that can be mutated without affecting the original.

__iter__

__iter__()

Iterate over every generated combination as a manager instance.

Yields:

Name Type Description
GeneralManagerType GeneralManagerType

Manager constructed from each valid set of inputs.

generate_combinations

generate_combinations()

Compute (and cache) the list of valid input combinations.

This framework helper materializes the bucket. It orders inputs by dependency, applies input-level filters/excludes while enumerating candidate values, then applies property-level filters/excludes and sorting when manager access is required. The returned list is the bucket's cached mutable list; callers should treat it as read-only.

Returns:

Type Description
List[Combination]

list[Combination]: Cached list of input dictionaries satisfying filters, excludes, and ordering.

Raises:

Type Description
CyclicDependencyError

If input dependencies contain a cycle.

InvalidPossibleValuesError

If a required input cannot provide iterable or bucket-backed possible values.

UnknownInputFieldError

If stored filter definitions reference an unknown input or property.

AttributeError

Propagated from missing computed properties during property filtering or sorting.

TypeError

Propagated from invalid casts, downstream bucket filtering, or incomparable sort values.

ValueError

Propagated from input parsing or normalization.

topological_sort_inputs

topological_sort_inputs()

Produce a dependency-respecting order of input fields.

This framework helper includes every configured input name and orders dependencies before the inputs that depend on them.

Returns:

Type Description
List[str]

list[str]: Input names ordered so each dependency appears before its dependents.

Raises:

Type Description
CyclicDependencyError

If the dependency graph contains a cycle; the exception's node identifies a node involved in the cycle.

get_possible_values

get_possible_values(key_name, input_field, current_combo)

Resolve potential values for an input field based on the current partial input combination.

This framework helper resolves static, callable, domain, iterable, or bucket-backed possible_values for one input. Optional inputs with no possible-values source return None; required inputs without a valid iterable, domain, or bucket source raise InvalidPossibleValuesError.

Parameters:

Name Type Description Default
key_name str

Name of the input field used for error context.

required
input_field Input

Input definition that may include possible_values and depends_on.

required
current_combo dict

Partial mapping of already-selected input values required to evaluate dependencies.

required

Returns:

Type Description
Union[Iterable[object], Bucket['GeneralManager'], None]

Iterable[object] | Bucket[GeneralManager] | None: An iterable of allowed values for the input, a Bucket supplying candidate values, or None when an optional input has no explicit domain.

Raises:

Type Description
InvalidPossibleValuesError

If the input field's possible_values is neither callable nor an iterable/Bucket.

first

first()

Return the first generated manager instance.

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: First instance or None when no combinations exist.

last

last()

Return the last generated manager instance.

Returns:

Type Description
GeneralManagerType | None

GeneralManagerType | None: Last instance or None when no combinations exist.

count

count()

Return the number of calculation combinations.

Returns:

Name Type Description
int int

Number of generated combinations.

__len__

__len__()

Return the number of generated combinations.

Returns:

Name Type Description
int int

Cached number of combinations.

__getitem__

__getitem__(item)

Retrieve a manager instance or subset of combinations.

Parameters:

Name Type Description Default
item int | slice

Index or slice specifying which combinations to return.

required

Returns:

Type Description
GeneralManagerType | CalculationBucket[GeneralManagerType]

GeneralManagerType | CalculationBucket[GeneralManagerType]: Manager instance for single indices or bucket wrapping the sliced combinations.

__contains__

__contains__(item)

Determine whether the provided manager instance exists among generated combinations.

Parameters:

Name Type Description Default
item GeneralManagerType

Manager instance to test for membership.

required

Returns:

Name Type Description
bool bool

True when the instance matches one of the generated combinations.

get

get(**kwargs)

Return the single manager instance that matches the provided field filters.

Parameters:

Name Type Description Default
**kwargs object

Field filters to apply when selecting a calculation (e.g., property or input names mapped to expected values).

{}

Returns:

Type Description
GeneralManagerType

The single manager instance that satisfies the provided filters.

Raises:

Type Description
MissingCalculationMatchError

If no matching manager exists.

MultipleCalculationMatchError

If more than one matching manager exists.

sort

sort(key, reverse=False)

Create a new CalculationBucket configured to order generated combinations by the given attribute key.

Sorting by raw input keys happens before managers are built. Sorting by computed properties builds manager instances and reads the named attributes. Missing attributes raise AttributeError when the bucket materializes; incomparable values raise TypeError from Python's sort. Exceptions raised by computed properties propagate unchanged.

Parameters:

Name Type Description Default
key str | tuple[str]

Attribute name or tuple of attribute names to use for ordering generated manager combinations.

required
reverse bool

If True, sort in descending order.

False

Returns:

Type Description
CalculationBucket[GeneralManagerType]

A new CalculationBucket configured to sort combinations by the provided key and direction.

group_by

group_by(*group_by_keys)

Group this bucket only when its snapshot matches the active context.

none

none()

Return an empty calculation bucket for the same manager class.

The returned bucket starts from an all() copy, then clears cached data and raw/parsed filter and exclude definitions. It preserves the manager class, sort key, and reverse flag.

Returns:

Type Description
CalculationBucket[GeneralManagerType]

CalculationBucket[GeneralManagerType]: Bucket with no combinations

CalculationBucket[GeneralManagerType]

and cleared filter/exclude state.

CalculationBucket is the lazy collection behind calculation-manager all(), filter(), and exclude(). It stores raw filter/exclude definitions, parses them against calculation inputs and derived GraphQL properties, and materializes combinations only when iterated, counted, indexed, or converted to text. all() returns an independent copy. filter(**kwargs) and exclude(**kwargs) return new buckets with additional lookup definitions. Keys use field or field__lookup; Python-level lookup operators are exact, lt, lte, gt, gte, contains, startswith, endswith, and in. Manager-typed inputs can be filtered by the manager object, by <input>_id, or by nested manager lookups such as project__name__startswith. Derived GraphQL properties can be filtered with the same Python lookup operators and do not use the database-bucket filterable marker. Unknown filter or exclude fields raise UnknownInputFieldError from general_manager.utils.filter_parser.

Terminal helpers mirror the other bucket types: first() and last() return a manager or None, get(**kwargs) requires exactly one match and raises MissingCalculationMatchError or MultipleCalculationMatchError otherwise, count() and len(bucket) count generated combinations, scalar indexing returns a manager instance, slicing returns a new bucket with cached combinations, and none() returns an empty bucket with the same manager class, sort key, and reverse flag while clearing raw and parsed filters/excludes. Sorting accepts one key or a tuple of keys and can sort either raw inputs or computed properties. Missing sort attributes raise AttributeError, incomparable sort values raise TypeError, and computed-property exceptions propagate unchanged when the bucket materializes. Invalid calculation interfaces raise InvalidCalculationInterfaceError, incompatible bucket unions raise IncompatibleBucketTypeError or IncompatibleBucketManagerError, cyclic input dependencies raise CyclicDependencyError, and required inputs without an iterable or bucket-backed domain raise InvalidPossibleValuesError.

The | operator is a compatibility merge for calculation buckets, not a materialized set union. Combining two compatible CalculationBucket instances keeps only filter and exclude definitions that exist with equal values on both operands, producing a bucket for their common constraints. Passing a same-class manager instance first converts that instance into an id__in=[identification] filter bucket before applying the same common-constraint merge.

generate_combinations(), topological_sort_inputs(), get_possible_values(), and transform_properties_to_input_fields() are framework helpers. They remain callable for advanced integrations, but application code should usually use all(), filter(), exclude(), sort(), and terminal helpers instead. SortedFilters is an internal typed partition of parsed filters used during combination generation and is not a user-facing extension point.

general_manager.bucket.request_bucket.RequestBucket

Bases: Bucket[GeneralManagerType]

Lazy bucket backed by a compiled request query plan.

Pickling preserves the compiled request plan and any serialized items, but unpickling does not immediately re-run network requests. Restored buckets keep their operation name and request plan metadata for equality and follow-up query compilation, but are marked as already materialized for iteration. Callers should only pickle buckets with serialized items if they expect iteration after unpickling to preserve results.

operation_name property

operation_name

Return the query operation name preserved on this bucket.

Concrete item buckets created from slices, unions, or none() keep the source operation name for observability and equality context even though they no longer have a request plan.

__init__

__init__(
    manager_class,
    interface_cls,
    *,
    operation_name="list",
    request_plan=None,
    filters=None,
    excludes=None,
    items=None,
    raw_items=None,
    count_override=None
)

Create a lazy request-plan bucket or a materialized item bucket.

request_plan creates a lazy bucket unless serialized items or raw_items are supplied. items are already-built managers. raw_items are request payloads used to reconstruct managers and reinstall payload caches, including during pickle restoration. Filter and exclude lookup maps are copied into bucket-owned dictionaries so later caller mutations do not affect this bucket. count_override is the count returned after materialization.

__reduce__

__reduce__()

Return pickle reconstruction data without executing a request.

__setstate__

__setstate__(state)

Restore pickle state without executing a request.

Serialized raw payloads rebuild manager instances and reinstall their request payload caches. If no raw payloads were serialized, the restored bucket uses the serialized manager items.

__or__

__or__(other)

Return a concrete item bucket containing both operands' items.

Raises:

Type Description
RequestBucketManagerMismatchError

If another request bucket is backed by a different manager class.

RequestBucketTypeMismatchError

If other is neither a compatible request bucket nor one manager instance.

__eq__

__eq__(other)

Compare request buckets by manager, operation, plan, or item identities.

__iter__

__iter__()

Yield materialized items, executing the request plan at most once.

filter

filter(**kwargs)

Return a bucket restricted by the supplied request or local lookups.

Lazy request-plan buckets merge the lookups into the compiled request plan and validate them through the query capability, even after iteration caches fetched items. Concrete item buckets created by slicing, unioning, or none() have no request plan; they validate the same lookup vocabulary and then filter contained manager instances in memory. Materialized lookups are ANDed across keys. Missing attributes do not match.

Raises:

Type Description
Request-interface lookup validation errors

Propagated from query capability when a lookup is unknown, unsupported, requires an unavailable local fallback, conflicts in the request plan, or targets an unsupported request location.

exclude

exclude(**kwargs)

Return a bucket excluding items that match the supplied lookups.

Lazy request-plan buckets compile exclude lookups into the request plan. Concrete item buckets created by slicing, unioning, or none() first validate exclude support and then remove matching manager instances in memory. Missing attributes do not match and therefore are not excluded. Unsupported exclude lookups raise the request-interface validation errors produced by the query capability.

Raises:

Type Description
RequestExcludeNotSupportedError

If exclude is requested for a lookup without remote exclude support or local fallback.

Request-interface lookup validation errors

Propagated from query capability when a lookup is unknown, unsupported, conflicts in the request plan, or targets an unsupported request location.

first

first()

Return the first materialized item, or None when the bucket is empty.

last

last()

Return the last materialized item, or None when the bucket is empty.

count

count()

Materialize, then return the current count override or item count.

Lazy materialization stores the upstream total_count as the count override when available, stores the local fallback result count when local predicates are applied, and otherwise falls back to the materialized item count. Concrete buckets keep the override installed by slicing, unioning, or none().

all

all()

Return a new request bucket for the same query plan or concrete items.

get

get(**kwargs)

Return exactly one item, optionally after applying additional filters.

Raises:

Type Description
RequestSingleItemRequiredError

If the resulting bucket does not contain exactly one item.

__getitem__

__getitem__(item)

Return one materialized item or a materialized bucket slice.

__len__

__len__()

Return the number of materialized items.

__contains__

__contains__(item)

Return whether an equal manager instance is present.

sort

sort(key, reverse=False)

Return a materialized bucket sorted by one or more manager attributes.

Raises:

Type Description
RequestBucketSortAttributeError

If any item lacks a requested sort attribute.

TypeError

Propagated when Python cannot compare the resolved sort values, such as mixed unrelated value types.

none

none()

Return an empty materialized bucket preserving the operation name.

RequestBucket is the lazy collection returned by request-backed managers. filter(), exclude(), and all() preserve the configured request operation for lazy request-plan buckets, even after iteration caches the fetched items. Buckets built from concrete items, such as slices, unions, and none(), have no request plan; their follow-up filter() and exclude() calls validate the same request lookup rules and then operate on the contained manager instances in memory. Missing attributes do not match materialized filters. These methods return RequestBucket instances. Materialized filter() combines lookup keys with AND semantics; materialized exclude() removes an item when any supplied lookup matches, so a missing attribute does not exclude that item. Lookup suffix semantics come from request filters: bare or unknown suffixes are exact matches, supported suffixes include comparisons, contains, icontains, in, and isnull, and incompatible comparisons return False. The constructor accepts the manager class, request interface class, operation name, optional request plan, optional filter/exclude lookup maps, optional serialized manager items, optional raw request payloads, and an optional count override. Lookup maps are copied into bucket-owned dictionaries. Supplying items creates a concrete manager-item bucket; supplying raw_items rebuilds manager instances from extract_identification() and installs each raw payload as the manager interface's request payload cache. Lazy filter(), exclude(), and all() compile a new request plan and can raise the same lookup validation and planning errors as the request query capability, including unknown or unsupported filters, unsupported exclude lookups, required local fallbacks, fragment conflicts, and unsupported request locations. Any method that materializes a lazy bucket, including iteration, len(), count(), first(), last(), get(), indexing, slicing, membership, sorting, equality against a concrete bucket, and concrete follow-up filters, can propagate request execution, response-shape, permission, and validation errors from the underlying request interface.

Concrete buckets keep the source operation_name as metadata even though they no longer have a request plan. Unioning request buckets or adding a single manager instance also produces a concrete item bucket; incompatible bucket types raise RequestBucketTypeMismatchError, and request buckets for different manager classes raise RequestBucketManagerMismatchError. Only bucket | other is implemented here; manager | bucket follows the manager's own union behavior. Union order is left items followed by right items, and duplicates are not removed. Equality compares manager class and operation name first; when both sides still have request plans it compares plan plus compiled filters/excludes, otherwise it materializes and compares the ordered sequence of each item’s identification mapping. sort(key, reverse=False) materializes the bucket, accepts one attribute name or a tuple of attribute names, and raises RequestBucketSortAttributeError when an item lacks a requested attribute. Tuple keys sort lexicographically by the resolved attribute values. Nested attribute paths are not parsed; each key part is passed directly to getattr. Python TypeError propagates for incomparable values such as mixed unrelated types.

Pickle-restored buckets keep their operation name and request plan metadata, but unpickling does not execute a request. Iteration after unpickling uses whatever items were serialized, and serialized raw payloads are reinstalled on rebuilt manager instances for field reads. Follow-up filter(), exclude(), or all() calls on a restored bucket with a request plan compile a new lazy request bucket. If neither serializable manager items nor raw payloads were stored, iteration after unpickling yields the empty serialized item set even when request-plan metadata is present. Normal pickle failures for unserializable manager instances propagate from Python's pickle machinery.

get() requires exactly one result and raises RequestSingleItemRequiredError otherwise. count() always materializes first. After materialization the current count override wins; lazy materialization installs the upstream total_count when the response provides one, installs the local fallback item count when local predicates are applied, and otherwise falls back to the number of materialized items. A constructor count_override on a still-lazy bucket can therefore be replaced by the count observed during request execution. Local fallback predicates reject partial remote pages with RequestLocalPaginationUnsupportedError when the upstream total_count does not match the returned item count. Slices, unions, and none() are concrete buckets whose count override is their concrete item count; all() always returns a new bucket rather than self. __contains__ delegates to tuple membership over materialized manager objects, so it uses normal manager equality/identity rather than request lookup semantics.

general_manager.rule.rule.Rule

Bases: Generic[GeneralManagerType]

Encapsulate a boolean predicate and derive contextual error messages from its AST.

When the predicate evaluates to False, the rule inspects the parsed abstract syntax tree to determine which variables failed and crafts either autogenerated or custom error messages.

__init__

__init__(
    func, custom_error_message=None, ignore_if_none=True
)

Initialize a Rule that wraps a predicate function, captures its source AST to discover referenced variables, and prepares handlers for generating error messages.

Parameters:

Name Type Description Default
func Callable[[GeneralManagerType], bool]

Predicate that evaluates a GeneralManager instance.

required
custom_error_message Optional[str]

Optional template used to format generated error messages; placeholders must match variables referenced by the predicate.

None
ignore_if_none bool

If True, evaluation will be skipped (result recorded as None) when any referenced variable resolves to None.

True

evaluate

evaluate(x)

Evaluate the rule's predicate against a GeneralManager instance and record evaluation context.

Binds the primary parameter to the provided input, extracts referenced variable values, and sets the last evaluation result to the predicate outcome. If ignore_if_none is true and any referenced variable value is None, the evaluation is skipped and the last result is set to None.

Parameters:

Name Type Description Default
x GeneralManagerType

Manager instance supplied to the predicate.

required

Returns:

Type Description
Optional[bool]

True if the predicate evaluates to true, False if it evaluates to false, None if evaluation was skipped because a referenced value was None and ignore_if_none is enabled.

validate_custom_error_message

validate_custom_error_message()

Validate that a provided custom error message template includes placeholders for every variable referenced by the rule.

Raises:

Type Description
MissingErrorTemplateVariableError

If one or more extracted variables are not present as {name} placeholders in the custom template.

get_error_message

get_error_message()

Construct error messages for the last failed evaluation.

Returns:

Type Description
Optional[Dict[str, str]]

dict[str, str] | None: Mapping keyed by referenced variables or

Optional[Dict[str, str]]

Django's NON_FIELD_ERRORS fallback when no variables are available;

Optional[Dict[str, str]]

None if the predicate passed, was skipped, or has not been evaluated.

Raises:

Type Description
MissingErrorTemplateVariableError

If a failed rule's custom message omits a placeholder for a referenced variable.

ErrorMessageGenerationError

If internal evaluation state records a failed result without retaining its evaluated input.

Exception

A matching rule handler's documented message-generation exceptions propagate unchanged.

Rule(func, custom_error_message=None, ignore_if_none=True) returns the predicate result from evaluate(manager) as True, False, or None when a referenced value is skipped. After False, get_error_message() returns a non-empty dict[str, str]: handler-derived messages when available, a variable-keyed combination fallback otherwise, or Django's "__all__" key for a variable-free predicate. A custom message is retained by the fallback. Calling get_error_message() before evaluation or after a passing/skipped evaluation returns None. For a failed rule, missing custom-message placeholders raise MissingErrorTemplateVariableError, and documented custom or built-in handler exceptions propagate unchanged. The defensive ErrorMessageGenerationError applies only if internal state records failure without retaining the evaluated input. The non-empty failed-rule fallback is guaranteed from 0.62.2. See the task guide and cookbook recipe.

BaseRuleHandler.handle(node, left, right, op, var_values, rule) is called by Rule while explaining a failed predicate. It returns {variable: message} and does not re-run or decide validation. Custom handlers should set function_name to a non-empty string; duplicate names replace earlier registrations from RULE_HANDLERS in order. RULE_HANDLERS entries must be dotted import paths to BaseRuleHandler subclasses; import errors, non-subclasses, invalid function_name values, and constructor errors surface during Rule construction.

general_manager.rule.handler.BaseRuleHandler

Bases: ABC

Define the protocol for generating rule-specific error messages.

Rule handlers are used after a predicate has already failed. They explain a comparison by returning messages keyed by variable name; they do not decide whether a rule passes. Subclasses must set function_name, which is the dispatch key used by Rule and RULE_HANDLERS registration.

handle abstractmethod

handle(node, left, right, op, var_values, rule)

Produce error messages for a comparison or function call node.

Parameters:

Name Type Description Default
node AST

AST node representing the expression being evaluated.

required
left expr | None

Left operand when applicable.

required
right expr | None

Right operand when applicable.

required
op cmpop | None

Comparison operator node.

required
var_values dict[str, object | None]

Resolved variable values used during evaluation.

required
rule RuleHandlerContext

Rule-like object invoking the handler.

required

Returns:

Type Description
RuleErrorMap

dict[str, str]: Mapping of variable names to error messages. Return an empty mapping when the handler cannot explain the node.

general_manager.rule.handler.InvalidFunctionNodeError

Bases: ValueError

Raised when a rule handler receives an invalid AST node for its function.

__init__

__init__(function_name)

Initialize the exception for an invalid left-hand AST node used with a function call.

Parameters:

Name Type Description Default
function_name str

Name of the function with the invalid left node; stored on the exception and used to form the message "Invalid left node for {function_name}() function."

required

general_manager.rule.handler.InvalidLenThresholdError

Bases: TypeError

Raised when len() comparisons use a non-numeric threshold.

__init__

__init__()

Exception raised when a len() threshold is not a numeric value.

Initializes the exception with a default message indicating invalid arguments for the len function.

general_manager.rule.handler.InvalidNumericThresholdError

Bases: TypeError

Raised when aggregate handlers use a non-numeric threshold.

__init__

__init__(function_name)

Create an InvalidFunctionNodeError with a formatted message for the given function name.

Parameters:

Name Type Description Default
function_name str

Name of the aggregate function (e.g., "sum", "max", "min") included in the message.

required

general_manager.rule.handler.NonEmptyIterableError

Bases: ValueError

Raised when an aggregate function expects a non-empty iterable.

__init__

__init__(function_name)

Initialize the error indicating an aggregate function received an empty iterable.

Parameters:

Name Type Description Default
function_name str

Name of the aggregate function (e.g., 'sum', 'max', 'len') used to build the error message.

required

general_manager.rule.handler.NumericIterableError

Bases: TypeError

Raised when an aggregate function expects numeric elements.

__init__

__init__(function_name)

Initialize the exception indicating that a function expected an iterable of numeric values.

Parameters:

Name Type Description Default
function_name str

Name of the function included in the exception message (message: " expects an iterable of numbers.").

required

general_manager.rule.rule.InvalidRuleHandlerConfigurationError

Bases: TypeError

Raised when a RULE_HANDLERS entry does not resolve to a rule handler class.