Exemple #1
0
    def _pygmented_scope_lines(self) -> Optional[Tuple[int, List[str]]]:
        # noinspection PyUnresolvedReferences
        from pygments.formatters import HtmlFormatter

        formatter = self.options.pygments_formatter
        scope = self.scope
        assert_(formatter, ValueError("Must set a pygments formatter in Options"))
        assert_(scope)

        if isinstance(formatter, HtmlFormatter):
            formatter.nowrap = True

        atok = self.source.asttokens()
        node = self.executing.node
        if node and getattr(formatter.style, "for_executing_node", False):
            scope_start = atok.get_text_range(scope)[0]
            start, end = atok.get_text_range(node)
            start -= scope_start
            end -= scope_start
            ranges = [(start, end)]
        else:
            ranges = []

        code = atok.get_text(scope)
        lines = _pygmented_with_ranges(formatter, code, ranges)

        start_line = line_range(scope)[0]

        return start_line, lines
    def __init__(
            self, *,
            options=Options(),
            pygmented=False,
            show_executing_node=True,
            pygments_formatter_cls=None,
            pygments_formatter_kwargs=None,
            pygments_style="monokai",
            executing_node_modifier="bg:#005080",
            executing_node_underline="^",
            current_line_indicator="-->",
            line_gap_string="(...)",
            show_variables=False,
            use_code_qualname=True,
            show_linenos=True,
            strip_leading_indent=True,
            html=False,
            chain=True,
            collapse_repeated_frames=True
    ):
        if pygmented and not options.pygments_formatter:
            if show_executing_node:
                pygments_style = style_with_executing_node(
                    pygments_style, executing_node_modifier
                )

            if pygments_formatter_cls is None:
                from pygments.formatters.terminal256 import Terminal256Formatter \
                    as pygments_formatter_cls

            options.pygments_formatter = pygments_formatter_cls(
                style=pygments_style,
                **pygments_formatter_kwargs or {},
            )

        self.pygmented = pygmented
        self.show_executing_node = show_executing_node
        assert_(
            len(executing_node_underline) == 1,
            ValueError("executing_node_underline must be a single character"),
        )
        self.executing_node_underline = executing_node_underline
        self.current_line_indicator = current_line_indicator or ""
        self.line_gap_string = line_gap_string
        self.show_variables = show_variables
        self.show_linenos = show_linenos
        self.use_code_qualname = use_code_qualname
        self.strip_leading_indent = strip_leading_indent
        self.html = html
        self.chain = chain
        self.options = options
        self.collapse_repeated_frames = collapse_repeated_frames
Exemple #3
0
    def render(self,
               markers: Iterable[MarkerInLine] = (),
               *,
               strip_leading_indent: bool = True,
               pygmented: bool = False,
               escape_html: bool = False) -> str:
        """
        Produces a string for display consisting of .text
        with the .strings of each marker inserted at the correct positions.
        If strip_leading_indent is true (the default) then leading spaces
        common to all lines in this frame will be excluded.
        """
        if pygmented:
            assert_(not markers,
                    ValueError("Cannot use pygmented with markers"))
            start_line, lines = self.frame_info._pygmented_scope_lines
            result = lines[self.lineno - start_line]
            if strip_leading_indent:
                result = result.replace(self.text[:self.leading_indent], "", 1)
            return result

        text = self.text

        # This just makes the loop below simpler
        markers = list(markers) + [
            MarkerInLine(position=len(text), is_start=False, string='')
        ]

        markers.sort(key=lambda t: t[:2])

        parts = []
        if strip_leading_indent:
            start = self.leading_indent
        else:
            start = 0
        original_start = start

        for marker in markers:
            text_part = text[start:marker.position]
            if escape_html:
                text_part = html.escape(text_part)
            parts.append(text_part)
            parts.append(marker.string)

            # Ensure that start >= leading_indent
            start = max(marker.position, original_start)
        return ''.join(parts)
Exemple #4
0
    def format_frame(
            self, frame: Union[FrameInfo, FrameType,
                               TracebackType]) -> Iterable[str]:
        if not isinstance(frame, FrameInfo):
            frame = FrameInfo(frame, self.options)

        yield self.format_frame_header(frame)

        for line in frame.lines:
            if isinstance(line, Line):
                yield self.format_line(line)
            else:
                assert_(line is LINE_GAP)
                yield self.line_gap_string + "\n"

        if self.show_variables:
            yield from self.format_variables(frame)