Base interfaces and metaclasses for implementation plug-ins.

This module defines
  • Impl: Marker base for concrete implementation backends.
  • ImplClientMeta: Metaclass that aggregates and propagates required operation names.
  • ImplClient: Mixin for objects using implementations to declare/query required operations.

Impl

Marker base class for concrete implementation backends.

Source code in src/pyspect/impls/base.py
class Impl[R]:
    """Marker base class for concrete implementation backends."""

ImplClient

Client-side mixin for declaring and checking required operations.

Clients refer to objects that use an implementation backend. ImplClient ensures to list the names of operations they need the implementation to provide via the class attribute require. This mixin offers methods to: - report which operations are missing on a given Impl - test if an implementation satisfies all requirements - extend or inherit requirement sets dynamically

Source code in src/pyspect/impls/base.py
class ImplClient[R](metaclass=ImplClientMeta):
    """Client-side mixin for declaring and checking required operations.

    Clients refer to objects that use an implementation backend. ImplClient
    ensures to list the names of operations they need the implementation to
    provide via the class attribute __require__. This mixin offers methods to:
        - report which operations are missing on a given Impl
        - test if an implementation satisfies all requirements
        - extend or inherit requirement sets dynamically
    """

    @classmethod
    def missing_ops(cls, impl: Impl[R]) -> list[str]:
        """Return the names of required operations not found on impl."""
        return [
            field
            for field in cls.__require__
            if not hasattr(impl, field)
        ]

    @classmethod
    def is_supported(cls, impl: Impl[R]) -> bool:
        """Return True if impl provides all operations listed in __require__."""
        return not cls.missing_ops(impl)

    def add_requirements(self, funcnames: Sequence[str]) -> None:
        """Add function names to the set of required operations."""
        _require = set(self.__require__)
        _require = _require.union(funcnames)
        self.__require__ = tuple(_require)

    def inherit_requirements(self, *others: ImplClient[R]) -> None:
        """Merge requirement sets from other ImplClient-like classes."""
        for other in others:
            self.add_requirements(other.__require__)

add_requirements(funcnames)

Add function names to the set of required operations.

Source code in src/pyspect/impls/base.py
def add_requirements(self, funcnames: Sequence[str]) -> None:
    """Add function names to the set of required operations."""
    _require = set(self.__require__)
    _require = _require.union(funcnames)
    self.__require__ = tuple(_require)

inherit_requirements(*others)

Merge requirement sets from other ImplClient-like classes.

Source code in src/pyspect/impls/base.py
def inherit_requirements(self, *others: ImplClient[R]) -> None:
    """Merge requirement sets from other ImplClient-like classes."""
    for other in others:
        self.add_requirements(other.__require__)

is_supported(impl) classmethod

Return True if impl provides all operations listed in require.

Source code in src/pyspect/impls/base.py
@classmethod
def is_supported(cls, impl: Impl[R]) -> bool:
    """Return True if impl provides all operations listed in __require__."""
    return not cls.missing_ops(impl)

missing_ops(impl) classmethod

Return the names of required operations not found on impl.

Source code in src/pyspect/impls/base.py
@classmethod
def missing_ops(cls, impl: Impl[R]) -> list[str]:
    """Return the names of required operations not found on impl."""
    return [
        field
        for field in cls.__require__
        if not hasattr(impl, field)
    ]

ImplClientMeta

Bases: type

Metaclass that aggregates required operation names across inheritance.

Classes using this metaclass can declare a tuple[str, ...] in require. During class creation, this metaclass unions all require tuples found in the base classes (that also use ImplClientMeta) with the one declared on the subclass, storing the result back into require.

Source code in src/pyspect/impls/base.py
class ImplClientMeta(type):
    """Metaclass that aggregates required operation names across inheritance.

    Classes using this metaclass can declare a tuple[str, ...] in __require__.
    During class creation, this metaclass unions all __require__ tuples found
    in the base classes (that also use ImplClientMeta) with the one declared
    on the subclass, storing the result back into __require__.
    """

    __require__: ClassVar[tuple[str, ...]]

    def __new__(mcs, name: str, bases: tuple[type, ...], namespace: dict[str, Any]) -> None:
        _require = namespace.setdefault('__require__', ())

        require = set(_require)
        for base in bases:
            if isinstance(base, ImplClientMeta):
                require = require.union(base.__require__)

        namespace['__require__'] = tuple(require)

        return super().__new__(mcs, name, bases, namespace)