def __init__(self, read: Callable[[], bytes], paths_or_modules: Union[Iterable[python_protos.PathOrModule], python_protos.Library], channels: Iterable[pw_rpc.Channel], output: Callable[[bytes], Any] = write_to_file, client_impl: pw_rpc.client.ClientImpl = None): """Creates an RPC client configured to communicate using HDLC. Args: read: Function that reads bytes; e.g serial_device.read. paths_or_modules: paths to .proto files or proto modules channel: RPC channels to use for output output: where to write "stdout" output from the device """ if isinstance(paths_or_modules, python_protos.Library): self.protos = paths_or_modules else: self.protos = python_protos.Library.from_paths(paths_or_modules) if client_impl is None: client_impl = callback_client.Impl() self.client = pw_rpc.Client.from_modules(client_impl, channels, self.protos.modules()) frame_handlers: FrameHandlers = { DEFAULT_ADDRESS: self._handle_rpc_packet, STDOUT_ADDRESS: lambda frame: output(frame.data), } # Start background thread that reads and processes RPC packets. threading.Thread(target=read_and_process_data, daemon=True, args=(read, lambda exc: None, frame_handlers)).start()
def __init__( self, read: Callable[[], bytes], write: Callable[[bytes], int], paths_or_modules: Union[Iterable["python_protos.PathOrModule"], "python_protos.Library"]): """Creates an RPC client configured to communicate using HDLC. Args: read: Function that reads bytes; e.g serial_device.read. write: Function that writes bytes; e.g serial_device.write. paths_or_modules: Paths to .proto files or proto modules. """ if not PIGWEED_IMPORT: raise errors.DependencyUnavailableError( "Pigweed python packages are not available in this environment." ) if isinstance(paths_or_modules, python_protos.Library): self.protos = paths_or_modules else: self.protos = python_protos.Library.from_paths(paths_or_modules) client_impl = callback_client.Impl() channels = rpc.default_channels(write) self.client = pw_rpc.Client.from_modules(client_impl, channels, self.protos.modules()) self.frame_handlers = { _DEFAULT_ADDRESS: self._handle_rpc_packet, _STDOUT_ADDRESS: lambda frame: rpc.write_to_file(frame.data) } self.read = read self._stop_event = threading.Event() self._worker = None
def __init__(self, device: Any, proto_paths_or_modules: Iterable[python_protos.PathOrModule], output: Callable[[bytes], Any] = write_to_file, channels: Iterable[pw_rpc.Channel] = None, client_impl: pw_rpc.client.ClientImpl = None): """Creates an RPC client configured to communicate using HDLC. Args: device: serial.Serial (or any class that implements read and write) for reading/writing data proto_paths_or_modules: paths to .proto files or proto modules output: where to write "stdout" output from the device """ self.device = device self.protos = python_protos.Library.from_paths(proto_paths_or_modules) if channels is None: channels = [pw_rpc.Channel(1, channel_output(device.write))] if client_impl is None: client_impl = callback_client.Impl() self.client = pw_rpc.Client.from_modules(client_impl, channels, self.protos.modules()) frame_handlers: _FrameHandlers = { DEFAULT_ADDRESS: self._handle_rpc_packet, STDOUT_ADDRESS: lambda frame: output(frame.data), } # Start background thread that reads and processes RPC packets. threading.Thread(target=read_and_process_data, daemon=True, args=(device, frame_handlers)).start()
def setUp(self) -> None: self._protos = python_protos.Library.from_strings(_PROTO) self._info = ClientInfo( 'the_client', object(), pw_rpc.Client.from_modules(callback_client.Impl(), [ pw_rpc.Channel(1, lambda _: None), pw_rpc.Channel(2, lambda _: None), ], self._protos.modules()))
def setUp(self): self._protos = python_protos.Library.from_strings(TEST_PROTO_1) self._client = client.Client.from_modules( callback_client.Impl(), [client.Channel(1, self._handle_request)], self._protos.modules()) self._last_request: packet_pb2.RpcPacket = None self._next_packets: List[Tuple[bytes, Status]] = [] self._send_responses_on_request = True
def console(device: str, baudrate: int, token_databases: Collection[tokens.Database], socket_addr: str, output: Any, raw_serial: bool) -> int: """Starts an interactive RPC console for HDLC.""" # argparse.FileType doesn't correctly handle '-' for binary files. if output is sys.stdout: output = sys.stdout.buffer logfile = create_temp_log_file() pw_cli.log.install(logging.INFO, True, False, logfile) serial_impl = SerialWithLogging if socket_addr is None: serial_device = serial_impl(device, baudrate, timeout=0) def read(): return serial_device.read(8192) write = serial_device.write else: try: socket_device = SocketClientImpl(socket_addr) read = socket_device.read write = socket_device.write except ValueError: _LOG.exception('Failed to initialize socket at %s', socket_addr) return 1 callback_client_impl = callback_client.Impl( default_unary_timeout_s=5.0, default_stream_timeout_s=None, ) detokenizer = Detokenizer(tokens.Database.merged(*token_databases), show_errors=False) if token_databases else None if raw_serial: threading.Thread( target=_read_raw_serial, daemon=True, args=( read, lambda data: write_to_output(data, output, detokenizer), )).start() _start_ipython_raw_terminal() else: _start_ipython_hdlc_terminal( HdlcRpcClient( read, PROTOS, default_channels(write), lambda data: write_to_output(data, output, detokenizer), client_impl=callback_client_impl)) return 0
def test_default_timeouts_set_for_all_rpcs(self): rpc_client = client.Client.from_modules(callback_client.Impl( 99, 100), [client.Channel(1, lambda *a, **b: None)], self._protos.modules()) rpcs = rpc_client.channel(1).rpcs self.assertEqual( rpcs.pw.test1.PublicService.SomeUnary.default_timeout_s, 99) self.assertEqual( rpcs.pw.test1.PublicService.SomeServerStreaming.default_timeout_s, 100)
def test_set_target_switches_between_clients(self) -> None: client_1_channel = self._info.rpc_client.channel(1).channel client_2_channel = pw_rpc.Channel(99, lambda _: None) info_2 = ClientInfo( 'other_client', object(), pw_rpc.Client.from_modules(callback_client.Impl(), [client_2_channel], self._protos.modules())) variables = multi_client_terminal_variables( clients=[self._info, info_2], default_client=self._info.client, protos=self._protos) # Make sure the RPC service switches from one client to the other. self.assertIs(variables['the'].pkg.Service.Unary.channel, client_1_channel) variables['set_target'](info_2.client) self.assertIs(variables['the'].pkg.Service.Unary.channel, client_2_channel)
def console(device: str, baudrate: int, socket_addr: str, output: Any) -> int: """Starts an interactive RPC console for HDLC.""" # argparse.FileType doesn't correctly handle '-' for binary files. if output is sys.stdout: output = sys.stdout.buffer logfile = create_temp_log_file() pw_cli.log.install(logging.INFO, True, False, logfile) if socket_addr is None: serial_device = serial.Serial(device, baudrate, timeout=1) def read(): return serial_device.read(8192) write = serial_device.write else: try: socket_device = SocketClientImpl(socket_addr) read = socket_device.read write = socket_device.write except ValueError: _LOG.exception('Failed to initialize socket at %s', socket_addr) return 1 callback_client_impl = callback_client.Impl( default_unary_timeout_s=5.0, default_stream_timeout_s=None, ) _start_ipython_terminal( HdlcRpcClient(read, PROTOS, default_channels(write), lambda data: write_to_output(data, output), client_impl=callback_client_impl)) return 0
def _test_setup(output=None): protos = python_protos.Library.from_strings([TEST_PROTO_1, TEST_PROTO_2]) return protos, client.Client.from_modules(callback_client.Impl(), [client.Channel(1, output)], protos.modules())
def test_default_timeouts_set_on_impl(self): impl = callback_client.Impl(None, 1.5) self.assertEqual(impl.default_unary_timeout_s, None) self.assertEqual(impl.default_stream_timeout_s, 1.5)