async def test_create_future_for_given_loop(self, mocker, event_loop):
     spy_create_future = mocker.spy(event_loop, "create_future")
     result = asyncio_compat.create_future(event_loop)
     assert isinstance(result, asyncio.Future)
     assert result._loop == event_loop  # Future.get_loop() only works in Python 3.7+
     assert spy_create_future.call_count == 1
     assert spy_create_future.call_args == mocker.call()
 async def test_create_future_for_given_loop_py351orless_compat(self, mocker, event_loop):
     spy_future = mocker.spy(asyncio, "Future")
     result = asyncio_compat.create_future(event_loop)
     assert isinstance(
         result, spy_future.side_effect
     )  # spy_future.side_effect == asyncio.Future
     assert result._loop == event_loop  # Future.get_loop() only works in Python 3.7+
     assert spy_future.call_count == 1
     assert spy_future.call_args == mocker.call(loop=event_loop)
    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