Backref resolution

didactic.api.resolve_backrefs

resolve_backrefs(
    target: Model,
    candidates: Iterable[B],
    *,
    via: str,
    key: str = "id",
) -> list[B]

Return the subset of candidates whose via field points at target.

PARAMETER DESCRIPTION
target

The Model instance to find inbound references to.

TYPE: Model

candidates

An iterable of Model instances that may contain the inverse Ref.

TYPE: Iterable[B]

via

The name of the field on each candidate that holds the Ref. Typically this is the field declared as Ref[type(target)].

TYPE: str

key

The attribute on target whose value the Ref stores. Defaults to "id", which matches didactic's conventional vertex identifier.

TYPE: str DEFAULT: 'id'

RETURNS DESCRIPTION
list

Every candidate c for which getattr(c, via) == getattr(target, key). The order matches the iteration order of candidates.

RAISES DESCRIPTION
AttributeError

If target has no key attribute, or any candidate has no via attribute.

Examples:

>>> import didactic.api as dx
>>> class Author(dx.Model):
...     id: str
...     name: str
>>> class Book(dx.Model):
...     id: str
...     title: str
...     author: dx.Ref[Author]
>>> ada = Author(id="a1", name="Ada Lovelace")
>>> books = [
...     Book(id="b1", title="Note A", author="a1"),
...     Book(id="b2", title="Note B", author="a2"),
...     Book(id="b3", title="Note C", author="a1"),
... ]
>>> [b.id for b in dx.resolve_backrefs(ada, books, via="author")]
['b1', 'b3']

didactic.api.ModelPool

ModelPool(instances: Iterable[Model] | None = None)

An in-memory pool of Model instances, grouped by class.

PARAMETER DESCRIPTION
instances

Optional initial collection of Model instances. Each is registered under its concrete class.

TYPE: Iterable[Model] | None DEFAULT: None

Notes

The pool is a plain dict-of-lists keyed by class identity. It does not deduplicate, observe mutations, or check that ids are unique; it is a tiny convenience for collecting test fixtures and short-lived application state. For durable storage, use didactic.api.Repository.

Examples:

>>> import didactic.api as dx
>>> class Author(dx.Model):
...     id: str
>>> class Book(dx.Model):
...     id: str
...     author: dx.Ref[Author]
>>>
>>> pool = dx.ModelPool()
>>> ada = Author(id="a1")
>>> _ = pool.add(ada)
>>> _ = pool.add(Book(id="b1", author="a1"))
>>> _ = pool.add(Book(id="b2", author="a2"))
>>>
>>> [b.id for b in pool.backrefs(ada, Book, via="author")]
['b1']

add

add(instance: M) -> M

Register instance under its concrete class.

PARAMETER DESCRIPTION
instance

A Model instance.

TYPE: M

RETURNS DESCRIPTION
Model

instance itself, for fluent chaining.

all_of

all_of(cls: type[M]) -> list[M]

Return every instance registered under cls.

PARAMETER DESCRIPTION
cls

The Model class to look up.

TYPE: type[M]

RETURNS DESCRIPTION
list

Instances registered under exactly cls (subclass instances are stored under their own concrete class, not under cls). Order is registration order.

backrefs

backrefs(
    target: Model,
    candidate_cls: type[B],
    *,
    via: str,
    key: str = "id",
) -> list[B]

Resolve backrefs to target from instances of candidate_cls.

PARAMETER DESCRIPTION
target

The Model instance to find inbound references to.

TYPE: Model

candidate_cls

The Model class to scan for the inverse Ref.

TYPE: type[B]

via

The name of the field on candidate_cls that holds the Ref.

TYPE: str

key

The attribute on target whose value the Ref stores. Defaults to "id".

TYPE: str DEFAULT: 'id'

RETURNS DESCRIPTION
list

All registered candidate_cls instances whose via field equals getattr(target, key).