Skip to content

dispatch

dispatch #

How a fluent navigation step picks its access node — the dispatch table.

Descending a procedure one step builds an access node. Two things choose which:

  • the level — the procedure's return type is either a Path[…] (an address: descending yields a deeper Path) or a plain value (descending computes the child value); and
  • the container kindStruct for .field, Array for [int], Map for [key] / .keys() / .values().

Struct, array, and map [key] steps work at either level, so they vary by level in [AccessNodes][]:

.field [int] [key]
Path[…] PathField PathIndex PathKey
value StructField ArrayIndex MapKey

A node can return a Map value (CaptureImagesByLabel collects one image sequence per label), so [key] has a value twin (MapKey) just like the struct and array steps. Map enumeration stays path-level — .keys()PathKeys, .values()PathValues — since enumerating entry positions to fan out over is a navigation, not a value computation.

The operators in [...navigation][] classify a node with [navigable][], then build the cell — every access node takes the position it descends as source.

PATH = AccessNodes(field=PathField, index=PathIndex, key=PathKey) module-attribute #

Addressing a Path[…]: each step yields a deeper Path.

VALUE = AccessNodes(field=StructField, index=ArrayIndex, key=MapKey) module-attribute #

Computing on a value: each step yields the child value.

AccessNodes dataclass #

The struct-field, array-index, and map-key builders for one level.

The three steps that descend both a Path and a value.

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/dispatch.py
@dataclass(frozen=True)
class AccessNodes:
    """The struct-field, array-index, and map-key builders for one level.

    The three steps that descend both a ``Path`` and a value.
    """

    field: Callable[..., Procedure[CGType]]
    index: Callable[..., Procedure[CGType]]
    key: Callable[..., Procedure[CGType]]

Navigable dataclass #

A navigable position: the container being descended and the level.

Also carries the level's struct/array access nodes, and whether it is addressed as a Path (vs computed as a value).

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/dispatch.py
@dataclass(frozen=True)
class Navigable:
    """A navigable position: the container being descended and the level.

    Also carries the level's struct/array access nodes, and whether it is addressed
    as a ``Path`` (vs computed as a value).
    """

    container: type[CGType]
    nodes: AccessNodes
    is_path: bool

    @property
    def is_struct(self) -> bool:
        """Whether the descended container is a ``Struct``."""
        return issubclass(self.container, Struct)

    @property
    def is_array(self) -> bool:
        """Whether the descended container is an ``Array``."""
        return issubclass(self.container, Array)

    @property
    def is_map(self) -> bool:
        """Whether the descended container is a ``Map``."""
        return issubclass(self.container, Map)

    def has_field(self, name: str) -> bool:
        """Whether the descended ``Struct`` declares a field named ``name``."""
        return self.is_struct and name in getattr(self.container, "_fields", {})

is_array property #

Whether the descended container is an Array.

is_map property #

Whether the descended container is a Map.

is_struct property #

Whether the descended container is a Struct.

has_field(name) #

Whether the descended Struct declares a field named name.

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/dispatch.py
def has_field(self, name: str) -> bool:
    """Whether the descended ``Struct`` declares a field named ``name``."""
    return self.is_struct and name in getattr(self.container, "_fields", {})

navigable(node) #

Classify node's return type for navigation.

Returns None if it is a leaf (a scalar / void / bare composite — nothing to descend into). A Path[T] is descended by its target T with the [PATH][] nodes; any other value is descended by its own type with the [VALUE][] nodes. Struct, Array, and Map are navigable at either level — a node may return a Map value (CaptureImagesByLabel), descended by [key] (MapKey).

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/dispatch.py
def navigable(node: Procedure[CGType]) -> Navigable | None:
    """Classify ``node``'s return type for navigation.

    Returns ``None`` if it is a leaf (a scalar / void / bare composite — nothing to
    descend into). A ``Path[T]`` is descended by its target ``T`` with the
    [PATH][] nodes; any other value is descended by its own type with the
    [VALUE][] nodes. ``Struct``, ``Array``, and ``Map`` are navigable at either
    level — a node may return a ``Map`` value (``CaptureImagesByLabel``), descended
    by ``[key]`` (``MapKey``).
    """
    return_type = node.return_type
    if not isinstance(return_type, type):
        return None
    is_path = issubclass(return_type, Path)
    container = return_type._target if is_path else return_type
    if not isinstance(container, type):
        return None
    if not issubclass(container, (Struct, Array, Map)):
        return None
    return Navigable(
        container=container,
        nodes=PATH if is_path else VALUE,
        is_path=is_path,
    )