예제 #1
0
def test_subscribe_emit_assign(factory):
    hub = Hub(topic_factory=factory)

    mock_sink = mock.Mock()
    mock_sink2 = mock.Mock()

    disposable = hub['value1'] | op.Sink(mock_sink)

    mock_sink.assert_not_called()

    assert len(hub['value1']._subscriptions) == 1

    hub['value1'].emit(1)
    hub['value1'].emit(2)

    mock_sink.assert_not_called()

    disposable.dispose()

    assert len(hub['value1']._subscriptions) == 0

    hub['value1'] | op.Sink(mock_sink)
    hub['value1'] | op.Sink(mock_sink2)

    value = Value(0)

    hub['value1'].assign(value)
    mock_sink.calls(mock.call(0), mock.call(1), mock.call(2))
예제 #2
0
def test_assign_subscribe_emit(factory):
    hub = Hub(topic_factory=factory)

    # assign, subscribe and emit
    value1 = Value(0)
    assert not hub['value1'].assigned
    assert hub['value1'].subject is None

    hub['value1'].assign(value1)

    with pytest.raises(ValueError):
        hub['value1'].assign(value1)

    assert hub['value1'].path == 'value1'
    assert hub['value1'].assigned
    assert 'value1' in hub
    assert hub['value1'] is not value1
    assert hub['value1'].subject is value1

    assert len(value1._subscriptions) == 0
    assert len(hub['value1']._subscriptions) == 0

    value2 = Subject()
    hub['value2'].assign(value2)

    mock_sink1 = mock.Mock()
    mock_sink2 = mock.Mock()

    dispose_value1 = hub['value1'] | op.Sink(mock_sink1)
    dispose_value2 = hub['value2'] | op.Sink(mock_sink2)

    assert len(value1._subscriptions) == 1
    assert len(hub['value1']._subscriptions) == 1
    mock_sink1.assert_called_once_with(0)

    assert len(value1._subscriptions) == 1
    assert len(hub['value1']._subscriptions) == 1
    mock_sink2.assert_not_called()

    mock_sink1.reset_mock()
    mock_sink2.reset_mock()
    hub['value1'].emit(1)
    hub['value2'].emit(1)
    mock_sink1.assert_called_once_with(1)
    mock_sink2.assert_called_once_with(1)
    assert value1.get() == 1

    mock_sink1b = mock.Mock()
    dispose_value1b = hub['value1'] | op.Sink(mock_sink1b)
    mock_sink1b.assert_called_once_with(1)

    dispose_value1.dispose()
    dispose_value1b.dispose()

    mock_sink2b = mock.Mock()
    hub['value2'] | op.Sink(mock_sink2b)
    mock_sink2b.assert_not_called()

    assert len(value1._subscriptions) == 0
    assert len(hub['value1']._subscriptions) == 0
async def test_errorhandler(operator_cls, publisher, args, capsys):
    mock = Mock(side_effect=ZeroDivisionError)

    # test default error handler
    if publisher is not None:
        dut = publisher | operator_cls(*args)
    else:
        dut = operator_cls(*args)

    dut | op.Sink(mock)

    await asyncio.sleep(0.1)

    captured = capsys.readouterr()
    assert 'Traceback' in captured.err
    assert 'ZeroDivisionError' in captured.err

    # test custom default error handler
    mock_errorhandler = Mock()
    default_error_handler.set(mock_errorhandler)

    if publisher is not None:
        dut = publisher | operator_cls(*args)
    else:
        dut = operator_cls(*args)

    dut | op.Sink(mock)

    await asyncio.sleep(0.1)

    mock_errorhandler.assert_called_with(ZeroDivisionError, ANY, ANY)

    default_error_handler.reset()

    # test custom error handler
    mock_errorhandler_custom = Mock()

    if publisher is not None:
        dut = publisher | operator_cls(*args,
                                       error_callback=mock_errorhandler_custom)
    else:
        dut = operator_cls(*args, error_callback=mock_errorhandler_custom)

    dut | op.Sink(mock)

    await asyncio.sleep(0.1)

    mock_errorhandler_custom.assert_called_with(ZeroDivisionError, ANY, ANY)

    default_error_handler.reset()
예제 #4
0
def test_freeze():
    hub = Hub()

    hub['value1'].assign(StatefulPublisher(0))

    assert 'value1' in hub

    hub.freeze()

    assert len(tuple(hub)) == 1

    hub.freeze(False)

    hub['value2'] | op.Sink()
    hub['value3'].emit(1)

    assert 'value2' in hub
    assert 'value3' in hub

    with pytest.raises(ValueError):
        hub.freeze()

    hub['value2'].assign(Value(0))
    hub['value3'].assign(Value(0))

    hub.freeze()

    with pytest.raises(ValueError):
        hub['value4'].assign(StatefulPublisher(0))

    with pytest.raises(ValueError):
        hub['value5'] | op.Sink()

    with pytest.raises(ValueError):
        hub['value6'].emit(1)

    assert len(tuple(hub)) == 3

    hub.freeze(False)

    hub['value4'] | op.Sink()
    hub['value5'].assign(StatefulPublisher(0))
    hub['value6'].emit(1)

    assert 'value4' in hub
    assert 'value5' in hub
    assert 'value6' in hub

    assert len(tuple(hub)) == 6
def test_operator_with_constant_r():
    v1 = 1
    v2 = Value(0)

    o = v1 - v2

    assert isinstance(o, Publisher)
    assert o.get() == 1

    v2.emit(1)
    assert o.get() == 0

    assert len(o.subscriptions) == 0

    mock_sink = mock.Mock()

    o | op.Sink(mock_sink)
    assert len(o.subscriptions) == 1
    mock_sink.assert_called_once_with(0)
    mock_sink.reset_mock()

    v2.emit(3)
    mock_sink.assert_called_once_with(-2)

    with pytest.raises(ValueError):
        Value(1) | o

    with pytest.raises(ValueError):
        o.emit_op(0, who=Publisher())
def test_getattr_attribute():
    p = StatefulPublisher()

    class Foo:
        a = None

        def __init__(self, a=5):
            self.a = a

    p.inherit_type(Foo)

    dut = p.a
    m = mock.Mock()
    dut | op.Sink(m)

    with pytest.raises(ValueError):
        dut.get()

    m.assert_not_called()

    p.notify(Foo(3))

    assert dut.get() == 3

    m.assert_called_once_with(3)

    with pytest.raises(ValueError):
        dut.emit_op(0, who=Publisher())

    with pytest.raises(AttributeError):
        dut.assnign(5)
def test_operator_with_publishers():
    v1 = Value(0)
    v2 = Value(0)

    o = v1 + v2

    assert isinstance(o, Publisher)
    assert not isinstance(o, Subscriber)
    assert o.get() == 0

    v1.emit(1)
    assert o.get() == 1

    assert len(o.subscriptions) == 0

    mock_sink = mock.Mock()

    o | op.Sink(mock_sink)
    assert len(o.subscriptions) == 1
    mock_sink.assert_called_once_with(1)
    mock_sink.reset_mock()

    v2.emit(3)
    mock_sink.assert_called_once_with(4)

    with pytest.raises(ValueError):
        o.emit_op(0, who=Publisher())

    with pytest.raises(AttributeError):
        Value(1) | o
def test_inherit_with_operators():
    p = StatefulPublisher()
    p.inherit_type(str)

    dut = op.Len(('abc' + p + 'ghi').upper())
    m = mock.Mock()
    dut | op.Sink(m)

    p.notify('def')
    m.assert_called_once_with(9)
def test_inherit_getattr():
    p = StatefulPublisher()
    p.inherit_type(str)

    dut = p.lower().split(' ')
    m = mock.Mock()
    dut | op.Sink(m)

    p.notify('This is a TEST')
    m.assert_called_once_with(['this', 'is', 'a', 'test'])
def test_getattr_method():
    p = StatefulPublisher()
    p.inherit_type(str)

    dut1 = p.split()
    dut2 = p.split(',')
    dut3 = p.split(sep='!')

    mock1 = mock.Mock()
    mock2 = mock.Mock()
    mock3 = mock.Mock()

    dut1 | op.Sink(mock1)
    dut2 | op.Sink(mock2)
    dut3 | op.Sink(mock3)

    with pytest.raises(ValueError):
        dut1.get()

    with pytest.raises(ValueError):
        dut2.get()

    with pytest.raises(ValueError):
        dut3.get()

    mock1.assert_not_called()
    mock2.assert_not_called()
    mock3.assert_not_called()

    p.notify('This is just a test, honestly!')

    assert dut1.get() == ['This', 'is', 'just', 'a', 'test,', 'honestly!']
    assert dut2.get() == ['This is just a test', ' honestly!']
    assert dut3.get() == ['This is just a test, honestly', '']

    mock1.assert_called_once_with(
        ['This', 'is', 'just', 'a', 'test,', 'honestly!'])
    mock2.assert_called_once_with(['This is just a test', ' honestly!'])
    mock3.assert_called_once_with(['This is just a test, honestly', ''])
예제 #11
0
def test_type_checks(factory):
    hub = Hub(topic_factory=factory)

    # test unassigned topic .get
    with pytest.raises(ValueError):
        hub['value1'].get()

    # test subscribing to a subscriber
    hub['value2'].assign(op.Sink())

    with pytest.raises(TypeError):
        hub['value2'] | op.Sink()

    # test emiting to a publisher
    hub['value3'].assign(Publisher())

    with pytest.raises(TypeError):
        hub['value3'].emit(0)

    # test assigning of non Publisher or Subscriber

    with pytest.raises(TypeError):
        hub['value4'].assign(None)
def test_unary_operators(operator, value, result):
    v = StatefulPublisher(value)

    try:
        value_applied = operator(v).get()
    except Exception as e:
        assert isinstance(e, result)
    else:
        assert value_applied == result

    cb = mock.Mock()

    try:
        operator(v) | op.Sink(cb)
    except Exception as e:
        assert isinstance(e, result)
    else:
        assert cb.mock_called_once_with(result)

    with pytest.raises(ValueError):
        Value(1) | operator(v)

    with pytest.raises(ValueError):
        operator(v).emit_op(0, who=Publisher())
예제 #13
0
def test_stateful_publisher():
    p = StatefulPublisher()
    v = Value(0)

    with pytest.raises(ValueError):
        p.get()

    mock_sink = mock.Mock()

    disposable = p | v
    v | op.Sink(mock_sink)

    mock_sink.assert_called_once_with(0)
    mock_sink.reset_mock()

    p.notify(1)

    mock_sink.assert_called_once_with(1)
    assert p.get() == 1
    mock_sink.reset_mock()

    p.notify(1)
    assert p.get() == 1
    mock_sink.assert_not_called()

    p.notify(2)
    assert p.get() == 2
    mock_sink.assert_called_once_with(2)

    p.reset_state()

    with pytest.raises(ValueError):
        p.get()

    p.reset_state(3)
    assert p.get() == 3
예제 #14
0
async def test_debounce():
    import asyncio
    from broqer import default_error_handler, Publisher, op

    p = Publisher()
    mock_sink = mock.Mock()
    mock_error_handler = mock.Mock()

    default_error_handler.set(mock_error_handler)

    disposable = p | op.Debounce(0.1) | op.Sink(mock_sink)

    mock_sink.side_effect = ZeroDivisionError('FAIL')

    # test error_handler
    p.notify(1)
    mock_error_handler.assert_not_called()
    await asyncio.sleep(0.05)
    mock_error_handler.assert_not_called()
    await asyncio.sleep(0.1)
    mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY,
                                               mock.ANY)
    mock_sink.assert_called_once_with(1)

    mock_sink.reset_mock()

    # test unsubscribe
    p.notify(2)
    await asyncio.sleep(0.05)
    disposable.dispose()
    await asyncio.sleep(0.1)
    mock_sink.assert_not_called()

    # test reset
    mock_sink.reset_mock()
    debounce = p | op.Debounce(0.1)
    disposable = debounce | op.Sink(mock_sink)
    p.notify(1)
    await asyncio.sleep(0.05)
    debounce.reset()
    await asyncio.sleep(0.1)
    mock_sink.assert_not_called()

    disposable.dispose()

    # test reset again
    mock_sink.reset_mock()
    mock_sink.side_effect = None
    debounce = p | op.Debounce(0, False)
    disposable = debounce | op.Sink(mock_sink)
    p.notify(True)
    await asyncio.sleep(0.05)
    debounce.reset()
    mock_sink.assert_has_calls(
        (mock.call(False), mock.call(True), mock.call(False)))

    # resubscribe
    mock_sink.reset_mock()
    p.notify(True)
    await asyncio.sleep(0.05)
    mock_sink.assert_called_once_with(True)

    disposable.dispose()

    debounce | op.Sink()

    p.notify(True)

    await asyncio.sleep(0.05)

    assert debounce.get() == True
    await debounce | op.True_()
    mock_sink.assert_called_once_with(True)

    # test argument check
    with pytest.raises(ValueError):
        op.Debounce(-1)
예제 #15
0
import asyncio
import subprocess
import operator

from broqer import op

(op.FromPolling(1, subprocess.check_output, 'uptime')
 | op.Map(str, encoding='utf - 8')
 | op.Map(str.split, sep=', ')
 | op.Map(lambda v: v[0])
 | op.Sink(print))

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.sleep(10))
예제 #16
0
async def test_throttle():
    import asyncio
    from broqer import default_error_handler, Publisher, op

    p = Publisher()
    mock_sink = mock.Mock()
    mock_error_handler = mock.Mock()

    default_error_handler.set(mock_error_handler)

    disposable = p | op.Throttle(0.1) | op.Sink(mock_sink)

    mock_sink.side_effect = (None, ZeroDivisionError('FAIL'))

    # test error_handler
    p.notify(1)
    await asyncio.sleep(0.05)
    mock_sink.assert_called_once_with(1)
    p.notify(2)
    await asyncio.sleep(0.1)
    mock_error_handler.assert_called_once_with(ZeroDivisionError, mock.ANY,
                                               mock.ANY)

    mock_sink.reset_mock()

    # test unsubscribe
    p.notify(2)
    mock_sink.reset_mock()
    await asyncio.sleep(0.05)
    disposable.dispose()
    await asyncio.sleep(0.1)
    mock_sink.assert_called_once_with(2)

    # test reset
    mock_sink.reset_mock()
    mock_sink.side_effect = None
    throttle = p | op.Throttle(0.1)
    disposable = throttle | op.Sink(mock_sink)
    p.notify(1)
    mock_sink.reset_mock()
    await asyncio.sleep(0.05)
    throttle.reset()
    p.notify(2)
    await asyncio.sleep(0.05)
    mock_sink.assert_called_once_with(2)

    disposable.dispose()

    # test reset again
    mock_sink.reset_mock()
    mock_sink.side_effect = None
    throttle = p | op.Throttle(0.1)
    disposable = throttle | op.Sink(mock_sink)

    # resubscribe
    mock_sink.reset_mock()
    p.notify(1)
    await asyncio.sleep(0.05)
    mock_sink.assert_called_once_with(1)

    disposable.dispose()

    throttle | op.Sink()

    p.notify(2)
    await asyncio.sleep(0.05)
    p.notify(3)

    with pytest.raises(ValueError):
        throttle.get()
    assert await throttle == 3
    mock_sink.assert_called_once_with(1)

    # reset when nothing is to be emitted
    disposable = throttle | op.Sink(mock_sink)
    mock_sink.reset_mock()
    await asyncio.sleep(0.15)

    throttle.reset()
    p.notify(4)
    mock_sink.assert_called_once_with(4)
def test_with_publisher(operator, l_value, r_value, result):
    vl = Value(l_value)
    vr = Value(r_value)
    pl = Publisher()
    pr = Publisher()
    cl = l_value
    cr = r_value

    o1 = operator(vl, vr)
    o2 = operator(vl, cr)
    o3 = operator(vl, pr)

    o4 = operator(pl, vr)
    o5 = operator(pl, cr)
    o6 = operator(pl, pr)

    o7 = operator(cl, vr)
    try:
        o8 = operator(cl, cr)
    except Exception as e:
        assert isinstance(e, result)
        o8 = result  # to pass the following test

    o9 = operator(cl, pr)

    mock_sink_o3 = mock.Mock()
    mock_sink_o4 = mock.Mock()
    mock_sink_o5 = mock.Mock()
    mock_sink_o6 = mock.Mock()
    mock_sink_o9 = mock.Mock()

    o3 | op.Sink(mock_sink_o3)
    o4 | op.Sink(mock_sink_o4)
    o5 | op.Sink(mock_sink_o5)
    o6 | op.Sink(mock_sink_o6)
    o9 | op.Sink(mock_sink_o9)

    for output in (o1, o2, o3, o4, o5, o6, o7, o9):
        assert isinstance(output, Publisher)

    assert o8 == result

    for output in (o1, o2, o7):
        try:
            assert output.get() == result
        except Exception as e:
            assert isinstance(e, result)

    for output in (o3, o4, o5, o6, o9):
        with pytest.raises(ValueError):
            output.get()

    mock_sink_o3.assert_not_called()
    mock_sink_o4.assert_not_called()
    mock_sink_o5.assert_not_called()
    mock_sink_o6.assert_not_called()
    mock_sink_o9.assert_not_called()

    try:
        pl.notify(l_value)
    except Exception as e:
        assert isinstance(e, result)
    else:
        mock_sink_o3.assert_not_called()
        mock_sink_o4.assert_called_once_with(result)
        mock_sink_o5.assert_called_once_with(result)
        mock_sink_o6.assert_not_called()
        mock_sink_o9.assert_not_called()

    try:
        pr.notify(r_value)
    except Exception as e:
        assert isinstance(e, result)
    else:
        mock_sink_o3.assert_called_once_with(result)
        mock_sink_o4.assert_called_once_with(result)
        mock_sink_o5.assert_called_once_with(result)
        mock_sink_o6.assert_called_once_with(result)
        mock_sink_o9.assert_called_once_with(result)