"""Implements Parallel node type for the sequenceer.
"""
import logging
import attr
from .action import make_node
from .state import T_STATE
from .sequence import Sequence
logger = logging.getLogger(__name__)
[docs]@attr.s
class Parallel(Sequence):
"""
Parallel node definition.
Use the :meth:`create` method to build properly :class:`Parallel` nodes.
Since it inherits from :class:`Sequence` it has access to the same context variables.
Example:
One can access the running Sequence using Sequence.current_tpl context variable.
>>> s = Parallel.create(a,b, name="my sequence")
# execute Sequence
>>> await s.start()
# Get running Sequence from Inside function a():
>>> def a():
... current_tpl = Sequence.current_tpl
... # now current_tpl is the node s
... assert current_tpl == s
"""
seq_args = attr.ib(kw_only=True, default=attr.Factory(list), repr=False)
def __attrs_post_init__(self):
if self.name is None:
self.name = "Par"
super().__attrs_post_init__()
self.seq = self.seq_args
def __repr__(self):
return "<Parallel (%s)...>" % (self.id)
def make_sequence(self):
logger.debug("build parallel sequence: %s", self.seq)
G = self.graph
st = self.start_node
end = self.end_node
G.add_node(st.id, node=st)
G.add_node(end.id, node=end)
for el in self.seq:
G.add_node(el.id, node=el)
G.add_edge(st.id, el.id)
G.add_edge(el.id, end.id)
el.make_sequence()
logger.debug("Parallel sequence: %s", str(self))
[docs] @staticmethod
def create(*args, **kw):
"""Creates a :class:`Parallel` node
Args:
*args: Variable length list of nodes or coroutines that compose the sequence.
Keyword Args:
id: Node id
name: node name
"""
a = Parallel(seq_args=args, **kw)
return a