async def test_returns_currently_running_event_loop_py36orless_compat(
         self, mocker, event_loop):
     spy_get_event_loop = mocker.spy(asyncio, "_get_running_loop")
     result = asyncio_compat.get_running_loop()
     assert result == event_loop
     assert spy_get_event_loop.call_count == 1
     assert spy_get_event_loop.call_args == mocker.call()
    def __init__(self, callback):
        """Creates an instance of an AwaitableCallback from a callback function.

        :param callback: Callback function to be made awaitable.
        """
        loop = asyncio_compat.get_running_loop()
        self.future = asyncio_compat.create_future(loop)

        def wrapping_callback(*args, **kwargs):
            result = callback(*args, **kwargs)
            # Use event loop from outer scope, since the threads it will be used in will not have
            # an event loop. future.set_result() has to be called in an event loop or it does not work.
            loop.call_soon_threadsafe(self.future.set_result, result)
            return result

        self.callback = wrapping_callback
    def __init__(self, return_arg_name=None):
        """Creates an instance of an AwaitableCallback
        """

        # LBYL because this mistake doesn't cause an exception until the callback
        # which is much later and very difficult to trace back to here.
        if return_arg_name and not isinstance(return_arg_name, str):
            raise TypeError("internal error: return_arg_name must be a string")

        loop = asyncio_compat.get_running_loop()
        self.future = asyncio_compat.create_future(loop)

        def wrapping_callback(*args, **kwargs):
            # Use event loop from outer scope, since the threads it will be used in will not have
            # an event loop. future.set_result() and future.set_exception have to be called in an
            # event loop or they do not work.
            if "error" in kwargs and kwargs["error"]:
                exception = kwargs["error"]
            elif return_arg_name:
                if return_arg_name in kwargs:
                    exception = None
                    result = kwargs[return_arg_name]
                else:
                    raise TypeError(
                        "internal error: excepected argument with name '{}', did not get"
                        .format(return_arg_name))
            else:
                exception = None
                result = None

            if exception:
                # Do not use exc_info parameter on logger.error.  This casuses pytest to save the traceback which saves stack frames which shows up as a leak
                logger.error(
                    "Callback completed with error {}".format(exception))
                logger.error(
                    traceback.format_exception_only(type(exception),
                                                    exception))
                loop.call_soon_threadsafe(self.future.set_exception, exception)
            else:
                logger.debug(
                    "Callback completed with result {}".format(result))
                loop.call_soon_threadsafe(self.future.set_result, result)

        self.callback = wrapping_callback
Exemple #4
0
    async def async_fn_wrapper(*args, **kwargs):
        loop = asyncio_compat.get_running_loop()

        # Run fn in default ThreadPoolExecutor (CPU * 5 threads)
        return await loop.run_in_executor(
            None, functools.partial(fn, *args, **kwargs))
 async def test_raises_runtime_error_if_no_running_event_loop_py36orless_compat(self, mocker):
     mocker.patch.object(asyncio, "_get_running_loop", return_value=None)
     with pytest.raises(RuntimeError, message="Expecting Runtime Error"):
         asyncio_compat.get_running_loop()
 async def test_raises_runtime_error_if_no_running_event_loop(self, mocker):
     mocker.patch.object(asyncio, "get_running_loop", side_effect=RuntimeError)
     with pytest.raises(RuntimeError):
         asyncio_compat.get_running_loop()