def __init__(self, docstring):
     # type: (Text) -> None
     docstring = self._cleanup(docstring)
     docstring = IndentTrimmer.trim_empty_lines(docstring)
     docstring = IndentTrimmer.trim_text(docstring)
     lines = docstring.split("\n")
     self._lines = IndentTrimmer.trim_lines(lines)
Exemple #2
0
 def test_trim_empty_lines(self):
     self.assertEqual(
         IndentTrimmer.trim_empty_lines("\n  \n test\ntest2\n \n "),
         " test\ntest2")
     self.assertEqual(IndentTrimmer.trim_empty_lines("\n  \n\n "), "")
     self.assertEqual(IndentTrimmer.trim_empty_lines("\n  \n  test \n "),
                      "  test ")
Exemple #3
0
 def test_trim_text(self):
     self.assertEqual(IndentTrimmer.trim_text("  asd\n asd\n   asd\n"),
                      " asd\nasd\n  asd\n")
     self.assertEqual(IndentTrimmer.trim_text("  asd\nasd\n   asd\n"),
                      "  asd\nasd\n   asd\n")
     self.assertEqual(IndentTrimmer.trim_text(" asd\n asd\n  asd\n"),
                      "asd\nasd\n asd\n")
Exemple #4
0
 def test_trim_lines(self):
     self.assertEqual(
         IndentTrimmer.trim_lines(["  asd", " asd", "   asd"]),
         [" asd", "asd", "  asd"],
     )
     self.assertEqual(
         IndentTrimmer.trim_lines(["  asd", " asd", "", "   asd"]),
         [" asd", "asd", "", "  asd"],
     )
     self.assertEqual(
         IndentTrimmer.trim_lines(["  asd", "asd", "   asd", ""]),
         ["  asd", "asd", "   asd", ""],
     )
     self.assertEqual(IndentTrimmer.trim_lines([]), [])
Exemple #5
0
    def _get_function_def_lines(self, function_record):
        # type: (FunctionRecord) -> List[Text]
        """
		Get all function definition lines for comment type
		hints lookup.

		Removes indentation.

		Arguments:
			function_record -- Function record for source lookup.

		Returns:
			Function definition lines as an array.
		"""
        if not isinstance(function_record.node,
                          (ast.AsyncFunctionDef, ast.FunctionDef)):
            raise TypeError

        result = []  # type: List[Text]
        start_index = function_record.line_number - 1
        end_index = function_record.node.body[0].lineno - 1
        result = self.source_lines[start_index:end_index]
        result = [i.rstrip("\n") for i in result]
        result = IndentTrimmer.trim_lines(result)
        return result
Exemple #6
0
    def add_line_indent(self, section_name, line):
        # type: (Text, Text) -> None
        """
		Add line respecting indent of the current section block.

		Arguments:
			section_name -- Target section title
			line -- Line to add
		"""
        if section_name in self:
            section = self[section_name]
            if section.blocks and section.blocks[-1].lines:
                indent = IndentTrimmer.get_line_indent(
                    section.blocks[-1].lines[-1])
                line = IndentTrimmer.indent_line(line, indent)

        self.add_line(section_name, line)
Exemple #7
0
    def render(self):
        # type: () -> Text
        """
		Render trimmed block lines.

		Returns:
			Block lines as a text.
		"""
        lines = IndentTrimmer.trim_lines(self.lines)
        return "\n".join(lines)
Exemple #8
0
    def build_sections(self, content):
        # type: (Text) -> SectionMap
        """
		Parse docstring and split it to sections with arrays of strings.

		Arguments:
			content -- Object docstring.

		Returns:
			A dictionary where key is a section name and value is a list of string sof this
			section.
		"""
        self._reset()

        for line in content.split("\n"):
            self._current_indent = IndentTrimmer.get_line_indent(line)
            line = line.strip()

            # adding new lines to a doctest code block
            if self._in_doctest_block:
                self._parse_doctest_line(line)
                continue

            # adding new lines to a tilde block
            if self._in_tilde_block:
                self._parse_tilde_block_line(line)
                continue

            # adding new lines to a code block
            if self._in_md_codeblock:
                self._parse_md_codeblock_line(line)
                continue

            # adding new lines to an indented code block
            if self._in_indent_codeblock:
                self._parse_indent_codeblock_line(line)
                continue

            # adding new block on empty line outside of a code block
            if not line:
                self._add_block()
                continue

            self._parse_line(line)

        if self._in_indent_codeblock:
            self._trim_empty_lines()
            self._add_line("```", indent=0)

        return self.section_map
Exemple #9
0
    def get_toc_line(cls, line, level=0):
        # type: (Text, int) -> Text
        """
		Get ToC `line` of given `level`.

		Arguments:
			line -- Line to prepare.
			level -- Line level, starts with `0`.

		Returns:
			Ready to insert ToC line.
		"""
        indent = cls.TOC_INDENT * level
        return IndentTrimmer.indent_line("- {}".format(line), indent)
Exemple #10
0
    def _cleanup(docstring):
        # type: (Text) -> Text
        """
		Fix multiline docstrings starting with no newline after quotes.

		Arguments:
			docstring -- Raw docstring.

		Returns:
			Aligned docstring.
		"""
        if "\n" in docstring and docstring[0] != "\n":
            lines = docstring.split("\n")
            next_line_index = 1
            next_line = lines[next_line_index]
            while not next_line.strip() and next_line_index < len(lines) - 1:
                next_line_index += 1
                next_line = lines[next_line_index]

            indent = IndentTrimmer.get_line_indent(next_line)
            docstring = "\n{}{}".format(" " * indent, docstring)

        return IndentTrimmer.trim_text(docstring)
Exemple #11
0
    def append(self, content):
        # type: (Text) -> None
        """
		Append `content` to the document.
		Handle trimming and sectioning the content and update
		`title` and `toc_section` fields.

		Arguments:
			content -- Text to add.
		"""
        content = IndentTrimmer.trim_empty_lines(content)
        if not content:
            return

        if not self.subtitle and not self.sections and not content.startswith(
                "#"):
            self.subtitle = content
        else:
            self._sections.append(content)

        self._content = self._build_content()
Exemple #12
0
    def read(self, source_path=None):
        # type: (Optional[Path]) -> None
        """
		Read and parse content from `source_path`.

		Arguments:
			source_path -- Input file path. If not provided - `path` is used.
		"""
        path = source_path or self._path
        self._content = path.read_text(encoding="utf-8")
        self._title = ""
        self._toc_section = ""
        title, content = extract_md_title(self._content)
        if title:
            self._title = title

        sections = content.split(self._section_separator)
        self._sections = []
        for section in sections:
            section = IndentTrimmer.trim_empty_lines(section)
            if not section:
                continue
            if self.is_toc(section) and not self._toc_section:
                self._toc_section = section
                if self._sections:
                    self._subtitle = self._section_separator.join(
                        self._sections)
                    self._sections = []
                continue

            self._sections.append(section)

        # extract subtitle from the first section if it is not a title
        if (not self._subtitle and self._sections
                and not self._sections[0].startswith("#")):
            self._subtitle = self._sections.pop(0)
Exemple #13
0
 def test_trim_line(self):
     self.assertEqual(IndentTrimmer.trim_line("   test", 2), " test")
     self.assertEqual(IndentTrimmer.trim_line(" test", 2), "test")
     self.assertEqual(IndentTrimmer.trim_line("test", 2), "test")
     self.assertEqual(IndentTrimmer.trim_line("   ", 2), " ")
Exemple #14
0
 def test_get_line_indent(self):
     self.assertEqual(IndentTrimmer.get_line_indent("   test"), 3)
     self.assertEqual(IndentTrimmer.get_line_indent("test"), 0)
     self.assertEqual(IndentTrimmer.get_line_indent("  "), 2)
     self.assertEqual(IndentTrimmer.get_line_indent(""), 0)