def test_wrong_source(): p = Publisher() on_emit_future = OnEmitFuture() p | on_emit_future with pytest.raises(ValueError): on_emit_future.emit(0, who=Publisher())
def __init__( self, publisher: Publisher, coro_with_args, mode=AsyncMode.CONCURRENT, error_callback=default_error_handler, ) -> None: Operator.__init__(self, publisher) self._coro = coro_with_args self._mode = mode self._error_callback = error_callback # ._future is the reference to a running coroutine encapsulated as task self._future = None # type: Optional[asyncio.Future] # ._last_emit is used for LAST_DISTINCT and keeps the last emit from # source publisher self._last_emit = NONE # type: Any # .scheduled is a Publisher which is emitting the value of the source # publisher when the coroutine is actually started self.scheduled = Publisher() # queue is initialized with following sizes: # Mode: size: # QUEUE unlimited # LAST, LAST_DISTINCT 1 # all others no queue used self._queue = None # type: Optional[MutableSequence] if mode in (AsyncMode.QUEUE, AsyncMode.LAST, AsyncMode.LAST_DISTINCT): maxlen = (None if mode is AsyncMode.QUEUE else 1) self._queue = deque(maxlen=maxlen)
def check_get_method(operator, input_vector, output_vector): input_value, output_value = input_vector[0], output_vector[0] p = Publisher() p.get = mock.MagicMock(return_value=input_value) o = p | operator with pytest.raises(ValueError): o.emit(input_value, who=None) assert o.get() == output_value disposable = o.subscribe(Sink()) if input_value is not NONE: o.emit(input_value, who=p) # simulate emit on subscribe p.get = None # .get should not be called when operator has a subscription assert o.get() == output_value # this should retrieve the internal state # after unsubscription it should remove the internal state and retrieve it # directly from orignator publisher via get disposable.dispose() p.get = mock.MagicMock(return_value=input_value) assert o.get() == output_value p.get.assert_called_once_with()
def get(self): for publisher in self._publishers: try: return publisher.get() except ValueError: pass Publisher.get(self) # raises ValueError
def test_wrong_comparision(): p1 = Publisher() p2 = Publisher() with pytest.raises(ValueError): assert p1 == p2 with pytest.raises(ValueError): if p1 == p2: pass with pytest.raises(ValueError): if p1 != p2: pass with pytest.raises(ValueError): assert p2 in (p1, p2) with pytest.raises(ValueError): p1 in (p2, p2) with pytest.raises(ValueError): assert p1 not in (p2, p2) l = [p1, p2] with pytest.raises(ValueError): l.remove(p2)
def get(self): try: return self._publisher.get() # may raise ValueError except ValueError: if self._state is not NONE: return self._state Publisher.get(self) # raises ValueError
async def test_cancel(): p = Publisher() future = p | OnEmitFuture(timeout=0.01) future.cancel() p.notify(1) with pytest.raises(asyncio.CancelledError): future.result()
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)
def __init__( self, hub: 'Hub', # pylint: disable=unused-argument path: str) -> None: Publisher.__init__(self) self._subject = None # type: Publisher self._path = path self._hub = hub self._pre_assign_emit = None # type: list
def emit(self, value: Any_, who: Publisher) -> None: if who is not self._orginator: raise ValueError('Emit from non assigned publisher') attribute = getattr(value, self._attribute_name) if self._args is None: return Publisher.notify(self, attribute) return Publisher.notify(self, attribute(*self._args, **self._kwargs))
def emit(self, value: Any, who: Publisher) -> None: if who is not self._orginator: raise ValueError('Emit from non assigned publisher') if self._unpack: if self._predicate(*value): return Publisher.notify(self, value) elif self._predicate(value): return Publisher.notify(self, value) return None
def get(self): selection = self._publisher.get() # may raises ValueError try: item = self._mapping[selection] except (IndexError, KeyError, TypeError): if self._default is NONE: Publisher.get(self) # raises ValueError item = self._default if isinstance(item, Publisher): return item.get() # may raises ValueError return item
def test_partition(): mock = Mock() p = Publisher() dut = p | Partition(3) dut | Sink(mock) p.notify(1) p.notify(2) mock.assert_not_called() dut.flush() mock.assert_called_once_with((1, 2))
def _wait_done_cb(self): if self._last_state is not NONE: try: Publisher.notify(self, self._last_state) except Exception: # pylint: disable=broad-except self._error_callback(*sys.exc_info()) self._last_state = NONE self._call_later_handler = self._loop.call_later( self._duration, self._wait_done_cb) else: self._call_later_handler = None
def _delayed_emit_cb(self, value=NONE): if value is NONE: # since the last emit the given duration has passed without another # emit return try: Publisher.notify(self, value) except Exception: # pylint: disable=broad-except self._error_callback(*sys.exc_info()) self._timer.start(self._duration)
def test_adding_publisher(): p1 = Publisher() p2 = Publisher() dut = Merge(p1, p2) assert len(dut.source_publishers) == 2 p3 = Publisher() p3 | dut assert len(dut.source_publishers) == 3 assert p3 in dut.source_publishers
def get(self): value = self._publisher.get() # may raise ValueError if self._unpack: result = self._function(*value) else: result = self._function(value) if result is NONE: Publisher.get(self) # raises ValueError return result
def subscribe(self, subscriber: 'Subscriber', prepend: bool = False) -> SubscriptionDisposable: disposable = MultiOperator.subscribe(self, subscriber, prepend) if self._missing: self._missing.clear() if self._state is NONE: Publisher.notify(self, self._init) else: Publisher.notify(self, self._state) return disposable
async def test_errorhandler(): mock = Mock(side_effect=ZeroDivisionError) mock_errorhandler = Mock() p = Publisher() dut = p | Delay(0.1, error_callback=mock_errorhandler) dut | Sink(mock) p.notify(1) await asyncio.sleep(0.15) mock.assert_called_once_with(1) mock_errorhandler.assert_called_once_with(ZeroDivisionError, ANY, ANY)
def test_exception(): source = Publisher() dut = source | CatchException(ValueError) class _Subscriber(Subscriber): exception = None results = [] def emit(self, arg, who: Publisher) -> None: if self.exception is not None: raise self.exception self.results.append(arg) subscriber = _Subscriber() dut.subscribe(subscriber) source.notify(1) source.notify(2) assert tuple(subscriber.results) == (1, 2) subscriber.exception = ValueError() source.notify(1) assert tuple(subscriber.results) == (1, 2) subscriber.exception = ZeroDivisionError() with pytest.raises(ZeroDivisionError): source.notify(3) with pytest.raises(ValueError): CatchException()
async def test_future_return(): class S(Subscriber): def __init__(self): self.future = asyncio.get_event_loop().create_future() def emit(self, value, who: Publisher) -> asyncio.Future: return self.future p = Publisher() s1 = S() p.subscribe(s1) assert p.notify(None) is s1.future s2 = S() p.subscribe(s2) gathered_future = p.notify(None) await asyncio.sleep(0) assert not gathered_future.done() s1.future.set_result(1) await asyncio.sleep(0) assert not gathered_future.done() s2.future.set_result(1) await asyncio.sleep(0) assert gathered_future.done()
def test_stateless_nested(): source1 = Publisher() dut1 = CombineLatest(source1, allow_stateless=True) source2 = Publisher() dut2 = CombineLatest(dut1, source2, allow_stateless=True) assert len(source1.subscriptions) == 0 assert len(source2.subscriptions) == 0 assert len(dut1.subscriptions) == 0 assert len(dut2.subscriptions) == 0 collector = Collector() dut2 | collector assert len(source1.subscriptions) == 1 assert len(source2.subscriptions) == 1 assert len(dut1.subscriptions) == 1 assert len(dut2.subscriptions) == 1 with pytest.raises(ValueError): dut2.get() assert collector.result_vector == () collector.reset() source1.notify(True) assert collector.result_vector == (((True, ), NONE), ) collector.reset() source2.notify(False) assert collector.result_vector == ((NONE, False), )
def test_stateless_map(): source1 = StatefulPublisher(0) source2 = Publisher() dut = CombineLatest(source1, source2, map_=lambda a, b: a + (0 if b is NONE else b), allow_stateless=True) collector = Collector() dut.subscribe(collector) with pytest.raises(ValueError): dut.get() assert collector.result_vector == () collector.reset() source1.notify(1) assert collector.result_vector == (1, ) source1.notify(1) assert collector.result_vector == (1, ) source1.notify(1.0) assert collector.result_vector == (1, ) source2.notify(0) assert collector.result_vector == (1, 1) source2.notify(1) assert collector.result_vector == (1, 1, 2) source2.notify(1) assert collector.result_vector == (1, 1, 2, 2)
def test_getattr_without_inherit(): p = Publisher() class Foo: a = None def __init__(self, a=5): self.a = a with pytest.raises(AttributeError): dut = p.a with pytest.raises(AttributeError): p.assnign(5)
def test_notify(init, number_of_subscribers): """ Testing .notify(v) method """ p = Publisher(init) m = mock.Mock() # subscribing Sinks to the publisher and test .notify on subscribe subscribers = [Sink(m, i) for i in range(number_of_subscribers)] m.assert_not_called() for s in subscribers: p.subscribe(s) if init is not NONE: m.assert_has_calls([mock.call(i, init) for i in range(number_of_subscribers)]) else: m.assert_not_called() m.reset_mock() # test .notify() for listening subscribers p.notify(1) m.assert_has_calls([mock.call(i, 1) for i in range(number_of_subscribers)]) m.reset_mock() # re- .notify() with the same value p.notify(1) m.assert_has_calls([mock.call(i, 1) for i in range(number_of_subscribers)])
def __init__(self, interval, poll_func: Callable[[Any], Any], *args, error_callback=default_error_handler, loop=None, **kwargs) -> None: Publisher.__init__(self) self._interval = interval if args or kwargs: self._poll_func = \ partial(poll_func, *args, **kwargs) # type: Callable else: self._poll_func = poll_func # type: Callable self._loop = loop or asyncio.get_event_loop() self._call_later_handler = None self._error_callback = error_callback
def get(self): # if all publishers are stateful ._state will be defined if self._state is not NONE: return self._state # get value of all publishers values = (p.get() for p in self._publishers) # may raise ValueError if not self._map: return tuple(values) result = self._map(*values) if result is NONE: Publisher.get(self) # raises ValueError return result
def get(self): queue = list(self._queue) value = self._publisher.get() # may raises ValueError queue.append(value) if self._size and len(queue) == self._size: return tuple(queue) return Publisher.get(self) # raises ValueError
def test_bitwise_combine_latest(method, init, bit_value_map, input_vector, output_vector): publisher_bit_mapping = OrderedDict([(Publisher(v), b) for b, v in bit_value_map]) i_vector = [tuple(v for k, v in bit_value_map)] + input_vector operator = BitwiseCombineLatest(publisher_bit_mapping, init) method(operator, i_vector, output_vector)
def emit(self, value: Any, who: Publisher) -> None: if who is not self._orginator: raise ValueError('Emit from non assigned publisher') if not bool(value): return Publisher.notify(self, value) return None