async def test_takewhile(assert_run, event_loop): with event_loop.assert_cleanup(): xs = (stream.range(1, 10) | add_resource.pipe(1) | pipe.takewhile(lambda x: x < 4)) await assert_run(xs, [1, 2, 3]) async def afunc(x): await asyncio.sleep(1) return x < 4 with event_loop.assert_cleanup(): xs = stream.range(1, 10) | add_resource.pipe(1) | pipe.takewhile(afunc) await assert_run(xs, [1, 2, 3]) assert event_loop.steps == [1] * 5
async def euclidean_norm_handler(reader, writer): # Define lambdas strip = lambda x: x.decode().strip() nonempty = lambda x: x != '' square = lambda x: x ** 2 write_cursor = lambda x: writer.write(b'> ') square_root = lambda x: x ** 0.5 # Create awaitable handle_request = ( stream.iterate(reader) | pipe.print('string: {}') | pipe.map(strip) | pipe.takewhile(nonempty) | pipe.map(float) | pipe.map(square) | pipe.print('square: {:.2f}') | pipe.action(write_cursor) | pipe.accumulate(initializer=0) | pipe.map(square_root) | pipe.print('norm -> {:.2f}') ) # Loop over norm computations while not reader.at_eof(): writer.write(INSTRUCTIONS.encode()) try: result = await handle_request except ValueError: writer.write(ERROR.encode()) else: writer.write(RESULT.format(result).encode())
async def euclidean_norm_handler(reader, writer): # Define lambdas strip = lambda x: x.decode().strip() nonempty = lambda x: x != '' square = lambda x: x**2 write_cursor = lambda x: writer.write(b'> ') square_root = lambda x: x**0.5 # Create awaitable handle_request = (stream.iterate(reader) | pipe.print('string: {}') | pipe.map(strip) | pipe.takewhile(nonempty) | pipe.map(float) | pipe.map(square) | pipe.print('square: {:.2f}') | pipe.action(write_cursor) | pipe.accumulate(initializer=0) | pipe.map(square_root) | pipe.print('norm -> {:.2f}')) # Loop over norm computations while not reader.at_eof(): writer.write(INSTRUCTIONS.encode()) try: result = await handle_request except ValueError: writer.write(ERROR.encode()) else: writer.write(RESULT.format(result).encode())
def _stream_config_updates( sensor: TinkerforgeSensor) -> AsyncGenerator[dict[str, Any], None]: """ Tries to fetch a config from the database. It also listens to 'nodes/tinkerforge/$UID/update' for new configs from the database. Parameters ---------- sensor: TinkerforgeSensor The brick or bricklet for which to fetch a config from the database Returns ------- AsyncGenerator of dict A dict containing the configuration of the device """ return stream.chain( stream.call( call_safely, "db_tinkerforge_sensors/get_config", "db_tinkerforge_sensors/status_update", sensor.device.uid, ) | pipe.takewhile(lambda config: config is not None), stream.iterate( event_bus.subscribe( f"nodes/tinkerforge/{sensor.device.uid}/update")), )
def stream_data(self) -> AsyncGenerator[DataEvent, None]: """ Generate the initial configuration of the sensor, configure it, and finally stream the data from the sensor. If there is a configuration update, reconfigure the sensor and start streaming again. Returns ------- AsyncGenerator of DataEvent The data from the device """ # Generates the first configuration # Query the database and if it does not have a config for the sensor, wait until there is one data_stream = ( stream.chain( stream.call( call_safely, "db_labnode_sensors/get_config", "db_labnode_sensors/status_update", self.__uuid ) | pipe.takewhile(lambda config: config is not None), stream.iterate(event_bus.subscribe(f"nodes/by_uuid/{self.__uuid}/update")), ) | pipe.action( lambda config: logging.getLogger(__name__).info( "Got new configuration for: %s", self._device, ) ) | pipe.map(self._create_config) | pipe.switchmap( lambda config: stream.empty() if config is None or not config["enabled"] else (self._configure_and_stream(config)) ) ) return data_stream
async def test_takewhile(assert_run, event_loop): with event_loop.assert_cleanup(): xs = (stream.range(1, 10) | add_resource.pipe(1) | pipe.takewhile(lambda x: x < 4)) await assert_run(xs, [1, 2, 3]) async def afunc(x): await asyncio.sleep(1) return x < 4 with event_loop.assert_cleanup(): xs = (stream.range(1, 10) | add_resource.pipe(1) | pipe.takewhile(afunc)) await assert_run(xs, [1, 2, 3]) assert event_loop.steps == [1]*5
async def run( subscription_kinds: List[SubscriptionKind], topic: str, begin_timestamp=None, interval_sec=None, num_msgs=10, on_message: Optional[Callable[[Any], Any]] = None, ): def log_message(msg): if not isinstance(msg, list): #LOGGER.info("Status: %s", json.dumps(msg)) pass else: LOGGER.debug("Received message: %s", json.dumps(msg)) def maybe_callback(m): if on_message: on_message(m) # the continuous version takes messages up until a time point if interval_sec: async with KrakenClient() as client: for kind in subscription_kinds: await subscribe(client, kind, PAIRS, SUBSCRIPTION_DEPTH) await (client.stream(reconnect_count=WEBSOCKET_RECONNECT_COUNT) | pipe.action(log_message) | pipe.filter(lambda msg: isinstance(msg, list)) | pipe.map(json.dumps) #| pipe.print() | pipe.takewhile( lambda x: time.time() - begin_timestamp < interval_sec) | pipe.action(maybe_callback)) client.disconnect() # the discrete version takes 100 distinct messages else: async with KrakenClient() as client: for kind in subscription_kinds: await subscribe(client, kind, PAIRS, SUBSCRIPTION_DEPTH) await (client.stream(reconnect_count=WEBSOCKET_RECONNECT_COUNT) | pipe.action(log_message) | pipe.filter(lambda msg: isinstance(msg, list)) | pipe.map(json.dumps) #| pipe.print() | pipe.take(num_msgs) | pipe.action(maybe_callback)) print("disconnecting") client.disconnect()