Files
deb-python-taskflow/taskflow/blocks/task.py
Ivan A. Melnikov a91dd6b0e4 State management for engines
All state management moved to storage, including flow (engine) state,
task states, task results and failures.

Notifications for state changes were added.

Storage is now implemented using taskflow.persistence and enhanced with
means for result mapping and fetching task result by name.

Partially implements blueprint patterns-and-engines.

Co-authored-by: Anastasia Karpinska <akarpinska at griddynamics.com>
Change-Id: Ia4e5707687096c948bd8db4f3d8936bdac40dd6c
2013-09-04 16:52:36 +04:00

92 lines
2.9 KiB
Python

# -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright (C) 2012-2013 Yahoo! Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Terminal blocks that actually run code
"""
from taskflow.blocks import base
from taskflow.utils import reflection
def _save_as_to_mapping(save_as):
"""Convert save_as to mapping name => index
Result should follow taskflow.storage.Storage convention
for mappings.
"""
if save_as is None:
return None
if isinstance(save_as, basestring):
return {save_as: None}
elif isinstance(save_as, tuple):
return dict((key, num) for num, key in enumerate(save_as))
raise TypeError('Task block save_as parameter '
'should be str or tuple, not %r' % save_as)
def _build_arg_mapping(rebind_args, task):
if rebind_args is None:
rebind_args = {}
task_args = reflection.get_required_callable_args(task.execute)
nargs = len(task_args)
if isinstance(rebind_args, (list, tuple)):
if len(rebind_args) < nargs:
raise ValueError('Task %(name)s takes %(nargs)d positional '
'arguments (%(real)d given)'
% dict(name=task.name, nargs=nargs,
real=len(rebind_args)))
result = dict(zip(task_args, rebind_args[:nargs]))
# extra rebind_args go to kwargs
result.update((a, a) for a in rebind_args[nargs:])
return result
elif isinstance(rebind_args, dict):
result = dict((a, a) for a in task_args)
result.update(rebind_args)
return result
else:
raise TypeError('rebind_args should be list, tuple or dict')
class Task(base.Block):
"""A block that wraps a single task
The task should be executed, and produced results should be saved.
"""
def __init__(self, task, save_as=None, rebind_args=None):
super(Task, self).__init__()
self._task = task
if isinstance(self._task, type):
self._task = self._task()
self._result_mapping = _save_as_to_mapping(save_as)
self._args_mapping = _build_arg_mapping(rebind_args, self._task)
@property
def task(self):
return self._task
@property
def result_mapping(self):
return self._result_mapping
@property
def args_mapping(self):
return self._args_mapping