Ejemplo n.º 1
0
def _feed_cli_with_input(text, editing_mode=EditingMode.EMACS, clipboard=None,
                         history=None):
    """
    Create a CommandLineInterface, feed it with the given user input and return
    the CLI object.

    This returns a (result, CLI) tuple.
    """
    # If the given text doesn't end with a newline, the interface won't finish.
    assert text.endswith('\n')

    loop = PosixEventLoop()
    try:
        inp = PipeInput()
        inp.send_text(text)
        cli = CommandLineInterface(
            application=Application(
                buffer=Buffer(accept_action=AcceptAction.RETURN_DOCUMENT,
                              history=history),
                editing_mode=editing_mode,
                clipboard=clipboard or InMemoryClipboard(),
                key_bindings_registry=KeyBindingManager.for_prompt().registry,
            ),
            eventloop=loop,
            input=inp,
            output=DummyOutput())
        result = cli.run()
        return result, cli
    finally:
        loop.close()
        inp.close()
Ejemplo n.º 2
0
 def setUp(self):
     self.input = PipeInput()
     output = DummyOutput()
     self.aws_shell = AWSShell(None,
                               mock.Mock(),
                               mock.Mock(),
                               input=self.input,
                               output=output)
     self.processor = self.aws_shell.cli.input_processor
class KeyBindingsTest(unittest.TestCase):
    def init(self):
        self.input = PipeInput()
        output = DummyOutput()
        # self.shell = Shell(input=self.input, output=output)
        self.processor = InputProcessor

    def tearDown(self):
        self.input.close()
Ejemplo n.º 4
0
class KeysTest(unittest.TestCase):
    def setUp(self):
        self.input = PipeInput()
        output = DummyOutput()
        self.aws_shell = AWSShell(None,
                                  mock.Mock(),
                                  mock.Mock(),
                                  input=self.input,
                                  output=output)
        self.processor = self.aws_shell.cli.input_processor

    def tearDown(self):
        self.input.close()

    def feed_key(self, key):
        self.processor.feed(KeyPress(key, u''))
        self.processor.process_keys()

    def test_F2(self):
        match_fuzzy = self.aws_shell.model_completer.match_fuzzy
        self.feed_key(Keys.F2)
        assert match_fuzzy != self.aws_shell.model_completer.match_fuzzy

    def test_F3(self):
        enable_vi_bindings = self.aws_shell.enable_vi_bindings
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F3)
        assert enable_vi_bindings != self.aws_shell.enable_vi_bindings

    def test_F4(self):
        show_completion_columns = self.aws_shell.show_completion_columns
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F4)
        assert show_completion_columns != \
            self.aws_shell.show_completion_columns

    def test_F5(self):
        show_help = self.aws_shell.show_help
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F5)
        assert show_help != self.aws_shell.show_help

    def test_F9(self):
        assert self.aws_shell.cli.current_buffer_name == u'DEFAULT_BUFFER'
        self.feed_key(Keys.F9)
        assert self.aws_shell.cli.current_buffer_name == u'clidocs'

    def test_F10(self):
        self.feed_key(Keys.F10)
        assert self.aws_shell.cli.is_exiting
Ejemplo n.º 5
0
    def run_server(self):
        # Ignore keyboard. (When people run "pymux server" and press Ctrl-C.)
        # Pymux has to be terminated by termining all the processes running in
        # its panes.
        def handle_sigint(*a):
            print('Ignoring keyboard interrupt.')

        signal.signal(signal.SIGINT, handle_sigint)

        # Run eventloop.

        # XXX: Both the PipeInput and DummyCallbacks are not used.
        #      This is a workaround to run the PosixEventLoop continuously
        #      without having a CommandLineInterface instance.
        #      A better API in prompt_toolkit is desired.
        try:
            self.eventloop.run(PipeInput(), DummyCallbacks())
        except:
            # When something bad happens, always dump the traceback.
            # (Otherwise, when running as a daemon, and stdout/stderr are not
            # available, it's hard to see what went wrong.)
            fd, path = tempfile.mkstemp(prefix='pymux.crash-')
            logger.fatal(
                'Pymux has crashed, dumping traceback to {0}'.format(path))
            os.write(fd, traceback.format_exc().encode('utf-8'))
            os.close(fd)
            raise

        # Clean up socket.
        os.remove(self.socket_name)
Ejemplo n.º 6
0
class KeysTest(unittest.TestCase):

    def setUp(self):
        self.input = PipeInput()
        output = DummyOutput()
        self.aws_shell = AWSShell(None, mock.Mock(), mock.Mock(),
                                  input=self.input, output=output)
        self.processor = self.aws_shell.cli.input_processor

    def tearDown(self):
        self.input.close()

    def feed_key(self, key):
        self.processor.feed(KeyPress(key, u''))
        self.processor.process_keys()

    def test_F2(self):
        match_fuzzy = self.aws_shell.model_completer.match_fuzzy
        self.feed_key(Keys.F2)
        assert match_fuzzy != self.aws_shell.model_completer.match_fuzzy

    def test_F3(self):
        enable_vi_bindings = self.aws_shell.enable_vi_bindings
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F3)
            assert enable_vi_bindings != self.aws_shell.enable_vi_bindings

    def test_F4(self):
        show_completion_columns = self.aws_shell.show_completion_columns
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F4)
            assert show_completion_columns != \
                self.aws_shell.show_completion_columns

    def test_F5(self):
        show_help = self.aws_shell.show_help
        with self.assertRaises(InputInterrupt):
            self.feed_key(Keys.F5)
            assert show_help != self.aws_shell.show_help

    def test_F10(self):
        self.feed_key(Keys.F10)
        assert self.aws_shell.cli.is_exiting
Ejemplo n.º 7
0
    def __init__(self, get_globals, get_locals=None):
        assert callable(get_globals)
        assert get_locals is None or callable(get_locals)

        self._chan = None

        def _globals():
            data = get_globals()
            data.setdefault('print', self._print)
            return data

        repl = PythonRepl(get_globals=_globals,
                          get_locals=get_locals or _globals)

        # 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.
        repl.enable_open_in_editor = False
        repl.enable_system_bindings = False

        # 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 = PipeInput()

        # Output object. Don't render to the real stdout, but write everything
        # in the SSH channel.
        class Stdout(object):
            def write(s, data):
                if self._chan is not None:
                    self._chan.write(data.replace('\n', '\r\n'))

            def flush(s):
                pass

        # Create command line interface.
        self.cli = CommandLineInterface(application=repl.create_application(),
                                        eventloop=create_asyncio_eventloop(),
                                        input=self._input_pipe,
                                        output=Vt100_Output(
                                            Stdout(), self._get_size))

        self._callbacks = self.cli.create_eventloop_callbacks()
Ejemplo n.º 8
0
def feed_app_with_input(type, message, text, **kwargs):
    """
    Create a CommandLineInterface, feed it with the given user input and return
    the CLI object.

    This returns a (result, CLI) tuple.
    note: this only works if you import your prompt and then this function!!
    """
    # If the given text doesn't end with a newline, the interface won't finish.
    assert text.endswith('\n')

    application = getattr(prompts, type).question(message, **kwargs)

    loop = PosixEventLoop()
    try:
        inp = PipeInput()
        inp.send_text(text)
        cli = CommandLineInterface(
            application=application,
            eventloop=loop,
            input=inp,
            output=DummyOutput())
        result = cli.run()
        return result, cli
    finally:
        loop.close()
        inp.close()
Ejemplo n.º 9
0
def _feed_cli_with_input(text,
                         editing_mode=EditingMode.EMACS,
                         clipboard=None,
                         history=None):
    """
    Create a CommandLineInterface, feed it with the given user input and return
    the CLI object.

    This returns a (result, CLI) tuple.
    """
    # If the given text doesn't end with a newline, the interface won't finish.
    assert text.endswith('\n')

    from prompt_toolkit.eventloop.posix import PosixEventLoop as EventLoop
    loop = EventLoop()
    try:
        inp = PipeInput()
        inp.send_text(text)
        cli = CommandLineInterface(application=Application(
            buffer=Buffer(accept_action=AcceptAction.RETURN_DOCUMENT,
                          history=history),
            editing_mode=editing_mode,
            clipboard=clipboard or InMemoryClipboard(),
            key_bindings_registry=KeyBindingManager.for_prompt().registry,
        ),
                                   eventloop=loop,
                                   input=inp,
                                   output=DummyOutput())
        result = cli.run()
        return result, cli
    finally:
        loop.close()
        inp.close()
Ejemplo n.º 10
0
    def __init__(self, get_globals, get_locals=None):
        assert callable(get_globals)
        assert get_locals is None or callable(get_locals)

        self._chan = None

        def _globals():
            data = get_globals()
            data.setdefault('print', self._print)
            return data

        repl = PythonRepl(get_globals=_globals,
                          get_locals=get_locals or _globals)

        # 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.
        repl.enable_open_in_editor = False
        repl.enable_system_bindings = False

        # 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 = PipeInput()

        # Output object. Don't render to the real stdout, but write everything
        # in the SSH channel.
        class Stdout(object):

            def write(s, data):
                if self._chan is not None:
                    self._chan.write(data.replace('\n', '\r\n'))

            def flush(s):
                pass

        # Create command line interface.
        self.cli = CommandLineInterface(
            application=repl.create_application(),
            eventloop=create_asyncio_eventloop(),
            input=self._input_pipe,
            output=Vt100_Output(Stdout(), self._get_size))

        self._callbacks = self.cli.create_eventloop_callbacks()
Ejemplo n.º 11
0
def _feed_cli_with_input(text, editing_mode=EditingMode.EMACS):
    """
    Create a CommandLineInterface, feed it with the given user input and return
    the CLI object.

    This returns a (result, CLI) tuple.
    """
    # If the given text doesn't end with a newline, the interface won't finish.
    assert text.endswith('\n')

    loop = PosixEventLoop()
    try:
        inp = PipeInput()
        inp.send_text(text)
        cli = CommandLineInterface(
            application=Application(editing_mode=editing_mode),
            eventloop=loop,
            input=inp,
            output=DummyOutput())
        result = cli.run()
        return result, cli
    finally:
        loop.close()
        inp.close()
Ejemplo n.º 12
0
class ReplSSHServerSession(asyncssh.SSHServerSession):

    """
    SSH server session that runs a Python REPL.

    :param get_globals: callable that returns the current globals.
    :param get_locals: (optional) callable that returns the current locals.
    """

    def __init__(self, get_globals, get_locals=None):
        assert callable(get_globals)
        assert get_locals is None or callable(get_locals)

        self._chan = None

        def _globals():
            data = get_globals()
            data.setdefault('print', self._print)
            return data

        repl = PythonRepl(get_globals=_globals,
                          get_locals=get_locals or _globals)

        # 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.
        repl.enable_open_in_editor = False
        repl.enable_system_bindings = False

        # 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 = PipeInput()

        # Output object. Don't render to the real stdout, but write everything
        # in the SSH channel.
        class Stdout(object):

            def write(s, data):
                if self._chan is not None:
                    self._chan.write(data.replace('\n', '\r\n'))

            def flush(s):
                pass

        # Create command line interface.
        self.cli = CommandLineInterface(
            application=repl.create_application(),
            eventloop=create_asyncio_eventloop(),
            input=self._input_pipe,
            output=Vt100_Output(Stdout(), self._get_size))

        self._callbacks = self.cli.create_eventloop_callbacks()

    def _get_size(self):
        """
        Callable that returns the current `Size`, required by Vt100_Output.
        """
        if self._chan is None:
            return Size(rows=20, columns=79)
        else:
            width, height, pixwidth, pixheight = self._chan.get_terminal_size()
            return Size(rows=height, columns=width)

    def connection_made(self, chan):
        """
        Client connected, run repl in coroutine.
        """
        self._chan = chan

        # Run REPL interface.
        f = asyncio.async(self.cli.run_async())

        # Close channel when done.
        def done(_):
            chan.close()
            self._chan = None
        f.add_done_callback(done)

    def shell_requested(self):
        return True

    def terminal_size_changed(self, width, height, pixwidth, pixheight):
        """
        When the terminal size changes, report back to CLI.
        """
        self._callbacks.terminal_size_changed()

    def data_received(self, data, datatype):
        """
        When data is received, send to inputstream of the CLI and repaint.
        """
        self._input_pipe.send(data)

    def _print(self, *data, **kw):
        """
        _print(self, *data, sep=' ', end='\n', file=None)

        Alternative 'print' function that prints back into the SSH channel.
        """
        # Pop keyword-only arguments. (We cannot use the syntax from the
        # signature. Otherwise, Python2 will give a syntax error message when
        # installing.)
        sep = kw.pop('sep', ' ')
        end = kw.pop('end', '\n')
        file = kw.pop('end', None)
        assert not kw, 'Too many keyword-only arguments'

        data = sep.join(map(str, data))
        self._chan.write(data + end)
 def init(self):
     self.input = PipeInput()
     output = DummyOutput()
     # self.shell = Shell(input=self.input, output=output)
     self.processor = InputProcessor
Ejemplo n.º 14
0
 def setUp(self):
     self.input = PipeInput()
     output = DummyOutput()
     self.aws_shell = AWSShell(None, mock.Mock(), mock.Mock(),
                               input=self.input, output=output)
     self.processor = self.aws_shell.cli.input_processor
Ejemplo n.º 15
0
class ReplSSHServerSession(asyncssh.SSHServerSession):
    """
    SSH server session that runs a Python REPL.

    :param get_globals: callable that returns the current globals.
    :param get_locals: (optional) callable that returns the current locals.
    """
    def __init__(self, get_globals, get_locals=None):
        assert callable(get_globals)
        assert get_locals is None or callable(get_locals)

        self._chan = None

        def _globals():
            data = get_globals()
            data.setdefault('print', self._print)
            return data

        repl = PythonRepl(get_globals=_globals,
                          get_locals=get_locals or _globals)

        # 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.
        repl.enable_open_in_editor = False
        repl.enable_system_bindings = False

        # 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 = PipeInput()

        # Output object. Don't render to the real stdout, but write everything
        # in the SSH channel.
        class Stdout(object):
            def write(s, data):
                if self._chan is not None:
                    self._chan.write(data.replace('\n', '\r\n'))

            def flush(s):
                pass

        # Create command line interface.
        self.cli = CommandLineInterface(application=repl.create_application(),
                                        eventloop=create_asyncio_eventloop(),
                                        input=self._input_pipe,
                                        output=Vt100_Output(
                                            Stdout(), self._get_size))

        self._callbacks = self.cli.create_eventloop_callbacks()

    def _get_size(self):
        """
        Callable that returns the current `Size`, required by Vt100_Output.
        """
        if self._chan is None:
            return Size(rows=20, columns=79)
        else:
            width, height, pixwidth, pixheight = self._chan.get_terminal_size()
            return Size(rows=height, columns=width)

    def connection_made(self, chan):
        """
        Client connected, run repl in coroutine.
        """
        self._chan = chan

        # Run REPL interface.
        f = asyncio.ensure_future(self.cli.run_async())

        # Close channel when done.
        def done(_):
            chan.close()
            self._chan = None

        f.add_done_callback(done)

    def shell_requested(self):
        return True

    def terminal_size_changed(self, width, height, pixwidth, pixheight):
        """
        When the terminal size changes, report back to CLI.
        """
        self._callbacks.terminal_size_changed()

    def data_received(self, data, datatype):
        """
        When data is received, send to inputstream of the CLI and repaint.
        """
        self._input_pipe.send(data)

    def _print(self, *data, **kw):
        """
        _print(self, *data, sep=' ', end='\n', file=None)

        Alternative 'print' function that prints back into the SSH channel.
        """
        # Pop keyword-only arguments. (We cannot use the syntax from the
        # signature. Otherwise, Python2 will give a syntax error message when
        # installing.)
        sep = kw.pop('sep', ' ')
        end = kw.pop('end', '\n')
        _ = kw.pop('file', None)
        assert not kw, 'Too many keyword-only arguments'

        data = sep.join(map(str, data))
        self._chan.write(data + end)