Пример #1
0
    def run_generic(self) -> List[nodes.Node]:
        """
		Generate generic reStructuredText output.
		"""

        content = StringList()
        content.indent_type = ' '

        for obj_name in get_random_sample(sorted(set(self.content))):
            if self.options.get("module", '') and obj_name.startswith('.'):
                obj_name = obj_name.replace('.', f"{self.options['module']}.",
                                            1)

            name_parts = obj_name.split('.')
            module = import_module('.'.join(name_parts[:-1]))
            obj = getattr(module, name_parts[-1])

            if isinstance(obj, FunctionType):
                content.append(
                    f"* :func:`{'.'.join(name_parts[1:])}() <.{obj_name}>`")
            elif isinstance(obj, type):
                content.append(
                    f"* :class:`{'.'.join(name_parts[1:])} <.{obj_name}>`")
            else:
                content.append(
                    f"* :py:obj:`{'.'.join(name_parts[1:])} <.{obj_name}>`")

            with content.with_indent_size(2):
                content.blankline()
                content.append(format_signature(obj))
                content.blankline()
                content.append(
                    inspect.cleandoc(obj.__doc__ or '').split("\n\n")[0])
                content.blankline()

        targetid = f'sphinx-highlights-{self.env.new_serialno("sphinx-highlights"):d}'
        targetnode = nodes.target('', '', ids=[targetid])

        view = ViewList(content)
        body_node = nodes.container(rawsource=str(content))
        self.state.nested_parse(view, self.content_offset,
                                body_node)  # type: ignore

        sphinx_highlights_purger.add_node(self.env, body_node, targetnode,
                                          self.lineno)

        return [targetnode, body_node]
Пример #2
0
def format_signature(obj: Union[type, FunctionType]) -> StringList:
    """
	Format the signature of the given object, for insertion into the highlight panel.

	:param obj:

	:return: A list of reStructuredText lines.
	"""

    with monkeypatcher():
        obj.__annotations__ = get_type_hints(obj)

    signature: inspect.Signature = inspect.signature(obj)

    buf = StringList(".. parsed-literal::")
    buf.blankline()
    buf.indent_type = "    "
    buf.indent_size = 1

    if signature.return_annotation is not inspect.Signature.empty and not isinstance(
            obj, type):
        return_annotation = f") -> {format_annotation(signature.return_annotation)}"
    else:
        return_annotation = f")"

    total_length = len(obj.__name__) + len(return_annotation)

    arguments_buf: DelimitedList[str] = DelimitedList()

    param: inspect.Parameter
    for param in signature.parameters.values():
        arguments_buf.append(f"{format_parameter(param)}")
        total_length += len(arguments_buf[-1])

    if total_length <= 60:
        signature_buf = StringList(''.join(
            [f"{obj.__name__}(", f"{arguments_buf:, }", return_annotation]))
    else:
        signature_buf = StringList([f"{obj.__name__}("])
        signature_buf.indent_type = "  "
        with signature_buf.with_indent_size(1):
            signature_buf.extend(
                [f"{arguments_buf:,\n}" + ',', return_annotation])

    buf.extend(signature_buf)

    return buf
Пример #3
0
def add_autosummary(self):
	"""
	Add the :rst:dir:`autosummary` table of this documenter.
	"""

	if not self.options.get("autosummary", False):
		return

	content = StringList()
	content.indent_type = ' ' * 4
	sourcename = self.get_sourcename()
	grouped_documenters = self.get_grouped_documenters()

	for section, documenters in grouped_documenters.items():
		if not self.options.get("autosummary-no-titles", False):
			content.append(f"**{section}:**")

		content.blankline(ensure_single=True)

		content.append(".. autosummary::")
		content.blankline(ensure_single=True)

		member_order = get_first_matching(
				lambda x: x != "groupwise",
				[
						self.options.get("member-order", ''),
						self.env.config.autodocsumm_member_order,
						self.env.config.autodoc_member_order,
						],
				default="alphabetical",
				)

		with content.with_indent_size(content.indent_size + 1):
			for documenter, _ in self.sort_members(documenters, member_order):
				content.append(f"~{documenter.fullname}")

		content.blankline()

	for line in content:
		self.add_line(line, sourcename)
Пример #4
0
def rewrite_docs_index(repo_path: pathlib.Path,
                       templates: Environment) -> List[str]:
    """
	Update blocks in the documentation ``index.rst`` file.

	:param repo_path: Path to the repository root.
	:param templates:
	"""

    index_rst_file = PathPlus(repo_path / templates.globals["docs_dir"] /
                              "index.rst")
    index_rst_file.parent.maybe_make()

    # Set up the blocks
    sb = ShieldsBlock(
        username=templates.globals["username"],
        repo_name=templates.globals["repo_name"],
        version=templates.globals["version"],
        conda=templates.globals["enable_conda"],
        tests=templates.globals["enable_tests"]
        and not templates.globals["stubs_package"],
        docs=templates.globals["enable_docs"],
        pypi_name=templates.globals["pypi_name"],
        docker_shields=templates.globals["docker_shields"],
        docker_name=templates.globals["docker_name"],
        platforms=templates.globals["platforms"],
        pre_commit=templates.globals["enable_pre_commit"],
        on_pypi=templates.globals["on_pypi"],
        primary_conda_channel=templates.globals["primary_conda_channel"],
    )

    sb.set_docs_mode()
    make_out = sb.make()

    shield_block_list = StringList([*make_out[0:2], ".. only:: html"])

    with shield_block_list.with_indent_size(1):
        shield_block_list.extend(make_out[1:-1])

    shield_block_list.append(make_out[-1])

    shields_block = str(shield_block_list)

    if templates.globals["license"] == "GNU General Public License v2 (GPLv2)":
        source = f"https://img.shields.io/github/license/{templates.globals['username']}/{templates.globals['repo_name']}"
        shields_block.replace(
            source, "https://img.shields.io/badge/license-GPLv2-orange")

    # .. image:: https://img.shields.io/badge/License-LGPL%20v3-blue.svg

    install_block = create_docs_install_block(
        templates.globals["repo_name"],
        templates.globals["username"],
        templates.globals["enable_conda"],
        templates.globals["on_pypi"],
        templates.globals["pypi_name"],
        templates.globals["conda_channels"],
    ) + '\n'

    links_block = create_docs_links_block(
        templates.globals["username"],
        templates.globals["repo_name"],
    )

    # Do the replacement
    index_rst = index_rst_file.read_text(encoding="UTF-8")
    index_rst = shields_regex.sub(shields_block, index_rst)
    index_rst = installation_regex.sub(install_block, index_rst)
    index_rst = links_regex.sub(links_block, index_rst)
    index_rst = short_desc_regex.sub(
        ".. start short_desc\n\n.. documentation-summary::\n\t:meta:\n\n.. end short_desc",
        index_rst,
    )

    if ":caption: Links" not in index_rst and not templates.globals[
            "preserve_custom_theme"]:
        index_rst = index_rst.replace(
            ".. start links", '\n'.join([
                ".. sidebar-links::",
                "\t:caption: Links",
                "\t:github:",
                (f"	:pypi: {templates.globals['pypi_name']}"
                 if templates.globals["on_pypi"] else ''),
                '',
                '',
                ".. start links",
            ]))

    index_rst_file.write_clean(index_rst)

    return [index_rst_file.relative_to(repo_path).as_posix()]
Пример #5
0
def walk_attrs(module: ModuleType, attr_name, converter=Converter()) -> str:
    """
	Create stubs for given class, including all attributes.

	:param module:
	:param attr_name:
	:param converter:

	:return:
	"""

    buf = StringList(convert_indents=True)
    buf.indent_type = "    "

    if not is_dunder(attr_name):
        obj = getattr(module, attr_name)

        # TODO: case where obj is not a class
        if not isinstance(obj, FunctionType):
            bases = []
            for base in obj.__bases__:
                if base not in {System.Object, object}:
                    if base.__name__ in converter.type_mapping:
                        bases.append(converter.type_mapping[base.__name__])
                    else:
                        bases.append(base.__name__)

            bases = list(filter(lambda x: x is Any, bases))

            if bases:
                buf.append(f"class {attr_name}({', '.join(bases)}):\n")
            else:
                buf.append(f"class {attr_name}:\n")

            for child_attr_name in get_child_attrs(obj):
                try:
                    child_obj = getattr(obj, child_attr_name)
                except TypeError as e:
                    if str(e) in {
                            "instance property must be accessed through a class instance",
                            "property cannot be read",
                    }:

                        make_property(buf, child_attr_name)
                        continue

                    elif str(
                            e
                    ) == "instance attribute must be accessed through a class instance":
                        print(
                            f"{e.__class__.__name__}: '{e}' occurred for {attr_name}.{child_attr_name}"
                        )
                        continue

                    else:
                        raise e

                # TODO: if isinstance(child_obj, FunctionType):

                return_type, arguments = get_signature(child_obj,
                                                       child_attr_name,
                                                       converter)

                with buf.with_indent_size(buf.indent_size + 1):

                    if arguments is not None and arguments:
                        signature = []

                        for idx, argument in enumerate(arguments.split(", ")):
                            signature.append(
                                f"{'_' * (idx + 1)}: {converter.convert_type(argument)}"
                            )

                        line = f"def {child_attr_name}(self, {', '.join(signature)}) -> {return_type}: ..."

                        if len(line) > 88:
                            buf.blankline(ensure_single=True)
                            buf.append(f"def {child_attr_name}(")

                            with buf.with_indent_size(buf.indent_size + 2):
                                buf.append("self,")
                                for line in signature:
                                    buf.append(f"{line},")
                                buf.append(f") -> {return_type}: ...\n")
                        else:
                            buf.append(line)

                    elif arguments is None:
                        buf.append(
                            f"def {child_attr_name}(self, *args, **kwargs) -> {return_type}: ..."
                        )

                    elif not arguments:
                        # i.e. takes no arguments
                        buf.append(
                            f"def {child_attr_name}(self) -> {return_type}: ..."
                        )

        buf.blankline(ensure_single=True)
        return str(buf)

    return ''
    def test_indent(self):
        sl = StringList()
        sl.set_indent_size(1)

        sl.append("Indented")

        assert sl == ["\tIndented"]

        sl.set_indent_type("    ")

        sl.append("Indented")

        assert sl == ["\tIndented", "    Indented"]

        expected_list = [
            "class Foo:",
            '',
            "\tdef bar(self, listicle: List[Item]):",
            "\t\t...",
            '',
            "\tdef __repr__(self) -> str:",
            '\t\treturn "Foo()"',
            '',
        ]

        expected_string = dedent("""\
		class Foo:

			def bar(self, listicle: List[Item]):
				...

			def __repr__(self) -> str:
				return "Foo()"
		""")

        sl = StringList()
        sl.append("class Foo:")
        sl.blankline(True)
        sl.set_indent_size(1)
        sl.append("def bar(self, listicle: List[Item]):")
        sl.indent_size += 1
        sl.append("...")
        sl.indent_size -= 1
        sl.blankline(True)
        sl.append("def __repr__(self) -> str:")
        sl.indent_size += 1
        sl.append('return "Foo()"')
        sl.indent_size -= 1
        sl.blankline(True)
        sl.set_indent_size(0)

        assert sl == expected_list
        assert str(sl) == expected_string
        assert sl == expected_string

        sl = StringList()
        sl.append("class Foo:")
        sl.blankline(True)

        with sl.with_indent('\t', 1):
            sl.append("def bar(self, listicle: List[Item]):")
            with sl.with_indent('\t', 2):
                sl.append("...")
            sl.blankline(True)
            sl.append("def __repr__(self) -> str:")
            with sl.with_indent('\t', 2):
                sl.append('return "Foo()"')
            sl.blankline(True)

        assert sl.indent_size == 0

        assert sl == expected_list
        assert str(sl) == expected_string
        assert sl == expected_string

        sl = StringList()
        sl.append("class Foo:")
        sl.blankline(True)

        with sl.with_indent_size(1):
            sl.append("def bar(self, listicle: List[Item]):")
            with sl.with_indent_size(2):
                sl.append("...")
            sl.blankline(True)
            sl.append("def __repr__(self) -> str:")
            with sl.with_indent_size(2):
                sl.append('return "Foo()"')
            sl.blankline(True)

        assert sl.indent_size == 0

        assert sl == expected_list
        assert str(sl) == expected_string
        assert sl == expected_string

        sl = StringList()
        sl.append("class Foo:")
        sl.set_indent(Indent(0, "    "))
        sl.blankline(True)

        with sl.with_indent_size(1):
            sl.append("def bar(self, listicle: List[Item]):")
            with sl.with_indent_size(2):
                sl.append("...")
            sl.blankline(True)
            sl.append("def __repr__(self) -> str:")
            with sl.with_indent_size(2):
                sl.append('return "Foo()"')
            sl.blankline(True)

        assert sl.indent_size == 0

        assert sl == [x.expandtabs(4) for x in expected_list]
        assert str(sl) == expected_string.expandtabs(4)
        assert sl == expected_string.expandtabs(4)

        sl = StringList()
        sl.append("class Foo:")
        sl.set_indent("    ", 0)
        sl.blankline(True)

        with sl.with_indent_size(1):
            sl.append("def bar(self, listicle: List[Item]):")
            with sl.with_indent_size(2):
                sl.append("...")
            sl.blankline(True)
            sl.append("def __repr__(self) -> str:")
            with sl.with_indent_size(2):
                sl.append('return "Foo()"')
            sl.blankline(True)

        assert sl.indent_size == 0

        assert sl == [x.expandtabs(4) for x in expected_list]
        assert str(sl) == expected_string.expandtabs(4)
        assert sl == expected_string.expandtabs(4)

        sl = StringList()
        sl.append("class Foo:")
        sl.blankline(True)

        with sl.with_indent_size(1):
            sl.append("def bar(self, listicle: List[Item]):")
            with sl.with_indent_size(2):
                sl.append("...")
            sl.blankline(True)
            sl.append("def __repr__(self) -> str:")
            with sl.with_indent_size(2):
                with sl.with_indent_type("    "):
                    sl.append('return "Foo()"')
            sl.blankline(True)

        assert sl.indent_size == 0

        expected_list[-2] = '        return "Foo()"'
        assert sl == expected_list
        assert str(sl) == expected_string.replace('\t\treturn "Foo()"',
                                                  '        return "Foo()"')
        assert sl == expected_string.replace('\t\treturn "Foo()"',
                                             '        return "Foo()"')