示例#1
0
def _repl(templates: list[typer.FileText] = configurator.templates,
          macro: list[str] = configurator.macro,
          target: Optional[str] = configurator.to,
          repl_name: Optional[str] = typer.Option('',
                                                  '--repl',
                                                  help='Name of repl'),
          separator: Optional[str] = typer.Option(
              '', '--sep', help='Input prompt including spaces')):
    if not is_repl_install:
        raise Exception("requires pexpect, ptpython\n"
                        "\trun 'python -m pip install kithon[repl]' to fix")
    prompt = PythonInput()
    transpiler = Transpiler()
    configurator.conf(transpiler, target, macro, templates)
    repl = pexpect.spawn(repl_name
                         or transpiler.templates['meta']['repl']['name'])
    sep = separator or transpiler.templates['meta']['repl']['separator']
    repl.expect(sep)
    code = ''
    while 1:
        src = prompt.app.run()
        if src.strip() == 'vars':
            pprint.pprint(transpiler.variables)
            continue
        if src.strip() == 'code':
            print(code)
            continue
        code = transpiler.generate(src, mode='block')
        repl.sendline(code)
        repl.expect(sep)
        print('\n'.join(
            repl.before.decode('utf-8').split('\n')[len(code.split('\n')):-1]))
示例#2
0
def main():
    locals_ = {}
    globals_ = globalenv
    eventloop = create_eventloop()
    try:
        python_input = PythonInput(get_globals=lambda: globals_,
                                   get_locals=lambda: locals_,
                                   history_filename=".sevalhist",
                                   _completer=BodgedPythonCompleter(
                                       lambda: locals_, lambda: globals_))
        cli = PythonCommandLineInterface(eventloop=eventloop,
                                         python_input=python_input)
        while 1:
            python_code = cli.run()
            if python_code.text == "exit":
                break
            try:
                result, env = parse_string(locals_, python_code.text)
                for x in result:
                    print(repr(x))
            except Exception as e:
                _handle_exception(cli=cli,
                                  e=e,
                                  style=python_input._current_style)
    except EOFError:
        pass
    finally:
        eventloop.close()
示例#3
0
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self._cli_history = FileHistory(os.path.expanduser('~/.ptpdb_history'))

        self.completer = None
        self.validator = None

        self.python_input = PythonInput(
                get_locals=lambda: self.curframe.f_locals,
                get_globals=lambda: self.curframe.f_globals,
                _completer=DynamicCompleter(lambda: self.completer),
                _validator=DynamicValidator(lambda: self.validator),
                _python_prompt_control=PdbLeftMargin(self._get_current_pdb_commands()),
                _extra_buffers={'source_code': Buffer()},
                _extra_buffer_processors=[CompletionHint()],
                _extra_sidebars=[
                    HSplit([
                        FileLocationToolbar(weakref.ref(self)),
                        ConditionalContainer(
                            Window(
                                BufferControl(
                                    buffer_name='source_code',
                                    lexer=PythonLexer,
                                ),
                            ),
                            filter=~IsDone()),
                        PdbShortcutsToolbar(weakref.ref(self)),
                    ]),
                ],
        )

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.python_input.complete_while_typing = False

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())
示例#4
0
def main():
    prompt = PythonInput(vi_mode=True)

    while True:
        try:
            text = prompt.app.run()
        except KeyboardInterrupt:
            continue
        except EOFError:
            break
        else:
            is_statement = False
            try:
                code = compile(text, '<stdin>', 'eval')
            except SyntaxError:
                is_statement = True
                code = compile(text, '<stdin>', 'exec')

            if is_statement:
                send(text)
            else:
                send_prefix('/eval', text)

    print("goodbye")
示例#5
0
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(
            BufferControl(
                buffer_name='source_code',
                lexer=PygmentsLexer(PythonLexer),
                input_processors=[
                    HighlightSearchProcessor(preview_search=True),
                    HighlightSelectionProcessor(),
                ],
            ),
            left_margins=[
                SourceCodeMargin(self),
                NumberredMargin(),
            ],
            right_margins=[ScrollbarMargin()],
            scroll_offsets=ScrollOffsets(top=2, bottom=2),
            height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
                    lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action = self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(
                    processor=CompletionHint(),
                    filter=~IsDone())
                ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0, bottom=0,
                                          content=BreakPointInfoToolbar(weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl('\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502', token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2, bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(
                    PdbShortcutsToolbar(weakref.ref(self)),
                    show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self, self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())
示例#6
0
class PtPdb(pdb.Pdb):
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(
            BufferControl(
                buffer_name='source_code',
                lexer=PygmentsLexer(PythonLexer),
                input_processors=[
                    HighlightSearchProcessor(preview_search=True),
                    HighlightSelectionProcessor(),
                ],
            ),
            left_margins=[
                SourceCodeMargin(self),
                NumberredMargin(),
            ],
            right_margins=[ScrollbarMargin()],
            scroll_offsets=ScrollOffsets(top=2, bottom=2),
            height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
                    lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action = self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(
                    processor=CompletionHint(),
                    filter=~IsDone())
                ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0, bottom=0,
                                          content=BreakPointInfoToolbar(weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl('\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502', token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2, bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(
                    PdbShortcutsToolbar(weakref.ref(self)),
                    show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self, self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())

    def _create_accept_action(self):
        """
        Create an AcceptAction for the input buffer that replaces shortcuts
        like 's' with the full command ('step') before returning it.
        """
        def handler(cli, buffer):
            # Get first part.
            parts = buffer.text.strip().split(None, 1)
            if len(parts) == 0:
                first, rest = '', ''
            elif len(parts) == 1:
                first, rest = parts[0], ''
            else:
                first, rest = parts

            # Replace text in buffer and return it.
            buffer.document = Document(shortcuts.get(first, first) + ' ' + rest)
            cli.set_return_value(buffer.document)
        return AcceptAction(handler)

    def cmdloop(self, intro=None):
        """
        Copy/Paste of pdb.Pdb.cmdloop. But using our own CommandLineInterface
        for reading input instead.
        """
        self.preloop()

        if intro is not None:
            self.intro = intro
        if self.intro:
            self.stdout.write(str(self.intro)+"\n")
        stop = None
        while not stop:
            if self.cmdqueue:
                line = self.cmdqueue.pop(0)
            else:
                if self.use_rawinput:
                    line = self._get_input()

            line = self.precmd(line)
            stop = self.onecmd(line)
            stop = self.postcmd(stop, line)
        self.postloop()

    def _get_current_pdb_commands(self):
        return (
            list(commands_with_help.keys()) +
            list(shortcuts.keys()) +
            list(self.aliases.keys()))

    def _create_grammar(self):
        """
        Return the compiled grammar for this PDB shell.

        The grammar of PDB depends on the available list of PDB commands (which
        depends on the currently defined aliases.) Therefor we generate a new
        grammar when it changes, but cache it otherwise. (It's still expensive
        to compile.)
        """
        pdb_commands = self._get_current_pdb_commands()

        if self._grammar_cache is None or self._grammar_cache[0] != pdb_commands:
            self._grammar_cache = [
                pdb_commands,
                create_pdb_grammar(pdb_commands)]

        return self._grammar_cache[1]

    def _get_input(self):
        """
        Read PDB input. Return input text.
        """
        # Reset multiline/paste mode every time.
        self.python_input.paste_mode = False
        self.python_input.currently_multiline = False

        # Set source code document.
        self._show_source_code(self.curframe.f_code.co_filename)

        self.cli.buffers[DEFAULT_BUFFER].document = Document('')

        # Select the current frame of the stack.
        for i, (frame, lineno) in enumerate(self.stack):
            if frame is self.curframe:
                self.callstack_selected_frame = i
                break

        # Set up a new completer and validator for the new grammar.
        g = self._create_grammar()

        self.completer = GrammarCompleter(g, completers={
            'enabled_breakpoint': BreakPointListCompleter(only_enabled=True),
            'disabled_breakpoint': BreakPointListCompleter(only_disabled=True),
            'alias_name': AliasCompleter(self),
            'python_code': PythonCompleter(lambda: self.curframe.f_globals, lambda: self.curframe.f_locals),
            'breakpoint': BreakPointListCompleter(),
            'pdb_command': PdbCommandsCompleter(self),
            'python_file': PythonFileCompleter(),
            'python_function': PythonFunctionCompleter(self),
        })
        self.validator = GrammarValidator(g, {
            'python_code': PythonValidator()
        })

        # Make sure not to start in Vi navigation mode.
        self.python_input.key_bindings_manager.reset(self.cli)
        self.cli.buffers[DEFAULT_BUFFER].reset()

        def pre_run():
            self._source_code_window.vertical_scroll = 100000 # source_code_doc.line_count

        try:
            return self.cli.run(reset_current_buffer=False, pre_run=pre_run).text
        except EOFError:
            # Turn Control-D key press into a 'quit' command.
            return 'quit'

    def _show_source_code(self, filename):
        """
        Show the source code in the `source_code` buffer.
        """
        source_code_doc = self._get_source_code_document(filename)
        self.cli.buffers['source_code']._set_text(source_code_doc.text + '\n')
        self.cli.buffers['source_code']._set_cursor_position(source_code_doc.cursor_position)

    def _get_source_code_document(self, filename):
        """
        Return source code around current line as string.
        """
        source_code = linecache.getlines(filename)
        if six.PY2:
            source_code = [l.decode('utf-8') for l in source_code]

        source_code = ''.join(source_code)
        document = Document(source_code)

        return Document(document.text, document.translate_row_col_to_index(
            row=self.curframe.f_lineno - 1, col=0))

    #
    # Methods overriden from Pdb, in order to add highlighting.
    #

    def postcmd(self, stop, line):
        """
        Override 'postcmd': (Insert whitespace.)
        """
        print('')
        return pdb.Pdb.postcmd(self, stop, line)

    def preloop(self):
        print('')
        return pdb.Pdb.preloop(self)

    def do_interact(self, args):
        """
        Interact: start interpreter.
        (Override the 'pdb' implementation. We call ptpython instead.)
        """
        print('')
        ns = self.curframe.f_globals.copy()
        ns.update(self.curframe_locals)
        embed(globals=ns)

    def error(self, msg):
        """
        Override default error handler from PDB.
        """
        self.cli.print_tokens([
            (Token.Pdb.Error, '  %s  \n' % msg)
        ])

    def print_stack_entry(self, frame_lineno, prompt_prefix=': '):
        """
        Override `print_stack_entry` of Pdb, in order to add highlighting.
        """
        frame, lineno = frame_lineno

        tokens = []
        tokens.extend(format_stack_entry(self, frame, lineno))
        tokens.append((Token, '\n'))

        self.cli.print_tokens(tokens)

    def do_list(self, arg):
        """
        Override `Pdb.do_list`: Add highlighting.
        """
        self.lastcmd = 'list'
        last = None
        if arg and arg != '.':
            try:
                if ',' in arg:
                    first, last = arg.split(',')
                    first = int(first.strip())
                    last = int(last.strip())
                    if last < first:
                        # assume it's a count
                        last = first + last
                else:
                    first = int(arg.strip())
                    first = max(1, first - 5)
            except ValueError:
                self.error('Error in argument: %r' % arg)
                return
        elif self.lineno is None or arg == '.':
            first = max(1, self.curframe.f_lineno - 5)
        else:
            first = self.lineno + 1
        if last is None:
            last = first + 10
        filename = self.curframe.f_code.co_filename
        breaklist = self.get_file_breaks(filename)
        try:
            lines = linecache.getlines(filename, self.curframe.f_globals)
            self._print_lines_2(lines, first, last, breaklist,
                              self.curframe)
            self.lineno = min(last, len(lines))
            if len(lines) < last:
                self.message('[EOF]')
        except KeyboardInterrupt:
            pass
    do_l = do_list

    def _print_lines_2(self, lines, start, end, breaks=(), frame=None):
        """
        Similar to `Pdb._print_lines`, except that this takes all the lines
        of the given file as input, it uses Pygments for the highlighting,
        it does slicing, and it prints everything in color.
        """
        if frame:
            current_lineno = frame.f_lineno
        else:
            current_lineno = exc_lineno = -1

        # Highlight everything. (Highlighting works much better from the
        # beginning of the file.)
        all_tokens = python_lexer.get_tokens(''.join(lines))

        # Slice lines.
        lines = list(split_lines(all_tokens))[start-1:end]

        # Add left margin. (Numbers + 'B' or '->'.)
        def add_margin(lineno, tokens):
            is_break = lineno in breaks
            is_current_line = lineno == current_lineno

            return get_line_prefix_tokens(is_break, is_current_line) \
                + [(Token.LineNumber, str(lineno).rjust(3) + ' ')] \
                + tokens + [(Token, '\n')]

        lines = [add_margin(i + start, tokens) for i, tokens in enumerate(lines)]

        for l in lines:
            self.cli.print_tokens(l)

    def message(self, msg):
        """ Print message to stdout. This function is present in Pdb for
        Python3, but not in Python2. """
        print(msg, file=self.stdout)
示例#7
0
文件: __init__.py 项目: sjas/ptpdb
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(BufferControl(
            buffer_name='source_code',
            lexer=PygmentsLexer(PythonLexer),
            input_processors=[
                HighlightSearchProcessor(preview_search=True),
                HighlightSelectionProcessor(),
            ],
        ),
                                          left_margins=[
                                              SourceCodeMargin(self),
                                              NumberredMargin(),
                                          ],
                                          right_margins=[ScrollbarMargin()],
                                          scroll_offsets=ScrollOffsets(
                                              top=2, bottom=2),
                                          height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
            lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action=self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(processor=CompletionHint(),
                                     filter=~IsDone())
            ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0,
                                          bottom=0,
                                          content=BreakPointInfoToolbar(
                                              weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl(
                                       '\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502',
                                                       token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2,
                                                                bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(PdbShortcutsToolbar(weakref.ref(self)),
                                     show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(
            self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self,
                                     self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())
示例#8
0
文件: __init__.py 项目: sjas/ptpdb
class PtPdb(pdb.Pdb):
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self.completer = None
        self.validator = None
        self.lexer = None

        self._source_code_window = Window(BufferControl(
            buffer_name='source_code',
            lexer=PygmentsLexer(PythonLexer),
            input_processors=[
                HighlightSearchProcessor(preview_search=True),
                HighlightSelectionProcessor(),
            ],
        ),
                                          left_margins=[
                                              SourceCodeMargin(self),
                                              NumberredMargin(),
                                          ],
                                          right_margins=[ScrollbarMargin()],
                                          scroll_offsets=ScrollOffsets(
                                              top=2, bottom=2),
                                          height=LayoutDimension(preferred=10))

        # Callstack window.
        callstack = CallStack(weakref.ref(self))
        self.callstack_focussed = False  # When True, show cursor there, and allow navigation through it.
        self.callstack_selected_frame = 0  # Top frame.

        show_pdb_content_filter = ~IsDone() & Condition(
            lambda cli: not self.python_input.show_exit_confirmation)

        self.python_input = PythonInput(
            get_locals=lambda: self.curframe.f_locals,
            get_globals=lambda: self.curframe.f_globals,
            _completer=DynamicCompleter(lambda: self.completer),
            _validator=DynamicValidator(lambda: self.validator),
            _accept_action=self._create_accept_action(),
            _extra_buffers={'source_code': Buffer(read_only=True)},
            _input_buffer_height=LayoutDimension(min=2, max=4),
            _lexer=PdbLexer(),
            _extra_buffer_processors=[
                ConditionalProcessor(processor=CompletionHint(),
                                     filter=~IsDone())
            ],
            _extra_layout_body=ConditionalContainer(
                HSplit([
                    VSplit([
                        HSplit([
                            SourceTitlebar(weakref.ref(self)),
                            FloatContainer(
                                content=self._source_code_window,
                                floats=[
                                    Float(right=0,
                                          bottom=0,
                                          content=BreakPointInfoToolbar(
                                              weakref.ref(self)))
                                ]),
                        ]),
                        HSplit([
                            Window(width=LayoutDimension.exact(1),
                                   height=LayoutDimension.exact(1),
                                   content=FillControl(
                                       '\u252c', token=Token.Toolbar.Title)),
                            Window(width=LayoutDimension.exact(1),
                                   content=FillControl('\u2502',
                                                       token=Token.Separator)),
                        ]),
                        HSplit([
                            StackTitlebar(weakref.ref(self)),
                            Window(callstack,
                                   scroll_offsets=ScrollOffsets(top=2,
                                                                bottom=2),
                                   right_margins=[ScrollbarMargin()],
                                   height=LayoutDimension(preferred=10)),
                        ]),
                    ]),
                ]),
                filter=show_pdb_content_filter),
            _extra_toolbars=[
                ConditionalContainer(PdbShortcutsToolbar(weakref.ref(self)),
                                     show_pdb_content_filter)
            ],
            history_filename=os.path.expanduser('~/.ptpdb_history'),
        )

        # Override prompt style.
        self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle(
            self._get_current_pdb_commands())
        self.python_input.prompt_style = 'pdb'

        # Override exit message.
        self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.'

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self,
                                     self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())

    def _create_accept_action(self):
        """
        Create an AcceptAction for the input buffer that replaces shortcuts
        like 's' with the full command ('step') before returning it.
        """
        def handler(cli, buffer):
            # Get first part.
            parts = buffer.text.strip().split(None, 1)
            if len(parts) == 0:
                first, rest = '', ''
            elif len(parts) == 1:
                first, rest = parts[0], ''
            else:
                first, rest = parts

            # Replace text in buffer and return it.
            buffer.document = Document(
                shortcuts.get(first, first) + ' ' + rest)
            cli.set_return_value(buffer.document)

        return AcceptAction(handler)

    def cmdloop(self, intro=None):
        """
        Copy/Paste of pdb.Pdb.cmdloop. But using our own CommandLineInterface
        for reading input instead.
        """
        self.preloop()

        if intro is not None:
            self.intro = intro
        if self.intro:
            self.stdout.write(str(self.intro) + "\n")
        stop = None
        while not stop:
            if self.cmdqueue:
                line = self.cmdqueue.pop(0)
            else:
                if self.use_rawinput:
                    line = self._get_input()

            line = self.precmd(line)
            stop = self.onecmd(line)
            stop = self.postcmd(stop, line)
        self.postloop()

    def _get_current_pdb_commands(self):
        return (list(commands_with_help.keys()) + list(shortcuts.keys()) +
                list(self.aliases.keys()))

    def _create_grammar(self):
        """
        Return the compiled grammar for this PDB shell.

        The grammar of PDB depends on the available list of PDB commands (which
        depends on the currently defined aliases.) Therefor we generate a new
        grammar when it changes, but cache it otherwise. (It's still expensive
        to compile.)
        """
        pdb_commands = self._get_current_pdb_commands()

        if self._grammar_cache is None or self._grammar_cache[
                0] != pdb_commands:
            self._grammar_cache = [
                pdb_commands, create_pdb_grammar(pdb_commands)
            ]

        return self._grammar_cache[1]

    def _get_input(self):
        """
        Read PDB input. Return input text.
        """
        # Reset multiline/paste mode every time.
        self.python_input.paste_mode = False
        self.python_input.currently_multiline = False

        # Set source code document.
        self._show_source_code(self.curframe.f_code.co_filename)

        self.cli.buffers[DEFAULT_BUFFER].document = Document('')

        # Select the current frame of the stack.
        for i, (frame, lineno) in enumerate(self.stack):
            if frame is self.curframe:
                self.callstack_selected_frame = i
                break

        # Set up a new completer and validator for the new grammar.
        g = self._create_grammar()

        self.completer = GrammarCompleter(
            g,
            completers={
                'enabled_breakpoint':
                BreakPointListCompleter(only_enabled=True),
                'disabled_breakpoint':
                BreakPointListCompleter(only_disabled=True),
                'alias_name':
                AliasCompleter(self),
                'python_code':
                PythonCompleter(lambda: self.curframe.f_globals,
                                lambda: self.curframe.f_locals),
                'breakpoint':
                BreakPointListCompleter(),
                'pdb_command':
                PdbCommandsCompleter(self),
                'python_file':
                PythonFileCompleter(),
                'python_function':
                PythonFunctionCompleter(self),
            })
        self.validator = GrammarValidator(g,
                                          {'python_code': PythonValidator()})

        # Make sure not to start in Vi navigation mode.
        self.python_input.key_bindings_manager.reset(self.cli)
        self.cli.buffers[DEFAULT_BUFFER].reset()

        def pre_run():
            self._source_code_window.vertical_scroll = 100000  # source_code_doc.line_count

        try:
            return self.cli.run(reset_current_buffer=False,
                                pre_run=pre_run).text
        except EOFError:
            # Turn Control-D key press into a 'quit' command.
            return 'quit'

    def _show_source_code(self, filename):
        """
        Show the source code in the `source_code` buffer.
        """
        source_code_doc = self._get_source_code_document(filename)
        self.cli.buffers['source_code']._set_text(source_code_doc.text + '\n')
        self.cli.buffers['source_code']._set_cursor_position(
            source_code_doc.cursor_position)

    def _get_source_code_document(self, filename):
        """
        Return source code around current line as string.
        """
        source_code = linecache.getlines(filename)
        if six.PY2:
            source_code = [l.decode('utf-8') for l in source_code]

        source_code = ''.join(source_code)
        document = Document(source_code)

        return Document(
            document.text,
            document.translate_row_col_to_index(row=self.curframe.f_lineno - 1,
                                                col=0))

    #
    # Methods overriden from Pdb, in order to add highlighting.
    #

    def postcmd(self, stop, line):
        """
        Override 'postcmd': (Insert whitespace.)
        """
        print('')
        return pdb.Pdb.postcmd(self, stop, line)

    def preloop(self):
        print('')
        return pdb.Pdb.preloop(self)

    def do_interact(self, args):
        """
        Interact: start interpreter.
        (Override the 'pdb' implementation. We call ptpython instead.)
        """
        print('')
        ns = self.curframe.f_globals.copy()
        ns.update(self.curframe_locals)
        embed(globals=ns)

    def error(self, msg):
        """
        Override default error handler from PDB.
        """
        self.cli.print_tokens([(Token.Pdb.Error, '  %s  \n' % msg)])

    def print_stack_entry(self, frame_lineno, prompt_prefix=': '):
        """
        Override `print_stack_entry` of Pdb, in order to add highlighting.
        """
        frame, lineno = frame_lineno

        tokens = []
        tokens.extend(format_stack_entry(self, frame, lineno))
        tokens.append((Token, '\n'))

        self.cli.print_tokens(tokens)

    def do_list(self, arg):
        """
        Override `Pdb.do_list`: Add highlighting.
        """
        self.lastcmd = 'list'
        last = None
        if arg and arg != '.':
            try:
                if ',' in arg:
                    first, last = arg.split(',')
                    first = int(first.strip())
                    last = int(last.strip())
                    if last < first:
                        # assume it's a count
                        last = first + last
                else:
                    first = int(arg.strip())
                    first = max(1, first - 5)
            except ValueError:
                self.error('Error in argument: %r' % arg)
                return
        elif self.lineno is None or arg == '.':
            first = max(1, self.curframe.f_lineno - 5)
        else:
            first = self.lineno + 1
        if last is None:
            last = first + 10
        filename = self.curframe.f_code.co_filename
        breaklist = self.get_file_breaks(filename)
        try:
            lines = linecache.getlines(filename, self.curframe.f_globals)
            self._print_lines_2(lines, first, last, breaklist, self.curframe)
            self.lineno = min(last, len(lines))
            if len(lines) < last:
                self.message('[EOF]')
        except KeyboardInterrupt:
            pass

    do_l = do_list

    def _print_lines_2(self, lines, start, end, breaks=(), frame=None):
        """
        Similar to `Pdb._print_lines`, except that this takes all the lines
        of the given file as input, it uses Pygments for the highlighting,
        it does slicing, and it prints everything in color.
        """
        if frame:
            current_lineno = frame.f_lineno
        else:
            current_lineno = exc_lineno = -1

        # Highlight everything. (Highlighting works much better from the
        # beginning of the file.)
        all_tokens = python_lexer.get_tokens(''.join(lines))

        # Slice lines.
        lines = list(split_lines(all_tokens))[start - 1:end]

        # Add left margin. (Numbers + 'B' or '->'.)
        def add_margin(lineno, tokens):
            is_break = lineno in breaks
            is_current_line = lineno == current_lineno

            return get_line_prefix_tokens(is_break, is_current_line) \
                + [(Token.LineNumber, str(lineno).rjust(3) + ' ')] \
                + tokens + [(Token, '\n')]

        lines = [
            add_margin(i + start, tokens) for i, tokens in enumerate(lines)
        ]

        for l in lines:
            self.cli.print_tokens(l)

    def message(self, msg):
        """ Print message to stdout. This function is present in Pdb for
        Python3, but not in Python2. """
        print(msg, file=self.stdout)
示例#9
0
def main():
    prompt = PythonInput()

    text = prompt.app.run()
    print("You said: " + text)
示例#10
0
class PtPdb(pdb.Pdb):
    def __init__(self):
        pdb.Pdb.__init__(self)

        # Cache for the grammar.
        self._grammar_cache = None  # (current_pdb_commands, grammar) tuple.

        self._cli_history = FileHistory(os.path.expanduser('~/.ptpdb_history'))

        self.completer = None
        self.validator = None

        self.python_input = PythonInput(
                get_locals=lambda: self.curframe.f_locals,
                get_globals=lambda: self.curframe.f_globals,
                _completer=DynamicCompleter(lambda: self.completer),
                _validator=DynamicValidator(lambda: self.validator),
                _python_prompt_control=PdbLeftMargin(self._get_current_pdb_commands()),
                _extra_buffers={'source_code': Buffer()},
                _extra_buffer_processors=[CompletionHint()],
                _extra_sidebars=[
                    HSplit([
                        FileLocationToolbar(weakref.ref(self)),
                        ConditionalContainer(
                            Window(
                                BufferControl(
                                    buffer_name='source_code',
                                    lexer=PythonLexer,
                                ),
                            ),
                            filter=~IsDone()),
                        PdbShortcutsToolbar(weakref.ref(self)),
                    ]),
                ],
        )

        # Set UI styles.
        self.python_input.ui_styles = {
            'ptpdb': get_ui_style(),
        }
        self.python_input.use_ui_colorscheme('ptpdb')

        # Set autocompletion style. (Multi-column works nicer.)
        self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN
        self.python_input.complete_while_typing = False

        # Load additional key bindings.
        load_custom_pdb_key_bindings(self.python_input.key_bindings_registry)

        self.cli = CommandLineInterface(
            eventloop=create_eventloop(),
            application=self.python_input.create_application())

    def cmdloop(self, intro=None):
        """
        Copy/Paste of pdb.Pdb.cmdloop. But using our own CommandLineInterface
        for reading input instead.
        """
        self.preloop()

        if intro is not None:
            self.intro = intro
        if self.intro:
            self.stdout.write(str(self.intro)+"\n")
        stop = None
        while not stop:
            if self.cmdqueue:
                line = self.cmdqueue.pop(0)
            else:
                if self.use_rawinput:
                    line = self._get_input()

            line = self.precmd(line)
            stop = self.onecmd(line)
            stop = self.postcmd(stop, line)
        self.postloop()

    def _get_current_pdb_commands(self):
        return (
            list(commands_with_help.keys()) +
            list(shortcuts.keys()) +
            list(self.aliases.keys()))

    def _create_grammar(self):
        """
        Return the compiled grammar for this PDB shell.

        The grammar of PDB depends on the available list of PDB commands (which
        depends on the currently defined aliases.) Therefor we generate a new
        grammar when it changes, but cache it otherwise. (It's still expensive
        to compile.)
        """
        pdb_commands = self._get_current_pdb_commands()

        if self._grammar_cache is None or self._grammar_cache[0] != pdb_commands:
            self._grammar_cache = [
                pdb_commands,
                create_pdb_grammar(pdb_commands)]

        return self._grammar_cache[1]

    def _get_input(self):
        """
        Read PDB input. Return input text.
        """
        # Reset multiline/paste mode every time.
        self.python_input.paste_mode = False
        self.python_input.currently_multiline = False

        # Make sure not to start in Vi navigation mode.
        self.python_input.key_bindings_manager.reset()  # XXX: we should not have to do this here...

        # Set source code document.
        self.cli.buffers['source_code'].document = Document(self._get_source_code())

        # Set up a new completer and validator for the new grammar.
        g = self._create_grammar()

        self.completer = GrammarCompleter(g, completers={
            'enabled_breakpoint': BreakPointListCompleter(only_enabled=True),
            'disabled_breakpoint': BreakPointListCompleter(only_disabled=True),
            'alias_name': AliasCompleter(self),
            'python_code': PythonCompleter(lambda: self.curframe.f_globals, lambda: self.curframe.f_locals),
            'breakpoint': BreakPointListCompleter(),
            'pdb_command': PdbCommandsCompleter(self),
            'python_file': PythonFileCompleter(),
            'python_function': PythonFunctionCompleter(self),
        })
        self.validator = GrammarValidator(g, {
            'python_code': PythonValidator()
        })

        try:
            return self.cli.run().text
        except EOFError:
            # Turn Control-D key press into a 'quit' command.
            return 'q'

    def _get_source_code(self):
        """
        Return source code around current line as string.
        (Partly taken from Pdb.do_list.)
        """
        filename = self.curframe.f_code.co_filename
        breaklist = self.get_file_breaks(filename)

        first = max(1,  self.curframe.f_lineno - 3)
        last = first + 12 # 6

        result = []

        for lineno in range(first, last+1):
            line = linecache.getline(filename, lineno, self.curframe.f_globals)
            if not line:
                line = '[EOF]'
                break
            else:
                s = repr(lineno).rjust(3)
                if len(s) < 4:
                    s = s + ' '
                if lineno in breaklist:
                    s = s + 'B'
                else:
                    s = s + ' '
                if lineno == self.curframe.f_lineno:
                    s = s + '->'
                else:
                    s = s + '  '

                result.append(s + ' ' + line)

        return ''.join(result)