diff --git a/heat/engine/scheduler.py b/heat/engine/scheduler.py index 1e97343b13..211d9b3f46 100644 --- a/heat/engine/scheduler.py +++ b/heat/engine/scheduler.py @@ -11,11 +11,9 @@ # License for the specific language governing permissions and limitations # under the License. -import functools import sys import types -import debtcollector import eventlet from oslo_log import log as logging from oslo_utils import encodeutils @@ -294,61 +292,6 @@ class TaskRunner(object): return self.__nonzero__() -@debtcollector.removals.remove(message="Use the Python 3 'yield from' keyword " - "in place of 'yield', instead of " - "decorating with @wrappertask.", - stacklevel=1) -def wrappertask(task): - """Decorator for a task that needs to drive a subtask. - - This is essentially a replacement for the Python 3-only "yield from" - keyword (PEP 380), using the "yield" keyword that is supported in - Python 2. For example:: - - @wrappertask - def parent_task(self): - self.setup() - - yield self.child_task() - - self.cleanup() - """ - - @functools.wraps(task) - def wrapper(*args, **kwargs): - # This could be simplified by using 'yield from' for the parent loop - # as well, but not without adding yet another frame to the stack - # for the subtasks. - parent = task(*args, **kwargs) - - try: - subtask = next(parent) - except StopIteration: - return - - while True: - try: - if isinstance(subtask, types.GeneratorType): - yield from subtask - else: - yield subtask - except GeneratorExit: - parent.close() - raise - except: # noqa - try: - subtask = parent.throw(*sys.exc_info()) - except StopIteration: - return - else: - try: - subtask = next(parent) - except StopIteration: - return - - return wrapper - - class DependencyTaskGroup(object): """Task which manages group of subtasks that have ordering dependencies.""" diff --git a/heat/tests/engine/test_scheduler.py b/heat/tests/engine/test_scheduler.py index 894c432638..3e2b5f2d89 100644 --- a/heat/tests/engine/test_scheduler.py +++ b/heat/tests/engine/test_scheduler.py @@ -1289,419 +1289,3 @@ class DescriptionTest(common.HeatTestCase): scheduler.task_description(C().m)) self.assertEqual(u'\u2665', scheduler.task_description(C())) - - -class WrapperTaskTest(common.HeatTestCase): - - def setUp(self): - super(WrapperTaskTest, self).setUp() - - def test_wrap(self): - child_tasks = [DummyTask() for i in range(3)] - - @scheduler.wrappertask - def task(): - for child_task in child_tasks: - yield child_task() - - yield - - for child_task in child_tasks: - child_task.do_step = mock.Mock(return_value=None) - self.patchobject(scheduler.TaskRunner, '_sleep', return_value=None) - - scheduler.TaskRunner(task)() - - for child_task in child_tasks: - child_task.do_step.assert_has_calls([mock.call(1), mock.call(2), - mock.call(3)]) - self.assertEqual(3, child_task.do_step.call_count) - scheduler.TaskRunner._sleep.assert_any_call(0) - scheduler.TaskRunner._sleep.assert_called_with(1) - self.assertEqual(1 + len(child_tasks) * 3, - scheduler.TaskRunner._sleep.call_count) - - def test_parent_yield_value(self): - @scheduler.wrappertask - def parent_task(): - yield - yield 3 - yield iter([1, 2, 4]) - - task = parent_task() - - self.assertIsNone(next(task)) - self.assertEqual(3, next(task)) - self.assertEqual([1, 2, 4], list(next(task))) - - def test_child_yield_value(self): - def child_task(): - yield - yield 3 - yield iter([1, 2, 4]) - - @scheduler.wrappertask - def parent_task(): - yield child_task() - - task = parent_task() - - self.assertIsNone(next(task)) - self.assertEqual(3, next(task)) - self.assertEqual([1, 2, 4], list(next(task))) - - def test_child_exception(self): - class MyException(Exception): - pass - - def child_task(): - yield - - raise MyException() - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except MyException: - raise - else: - self.fail('No exception raised in parent_task') - - task = parent_task() - next(task) - self.assertRaises(MyException, next, task) - - def test_child_exception_exit(self): - class MyException(Exception): - pass - - def child_task(): - yield - - raise MyException() - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except MyException: - return - else: - self.fail('No exception raised in parent_task') - - task = parent_task() - next(task) - self.assertRaises(StopIteration, next, task) - - def test_child_exception_swallow(self): - class MyException(Exception): - pass - - def child_task(): - yield - - raise MyException() - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except MyException: - yield - else: - self.fail('No exception raised in parent_task') - - yield - - task = parent_task() - next(task) - next(task) - - def test_child_exception_swallow_next(self): - class MyException(Exception): - pass - - def child_task(): - yield - - raise MyException() - - dummy = DummyTask() - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except MyException: - pass - else: - self.fail('No exception raised in parent_task') - - yield dummy() - - task = parent_task() - next(task) - - dummy.do_step = mock.Mock(return_value=None) - for i in range(1, dummy.num_steps + 1): - next(task) - self.assertRaises(StopIteration, next, task) - - dummy.do_step.assert_has_calls([mock.call(i) - for i in range(1, - dummy.num_steps + 1)]) - self.assertEqual(dummy.num_steps, dummy.do_step.call_count) - - def test_thrown_exception_swallow_next(self): - class MyException(Exception): - pass - - dummy = DummyTask() - - @scheduler.wrappertask - def child_task(): - try: - yield - except MyException: - yield dummy() - else: - self.fail('No exception raised in child_task') - - @scheduler.wrappertask - def parent_task(): - yield child_task() - - task = parent_task() - - dummy.do_step = mock.Mock(return_value=None) - - next(task) - task.throw(MyException) - - for i in range(2, dummy.num_steps + 1): - next(task) - self.assertRaises(StopIteration, next, task) - - dummy.do_step.assert_has_calls([mock.call(i) - for i in range(1, - dummy.num_steps + 1)]) - self.assertEqual(dummy.num_steps, dummy.do_step.call_count) - - def test_thrown_exception_raise(self): - class MyException(Exception): - pass - - dummy = DummyTask() - - @scheduler.wrappertask - def child_task(): - try: - yield - except MyException: - raise - else: - self.fail('No exception raised in child_task') - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except MyException: - yield dummy() - - task = parent_task() - - dummy.do_step = mock.Mock(return_value=None) - - next(task) - task.throw(MyException) - - for i in range(2, dummy.num_steps + 1): - next(task) - self.assertRaises(StopIteration, next, task) - - dummy.do_step.assert_has_calls([mock.call(i) - for i in range(1, - dummy.num_steps + 1)]) - self.assertEqual(dummy.num_steps, dummy.do_step.call_count) - - def test_thrown_exception_exit(self): - class MyException(Exception): - pass - - dummy = DummyTask() - - @scheduler.wrappertask - def child_task(): - try: - yield - except MyException: - return - else: - self.fail('No exception raised in child_task') - - @scheduler.wrappertask - def parent_task(): - yield child_task() - yield dummy() - - task = parent_task() - - dummy.do_step = mock.Mock(return_value=None) - - next(task) - task.throw(MyException) - - for i in range(2, dummy.num_steps + 1): - next(task) - self.assertRaises(StopIteration, next, task) - - dummy.do_step.assert_has_calls([mock.call(i) - for i in range(1, - dummy.num_steps + 1)]) - self.assertEqual(dummy.num_steps, dummy.do_step.call_count) - - def test_parent_exception(self): - class MyException(Exception): - pass - - def child_task(): - yield - - @scheduler.wrappertask - def parent_task(): - yield child_task() - raise MyException() - - task = parent_task() - next(task) - self.assertRaises(MyException, next, task) - - def test_parent_throw(self): - class MyException(Exception): - pass - - @scheduler.wrappertask - def parent_task(): - try: - yield DummyTask()() - except MyException: - raise - else: - self.fail('No exception raised in parent_task') - - task = parent_task() - next(task) - self.assertRaises(MyException, task.throw, MyException()) - - def test_parent_throw_exit(self): - class MyException(Exception): - pass - - @scheduler.wrappertask - def parent_task(): - try: - yield DummyTask()() - except MyException: - return - else: - self.fail('No exception raised in parent_task') - - task = parent_task() - next(task) - self.assertRaises(StopIteration, task.throw, MyException()) - - def test_parent_cancel(self): - @scheduler.wrappertask - def parent_task(): - try: - yield - except GeneratorExit: - raise - else: - self.fail('parent_task not closed') - - task = parent_task() - next(task) - task.close() - - def test_parent_cancel_exit(self): - @scheduler.wrappertask - def parent_task(): - try: - yield - except GeneratorExit: - return - else: - self.fail('parent_task not closed') - - task = parent_task() - next(task) - task.close() - - def test_cancel(self): - def child_task(): - try: - yield - except GeneratorExit: - raise - else: - self.fail('child_task not closed') - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except GeneratorExit: - raise - else: - self.fail('parent_task not closed') - - task = parent_task() - next(task) - task.close() - - def test_cancel_exit(self): - def child_task(): - try: - yield - except GeneratorExit: - return - else: - self.fail('child_task not closed') - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except GeneratorExit: - raise - else: - self.fail('parent_task not closed') - - task = parent_task() - next(task) - task.close() - - def test_cancel_parent_exit(self): - def child_task(): - try: - yield - except GeneratorExit: - return - else: - self.fail('child_task not closed') - - @scheduler.wrappertask - def parent_task(): - try: - yield child_task() - except GeneratorExit: - return - else: - self.fail('parent_task not closed') - - task = parent_task() - next(task) - task.close() diff --git a/requirements.txt b/requirements.txt index ee7cb57af0..04ebf4e9e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,6 @@ pbr>=3.1.1 # Apache-2.0 alembic>=1.8.0 # MIT croniter>=0.3.4 # MIT License cryptography>=2.5 # BSD/Apache-2.0 -debtcollector>=1.19.0 # Apache-2.0 eventlet!=0.18.3,!=0.20.1,!=0.21.0,!=0.23.0,!=0.25.0,>=0.18.2 # MIT keystoneauth1>=3.18.0 # Apache-2.0 keystonemiddleware>=5.1.0 # Apache-2.0