def add_done_callback(self, fn): """Add a callback to be executed when the operation is complete. If the operation is not already complete, this will start a helper thread to poll for the status of the operation in the background. Args: fn (Callable[Future]): The callback to execute when the operation is complete. """ if self._result_set: _helpers.safe_invoke_callback(fn, self) return self._done_callbacks.append(fn) if self._polling_thread is None: # The polling thread will exit on its own as soon as the operation # is done. self._polling_thread = _helpers.start_daemon_thread( target=self._blocking_poll)
def _invoke_callbacks(self, *args, **kwargs): """Invoke all done callbacks.""" for callback in self._done_callbacks: _helpers.safe_invoke_callback(callback, *args, **kwargs)
def test_safe_invoke_callback_exception(): callback = mock.Mock(spec=['__call__'], side_effect=ValueError()) result = _helpers.safe_invoke_callback(callback, 'a', b='c') assert result is None callback.assert_called_once_with('a', b='c')
def test_safe_invoke_callback(): callback = mock.Mock(spec=['__call__'], return_value=42) result = _helpers.safe_invoke_callback(callback, 'a', b='c') assert result == 42 callback.assert_called_once_with('a', b='c')