async def run_handler(client, HandlerBase, payload, expect_payload=None, stream='fake'): future = create_future() if expect_payload is None: expect_payload = payload class Handler(HandlerBase): def receive(self, p): p = super().receive(p) if future.done(): return future.set_result(p) client.start() client.handler(Handler()) await client._receive({'data': ACCOUNT_POSITION, 'stream': 'fake'}) await client._receive({'data': payload, 'stream': stream}) await client._receive([]) await client._receive({}) received = await future if callable(expect_payload): expect_payload(received) else: assert received == expect_payload
def _updated_future(self) -> Future: future = self.__updated_future if future is None: future = create_future() self.__updated_future = future return future
def _emit_updated(self, exc: Optional[Exception] = None) -> None: if self._fetching: # If the orderbook is still fetching, # which means the orderbook is not completely updated, # we will not emit the event return if exc is None: self._updated_future.set_result(None) else: self._updated_future.set_exception(exc) self.__updated_future = create_future()
async def run_orderbook_handler(client, init_orderbook_first): f = create_future() class OrderBookHandler(OrderBookHandlerBase): def receive(self, payload): f.set_result(super().receive(payload)) handler = OrderBookHandler() if init_orderbook_first: orderbook = handler.orderbook('BTCUSDT') client.handler(handler) await client.subscribe(SubType.ORDER_BOOK, 'BTCUSDT') info, [bids, asks] = await f assert isinstance(info, pandas.DataFrame) assert isinstance(bids, pandas.DataFrame) assert isinstance(asks, pandas.DataFrame) if not init_orderbook_first: orderbook = handler.orderbook('BTCUSDT') async def assert_no_change(): asks = [*orderbook.asks] await asyncio.sleep(0.2) # should have no change assert asks == orderbook.asks await orderbook.updated() # type: ignore assert len(orderbook.asks) != 0 # type: ignore assert len(orderbook.bids) != 0 # type: ignore assert await client.list_subscriptions() == ['btcusdt@depth'] client.stop() await assert_no_change() client.start() await client.unsubscribe(SubType.ORDER_BOOK, 'BTCUSDT') await assert_no_change() await client.close()
async def test_client_handler(client): f = create_future() class TickerHandler(TickerHandlerBase): # async receiver async def receive(self, payload): f.set_result(payload) client.handler(TickerHandler()) await client.subscribe(SubType.TICKER, 'BTCUSDT') payload = await f assert payload['e'] == '24hrTicker' assert payload['s'] == 'BTCUSDT' await client.close()
async def test_client_kline_handler(client): f = create_future() class KlineHandler(KlineHandlerBase): # async receiver async def receive(self, payload): f.set_result(payload) client.handler(KlineHandler()) await client.subscribe(SubType.KLINE, 'BTCUSDT', KlineInterval.DAY) payload = await f assert payload['e'] == 'kline' assert payload['s'] == 'BTCUSDT' await client.close()
async def send(self, msg: dict) -> Any: """Send a request to Binance stream and handle the asynchronous socket response Request:: { "method": "SUBSCRIBE", "params": [ "btcusdt@aggTrade", "btcusdt@depth" ], "id": 1 } Response:: { "result": null, "id": 1 } Then the result of `self.send()` is `None` (null) """ socket = self._socket if not socket: if self._open_future: socket = await self._open_future else: raise StreamDisconnectedException(self._uri) future = create_future() message_id = self._message_id self._message_id += 1 msg[STREAM_KEY_ID] = message_id self._message_futures[message_id] = future await socket.send(json_stringify(msg)) return await future
async def test_handler_exception_handler(client): exc = Exception() f = create_future() class TickerPrinter(TickerHandlerBase): def receive(self, payload): raise exc class ExceptionHandler(HandlerExceptionHandlerBase): def receive(self, e): f.set_result(e) client.handler(TickerPrinter(), ExceptionHandler()) await client._receive(TICKER_RES) assert await f == exc await client.close()
async def run_stream(): f = create_future() async def on_message(msg): f.set_result(msg) stream = Stream( STREAM_HOST + '/stream', on_message ) stream.connect() params = ['btcusdt@ticker'] print('\nsubscribed', await stream.send({ 'method': 'SUBSCRIBE', 'params': params })) assert await stream.send({ 'method': 'LIST_SUBSCRIPTIONS' }) == params msg = await f assert msg['stream'] == 'btcusdt@ticker' with pytest.raises( StreamSubscribeException, match='fails to subscribe' ): await stream.send({ 'method': 'SUBSCRIBE', 'params': [] }) print('before close') await stream.close()
async def test_handler_exception_handler(client): future = create_future() e = ValueError('this is an exception for testing, not a bug') class ExceptionHandler(HandlerExceptionHandlerBase): def receive(self, e): e = super().receive(e) future.set_exception(e) class AccountInfoHandler(AccountInfoHandlerBase): def receive(self, payload): raise e client.start() client.handler(ExceptionHandler()) client.handler(AccountInfoHandler()) await client._receive({'data': ACCOUNT_INFO}) try: await future except Exception as catched: assert catched is e
def _before_connect(self) -> None: self._open_future = create_future()
def _emit_exception(self, exc: Exception) -> None: self._updated_future.set_exception(exc) self.__updated_future = create_future()
def _emit_updated(self) -> None: self._updated_future.set_result(None) self.__updated_future = create_future()
def reset(self): self.f = create_future()