Исходный код lena.core.sequence
"""Sequence class."""
import sys
from .lena_sequence import LenaSequence
from . import adapters
from . import exceptions
from . import functions
[документация]class Sequence(LenaSequence):
"""Sequence of elements, such that next takes input
from the previous during *run*.
:meth:`Sequence.run` must accept input flow.
For sequence with no input data use :class:`Source`.
"""
def __init__(self, *args):
"""*args* are objects
which implement a method *run(flow)* or callables.
*args* can be a single tuple of such elements.
In this case one doesn't need to check argument type
when initializing a Sequence in a general function.
For more information about the *run* method and callables,
see :class:`Run`.
"""
# _name is used for representation.
# Subclass must set its own name or provide a different repr
self._name = "Sequence"
super(Sequence, self).__init__(*args)
seq = []
# todo: we could change self._seq in place,
# check performance (replacement + index access)
for el in self._data_seq:
if hasattr(el, "run") and callable(el.run):
seq.append(el)
else:
try:
# convert to a Run element
# (for example, el could be a Call)
run_el = adapters.Run(el)
except exceptions.LenaTypeError:
raise exceptions.LenaTypeError(
"arguments must implement run method, "
"or be callable generators (convertible to Run), "
"{} given".format(el)
)
else:
seq.append(run_el)
self._data_seq = seq
[документация] def run(self, flow):
"""Generator that transforms the incoming flow.
If this :class:`Sequence` is empty,
the flow passes unaltered, but
with a small change.
This function converts input flow to an iterator,
so that it always contains both *iter* and *next* methods.
This is done for the flow entering the first
sequence element and exiting from the sequence.
"""
flow = functions.flow_to_iter(flow)
for el in self._data_seq:
flow = el.run(flow)
flow = functions.flow_to_iter(flow)
# This function is not a generator, but returns a generator.
# The difference is very subtle.
# Most important is that the function is evaluated immediately,
# and raises in case of errors.
return flow
def __eq__(self, other):
if not isinstance(other, Sequence):
return NotImplemented
return self._seq == other._seq