From b68d504c9f99e180f0d630c5c101bd6136d23933 Mon Sep 17 00:00:00 2001 From: "Ivan A. Melnikov" Date: Tue, 27 Aug 2013 16:52:56 +0400 Subject: [PATCH] Add features to task.Task Old Task class renamed to BaseTask, and new Task class deriving from it added in place of it. This new class adds following features: - if no name is passed to task, name is autogenerated from task type - all __call__ argument names (except 'context') are added to task requirements. Change-Id: Ied69857932088b6e25d4817d2a8afeddccad36d8 --- taskflow/task.py | 29 ++++++++++++++++++-- taskflow/tests/unit/test_task.py | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 taskflow/tests/unit/test_task.py diff --git a/taskflow/task.py b/taskflow/task.py index 2a27b97af..90e9c08d7 100644 --- a/taskflow/task.py +++ b/taskflow/task.py @@ -3,6 +3,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (C) 2013 Rackspace Hosting Inc. All Rights Reserved. +# Copyright (C) 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 @@ -21,7 +22,7 @@ import abc from taskflow import utils -class Task(object): +class BaseTask(object): """An abstraction that defines a potential piece of work that can be applied and can be reverted to undo the work as a single unit. """ @@ -68,7 +69,31 @@ class Task(object): """ -class FunctorTask(Task): +class Task(BaseTask): + """Base class for user-defined tasks + + Adds following features to Task: + - auto-generates name from type of self + - adds all __call__ argument names to task requiremets + """ + + def __init__(self, name=None, requires_from_args=True): + """Initialize task instance + + :param name: task name, if None (the default) name will + be autogenerated + :param requires_from_args: if True (the default) __call__ + arguments names will be added to task requirements + """ + if name is None: + name = utils.get_callable_name(self) + super(Task, self).__init__(name) + if requires_from_args: + f_args = utils.get_required_callable_args(self) + self.requires.update(a for a in f_args if a != 'context') + + +class FunctorTask(BaseTask): """Adaptor to make task from a callable Take any callable and make a task from it. diff --git a/taskflow/tests/unit/test_task.py b/taskflow/tests/unit/test_task.py new file mode 100644 index 000000000..05e1085ac --- /dev/null +++ b/taskflow/tests/unit/test_task.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (C) 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 task +from taskflow import test + + +class MyTask(task.Task): + def __call__(self, context, spam, eggs): + pass + + +class TaskTestCase(test.TestCase): + + def test_passed_name(self): + my_task = MyTask(name='my name') + self.assertEquals(my_task.name, 'my name') + + def test_generated_name(self): + my_task = MyTask() + self.assertEquals(my_task.name, + '%s.%s' % (__name__, 'MyTask')) + + def test_requirements_added(self): + my_task = MyTask() + self.assertEquals(my_task.requires, set(['spam', 'eggs'])) + + def test_requirements_can_be_ignored(self): + my_task = MyTask(requires_from_args=False) + self.assertEquals(my_task.requires, set())