Skip to content

annotations

annotations #

Pure functions over field annotations.

The one place get_origin / get_args / optional-union unwrapping lives. Everything here is a small, total function from an annotation object to a plain answer; nothing imports the node layer or touches an instance. The classifier ([.fields][]), the validator (.validation), and the construction hook ([.construction][]) all read field annotations through here, so the rules for "what does Input[Image] | None mean" are written once.

input_value_type(annotation) #

The T an Input[T] field carries — the return type it accepts.

Unwraps an optional union (Input[Location] | None) to its input member, then extracts T. A bare Input / Procedure (or one parameterized by a still-unresolved TypeVar on a generic node) yields CGType — the "any CGType" bound, checked precisely by the node's own __post_init__.

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def input_value_type(annotation: object) -> object:
    """The ``T`` an ``Input[T]`` field carries — the return type it accepts.

    Unwraps an optional union (``Input[Location] | None``) to its input member,
    then extracts ``T``. A bare ``Input`` / ``Procedure`` (or one parameterized by
    a still-unresolved ``TypeVar`` on a generic node) yields ``CGType`` — the "any
    CGType" bound, checked precisely by the node's own ``__post_init__``.
    """
    for member in union_members(annotation):
        if _is_input_member(member):
            arguments = get_args(member)
            return arguments[0] if arguments else CGType
    return CGType

is_input(annotation) #

Whether annotation is an input field (optionally | None).

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def is_input(annotation: object) -> bool:
    """Whether ``annotation`` is an input field (optionally ``| None``)."""
    return any(_is_input_member(member) for member in union_members(annotation))

is_optional(annotation) #

Whether annotation is a union that includes None.

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def is_optional(annotation: object) -> bool:
    """Whether ``annotation`` is a union that includes ``None``."""
    return any(member is type(None) for member in union_members(annotation))

is_substeps(annotation) #

Whether annotation is the Substeps marker.

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def is_substeps(annotation: object) -> bool:
    """Whether ``annotation`` is the ``Substeps`` marker."""
    return annotation is Substeps

setting_value_type(annotation) #

The T a Setting[T] field holds, with the wrapper peeled away.

Also peels an optional | None off first. Setting[str]str; Setting[int | float] | Noneint | float; a plain (already-unwrapped) annotation is returned as-is.

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def setting_value_type(annotation: object) -> object:
    """The ``T`` a ``Setting[T]`` field holds, with the wrapper peeled away.

    Also peels an optional ``| None`` off first. ``Setting[str]`` → ``str``;
    ``Setting[int | float] | None`` → ``int | float``; a plain (already-unwrapped)
    annotation is returned as-is.
    """
    for member in union_members(annotation):
        if member is type(None):
            continue
        if get_origin(member) is Setting:
            arguments = get_args(member)
            return arguments[0] if arguments else Any
        return member
    return Any

union_members(annotation) #

The members of a union annotation, or (annotation,) if it is not one.

Input[Image] | None(Input[Image], NoneType); a non-union is returned as a one-tuple so callers can iterate uniformly.

Source code in capturegraph-lib/capturegraph/procedures/procedure/type_checking/annotations.py
def union_members(annotation: object) -> tuple[object, ...]:
    """The members of a union annotation, or ``(annotation,)`` if it is not one.

    ``Input[Image] | None`` → ``(Input[Image], NoneType)``; a non-union is
    returned as a one-tuple so callers can iterate uniformly.
    """
    if get_origin(annotation) in (Union, UnionType):
        return get_args(annotation)
    return (annotation,)