pyiron_workflow.channels module
Channels are access points for information to flow into and out of nodes. They accomplish this by forming connections between each other, and it should be as easy as possible to form sensible and reliable connections.
Nodes get the attention, but channels are the real heroes.
- class pyiron_workflow.channels.AccumulatingInputSignal(label: str, owner: Node, callback: Callable)[source]
Bases:
InputSignalAn input signal that only fires after receiving a signal from _all_ its connections instead of after _any_ of its connections.
- class pyiron_workflow.channels.Callback(callback: Callable[[...], Any] | None, *args: Any, **kwargs: Any)[source]
Bases:
object
- class pyiron_workflow.channels.Channel(label: str, owner: Node)[source]
Bases:
HasChannel,HasLabel,HasStateDisplay,Generic[ConjugateType],ABCChannels facilitate the flow of information (data or control signals) into and out of
Nodeobjects (namely nodes).They must have an identifier (label: str) and belong to an owner: pyiron_workflow.node.Node.
Channels may form (
connect()/disconnect()) and store (connections) connections with other channels.This connection information is reflexive, and is duplicated to be stored on _both_ channels in the form of a reference to their counterpart in the connection.
By using the provided methods to modify connections, the reflexive nature of these (dis)connections is guaranteed to be handled, and new connections are subjected to a validity test.
Child classes must specify a conjugate class in order to enforce connection conjugate pairs which have the same “flavor” (e.g. “data” or “signal”), and opposite “direction” (“input” vs “output”). And they must define a string representation.
Iterating over channels yields their connections.
The length of a channel is the length of its connections.
- owner
The channel’s owner.
- property channel: Self
- connect(*others: ConjugateType) None[source]
Form a connection between this and one or more other channels. Connections are reflexive, and should only occur between input and output channels, i.e. they are instances of each others
connection_conjugate().New connections get _prepended_ to the connection lists, so they appear first when searching over connections.
- Parameters:
*others (Channel) – The other channel objects to attempt to connect with.
- Raises:
(ChannelConnectionError) – If the other channel is of the correct type, but nonetheless not a valid connection.
(TypeError) – If the other channel is not an instance of this channel’s partner type.
- property connected: bool
Has at least one connection.
- abstractmethod classmethod connection_conjugate() type[ConjugateType][source]
The class forming a conjugate pair with this channel class – i.e. the same “flavor” of channel, but opposite in I/O.
- disconnect(*others: ConjugateType) list[tuple[Self, ConjugateType]][source]
If currently connected to any others, removes this and the other from eachothers respective connections lists.
- disconnect_all() list[tuple[Self, ConjugateType]][source]
Disconnect from all other channels currently in the connections list.
- display_state(state=None, ignore_private=True)[source]
A dictionary of JSON-compatible objects based on the object state (plus whatever modifications to the state the class designer has chosen to make).
Anything that fails to dump to JSON gets cast as a string and then dumped.
- Parameters:
state (dict|None) – The starting state. Default is None which uses __getstate__, but available in case child classes want to first sanitize the state values.
ignore_private (bool) – Whether to ignore or include any state element whose key starts with ‘_’. Default is True, only show public data.
- Return type:
dict
- property full_label: str
A label combining the channel’s usual label and its owner’s lexical path
- move_connections(other: Self) None[source]
Adds all the connections in another channel to this channel’s connections.
If an exception is encountered, all the new connections are disconnected before the exception is raised.
- property scoped_label: str
A label combining the channel’s usual label and its owner’s label
- exception pyiron_workflow.channels.ChannelConnectionError[source]
Bases:
ChannelError
- class pyiron_workflow.channels.DataChannel(label: str, owner: Node, default: Any | None = NOT_DATA, type_hint: Any | None = None, strict_hints: bool = True, value_receiver: ReceiverType | None = None)[source]
Bases:
FlavorChannel[DataChannel],Generic[ReceiverType],ABCData channels control the flow of data on the graph.
They store data persistently (
value).This value may have a default (
default) and the default-default is to be NOT_DATA.They may optionally have a type hint (
type_hint).New data and new connections are tested against type hints (if any).
In addition to the requirement of being a “conjugate pair”, if both connecting channels have type hints, the output channel must have a type hint that is as or more specific than the input channel.
In addition to connections, these channels can have a single partner (
value_receiver) that is of the same data flavor and the same direction (i.e. input or output) and obeys type hints as though it were the “downstream” (input) partner in a connection. Channels with such partners pass any data updates they receive directly to this partner (via thevaluesetter). (This is helpful for passing data between scopes, where we want input at one scope to be passed to the input of owners at a deeper scope, i.e. macro input passing to child node input, or vice versa for output.)All these type hint tests can be disabled on the input/receiving channel (
strict_hints: bool), and this is recommended for the optimal performance in production runs.Channels can indicate whether they hold data they are happy with (
ready: bool), which is to say it is data (not the singleton NOT_DATA) and that it conforms to the type hint (if one is provided and checking is active).Some comments on type hinting: For simple type hints like int or str, type hint comparison is trivial. However, some hints take arguments, e.g. dict[str, int] to specify key and value types; tuple[int, int, str] to specify a tuple with certain values; typing.Literal[‘a’, ‘b’, ‘c’] to specify particular choices; typing.Callable[[float, float], str] to specify a callable that takes particular argument types and has a return type; etc. For hints with the origin dict, tuple, and typing.Callable, the two hints must have _exactly the same arguments_ for one two qualify as “as or more specific”. E.g. tuple[int, int|float] is as or more specific than tuple[int|float, int|float], but not tuple[int, int|float, str]. For _all other hints_, we demand that the output hint arguments be a _subset_ of the input. E.g. Literal[1, 2] is as or more specific that both Literal[1, 2] and Literal[1, 2, “three”].
Warning
Type hinting in python is quite complex, and determining when a hint is “more specific” can be tricky. For instance, in python 3.11 you can now type hint a tuple with a mixture of fixed elements of fixed type, followed by an arbitrary elements of arbitrary type. This and other complex scenarios are not yet included in our test suite and behaviour is not guaranteed.
- value
The actual data value held by the channel.
- owner
The channel’s owner.
- default
The default value to initialize to. (Default is the singleton NOT_DATA.)
- Type:
Any|None
- type_hint
A type hint for values. (Default is None.)
- Type:
Any|None
- strict_hints
Whether to check new values, connections, and partners when this channel is a value receiver. This can potentially be expensive, so consider deactivating strict hints everywhere for production runs. (Default is True, raise exceptions when type hints get violated.)
- Type:
bool
- value_receiver
Another channel of the receiver type (i.e. also a data flavor and matching input/output type) whose value will always get updated when this channel’s value gets updated.
- Type:
ReceiverType|None
- display_state(state=None, ignore_private=True)[source]
A dictionary of JSON-compatible objects based on the object state (plus whatever modifications to the state the class designer has chosen to make).
Anything that fails to dump to JSON gets cast as a string and then dumped.
- Parameters:
state (dict|None) – The starting state. Default is None which uses __getstate__, but available in case child classes want to first sanitize the state values.
ignore_private (bool) – Whether to ignore or include any state element whose key starts with ‘_’. Default is True, only show public data.
- Return type:
dict
- has_ontologically_valid_connection(other: DataChannel, exception_on_invalid: bool = False) bool[source]
- property ready: bool
Check if the currently stored value is data and satisfies the channel’s type hint (if hint checking is activated).
- Returns:
Whether the value is data and matches the type hint.
- Return type:
(bool)
- property value
- property value_receiver: ReceiverType | None
Another data channel of the same type to whom new values are always pushed (without type checking of any sort, not even when forming the couple!)
Useful for macros, so that the IO of children and IO at the macro level can be kept synchronized.
- class pyiron_workflow.channels.FlavorChannel(label: str, owner: Node)[source]
Bases:
Channel[FlavorType],ABCAbstract base for all flavor-specific channels.
- class pyiron_workflow.channels.InputChannel(label: str, owner: Node)[source]
Bases:
Channel[OutputType],ABCMixin for input channels.
- class pyiron_workflow.channels.InputData(label: str, owner: Node, default: Any | None = NOT_DATA, type_hint: Any | None = None, strict_hints: bool = True, value_receiver: ReceiverType | None = None)[source]
Bases:
DataChannel[InputData],InputChannel[OutputData]- classmethod connection_conjugate() type[OutputData][source]
The class forming a conjugate pair with this channel class – i.e. the same “flavor” of channel, but opposite in I/O.
- fetch() None[source]
Sets
valueto the first value among connections (i.e. the most recent) that is something other than NOT_DATA; if no such value exists (e.g. because there are no connections or because all the connected output channels have NOT_DATA as their value),valueremains unchanged. I.e., the connection with the highest priority for updating input data is the 0th connection; build graphs accordingly.- Raises:
RuntimeError – If the owner is
running.
- property value
- exception pyiron_workflow.channels.InputLockedError[source]
Bases:
ChannelError,ValueError
- class pyiron_workflow.channels.InputSignal(label: str, owner: Node, callback: Callable)[source]
Bases:
SignalChannel[OutputSignal],InputChannel[OutputSignal]- property callback: Callable
- classmethod connection_conjugate() type[OutputSignal][source]
The class forming a conjugate pair with this channel class – i.e. the same “flavor” of channel, but opposite in I/O.
- exception pyiron_workflow.channels.InvalidReceiverError[source]
Bases:
ValueError,ChannelConnectionError
- class pyiron_workflow.channels.OutputChannel(label: str, owner: Node)[source]
Bases:
Channel[InputType],ABCMixin for output channels.
- class pyiron_workflow.channels.OutputData(label: str, owner: Node, default: Any | None = NOT_DATA, type_hint: Any | None = None, strict_hints: bool = True, value_receiver: ReceiverType | None = None)[source]
Bases:
DataChannel[OutputData],OutputChannel[InputData]
- class pyiron_workflow.channels.OutputSignal(label: str, owner: Node)[source]
Bases:
SignalChannel[InputSignal],OutputChannel[InputSignal]- classmethod connection_conjugate() type[InputSignal][source]
The class forming a conjugate pair with this channel class – i.e. the same “flavor” of channel, but opposite in I/O.
- class pyiron_workflow.channels.SignalChannel(label: str, owner: Node)[source]
Bases:
FlavorChannel[SignalType],ABCSignal channels give the option control execution flow by triggering callback functions when the channel is called. Callbacks must be methods on the owner that require no positional arguments. Inputs optionally accept an output signal on call, which output signals always send when they call their input connections.
Inputs hold a callback function to call, and outputs call each of their connections.
Signal channels support >> as syntactic sugar for their connections, i.e. some_output >> some_input is equivalent to some_input.connect(some_output). (This is also interoperable with Node objects.)
- exception pyiron_workflow.channels.TooManyConnectionsError[source]
Bases:
ChannelConnectionError