Task decorator was removed and examples updated
Change-Id: Ie49fe6c2f48a18130d1fd2a3aa5485cd8cee4ed4
This commit is contained in:
committed by
Ivan A. Melnikov
parent
eea2b91030
commit
a333c48523
@@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from taskflow import task as base
|
|
||||||
from taskflow import utils
|
|
||||||
from taskflow.utils import threading_utils
|
from taskflow.utils import threading_utils
|
||||||
|
|
||||||
|
|
||||||
@@ -60,43 +58,3 @@ def locked(*args, **kwargs):
|
|||||||
return decorator(args[0])
|
return decorator(args[0])
|
||||||
else:
|
else:
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def _original_function(fun):
|
|
||||||
"""Get original function from static or class method"""
|
|
||||||
if isinstance(fun, staticmethod):
|
|
||||||
return fun.__get__(object())
|
|
||||||
elif isinstance(fun, classmethod):
|
|
||||||
return fun.__get__(object()).im_func
|
|
||||||
return fun
|
|
||||||
|
|
||||||
|
|
||||||
def task(*args, **kwargs):
|
|
||||||
"""Decorates a given function so that it can be used as a task"""
|
|
||||||
|
|
||||||
def decorator(f):
|
|
||||||
def task_factory(execute, **factory_kwargs):
|
|
||||||
merged = kwargs.copy()
|
|
||||||
merged.update(factory_kwargs)
|
|
||||||
# NOTE(imelnikov): we can't capture f here because for
|
|
||||||
# bound methods and bound class methods the object it
|
|
||||||
# is bound to is yet unknown at the moment
|
|
||||||
#
|
|
||||||
# See: http://bit.ly/15Cfbjh
|
|
||||||
return base.FunctorTask(execute, **merged)
|
|
||||||
w_f = _original_function(f)
|
|
||||||
setattr(w_f, utils.TASK_FACTORY_ATTRIBUTE, task_factory)
|
|
||||||
return f
|
|
||||||
|
|
||||||
# This is needed to handle when the decorator has args or the decorator
|
|
||||||
# doesn't have args, python is rather weird here...
|
|
||||||
if kwargs:
|
|
||||||
if args:
|
|
||||||
raise TypeError('task decorator takes 0 positional arguments,'
|
|
||||||
'%s given' % len(args))
|
|
||||||
return decorator
|
|
||||||
else:
|
|
||||||
if len(args) == 1:
|
|
||||||
return decorator(args[0])
|
|
||||||
else:
|
|
||||||
return decorator
|
|
||||||
|
|||||||
@@ -5,149 +5,131 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
print('GraphFlow is under refactoring now, so this example '
|
|
||||||
'is temporarily broken')
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.ERROR)
|
logging.basicConfig(level=logging.ERROR)
|
||||||
|
|
||||||
my_dir_path = os.path.dirname(os.path.abspath(__file__))
|
my_dir_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
sys.path.insert(0, os.path.join(os.path.join(my_dir_path, os.pardir),
|
sys.path.insert(0, os.path.join(os.path.join(my_dir_path, os.pardir),
|
||||||
os.pardir))
|
os.pardir))
|
||||||
|
|
||||||
from taskflow import decorators
|
from taskflow.engines.action_engine import engine as eng
|
||||||
from taskflow.patterns import graph_flow as gf
|
from taskflow.patterns import graph_flow as gf
|
||||||
|
from taskflow.patterns import linear_flow as lf
|
||||||
|
from taskflow import task
|
||||||
|
|
||||||
|
|
||||||
def flow_notify(state, details):
|
def build_frame():
|
||||||
print("'%s' entered state: %s" % (details['flow'], state))
|
return 'steel'
|
||||||
|
|
||||||
|
|
||||||
def task_notify(state, details):
|
def build_engine():
|
||||||
print("'%s' entered state: %s" % (details['runner'], state))
|
return 'honda'
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['spec'])
|
def build_doors():
|
||||||
def build_spec(context):
|
return '2'
|
||||||
params = context['inputs']
|
|
||||||
verified = {}
|
|
||||||
for k, v in params.items():
|
|
||||||
verified[k] = int(v)
|
|
||||||
return {
|
|
||||||
'spec': verified,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['frame'])
|
def build_wheels():
|
||||||
def build_frame(context, spec):
|
return '4'
|
||||||
return {
|
|
||||||
'frame': 'steel',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['engine'])
|
def install_engine(frame, engine):
|
||||||
def build_engine(context, spec):
|
return True
|
||||||
return {
|
|
||||||
'engine': 'honda',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['doors'])
|
def install_doors(frame, windows_installed, doors):
|
||||||
def build_doors(context, spec):
|
return True
|
||||||
return {
|
|
||||||
'doors': '2',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['wheels'])
|
def install_windows(frame, doors):
|
||||||
def build_wheels(context, spec):
|
return True
|
||||||
return {
|
|
||||||
'wheels': '4',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['wheels'])
|
def install_wheels(frame, engine, engine_installed, wheels):
|
||||||
def build_windows(context, spec):
|
return True
|
||||||
return {
|
|
||||||
'windows': '4',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['engine_installed'])
|
def trash(**kwargs):
|
||||||
def install_engine(context, frame, engine):
|
|
||||||
return {
|
|
||||||
'engine_installed': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def install_doors(context, frame, windows_installed, doors):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(provides=['windows_installed'])
|
|
||||||
def install_windows(context, frame, doors):
|
|
||||||
return {
|
|
||||||
'windows_installed': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def install_wheels(context, frame, engine, engine_installed, wheels):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def trash(context, result, cause):
|
|
||||||
print("Throwing away pieces of car!")
|
print("Throwing away pieces of car!")
|
||||||
|
|
||||||
|
|
||||||
@decorators.task(revert=trash)
|
def startup(**kwargs):
|
||||||
def startup(context, **kwargs):
|
|
||||||
pass
|
pass
|
||||||
# TODO(harlowja): try triggering reversion here!
|
# TODO(harlowja): try triggering reversion here!
|
||||||
# raise ValueError("Car not verified")
|
# raise ValueError("Car not verified")
|
||||||
return {
|
return True
|
||||||
'ran': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
flow = gf.Flow("make-auto")
|
def verify(spec, **kwargs):
|
||||||
flow.notifier.register('*', flow_notify)
|
for key, value in kwargs.items():
|
||||||
flow.task_notifier.register('*', task_notify)
|
if spec[key] != value:
|
||||||
|
raise Exception("Car doesn't match spec!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# Lets build a car!!
|
def flow_watch(state, details):
|
||||||
flow.add(build_spec)
|
print('Flow => %s' % state)
|
||||||
flow.add(build_frame)
|
|
||||||
flow.add(build_engine)
|
|
||||||
flow.add(build_doors)
|
|
||||||
flow.add(build_wheels)
|
|
||||||
i_uuid1 = flow.add(install_engine)
|
|
||||||
i_uuid2 = flow.add(install_doors)
|
|
||||||
i_uuid3 = flow.add(install_windows)
|
|
||||||
i_uuid4 = flow.add(install_wheels)
|
|
||||||
install_uuids = [i_uuid1, i_uuid2, i_uuid3, i_uuid4]
|
|
||||||
|
|
||||||
# Lets add a manual dependency that startup needs all the installation to
|
|
||||||
# complete, this could be done automatically but lets now instead ;)
|
|
||||||
startup_uuid = flow.add(startup)
|
|
||||||
for i_uuid in install_uuids:
|
|
||||||
flow.add_dependency(i_uuid, startup_uuid)
|
|
||||||
|
|
||||||
# Now begin the build!
|
def task_watch(state, details):
|
||||||
context = {
|
print('Task %s => %s' % (details.get('task_name'), state))
|
||||||
"inputs": {
|
|
||||||
'engine': 123,
|
|
||||||
'tire': '234',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print '-' * 7
|
|
||||||
print 'Running'
|
|
||||||
print '-' * 7
|
|
||||||
flow.run(context)
|
|
||||||
|
|
||||||
print '-' * 11
|
|
||||||
print 'All results'
|
flow = lf.Flow("make-auto").add(
|
||||||
print '-' * 11
|
task.FunctorTask(startup, revert=trash, provides='ran'),
|
||||||
for (uuid, v) in flow.results.items():
|
gf.Flow("install-parts").add(
|
||||||
print '%s => %s' % (uuid, v)
|
task.FunctorTask(build_frame, provides='frame'),
|
||||||
|
task.FunctorTask(build_engine, provides='engine'),
|
||||||
|
task.FunctorTask(build_doors, provides='doors'),
|
||||||
|
task.FunctorTask(build_wheels, provides='wheels'),
|
||||||
|
task.FunctorTask(install_engine, provides='engine_installed'),
|
||||||
|
task.FunctorTask(install_doors, provides='doors_installed'),
|
||||||
|
task.FunctorTask(install_windows, provides='windows_installed'),
|
||||||
|
task.FunctorTask(install_wheels, provides='wheels_installed')),
|
||||||
|
task.FunctorTask(verify, requires=['frame',
|
||||||
|
'engine',
|
||||||
|
'doors',
|
||||||
|
'wheels',
|
||||||
|
'engine_installed',
|
||||||
|
'doors_installed',
|
||||||
|
'windows_installed',
|
||||||
|
'wheels_installed']))
|
||||||
|
|
||||||
|
engine = eng.SingleThreadedActionEngine(flow)
|
||||||
|
engine.notifier.register('*', flow_watch)
|
||||||
|
engine.task_notifier.register('*', task_watch)
|
||||||
|
|
||||||
|
engine.storage.inject({'spec': {
|
||||||
|
"frame": 'steel',
|
||||||
|
"engine": 'honda',
|
||||||
|
"doors": '2',
|
||||||
|
"wheels": '4',
|
||||||
|
"engine_installed": True,
|
||||||
|
"doors_installed": True,
|
||||||
|
"windows_installed": True,
|
||||||
|
"wheels_installed": True,
|
||||||
|
}})
|
||||||
|
|
||||||
|
print "Build a car"
|
||||||
|
engine.run()
|
||||||
|
|
||||||
|
engine = eng.SingleThreadedActionEngine(flow)
|
||||||
|
engine.notifier.register('*', flow_watch)
|
||||||
|
engine.task_notifier.register('*', task_watch)
|
||||||
|
|
||||||
|
engine.storage.inject({'spec': {
|
||||||
|
"frame": 'steel',
|
||||||
|
"engine": 'honda',
|
||||||
|
"doors": '5',
|
||||||
|
"wheels": '4',
|
||||||
|
"engine_installed": True,
|
||||||
|
"doors_installed": True,
|
||||||
|
"windows_installed": True,
|
||||||
|
"wheels_installed": True,
|
||||||
|
}})
|
||||||
|
|
||||||
|
try:
|
||||||
|
print "Build a wrong car that doesn't match specification"
|
||||||
|
engine.run()
|
||||||
|
except Exception as e:
|
||||||
|
print e
|
||||||
|
|||||||
@@ -8,36 +8,32 @@ my_dir_path = os.path.dirname(os.path.abspath(__file__))
|
|||||||
sys.path.insert(0, os.path.join(os.path.join(my_dir_path, os.pardir),
|
sys.path.insert(0, os.path.join(os.path.join(my_dir_path, os.pardir),
|
||||||
os.pardir))
|
os.pardir))
|
||||||
|
|
||||||
from taskflow import decorators
|
|
||||||
from taskflow.engines.action_engine import engine as eng
|
from taskflow.engines.action_engine import engine as eng
|
||||||
from taskflow.patterns import linear_flow as lf
|
from taskflow.patterns import linear_flow as lf
|
||||||
|
from taskflow import task
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def call_jim(context):
|
def call_jim(context):
|
||||||
print("Calling jim.")
|
print("Calling jim.")
|
||||||
print("Context = %s" % (context))
|
print("Context = %s" % (context))
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def call_joe(context):
|
def call_joe(context):
|
||||||
print("Calling joe.")
|
print("Calling joe.")
|
||||||
print("Context = %s" % (context))
|
print("Context = %s" % (context))
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def flow_watch(state, details):
|
def flow_watch(state, details):
|
||||||
print('Flow => %s' % state)
|
print('Flow => %s' % state)
|
||||||
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def task_watch(state, details):
|
def task_watch(state, details):
|
||||||
print('Task %s => %s' % (details.get('task_name'), state))
|
print('Task %s => %s' % (details.get('task_name'), state))
|
||||||
|
|
||||||
|
|
||||||
flow = lf.Flow("Call-them")
|
flow = lf.Flow("Call-them")
|
||||||
flow.add(call_jim)
|
flow.add(task.FunctorTask(execute=call_jim))
|
||||||
flow.add(call_joe)
|
flow.add(task.FunctorTask(execute=call_joe))
|
||||||
|
|
||||||
engine = eng.SingleThreadedActionEngine(flow)
|
engine = eng.SingleThreadedActionEngine(flow)
|
||||||
engine.notifier.register('*', flow_watch)
|
engine.notifier.register('*', flow_watch)
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
import abc
|
import abc
|
||||||
|
|
||||||
from taskflow.openstack.common import uuidutils
|
from taskflow.openstack.common import uuidutils
|
||||||
from taskflow import task
|
|
||||||
from taskflow import utils
|
|
||||||
|
|
||||||
|
|
||||||
def _class_name(obj):
|
def _class_name(obj):
|
||||||
@@ -67,16 +65,6 @@ class Flow(object):
|
|||||||
lines.append("%s" % (len(self)))
|
lines.append("%s" % (len(self)))
|
||||||
return "; ".join(lines)
|
return "; ".join(lines)
|
||||||
|
|
||||||
def _extract_item(self, item):
|
|
||||||
if isinstance(item, (task.BaseTask, Flow)):
|
|
||||||
return item
|
|
||||||
if issubclass(item, task.BaseTask):
|
|
||||||
return item()
|
|
||||||
task_factory = getattr(item, utils.TASK_FACTORY_ATTRIBUTE, None)
|
|
||||||
if task_factory:
|
|
||||||
return self._extract_item(task_factory(item))
|
|
||||||
raise TypeError("Invalid item %r: it's not task and not flow" % item)
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def add(self, *items):
|
def add(self, *items):
|
||||||
"""Adds a given item/items to this flow."""
|
"""Adds a given item/items to this flow."""
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ class Flow(flow.Flow):
|
|||||||
|
|
||||||
def add(self, *items):
|
def add(self, *items):
|
||||||
"""Adds a given task/tasks/flow/flows to this flow."""
|
"""Adds a given task/tasks/flow/flows to this flow."""
|
||||||
items = [self._extract_item(item) for item in items]
|
|
||||||
|
|
||||||
# NOTE(imelnikov): we add item to the end of flow, so it should
|
# NOTE(imelnikov): we add item to the end of flow, so it should
|
||||||
# not provide anything previous items of the flow require
|
# not provide anything previous items of the flow require
|
||||||
requires = self.requires
|
requires = self.requires
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ class Flow(flow.Flow):
|
|||||||
|
|
||||||
def add(self, *items):
|
def add(self, *items):
|
||||||
"""Adds a given task/tasks/flow/flows to this flow."""
|
"""Adds a given task/tasks/flow/flows to this flow."""
|
||||||
items = [self._extract_item(item) for item in items]
|
|
||||||
|
|
||||||
# check that items are actually independent
|
# check that items are actually independent
|
||||||
provides = self.provides
|
provides = self.provides
|
||||||
old_requires = self.requires
|
old_requires = self.requires
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
# -*- 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.
|
|
||||||
|
|
||||||
from taskflow import decorators
|
|
||||||
from taskflow.patterns import linear_flow
|
|
||||||
from taskflow import test
|
|
||||||
|
|
||||||
from taskflow.engines.action_engine import engine as eng
|
|
||||||
|
|
||||||
|
|
||||||
class WrapableObjectsTest(test.TestCase):
|
|
||||||
def _make_engine(self, flow):
|
|
||||||
e = eng.SingleThreadedActionEngine(flow)
|
|
||||||
e.compile()
|
|
||||||
return e
|
|
||||||
|
|
||||||
def test_simple_function(self):
|
|
||||||
values = []
|
|
||||||
|
|
||||||
def revert_one(*args, **kwargs):
|
|
||||||
values.append('revert one')
|
|
||||||
|
|
||||||
@decorators.task(revert=revert_one)
|
|
||||||
def run_one(*args, **kwargs):
|
|
||||||
values.append('one')
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def run_fail(*args, **kwargs):
|
|
||||||
values.append('fail')
|
|
||||||
raise RuntimeError('Woot!')
|
|
||||||
|
|
||||||
flow = linear_flow.Flow('test')
|
|
||||||
flow.add(
|
|
||||||
run_one,
|
|
||||||
run_fail
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegexp(RuntimeError, '^Woot'):
|
|
||||||
e = self._make_engine(flow)
|
|
||||||
e.run()
|
|
||||||
self.assertEquals(values, ['one', 'fail', 'revert one'])
|
|
||||||
|
|
||||||
def test_simple_method(self):
|
|
||||||
class MyTasks(object):
|
|
||||||
def __init__(self):
|
|
||||||
# NOTE(imelnikov): that's really *bad thing* to pass
|
|
||||||
# data between task like this; though, its good enough
|
|
||||||
# for our testing here
|
|
||||||
self.values = []
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def run_one(self, *args, **kwargs):
|
|
||||||
self.values.append('one')
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def run_fail(self, *args, **kwargs):
|
|
||||||
self.values.append('fail')
|
|
||||||
raise RuntimeError('Woot!')
|
|
||||||
|
|
||||||
tasks = MyTasks()
|
|
||||||
flow = linear_flow.Flow('test')
|
|
||||||
flow.add(
|
|
||||||
tasks.run_one,
|
|
||||||
tasks.run_fail
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegexp(RuntimeError, '^Woot'):
|
|
||||||
e = self._make_engine(flow)
|
|
||||||
e.run()
|
|
||||||
self.assertEquals(tasks.values, ['one', 'fail'])
|
|
||||||
|
|
||||||
def test_static_method(self):
|
|
||||||
values = []
|
|
||||||
|
|
||||||
class MyTasks(object):
|
|
||||||
@decorators.task
|
|
||||||
@staticmethod
|
|
||||||
def run_one(*args, **kwargs):
|
|
||||||
values.append('one')
|
|
||||||
|
|
||||||
# NOTE(imelnikov): decorators should work in any order:
|
|
||||||
@staticmethod
|
|
||||||
@decorators.task
|
|
||||||
def run_fail(*args, **kwargs):
|
|
||||||
values.append('fail')
|
|
||||||
raise RuntimeError('Woot!')
|
|
||||||
|
|
||||||
flow = linear_flow.Flow('test')
|
|
||||||
flow.add(
|
|
||||||
MyTasks.run_one,
|
|
||||||
MyTasks.run_fail
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegexp(RuntimeError, '^Woot'):
|
|
||||||
e = self._make_engine(flow)
|
|
||||||
e.run()
|
|
||||||
self.assertEquals(values, ['one', 'fail'])
|
|
||||||
|
|
||||||
def test_class_method(self):
|
|
||||||
|
|
||||||
class MyTasks(object):
|
|
||||||
values = []
|
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
@classmethod
|
|
||||||
def run_one(cls, *args, **kwargs):
|
|
||||||
cls.values.append('one')
|
|
||||||
|
|
||||||
# NOTE(imelnikov): decorators should work in any order:
|
|
||||||
@classmethod
|
|
||||||
@decorators.task
|
|
||||||
def run_fail(cls, *args, **kwargs):
|
|
||||||
cls.values.append('fail')
|
|
||||||
raise RuntimeError('Woot!')
|
|
||||||
|
|
||||||
flow = linear_flow.Flow('test')
|
|
||||||
flow.add(
|
|
||||||
MyTasks.run_one,
|
|
||||||
MyTasks.run_fail
|
|
||||||
)
|
|
||||||
with self.assertRaisesRegexp(RuntimeError, '^Woot'):
|
|
||||||
e = self._make_engine(flow)
|
|
||||||
e.run()
|
|
||||||
self.assertEquals(MyTasks.values, ['one', 'fail'])
|
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from taskflow import decorators
|
|
||||||
from taskflow.engines.action_engine import engine as eng
|
from taskflow.engines.action_engine import engine as eng
|
||||||
from taskflow import exceptions as exc
|
from taskflow import exceptions as exc
|
||||||
from taskflow.patterns import linear_flow as lw
|
from taskflow.patterns import linear_flow as lw
|
||||||
from taskflow import states
|
from taskflow import states
|
||||||
|
from taskflow import task
|
||||||
from taskflow import test
|
from taskflow import test
|
||||||
|
|
||||||
from taskflow.tests import utils
|
from taskflow.tests import utils
|
||||||
@@ -37,12 +37,11 @@ class LinearFlowTest(test.TestCase):
|
|||||||
|
|
||||||
def test_result_access(self):
|
def test_result_access(self):
|
||||||
|
|
||||||
@decorators.task(provides=['a', 'b'])
|
|
||||||
def do_apply1(context):
|
def do_apply1(context):
|
||||||
return [1, 2]
|
return [1, 2]
|
||||||
|
|
||||||
wf = lw.Flow("the-test-action")
|
wf = lw.Flow("the-test-action")
|
||||||
wf.add(do_apply1)
|
wf.add(task.FunctorTask(do_apply1, provides=['a', 'b']))
|
||||||
|
|
||||||
e = self._make_engine(wf)
|
e = self._make_engine(wf)
|
||||||
e.run()
|
e.run()
|
||||||
@@ -55,19 +54,17 @@ class LinearFlowTest(test.TestCase):
|
|||||||
def test_functor_flow(self):
|
def test_functor_flow(self):
|
||||||
wf = lw.Flow("the-test-action")
|
wf = lw.Flow("the-test-action")
|
||||||
|
|
||||||
@decorators.task(provides=['a', 'b', 'c'])
|
|
||||||
def do_apply1(context):
|
def do_apply1(context):
|
||||||
context['1'] = True
|
context['1'] = True
|
||||||
return ['a', 'b', 'c']
|
return ['a', 'b', 'c']
|
||||||
|
|
||||||
@decorators.task(requires=set(['c']))
|
|
||||||
def do_apply2(context, a, **kwargs):
|
def do_apply2(context, a, **kwargs):
|
||||||
self.assertTrue('c' in kwargs)
|
self.assertTrue('c' in kwargs)
|
||||||
self.assertEquals('a', a)
|
self.assertEquals('a', a)
|
||||||
context['2'] = True
|
context['2'] = True
|
||||||
|
|
||||||
wf.add(do_apply1)
|
wf.add(task.FunctorTask(do_apply1, provides=['a', 'b', 'c']))
|
||||||
wf.add(do_apply2)
|
wf.add(task.FunctorTask(do_apply2, requires=set(['c'])))
|
||||||
|
|
||||||
e = self._make_engine(wf)
|
e = self._make_engine(wf)
|
||||||
e.run()
|
e.run()
|
||||||
@@ -191,17 +188,15 @@ class LinearFlowTest(test.TestCase):
|
|||||||
|
|
||||||
def test_not_satisfied_inputs(self):
|
def test_not_satisfied_inputs(self):
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def task_a(context, *args, **kwargs):
|
def task_a(context, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@decorators.task
|
|
||||||
def task_b(context, c, *args, **kwargs):
|
def task_b(context, c, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
wf = lw.Flow("the-test-action")
|
wf = lw.Flow("the-test-action")
|
||||||
wf.add(task_a)
|
wf.add(task.FunctorTask(task_a))
|
||||||
wf.add(task_b)
|
wf.add(task.FunctorTask(task_b))
|
||||||
e = self._make_engine(wf)
|
e = self._make_engine(wf)
|
||||||
self.assertRaises(exc.MissingDependencies, e.run)
|
self.assertRaises(exc.MissingDependencies, e.run)
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from taskflow import decorators
|
|
||||||
from taskflow.engines.action_engine import engine as eng
|
from taskflow.engines.action_engine import engine as eng
|
||||||
from taskflow.patterns import unordered_flow as uf
|
from taskflow.patterns import unordered_flow as uf
|
||||||
|
from taskflow import task
|
||||||
from taskflow import test
|
from taskflow import test
|
||||||
|
|
||||||
from taskflow.tests import utils
|
from taskflow.tests import utils
|
||||||
@@ -33,12 +33,14 @@ class UnorderedFlowTest(test.TestCase):
|
|||||||
|
|
||||||
def test_result_access(self):
|
def test_result_access(self):
|
||||||
|
|
||||||
@decorators.task(provides=['a', 'b'])
|
class DoApply(task.Task):
|
||||||
def do_apply1(context):
|
default_provides = ('a', 'b')
|
||||||
return [1, 2]
|
|
||||||
|
def execute(self):
|
||||||
|
return [1, 2]
|
||||||
|
|
||||||
wf = uf.Flow("the-test-action")
|
wf = uf.Flow("the-test-action")
|
||||||
wf.add(do_apply1)
|
wf.add(DoApply())
|
||||||
|
|
||||||
e = self._make_engine(wf)
|
e = self._make_engine(wf)
|
||||||
e.run()
|
e.run()
|
||||||
@@ -57,18 +59,20 @@ class UnorderedFlowTest(test.TestCase):
|
|||||||
|
|
||||||
def test_functor_flow(self):
|
def test_functor_flow(self):
|
||||||
|
|
||||||
@decorators.task(provides=['a', 'b', 'c'])
|
class DoApply1(task.Task):
|
||||||
def do_apply1(context):
|
default_provides = ('a', 'b', 'c')
|
||||||
context['1'] = True
|
|
||||||
return ['a', 'b', 'c']
|
|
||||||
|
|
||||||
@decorators.task
|
def execute(self, context):
|
||||||
def do_apply2(context, **kwargs):
|
context['1'] = True
|
||||||
context['2'] = True
|
return ['a', 'b', 'c']
|
||||||
|
|
||||||
|
class DoApply2(task.Task):
|
||||||
|
def execute(self, context):
|
||||||
|
context['2'] = True
|
||||||
|
|
||||||
wf = uf.Flow("the-test-action")
|
wf = uf.Flow("the-test-action")
|
||||||
wf.add(do_apply1)
|
wf.add(DoApply1())
|
||||||
wf.add(do_apply2)
|
wf.add(DoApply2())
|
||||||
e = self._make_engine(wf)
|
e = self._make_engine(wf)
|
||||||
e.run()
|
e.run()
|
||||||
self.assertEquals(2, len(e.storage.fetch('context')))
|
self.assertEquals(2, len(e.storage.fetch('context')))
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from taskflow import decorators
|
|
||||||
from taskflow import task
|
from taskflow import task
|
||||||
|
|
||||||
ARGS_KEY = '__args__'
|
ARGS_KEY = '__args__'
|
||||||
@@ -47,18 +46,17 @@ def make_reverting_task(token, blowup=False):
|
|||||||
|
|
||||||
if blowup:
|
if blowup:
|
||||||
|
|
||||||
@decorators.task(name='blowup_%s' % token)
|
|
||||||
def blow_up(context, *args, **kwargs):
|
def blow_up(context, *args, **kwargs):
|
||||||
raise Exception("I blew up")
|
raise Exception("I blew up")
|
||||||
|
|
||||||
return blow_up
|
return task.FunctorTask(blow_up, name='blowup_%s' % token)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@decorators.task(revert=do_revert, name='do_apply_%s' % token)
|
|
||||||
def do_apply(context, *args, **kwargs):
|
def do_apply(context, *args, **kwargs):
|
||||||
context[token] = 'passed'
|
context[token] = 'passed'
|
||||||
|
|
||||||
return do_apply
|
return task.FunctorTask(do_apply, revert=do_revert,
|
||||||
|
name='do_apply_%s' % token)
|
||||||
|
|
||||||
|
|
||||||
class ProvidesRequiresTask(task.Task):
|
class ProvidesRequiresTask(task.Task):
|
||||||
|
|||||||
@@ -15,5 +15,3 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
TASK_FACTORY_ATTRIBUTE = '_TaskFlow_task_factory'
|
|
||||||
|
|||||||
Reference in New Issue
Block a user