def test_task_lambda(self): def func(): return 'Sentinel Result' t = Task(lambda: func()) t() self.assertTrue(t.done()) self.assertEqual('Sentinel Result', t.result())
def test_task_normal_callable(self): def func(): return 'Sentinel Result' t = Task(func) t() self.assertTrue(t.done()) self.assertEqual('Sentinel Result', t.result())
def test_task_normal_callable_kwargs(self): arg_in = 'Sentinel Arg' def func(kwarg=None): return kwarg t = Task(func, kwargs={'kwarg': arg_in}) t() self.assertEqual('Sentinel Arg', t.result())
def test_coroutine_args(self): arg_in = 'Sentinel Arg' async def coro(arg): return arg t = Task(coro, args=(arg_in, )) t() self.assertEqual('Sentinel Arg', t.result())
def test_task_normal_callable_args(self): arg_in = 'Sentinel Arg' def func(arg): return arg t = Task(func, args=(arg_in, )) t() self.assertEqual('Sentinel Arg', t.result())
def test_coroutine_kwargs(self): arg_in = 'Sentinel Arg' async def coro(kwarg=None): return kwarg t = Task(coro, kwargs={'kwarg': arg_in}) t() self.assertEqual('Sentinel Arg', t.result())
def test_coroutine_exception(self): async def coro(): e = Exception() e.sentinel_value = 'Sentinel Exception' raise e t = Task(coro) t() self.assertTrue(t.done()) self.assertEqual('Sentinel Exception', t.exception().sentinel_value) self.assertEqual(None, t.result())
def test_exception(self): def func(): e = Exception() e.sentinel_value = 'Sentinel Exception' raise e t = Task(func) t() self.assertTrue(t.done()) self.assertEqual('Sentinel Exception', t.exception().sentinel_value) self.assertEqual(None, t.result())
def test_done_task_done_callback_scheduled(self): executor = DummyExecutor() t = Task(lambda: None, executor=executor) t() self.assertTrue(t.done()) t.add_done_callback('Sentinel Value') self.assertEqual(1, len(executor.done_callbacks)) self.assertEqual('Sentinel Value', executor.done_callbacks[0][0]) args = executor.done_callbacks[0][1] self.assertEqual(1, len(args)) self.assertEqual(t, args[0])
def test_done_task_called(self): called = False def func(): nonlocal called called = True t = Task(func) t() self.assertTrue(called) self.assertTrue(t.done()) called = False t() self.assertFalse(called) self.assertTrue(t.done())
def create_task(self, callback: Union[Callable, Coroutine], *args, **kwargs) -> Task: """ Add a callback or coroutine to be executed during :meth:`spin` and return a Future. Arguments to this function are passed to the callback. :param callback: A callback to be run in the executor. """ task = Task(callback, args, kwargs, executor=self) with self._tasks_lock: self._tasks.append((task, None, None)) self._guard.trigger() # Task inherits from Future return task
def test_coroutine(self): called1 = False called2 = False async def coro(): nonlocal called1 nonlocal called2 called1 = True await asyncio.sleep(0) called2 = True return 'Sentinel Result' t = Task(coro) t() self.assertTrue(called1) self.assertFalse(called2) called1 = False t() self.assertFalse(called1) self.assertTrue(called2) self.assertTrue(t.done()) self.assertEqual('Sentinel Result', t.result())
def create_task(self, callback, *args, **kwargs): """ Add a callback or coroutine to be executed during :meth:`spin` and return a Future. Arguments to this function are passed to the callback. :param callback: A callback to be run in the executor :type callback: callable or coroutine function :rtype: :class:`rclpy.task.Future` instance """ task = Task(callback, args, kwargs, executor=self) with self._tasks_lock: self._tasks.append((task, None, None)) # Task inherits from Future return task
def _make_handler( self, entity: WaitableEntityType, node: 'Node', take_from_wait_list: Callable, call_coroutine: Coroutine ) -> Task: """ Make a handler that performs work on an entity. :param entity: An entity to wait on. :param node: The node associated with the entity. :param take_from_wait_list: Makes the entity to stop appearing in the wait list. :param call_coroutine: Does the work the entity is ready for """ # Mark this so it doesn't get added back to the wait list entity._executor_event = True async def handler(entity, gc, is_shutdown, work_tracker): if is_shutdown or not entity.callback_group.beginning_execution(entity): # Didn't get the callback, or the executor has been ordered to stop entity._executor_event = False gc.trigger() return with work_tracker: arg = take_from_wait_list(entity) # Signal that this has been 'taken' and can be added back to the wait list entity._executor_event = False gc.trigger() try: await call_coroutine(entity, arg) finally: entity.callback_group.ending_execution(entity) # Signal that work has been done so the next callback in a mutually exclusive # callback group can get executed gc.trigger() task = Task( handler, (entity, self._guard, self._is_shutdown, self._work_tracker), executor=self) with self._tasks_lock: self._tasks.append((task, entity, node)) return task
def _make_handler(self, entity, node, take_from_wait_list, call_coroutine): """ Make a handler that performs work on an entity. :param entity: An entity to wait on :param take_from_wait_list: Makes the entity to stop appearing in the wait list :type take_from_wait_list: callable :param call_coroutine: Does the work the entity is ready for :type call_coroutine: coroutine function :rtype: callable """ # Mark this so it doesn't get added back to the wait list entity._executor_event = True async def handler(entity, gc, is_shutdown, work_tracker): if is_shutdown or not entity.callback_group.beginning_execution( entity): # Didn't get the callback, or the executor has been ordered to stop entity._executor_event = False _rclpy.rclpy_trigger_guard_condition(gc) return with work_tracker: arg = take_from_wait_list(entity) # Signal that this has been 'taken' and can be added back to the wait list entity._executor_event = False _rclpy.rclpy_trigger_guard_condition(gc) try: await call_coroutine(entity, arg) finally: entity.callback_group.ending_execution(entity) # Signal that work has been done so the next callback in a mutually exclusive # callback group can get executed _rclpy.rclpy_trigger_guard_condition(gc) task = Task(handler, (entity, self._guard_condition, self._is_shutdown, self._work_tracker), executor=self) with self._tasks_lock: self._tasks.append((task, entity, node)) return task
def test_cancelled(self): t = Task(lambda: None) t.cancel() self.assertTrue(t.cancelled())
def test_done_task_cancelled(self): t = Task(lambda: None) t() t.cancel() self.assertFalse(t.cancelled())
def test_executing(self): t = Task(lambda: None) self.assertFalse(t.executing())