Source code for laserfarm.pipeline
import logging
from laserfarm.logger import Logger
from laserfarm.utils import get_args_from_configfile
logger = logging.getLogger(__name__)
[docs]
class Pipeline(object):
"""
Base Pipeline class to construct workflows. Inheriting classes should
define `pipeline` as the sequence of the methods that constitute the
pipeline. After storing the input of the various tasks in the `input`
dictionary, the pipeline can be run with the method `run`.
Example:
>>> class FooBar(Pipeline):
... def __init__(self):
... self.pipeline = ['foo', 'bar']
... def foo(self, a):
... print(a)
... def bar(self, b):
... print(b)
>>> test = FooBar()
>>> test.input = {'foo': {'a': 5}, 'bar': {'b': 6}}
>>> test.run()
5
6
"""
_pipeline = tuple()
_input = dict()
logger = None
label = 'pipeline'
@property
def pipeline(self):
"""
List containing the consecutive tasks that constitute the pipeline.
"""
return self._pipeline
@pipeline.setter
def pipeline(self, pipeline):
if isinstance(pipeline, str):
pipeline = tuple([pipeline])
try:
_ = iter(pipeline)
except TypeError:
logger.error('The sequence of tasks in the pipeline '
'should be provided as an iterable object.')
raise
for task in pipeline:
assert task in dir(self.__class__), \
('Error defining the pipeline: {} method not found'
'in class {}'.format(task, self.__class__.__name__))
self._pipeline = tuple([task for task in pipeline])
@property
def input(self):
"""
Dictionary containing the pipeline input. Each attribute entails the
input for a pipeline method that needs to be executed.
"""
return self._input
@input.setter
def input(self, input):
if not isinstance(input, dict):
raise TypeError("A dictionary is expected!")
self._input = input
[docs]
def config(self, from_dict=None, from_file=None):
"""
Set the pipeline input with a dictionary or by reading a configfile.
:param from_dict: Input is given as a dictionary
:param from_file: Path to the configfile
"""
is_valid = (from_dict is None) != (from_file is None)
assert is_valid, 'Either a dictionary or a file path should be given!'
if from_dict is not None:
self.input = from_dict
elif from_file is not None:
self.input = get_args_from_configfile(from_file)
return self
[docs]
def log_config(self, level=None, format=None, stream=None, filename=None):
self.logger.config(level, format, stream, filename)
[docs]
def run(self, pipeline=None):
"""
Run the full pipeline.
:param pipeline: (optional) Run the input pipeline if provided
"""
_input = self.input.copy()
_pipeline = pipeline if pipeline is not None else self.pipeline
_pipeline = ('log_config',) + _pipeline
self.logger = Logger(label=self.label)
for task_name in _pipeline:
if task_name in _input:
task = getattr(self, task_name)
input_task = _input.pop(task_name)
if isinstance(input_task, dict):
task(**input_task)
elif (isinstance(input_task, list)
or isinstance(input_task, tuple)):
task(*input_task)
else:
task(input_task)
if len(_input.keys()) > 0:
logger.warning('Some of the attributes in input have not been '
'used: {} '.format(', '.join(_input.keys())))
self.logger.terminate()
return