Skip to content

registry

ElementInfo dataclass

ElementInfo(name, module, kind, element=None, description=None, error=None, distribution=None)

Useful information associated with an element.

Parameters:

Name Type Description Default
name str

The element's name (class).

required
extra str

The extra package this element can be found in. The empty string represents no extra, or a base element.

required
module str

The module the element can be found in, represented as a string.

required
kind ElementType

The type of element, i.e. source element.

required
element type[Element] | Callable[..., Element] | None

If the element is not broken, a reference to this element's class or class method constructor.

None
description str | None

If the element is not broken, the documentation associated with this element.

None
error str | None

If the element is broken, the error raised when loading it.

None
distribution str | None

The distribution providing this element, where known. The plugin name is derived from it.

None

broken property

broken

Whether this element is broken.

doc_body cached property

doc_body

The element's documentation with developer-facing sections removed.

The argument documentation is presented separately via fields, and notes sections are dropped as they are primarily for element developers.

element_class cached property

element_class

The element's class, resolving class method constructors.

fields cached property

fields

The element-specific keyword arguments accepted at construction.

Arguments common to all elements (e.g. name, pad names) are excluded. For elements registered as classes these are the element's dataclass fields, ordered by defining class (most derived first); for class method constructors, the method's parameters.

frame_type cached property

frame_type

The frame type this element declares via its generic base, if any.

hierarchy cached property

hierarchy

The element class hierarchy, from the sgn base class to the element.

Only element classes (subclasses of the sgn element base classes) are included; other classes in the resolution order are listed in mixins.

mixins cached property

mixins

Non-element classes the element inherits from, e.g. mixins.

These generally provide additional features on top of the element base classes, summarized by their docstrings.

pad_topology cached property

pad_topology

The pad topology the element expects, if declared by a validator.

Extracted from the pad_constraint attribute that sgn.validator decorators attach to decorated methods; None if the element declares no such constraint.

plugin cached property

plugin

The plugin associated with this element.

This is tied to the providing distribution, where base sgn elements by default are associated with the base plugin. Elements not sourced from an entry point fall back to their top-level module.

qualname cached property

qualname

The fully-qualified name of the element's class.

short_description cached property

short_description

A one line description associated with this element, if not broken.

The first sentence of the element's documentation.

thread_safe cached property

thread_safe

Whether the element author has certified the element thread safe.

from_entrypoint classmethod

from_entrypoint(entrypoint)

Create an ElementInfo from a package entry point.

Parameters:

Name Type Description Default
entrypoint EntryPoint

The package entry point associated with an element.

required

Returns:

Type Description
ElementInfo

The element information.

Source code in src/sgn_inspect/registry.py
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
@classmethod
def from_entrypoint(cls, entrypoint: EntryPoint) -> Self:
    """Create an ElementInfo from a package entry point.

    Parameters
    ----------
    entrypoint : EntryPoint
        The package entry point associated with an element.

    Returns
    -------
    ElementInfo
        The element information.

    """
    module = entrypoint.module
    error = None
    try:
        # loading imports the element's module, and whatever that warns
        # about on the way in is between the plugin and its own users;
        # it tells the reader nothing about the element being inspected
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            element = entrypoint.load()
        kind = ElementType.from_element(element)
    except Exception as e:
        element = None
        kind = ElementType.INVALID
        description = None
        error = str(e)
    else:
        description = inspect.getdoc(element)
    return cls(
        entrypoint.name,
        module,
        kind,
        element,
        description,
        error,
        _distribution_name(entrypoint),
    )

pad_config

pad_config(direction)

The element's pad configuration for the given direction.

Parameters:

Name Type Description Default
direction PadDirection

The pad direction, either "sink" or "source".

required

Returns:

Type Description
PadConfig | None

The pad configuration, or None if the element has no pads in the given direction (e.g. sink pads on a source element) or is broken.

Source code in src/sgn_inspect/registry.py
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
def pad_config(self, direction: PadDirection) -> PadConfig | None:
    """The element's pad configuration for the given direction.

    Parameters
    ----------
    direction : PadDirection
        The pad direction, either "sink" or "source".

    Returns
    -------
    PadConfig | None
        The pad configuration, or None if the element has no pads in the
        given direction (e.g. sink pads on a source element) or is broken.

    """
    cls = self.element_class
    if cls is None:
        return None
    if direction == "sink" and not issubclass(cls, (TransformElement, SinkElement)):
        return None
    if direction == "source" and not issubclass(
        cls, (SourceElement, TransformElement)
    ):
        return None
    static = getattr(cls, f"static_{direction}_pads", [])
    static_computed = isinstance(static, property)
    doc = None
    if static_computed and static.__doc__:
        # not inspect.getdoc: an undocumented property inherits the
        # docstring of the base class attribute it shadows, which is the
        # empty list ElementLike declares, giving list.__doc__
        doc = inspect.cleandoc(static.__doc__)
    return PadConfig(
        static=() if static_computed else tuple(static),
        static_computed=static_computed,
        dynamic=bool(getattr(cls, f"allow_dynamic_{direction}_pads", True)),
        doc=doc,
    )

ElementType

Bases: IntEnum

Used to inform a particular element's type, i.e. source.

INVALID class-attribute instance-attribute

INVALID = auto()

not an element

SINK class-attribute instance-attribute

SINK = auto()

a sink element

SOURCE class-attribute instance-attribute

SOURCE = auto()

a source element

TRANSFORM class-attribute instance-attribute

TRANSFORM = auto()

a transform element

from_element classmethod

from_element(element)

Determine an element's type from an element class.

Parameters:

Name Type Description Default
element type[Element] | Callable[..., Element]

The element class or class method constructor associated with an element class.

required

Returns:

Type Description
ElementType

The element's type.

Source code in src/sgn_inspect/registry.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
@typing.no_type_check
@classmethod
def from_element(
    cls, element: type[Element] | Callable[..., Element]
) -> ElementType:
    """Determine an element's type from an element class.

    Parameters
    ----------
    element : type[Element] | Callable[..., Element]
        The element class or class method constructor associated with an
        element class.

    Returns
    -------
    ElementType
        The element's type.

    """
    if inspect.ismethod(element):
        element = element.__self__
    if issubclass(element, SourceElement):
        return ElementType.SOURCE
    if issubclass(element, TransformElement):
        return ElementType.TRANSFORM
    if issubclass(element, SinkElement):
        return ElementType.SINK
    msg = f"{element} is not an element"
    raise TypeError(msg)

FieldInfo dataclass

FieldInfo(name, annotation, default, description, defined_in=None)

A keyword argument accepted by an element's constructor.

Parameters:

Name Type Description Default
name str

The argument name.

required
annotation str

The argument's type annotation, or the empty string if not annotated.

required
default str | None

The argument's default value, formatted for display, or None if the argument is required.

required
description str | None

The argument's description, parsed from the element's docstring or those of its base classes.

required
defined_in str | None

The name of the class in the element's hierarchy that defines this argument, if known.

None

required property

required

Whether this argument must be provided.

MixinInfo dataclass

MixinInfo(qualname, summary)

A non-element class an element inherits from.

Parameters:

Name Type Description Default
qualname str

The fully-qualified name of the mixin class.

required
summary str | None

A one line summary of the feature the mixin provides, taken from its docstring.

required

name property

name

The unqualified class name.

PadConfig dataclass

PadConfig(static, static_computed, dynamic, doc=None)

An element's pad configuration for one direction (sink or source).

Parameters:

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

Pad names that are always present on this element.

required
static_computed bool

Whether the static pads are computed at construction time (and so cannot be known statically).

required
dynamic bool

Whether additional pads may be requested at construction via the <direction>_pad_names argument.

required
doc str | None

For pads computed at construction, the documentation describing how they are determined, if available.

None

PadTopology dataclass

PadTopology(sink_pads=None, source_pads=None, pad_names_match=False)

The pad topology an element expects, as enforced by its validator.

Extracted from the pad_constraint attached by sgn.validator decorators (e.g. @validator.one_to_one).

Parameters:

Name Type Description Default
sink_pads int | None

The exact number of sink pads required, or None if unconstrained.

None
source_pads int | None

The exact number of source pads required, or None if unconstrained.

None
pad_names_match bool

Whether source and sink pad names are required to match.

False

discover_elements

discover_elements()

Discover all elements registered via entry points.

Note that non-base elements are only discoverable after installing the corresponding extra package associated with a plugin.

Returns:

Type Description
dict[str, ElementInfo]

A mapping between element names and their information.

Source code in src/sgn_inspect/registry.py
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
def discover_elements() -> dict[str, ElementInfo]:
    """Discover all elements registered via entry points.

    Note that non-base elements are only discoverable after installing the
    corresponding extra package associated with a plugin.

    Returns
    -------
    dict[str, ElementInfo]
        A mapping between element names and their information.

    """
    elements: dict[str, ElementInfo] = {}
    entrypoints = entry_points(group="sgn_elements")
    for name in entrypoints.names:
        elements[name] = ElementInfo.from_entrypoint(entrypoints[name])
    return elements

discover_names

discover_names()

Discover registered element and plugin names, without loading elements.

Loading an element imports its module, which is far too slow to do on every keystroke; entry point names and their modules are both available without it. Element types therefore cannot be reported here.

Returns:

Type Description
dict[str, str]

A mapping of every element and plugin name to a description of what it is: the providing plugin for an element, or "plugin" for a plugin. Where an element shares a name with a plugin, the plugin takes precedence, as it does when the name is looked up.

Source code in src/sgn_inspect/registry.py
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
def discover_names() -> dict[str, str]:
    """Discover registered element and plugin names, without loading elements.

    Loading an element imports its module, which is far too slow to do on
    every keystroke; entry point names and their modules are both available
    without it. Element types therefore cannot be reported here.

    Returns
    -------
    dict[str, str]
        A mapping of every element and plugin name to a description of what
        it is: the providing plugin for an element, or "plugin" for a
        plugin. Where an element shares a name with a plugin, the plugin
        takes precedence, as it does when the name is looked up.

    """
    elements: dict[str, str] = {}
    plugins: dict[str, str] = {}
    for entrypoint in entry_points(group="sgn_elements"):
        plugin = plugin_name(
            _distribution_name(entrypoint) or entrypoint.module.split(".")[0]
        )
        elements[entrypoint.name] = plugin
        plugins[plugin] = "plugin"
    return {**elements, **plugins}

plugin_name

plugin_name(distribution)

The plugin name for the distribution providing an element.

The sgn prefix is stripped only where it is a genuine prefix, set off by a separator: sgn-ligo provides the ligo plugin, whereas sgnl is a name in its own right rather than the l plugin.

Parameters:

Name Type Description Default
distribution str

The distribution name, e.g. sgn-ligo. The top-level module is an acceptable stand-in where the distribution is unknown.

required

Returns:

Type Description
str

The plugin name. Base sgn elements are associated with the base plugin.

Source code in src/sgn_inspect/registry.py
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
def plugin_name(distribution: str) -> str:
    """The plugin name for the distribution providing an element.

    The sgn prefix is stripped only where it is a genuine prefix, set off
    by a separator: ``sgn-ligo`` provides the ``ligo`` plugin, whereas
    ``sgnl`` is a name in its own right rather than the ``l`` plugin.

    Parameters
    ----------
    distribution : str
        The distribution name, e.g. ``sgn-ligo``. The top-level module is
        an acceptable stand-in where the distribution is unknown.

    Returns
    -------
    str
        The plugin name. Base sgn elements are associated with the base
        plugin.

    """
    plugin = re.sub(r"^sgn[-_]", "", distribution)
    if plugin == "sgn":
        plugin = ""
    return re.sub(r"[-_]", "", plugin) or "base"