Ejemplo n.º 1
0
    def __init__(self, coro, *args, mode=AsyncMode.CONCURRENT,
                 error_callback=default_error_handler,
                 unpack: bool = False, **kwargs) -> None:

        _coro = wrap_coro(coro, unpack, *args, **kwargs)
        self._coro_queue = CoroQueue(_coro, mode=mode)
        self._error_callback = error_callback
Ejemplo n.º 2
0
async def test_concurrent():
    callback = mock.Mock()
    event = asyncio.Event()

    async def _coro(index):
        callback(f'Start {index}')
        await event.wait()
        callback(f'End {index}')
        return index

    coro_queue = CoroQueue(coro=_coro, mode=AsyncMode.CONCURRENT)

    # make two concurrent calls
    result1 = coro_queue.schedule(1)
    result2 = coro_queue.schedule(2)

    await asyncio.sleep(0)

    callback.assert_has_calls([mock.call('Start 1'), mock.call('Start 2')])
    callback.reset_mock()

    event.set()
    await asyncio.sleep(0.001)
    callback.assert_has_calls(
        [mock.call('End 1'), mock.call('End 2')], any_order=True)

    assert result1.result() == 1
    assert result2.result() == 2

    # make a non-concurrent call
    event.set()
    assert (await coro_queue.schedule(3)) == 3
Ejemplo n.º 3
0
async def test_skip(wait):
    callback = mock.Mock()
    event = asyncio.Event()

    async def _coro(index):
        callback(f'Start {index}')
        await event.wait()
        callback(f'End {index}')
        return index

    coro_queue = CoroQueue(coro=_coro, mode=AsyncMode.SKIP)

    # make two concurrent calls, the first one will be interrupted (canceld)
    result1 = coro_queue.schedule(1)
    if wait:
        await asyncio.sleep(0.0001)
    result2 = coro_queue.schedule(2)

    await asyncio.sleep(0)

    callback.assert_called_with('Start 1')
    callback.reset_mock()

    event.set()
    await asyncio.sleep(0.001)
    callback.assert_called_once_with('End 1')

    assert result1.result() == 1
    assert result2.result() == NONE

    # make a non-concurrent call
    event.set()
    assert (await coro_queue.schedule(3)) == 3
Ejemplo n.º 4
0
async def test_simple_run(mode, args):
    excpected_result = args

    async def _coro(*args):
        await asyncio.sleep(0)
        return args

    coro_queue = CoroQueue(coro=_coro, mode=mode)

    # test the first call and wait for finish
    future = coro_queue.schedule(*args)
    assert (await future) == excpected_result

    if mode == AsyncMode.LAST_DISTINCT:
        # for LAST_DISTINCT, the following results will be broqer.NONE
        excpected_result = NONE

    # test a second time
    future = coro_queue.schedule(*args)
    assert (await future) == excpected_result

    await asyncio.sleep(0.001)

    # test a third time
    future = coro_queue.schedule(*args)
    assert (await future) == excpected_result
Ejemplo n.º 5
0
class SinkAsync(Subscriber):  # pylint: disable=too-few-public-methods
    """ Apply ``coro`` to each emitted value allowing async processing

    :param coro: coroutine to be applied on emit
    :param \\*args: variable arguments to be used for calling coro
    :param mode: behavior when a value is currently processed
    :param error_callback: error callback to be registered
    :param unpack: value from emits will be unpacked as (\\*value)
    :param \\*\\*kwargs: keyword arguments to be used for calling coro
    """
    def __init__(self, coro, *args, mode=AsyncMode.CONCURRENT,
                 error_callback=default_error_handler,
                 unpack: bool = False, **kwargs) -> None:

        _coro = wrap_coro(coro, unpack, *args, **kwargs)
        self._coro_queue = CoroQueue(_coro, mode=mode)
        self._error_callback = error_callback

    def emit(self, value: Any, who: Publisher):
        self._coro_queue.schedule(value)
Ejemplo n.º 6
0
async def test_exception(mode):
    async def _coro(fail):
        if fail:
            raise ZeroDivisionError()

    coro_queue = CoroQueue(coro=_coro, mode=mode)

    # test the first call and wait for finish
    future = coro_queue.schedule(True)
    with pytest.raises(ZeroDivisionError):
        await future

    # test a second time
    future = coro_queue.schedule(False)
    assert (await future) == None

    # test a third time
    future = coro_queue.schedule(True)
    with pytest.raises(ZeroDivisionError):
        await future
Ejemplo n.º 7
0
async def test_queue():
    callback = mock.Mock()
    event = asyncio.Event()

    async def _coro(index):
        callback(f'Start {index}')
        await event.wait()
        callback(f'End {index}')
        return index

    coro_queue = CoroQueue(coro=_coro, mode=AsyncMode.QUEUE)

    # make two concurrent calls
    result1 = coro_queue.schedule(1)
    result2 = coro_queue.schedule(2)

    await asyncio.sleep(0.001)
    event.set()
    event.clear()

    await asyncio.sleep(0.001)

    callback.assert_has_calls(
        [mock.call('Start 1'),
         mock.call('End 1'),
         mock.call('Start 2')])

    assert result1.result() == 1
    assert not result2.done()

    callback.reset_mock()

    event.set()
    event.clear()
    await asyncio.sleep(0.001)

    callback.assert_called_once_with('End 2')

    # make a non-concurrent call
    event.set()
    assert (await coro_queue.schedule(3)) == 3
Ejemplo n.º 8
0
async def test_last(distinct):
    callback = mock.Mock()
    event = asyncio.Event()

    async def _coro(index):
        callback(f'Start {index}')
        await event.wait()
        callback(f'End {index}')
        return index

    mode = AsyncMode.LAST_DISTINCT if distinct else AsyncMode.LAST
    coro_queue = CoroQueue(coro=_coro, mode=mode)

    # make three concurrent calls
    result1 = coro_queue.schedule(1)
    result2 = coro_queue.schedule(2)
    result3 = coro_queue.schedule(1)

    await asyncio.sleep(0.001)
    event.set()
    await asyncio.sleep(0.001)

    expected_calls = [mock.call('Start 1'), mock.call('End 1')]

    if not distinct:
        expected_calls += [mock.call('Start 1'), mock.call('End 1')]

    callback.assert_has_calls(expected_calls)

    assert result1.result() == 1
    assert result2.result() == NONE
    assert result3.result() == (NONE if distinct else 1)

    # make a non-concurrent call
    event.set()
    assert (await coro_queue.schedule(3)) == 3
Ejemplo n.º 9
0
class MapAsync(Operator):  # pylint: disable=too-many-instance-attributes
    """ Apply ``coro(*args, value, **kwargs)`` to each emitted value allow
    async processing.

    :param coro: coroutine to be applied on emit
    :param \\*args: variable arguments to be used for calling coro
    :param mode: behavior when a value is currently processed
    :param error_callback: error callback to be registered
    :param unpack: value from emits will be unpacked as (\\*value)
    :param \\*\\*kwargs: keyword arguments to be used for calling coro

    :ivar scheduled: Publisher emitting the value when coroutine is actually
        started.
    """
    def __init__(self,
                 coro,
                 *args,
                 mode=AsyncMode.CONCURRENT,
                 error_callback=default_error_handler,
                 unpack: bool = False,
                 **kwargs) -> None:
        Operator.__init__(self)
        _coro = wrap_coro(coro, unpack, *args, **kwargs)
        self._coro_queue = CoroQueue(_coro, mode=mode)
        self._error_callback = error_callback

    def emit(self, value: Any, who: Publisher) -> None:
        if who is not self._originator:
            raise ValueError('Emit from non assigned publisher')

        future = self._coro_queue.schedule(value)
        future.add_done_callback(self._done)

    def _done(self, future: asyncio.Future):
        try:
            result = future.result()
        except Exception:  # pylint: disable=broad-except
            self._error_callback(*sys.exc_info())
        else:
            if result != NONE:
                Publisher.notify(self, result)