def _handle_exception(self, _: BaseException) -> None: t, v, tb = sys.exc_info() stack = Traceback.extract(t, v, tb.tb_next.tb_next, show_locals=self.show_locals).stacks[0] self.console.print( f"[red bold]{stack.exc_type}: [/red bold]'{stack.exc_value}' on line {stack.frames[0].lineno}" ) if self.show_locals: _locals = stack.frames[0].locals self.console.print("Locals: ", end="") self.console.print( {k: _locals[k].value_repr for k in list(_locals)[17:]})
async def on_client_connected(self, reader: StreamReader, writer: StreamWriter): self.logger.debug('client connected') while True: # TODO: while active instead raw_command = await reader.readline() if raw_command == b'': # TODO: not ideal, remove pooling if possible await asyncio.sleep(0.5) continue try: command = SymlServiceCommand.parse(raw_command) logging.debug("received command %s", command) callable_command = getattr(self, f'cmd_{command.name}') cmd_arg = get_type_hints(callable_command).get('cmd') if cmd_arg: args_type = get_args(cmd_arg)[0] command.args = args_type(**command.args) # TODO: handle generators try: response: SymlServiceResponse if cmd_arg: response = await callable_command(command) else: response = await callable_command() except Exception as e: exc_type, exc_value, traceback = sys.exc_info() tb = Traceback() trace = tb.extract(exc_type, exc_value, traceback, show_locals=False) trace = [dataclasses.asdict(s) for s in trace.stacks] trace = [{ **t, 'frames': t.get('frames')[1:] } for t in trace] response = SymlServiceResponse( data=dict(), errors=[ dict(message="unhandled exception while " "processing command (${exception})", exception=e, trace=trace) ]) response.command = command writer.write(response.jsonb()) writer.write('\n'.encode()) logging.debug("sending response %s", response) await writer.drain() except Exception as e: self.logger.exception("oh no", e)