def mock_prompt_input(): # TODO: remove if prompt-toolkit min version gets bumped if PIPE_INPUT_CONTEXT_MANAGER: with create_pipe_input() as pipe_input: with create_app_session(input=pipe_input, output=DummyOutput()): yield pipe_input else: pipe_input = create_pipe_input() try: with create_app_session(input=pipe_input, output=DummyOutput()): yield pipe_input finally: pipe_input.close()
def test_cli_argument(): arguments = ['ws-ui'] with patch.object(sys, 'argv', arguments): with create_app_session(input=create_pipe_input(), output=DummyOutput()): app = Application() asyncio.run(app.main())
async def _interact(self) -> None: if self._chan is None: # Should not happen. raise Exception("`_interact` called before `connection_made`.") if hasattr(self._chan, "set_line_mode") and self._chan._editor is not None: # Disable the line editing provided by asyncssh. Prompt_toolkit # provides the line editing. self._chan.set_line_mode(False) term = self._chan.get_terminal_type() self._output = Vt100_Output(self.stdout, self._get_size, term=term, write_binary=False) with create_pipe_input() as self._input: with create_app_session(input=self._input, output=self._output) as session: self.app_session = session try: await self.interact(self) except BaseException: traceback.print_exc() finally: # Close the connection. self._chan.close() self._input.close()
def __init__( self, interact: Callable[["PromptToolkitSSHSession"], Awaitable[None]]) -> None: self.interact = interact self._chan = None self.app_session: Optional[AppSession] = None # PipInput object, for sending input in the CLI. # (This is something that we can use in the prompt_toolkit event loop, # but still write date in manually.) self._input = create_pipe_input() self._output = None # Output object. Don't render to the real stdout, but write everything # in the SSH channel. class Stdout: def write(s, data): if self._chan is not None: self._chan.write(data.replace("\n", "\r\n")) def flush(s): pass @property def encoding(s): return self._chan._orig_chan.get_encoding()[0] self.stdout = cast(TextIO, Stdout())
def app(): pipe_input = create_pipe_input() try: with create_app_session(input=pipe_input, output=DummyOutput()): config = Config() app = App(config=config) yield app finally: pipe_input.close()
def mock_input() -> Generator[MockInput, None, None]: with create_pipe_input() as pipe_input: with create_app_session(input=pipe_input): def factory( input_sequence: Sequence[str]) -> None: # noqa: WPS 430 pipe_input.send_text("".join(input_sequence)) yield factory
def __init__( self, conn: socket.socket, addr: Tuple[str, int], interact: Callable[["TelnetConnection"], Awaitable[None]], server: "TelnetServer", encoding: str, style: Optional[BaseStyle], ) -> None: self.conn = conn self.addr = addr self.interact = interact self.server = server self.encoding = encoding self.style = style self._closed = False self._ready = asyncio.Event() self.vt100_output = None # Create "Output" object. self.size = Size(rows=40, columns=79) # Initialize. _initialize_telnet(conn) # Create input. self.vt100_input = create_pipe_input() # Create output. def get_size() -> Size: return self.size self.stdout = cast(TextIO, _ConnectionStdout(conn, encoding=encoding)) def data_received(data: bytes) -> None: """ TelnetProtocolParser 'data_received' callback """ self.vt100_input.send_bytes(data) def size_received(rows: int, columns: int) -> None: """ TelnetProtocolParser 'size_received' callback """ self.size = Size(rows=rows, columns=columns) if self.vt100_output is not None: get_app()._on_resize() def ttype_received(ttype: str) -> None: """ TelnetProtocolParser 'ttype_received' callback """ self.vt100_output = Vt100_Output(self.stdout, get_size, term=ttype, write_binary=False) self._ready.set() self.parser = TelnetProtocolParser(data_received, size_received, ttype_received) self.context: Optional[contextvars.Context] = None
def test_layout(self): input = create_pipe_input() with create_app_session(input=input, output=DummyOutput()): tui = TerminalUI() layout = tui.app.layout assert len(list(layout.find_all_windows())) > 1 children = layout.container.get_children() assert len(children) == 2 assert len(children[0].get_children()) == 2
def mock_input(): pipe_input = create_pipe_input() try: with create_app_session( input=pipe_input, output=DummyOutput(), ): yield pipe_input finally: pipe_input.close()
def mock_app(mocker): app = Application( input=create_pipe_input(), output=DummyOutput(), ) mocker.patch('upsies.uis.tui.tui.TUI._make_app', Mock(return_value=app)) mocker.patch('upsies.uis.tui.tui.TUI._jobs_container', Mock(children=[]), create=True) mocker.patch('upsies.uis.tui.tui.TUI._layout', Mock(), create=True)
def prompt(monkeypatch): monkeypatch.setattr('getpass.getpass', lambda _: 'mock_password') pipe = create_pipe_input() try: session = PromptSession( input=pipe, output=DummyOutput(), ) yield Prompt(session, pipe) finally: pipe.close()
def ptk_shell(xonsh_execer): from prompt_toolkit.input import create_pipe_input from prompt_toolkit.output import DummyOutput from xonsh.ptk_shell.shell import PromptToolkitShell inp = create_pipe_input() out = DummyOutput() shell = PromptToolkitShell( execer=xonsh_execer, ctx={}, ptk_args={"input": inp, "output": out} ) yield inp, out, shell inp.close()
def test_completer(self): text = 'server \t\r' inp = create_pipe_input() try: inp.send_text(text) session = PromptSession( input=inp, output=DummyOutput(), editing_mode=EditingMode.VI, completer=DshellCompleter.from_nested_dict(nested_dict)) result = session.prompt() finally: inp.close()
def __init__(self, get_globals: _GetNamespace, get_locals: Optional[_GetNamespace] = None) -> None: self._chan = None def _globals() -> dict: data = get_globals() data.setdefault("print", self._print) return data # PipInput object, for sending input in the CLI. # (This is something that we can use in the prompt_toolkit event loop, # but still write date in manually.) self._input_pipe = create_pipe_input() # Output object. Don't render to the real stdout, but write everything # in the SSH channel. class Stdout: def write(s, data: str) -> None: if self._chan is not None: data = data.replace("\n", "\r\n") self._chan.write(data) def flush(s) -> None: pass self.repl = PythonRepl( get_globals=_globals, get_locals=get_locals or _globals, input=self._input_pipe, output=Vt100_Output(cast(TextIO, Stdout()), self._get_size), ) # Disable open-in-editor and system prompt. Because it would run and # display these commands on the server side, rather than in the SSH # client. self.repl.enable_open_in_editor = False self.repl.enable_system_bindings = False
async def run() -> None: try: with create_pipe_input() as vt100_input: connection = TelnetConnection( conn, addr, self.interact, self, encoding=self.encoding, style=self.style, vt100_input=vt100_input, ) self.connections.add(connection) logger.info("Starting interaction %r %r", *addr) try: await connection.run_application() finally: self.connections.remove(connection) logger.info("Stopping interaction %r %r", *addr) except EOFError: # Happens either when the connection is closed by the client # (e.g., when the user types 'control-]', then 'quit' in the # telnet client) or when the user types control-d in a prompt # and this is not handled by the interact function. logger.info("Unhandled EOFError in telnet application.") except KeyboardInterrupt: # Unhandled control-c propagated by a prompt. logger.info( "Unhandled KeyboardInterrupt in telnet application.") except BaseException as e: print("Got %s" % type(e).__name__, e) import traceback traceback.print_exc() finally: self._application_tasks.remove(task)
def _feed_cli_with_input( text, editing_mode=None, clipboard=None, history=None, multiline=False, check_line_ending=True, key_bindings=None, ): """ Create a Prompt, feed it with the given user input and return the CLI object. This returns a (result, Application) tuple. """ # If the given text doesn't end with a newline, the interface won't finish. if check_line_ending: assert text.endswith("\r") inp = create_pipe_input() try: inp.send_text(text) session = PromptSession( input=inp, output=DummyOutput(), editing_mode=editing_mode, history=history, multiline=multiline, clipboard=clipboard, key_bindings=key_bindings, ) result = session.prompt() return session.default_buffer.document, session.app finally: inp.close()
def __init__( self, interact: Callable[["PromptToolkitSSHSession"], Awaitable[None]]) -> None: self.interact = interact self.interact_task: Optional[asyncio.Task[None]] = None self._chan: Optional[Any] = None self.app_session: Optional[AppSession] = None # PipInput object, for sending input in the CLI. # (This is something that we can use in the prompt_toolkit event loop, # but still write date in manually.) self._input = create_pipe_input() self._output: Optional[Vt100_Output] = None # Output object. Don't render to the real stdout, but write everything # in the SSH channel. class Stdout: def write(s, data: str) -> None: try: if self._chan is not None: self._chan.write(data.replace("\n", "\r\n")) except BrokenPipeError: pass # Channel not open for sending. def isatty(s) -> bool: return True def flush(s) -> None: pass @property def encoding(s) -> str: assert self._chan is not None return str(self._chan._orig_chan.get_encoding()[0]) self.stdout = cast(TextIO, Stdout())
def setUp(self): self.inp = create_pipe_input()
def _enter_tree(self): self.input = create_pipe_input()