def test_doctrings_are_corrrectly_rendered():
    from cleo.formatters.formatter import Formatter
    from cleo.ui.exception_trace import Highlighter

    source = '''
def test():
    """
    Doctring
    """
    ...
'''

    formatter = Formatter()
    highlighter = Highlighter()
    lines = highlighter.highlighted_lines(source)

    assert [formatter.format(l) for l in lines] == [
        "",
        "def test():",
        '    """',
        "    Doctring",
        '    """',
        "    ...",
        "",
    ]
Example #2
0
    def _render_exception(self, io: Union[IO, Output],
                          exception: Exception) -> None:
        from crashtest.inspector import Inspector

        inspector = Inspector(exception)
        if not inspector.frames:
            return

        if inspector.has_previous_exception():
            self._render_exception(io, inspector.previous_exception)
            io.write_line("")
            io.write_line(
                "The following error occurred when trying to handle this error:"
            )
            io.write_line("")

        self._render_trace(io, inspector.frames)

        self._render_line(io,
                          "<error>{}</error>".format(inspector.exception_name),
                          True)
        io.write_line("")
        exception_message = (Formatter().format(
            inspector.exception_message).replace("\n", "\n  "))
        self._render_line(io, "<b>{}</b>".format(exception_message))

        current_frame = inspector.frames[-1]
        self._render_snippet(io, current_frame)

        self._render_solution(io, inspector)
Example #3
0
    def _describe_command(self, command: Command, **options: Any) -> None:
        command.merge_application_definition(False)

        description = command.description
        if description:
            self._write("<b>Description:</b>")
            self._write("\n")
            self._write("  " + description)
            self._write("\n\n")

        self._write("<b>Usage:</b>")
        for usage in [command.synopsis(True)
                      ] + command.aliases + command.usages:
            self._write("\n")
            self._write("  " + Formatter.escape(usage))

        self._write("\n")

        definition = command.definition
        if definition.options or definition.arguments:
            self._write("\n")
            self._describe_definition(definition, **options)
            self._write("\n")

        help_text = command.processed_help
        if help_text and help_text != description:
            self._write("\n")
            self._write("<b>Help:</b>")
            self._write("\n")
            self._write("  " + help_text.replace("\n", "\n  "))
            self._write("\n")
Example #4
0
    def _format_default_value(self, default: Any) -> str:
        if isinstance(default, str):
            default = Formatter.escape(default)
        elif isinstance(default, list):
            new_default = []
            for value in default:
                if isinstance(value, str):
                    new_default.append(Formatter.escape(value))

            default = new_default
        elif isinstance(default, dict):
            new_default = {}
            for key, value in default.items():
                if isinstance(value, str):
                    new_default[key] = Formatter.escape(value)

            default = new_default

        return json.dumps(default).replace("\\\\", "\\")
Example #5
0
    def __init__(
        self,
        verbosity: Verbosity = Verbosity.NORMAL,
        decorated: bool = False,
        formatter: Optional[Formatter] = None,
    ) -> None:
        self._verbosity: Verbosity = verbosity
        if formatter is None:
            formatter = Formatter()

        self._formatter = formatter
        self._formatter.decorated(decorated)

        self._section_outputs = []
Example #6
0
    def _build_table_rows(self, rows: _Rows) -> Generator:
        unmerged_rows = {}
        row_key = 0
        while row_key < len(rows):
            rows = self._fill_next_rows(rows, row_key)

            # Remove any new line breaks and replace it with a new line
            for column, cell in enumerate(rows[row_key]):
                colspan = cell.colspan if isinstance(cell, TableCell) else 1

                if column in self._column_max_widths and self._column_max_widths[
                        column] < len(self._io.remove_format(cell)):
                    cell = self._io.formatter.format_and_wrap(
                        cell, self._column_max_widths[column] * colspan)

                if "\n" not in cell:
                    continue

                escaped = "\n".join(
                    Formatter.escape_trailing_backslash(c)
                    for c in cell.split("\n"))
                cell = (TableCell(escaped, colspan=cell.colspan) if isinstance(
                    cell, TableCell) else escaped)
                lines = cell.replace(
                    "\n", "<fg=default;bg=default>\n</>").split("\n")

                for line_key, line in enumerate(lines):
                    if colspan > 1:
                        line = TableCell(line, colspan=colspan)

                    if line_key == 0:
                        rows[row_key][column] = line
                    else:
                        if row_key not in unmerged_rows:
                            unmerged_rows[row_key] = {}

                        if line_key not in unmerged_rows[row_key]:
                            unmerged_rows[row_key][line_key] = self._copy_row(
                                rows, row_key)

                        unmerged_rows[row_key][line_key][column] = line

            row_key += 1

        for row_key, row in enumerate(rows):
            yield self._fill_cells(row)

            if row_key in unmerged_rows:
                for unmerged_row in unmerged_rows[row_key].values():
                    yield self._fill_cells(unmerged_row)
Example #7
0
def test_format_and_wrap_undecorated(text, width, expected):
    formatter = Formatter(False)

    assert formatter.format_and_wrap(text, width) == expected
Example #8
0
def test_format_and_wrap(text, width, expected):
    formatter = Formatter(True)

    assert formatter.format_and_wrap(text, width) == expected
Example #9
0
    def split_to_lines(self, source):
        lines = []
        current_line = 1
        current_col = 0
        buffer = ""
        current_type = None
        source_io = io.BytesIO(source.encode())
        formatter = Formatter()

        def readline():
            return formatter.format(
                formatter.escape(source_io.readline().decode())).encode()

        tokens = tokenize.tokenize(readline)
        line = ""
        for token_info in tokens:
            token_type, token_string, start, end, _ = token_info
            lineno = start[0]
            if lineno == 0:
                # Encoding line
                continue

            if token_type == tokenize.ENDMARKER:
                # End of source
                if current_type is None:
                    current_type = self.TOKEN_DEFAULT

                line += "<{}>{}</>".format(self._theme[current_type], buffer)
                lines.append(line)
                break

            if lineno > current_line:
                if current_type is None:
                    current_type = self.TOKEN_DEFAULT

                diff = lineno - current_line
                if diff > 1:
                    lines += [""] * (diff - 1)

                line += "<{}>{}</>".format(self._theme[current_type],
                                           buffer.rstrip("\n"))

                # New line
                lines.append(line)
                line = ""
                current_line = lineno
                current_col = 0
                buffer = ""

            if token_string in self.KEYWORDS:
                new_type = self.TOKEN_KEYWORD
            elif token_string in self.BUILTINS or token_string == "self":
                new_type = self.TOKEN_BUILTIN
            elif token_type == tokenize.STRING:
                new_type = self.TOKEN_STRING
            elif token_type == tokenize.NUMBER:
                new_type = self.TOKEN_NUMBER
            elif token_type == tokenize.COMMENT:
                new_type = self.TOKEN_COMMENT
            elif token_type == tokenize.OP:
                new_type = self.TOKEN_OP
            elif token_type == tokenize.NEWLINE:
                continue
            else:
                new_type = self.TOKEN_DEFAULT

            if current_type is None:
                current_type = new_type

            if start[1] > current_col:
                buffer += token_info.line[current_col:start[1]]

            if current_type != new_type:
                line += "<{}>{}</>".format(self._theme[current_type], buffer)
                buffer = ""
                current_type = new_type

            if lineno < end[0]:
                # The token spans multiple lines
                token_lines = token_string.split("\n")
                line += "<{}>{}</>".format(self._theme[current_type],
                                           token_lines[0])
                lines.append(line)
                for token_line in token_lines[1:-1]:
                    lines.append("<{}>{}</>".format(self._theme[current_type],
                                                    token_line))

                current_line = end[0]
                buffer = token_lines[-1][:end[1]]
                line = ""
                continue

            buffer += token_string
            current_col = end[1]
            current_line = lineno

        return lines
Example #10
0
    def _render_trace(self, io: Union[IO, Output],
                      frames: FrameCollection) -> None:
        stack_frames = FrameCollection()
        for frame in frames:
            if (self._ignore and re.match(self._ignore, frame.filename)
                    and not io.is_debug()):
                continue

            stack_frames.append(frame)

        remaining_frames_length = len(stack_frames) - 1
        if io.is_verbose() and remaining_frames_length:
            self._render_line(io, "<fg=yellow>Stack trace</>:", True)
            max_frame_length = len(str(remaining_frames_length))
            frame_collections = stack_frames.compact()
            i = remaining_frames_length
            for collection in frame_collections:
                if collection.is_repeated():
                    if len(collection) > 1:
                        frames_message = "<fg=yellow>{}</> frames".format(
                            len(collection))
                    else:
                        frames_message = "frame"

                    self._render_line(
                        io,
                        "<fg=blue>{:>{}}</>  Previous {} repeated <fg=blue>{}</> times"
                        .format(
                            "...",
                            max_frame_length,
                            frames_message,
                            collection.repetitions + 1,
                        ),
                        True,
                    )

                    i -= len(collection) * (collection.repetitions + 1)

                for frame in collection:
                    relative_file_path = self._get_relative_file_path(
                        frame.filename)
                    relative_file_path_parts = relative_file_path.split(
                        os.path.sep)
                    relative_file_path = "{}".format(
                        "<fg=default;options=dark>{}</>".format(
                            Formatter.escape(
                                os.sep)).join(relative_file_path_parts[:-1] + [
                                    "<fg=default;options=bold>{}</>".format(
                                        relative_file_path_parts[-1])
                                ]), )

                    self._render_line(
                        io,
                        "<fg=yellow>{:>{}}</>  {}<fg=default;options=dark>:</><b>{}</b> in <fg=cyan>{}</>"
                        .format(
                            i,
                            max_frame_length,
                            relative_file_path,
                            frame.lineno,
                            frame.function,
                        ),
                        True,
                    )

                    if io.is_debug():
                        if (frame, 2, 2) not in self._FRAME_SNIPPET_CACHE:
                            code_lines = Highlighter(
                                supports_utf8=io.supports_utf8()).code_snippet(
                                    frame.file_content,
                                    frame.lineno,
                                )

                            self._FRAME_SNIPPET_CACHE[(frame, 2,
                                                       2)] = code_lines

                        code_lines = self._FRAME_SNIPPET_CACHE[(frame, 2, 2)]

                        for code_line in code_lines:
                            self._render_line(
                                io,
                                "{:>{}}{}".format(" ", max_frame_length,
                                                  code_line),
                                indent=3,
                            )
                    else:
                        highlighter = Highlighter(
                            supports_utf8=io.supports_utf8())
                        try:
                            code_line = highlighter.highlighted_lines(
                                frame.line.strip())[0]
                        except tokenize.TokenError:
                            code_line = frame.line.strip()

                        self._render_line(
                            io,
                            "{:>{}}    {}".format(
                                " ",
                                max_frame_length,
                                code_line,
                            ),
                        )

                    i -= 1