diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1076de5..6ece139 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ Development version =================== + - sessionmanager.wait_for_tasks now wait for tasks that are started from + other tasks callbacks from different sessions. + 0.1.3 / 2015-06-16 ================== diff --git a/rcontrol/core.py b/rcontrol/core.py index c356efc..0ef6f2a 100644 --- a/rcontrol/core.py +++ b/rcontrol/core.py @@ -361,11 +361,28 @@ def __delattr__(self, name): def wait_for_tasks(self, raise_if_error=True): """ Wait for the running tasks lauched from the sessions. + + Note that it also wait for tasks that are started from other tasks + callbacks, like on_finished. + + :param raise_if_error: if True, raise all possible encountered + errors using :class:`TaskErrors`. Else the errors are returned + as a list. """ errors = [] - for session in self.values(): - errs = session.wait_for_tasks(raise_if_error=False) - errors.extend(errs) + tasks_seen = TaskCache() + while True: + for session in self.values(): + errs = session.wait_for_tasks(raise_if_error=False) + errors.extend(errs) + # look for tasks created after the wait (in callbacks of + # tasks from different sessions) + tasks = [] + for session in self.values(): + tasks.extend(session.tasks()) + # if none, then just break - else loop to wait for them + if not any(t for t in tasks if t not in tasks_seen): + break if raise_if_error and errors: raise TaskErrors(errors) return errors diff --git a/tests/test_core.py b/tests/test_core.py index d58cd4f..355fd09 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -223,9 +223,13 @@ def test_that_only_sessions_can_be_stored_in_dict(self): def test_wait_for_tasks(self): self.sessions.s1 = create_session( - wait_for_tasks=Mock(return_value=[])) + wait_for_tasks=Mock(return_value=[]), + tasks=Mock(return_value=[]), + ) self.sessions.s2 = create_session( - wait_for_tasks=Mock(return_value=[])) + wait_for_tasks=Mock(return_value=[]), + tasks=Mock(return_value=[]), + ) self.assertEqual(self.sessions.wait_for_tasks(), []) self.sessions.s1.wait_for_tasks.assert_called_with( @@ -236,9 +240,13 @@ def test_wait_for_tasks(self): def test_wait_for_tasks_with_tasks_errors(self): exc1, exc2 = Exception(), Exception() self.sessions.s1 = create_session( - wait_for_tasks=Mock(return_value=[exc1])) + wait_for_tasks=Mock(return_value=[exc1]), + tasks=Mock(return_value=[]), + ) self.sessions.s2 = create_session( - wait_for_tasks=Mock(return_value=[exc2])) + wait_for_tasks=Mock(return_value=[exc2]), + tasks=Mock(return_value=[]), + ) # by default, this raise an exception with self.assertRaises(core.TaskErrors) as cm: @@ -278,6 +286,7 @@ def test_inside_with_with_task_errors(self): s.s1 = create_session( wait_for_tasks=Mock(return_value=[exc1]), auto_close=True, + tasks=Mock(return_value=[]), ) def test_inside_with_with_errors(self): @@ -289,6 +298,7 @@ def test_inside_with_with_errors(self): s.s1 = create_session( wait_for_tasks=Mock(return_value=[exc1]), auto_close=True, + tasks=Mock(return_value=[]), ) raise KeyboardInterrupt