Source code for pyiron_workflow.mixin.has_interface_mixins

"""
For interface specification.

There are cases where we want to be able to depend on the presence of a particular
attribute or method, but care very little about its details -- nothing beyond, perhaps,
type hints. These mixins allow us to guarantee the presence of such interfaces while
leaving their actual implementation up to other classes in order to have the weakest
possible coupling between different components of a composed class.
"""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

if TYPE_CHECKING:  # pragma: no cover
    from pyiron_workflow.channels import Channel


[docs] class UsesState: """ A mixin for any class using :meth:`__getstate__` or :meth:`__setstate__`. Guarantees that `super()` can always be called in these methods to return a copy of the state dict or to update it, respectively. """ def __getstate__(self): # Make a shallow(! careful!) copy of the state so any modifications don't # immediately impact the object we're getting the state from) return dict(self.__dict__) def __setstate__(self, state): self.__dict__.update(**state)
[docs] class HasLabel(ABC): """ A mixin to guarantee the label interface exists. """ _label: str @property def label(self) -> str: """A label for the object.""" return self._label @label.setter def label(self, new_label: str): self._check_label(new_label) self._label = new_label def _check_label(self, new_label: str) -> None: """ Extensible checking routine for label validity. """ if not isinstance(new_label, str): raise TypeError(f"Expected a string label but got {new_label}") @property def full_label(self) -> str: """ A more verbose label based off the underlying label attribute (and possibly other data) -- in the root class, it's just the same as the label. """ return self.label
[docs] class HasChannel(ABC): """ A mix-in class for use with the :class:`Channel` class and its children. This is useful for letting channels attempt to connect to non-channel objects directly by pointing them to some channel that object holds. """ @property @abstractmethod def channel(self) -> Channel: ...
[docs] class HasRun(ABC): """ A mixin to guarantee that the :meth:`run` method exists. """
[docs] @abstractmethod def run(self, *args, **kwargs): ...