Example #1
0
def _write_options_page(options: OptionsDataDict, linter: PyLinter) -> None:
    """Create or overwrite the options page."""
    sections: list[str] = [
        ".. This file is auto-generated. Make any changes to the associated\n"
        ".. docs extension in 'doc/exts/pylint_options.py'.\n\n"
        ".. _all-options:",
        get_rst_title("Standard Checkers", "^"),
    ]
    found_extensions = False

    for checker, checker_options in options.items():
        if not found_extensions and checker_options[0].extension:
            sections.append(get_rst_title("Extensions", "^"))
            found_extensions = True
        sections.append(_create_checker_section(checker, checker_options, linter))

    sections_string = "\n\n".join(sections)
    with open(
        PYLINT_USERGUIDE_PATH / "configuration" / "all-options.rst",
        "w",
        encoding="utf-8",
    ) as stream:
        stream.write(
            f"""

{sections_string}"""
        )
Example #2
0
 def get_full_documentation(self, msgs, options, reports, doc=None, module=None):
     result = ""
     checker_title = "%s checker" % (self.name.replace("_", " ").title())
     if module:
         # Provide anchor to link against
         result += ".. _%s:\n\n" % module
     result += "%s\n" % get_rst_title(checker_title, "~")
     if module:
         result += "This checker is provided by ``%s``.\n" % module
     result += "Verbatim name of the checker is ``%s``.\n\n" % self.name
     if doc:
         # Provide anchor to link against
         result += get_rst_title("{} Documentation".format(checker_title), "^")
         result += "%s\n\n" % cleandoc(doc)
     # options might be an empty generator and not be False when casted to boolean
     options = list(options)
     if options:
         result += get_rst_title("{} Options".format(checker_title), "^")
         result += "%s\n" % get_rst_section(None, options)
     if msgs:
         result += get_rst_title("{} Messages".format(checker_title), "^")
         for msgid, msg in sorted(
             msgs.items(), key=lambda kv: (_MSG_ORDER.index(kv[0][0]), kv[1])
         ):
             msg = self.create_message_definition_from_tuple(msgid, msg)
             result += "%s\n" % msg.format_help(checkerref=False)
         result += "\n"
     if reports:
         result += get_rst_title("{} Reports".format(checker_title), "^")
         for report in reports:
             result += ":%s: %s\n" % report[:2]
         result += "\n"
     result += "\n"
     return result
Example #3
0
 def get_full_documentation(
     self,
     msgs: dict[str, MessageDefinitionTuple],
     options: Iterator[tuple[str, OptionDict, Any]],
     reports: tuple[tuple[str, str, ReportsCallable], ...],
     doc: str | None = None,
     module: str | None = None,
     show_options: bool = True,
 ) -> str:
     result = ""
     checker_title = f"{self.name.replace('_', ' ').title()} checker"
     if module:
         # Provide anchor to link against
         result += f".. _{module}:\n\n"
     result += f"{get_rst_title(checker_title, '~')}\n"
     if module:
         result += f"This checker is provided by ``{module}``.\n"
     result += f"Verbatim name of the checker is ``{self.name}``.\n\n"
     if doc:
         # Provide anchor to link against
         result += get_rst_title(f"{checker_title} Documentation", "^")
         result += f"{cleandoc(doc)}\n\n"
     # options might be an empty generator and not be False when cast to boolean
     options_list = list(options)
     if options_list:
         if show_options:
             result += get_rst_title(f"{checker_title} Options", "^")
             result += f"{get_rst_section(None, options_list)}\n"
         else:
             result += f"See also :ref:`{self.name} checker's options' documentation <{self.name}-options>`\n\n"
     if msgs:
         result += get_rst_title(f"{checker_title} Messages", "^")
         for msgid, msg in sorted(msgs.items(),
                                  key=lambda kv:
                                  (_MSG_ORDER.index(kv[0][0]), kv[1])):
             msg_def = self.create_message_definition_from_tuple(msgid, msg)
             result += f"{msg_def.format_help(checkerref=False)}\n"
         result += "\n"
     if reports:
         result += get_rst_title(f"{checker_title} Reports", "^")
         for report in reports:
             result += (
                 ":%s: %s\n" % report[:2]  # pylint: disable=consider-using-f-string
             )
         result += "\n"
     result += "\n"
     return result
Example #4
0
 def get_full_documentation(self,
                            msgs,
                            options,
                            reports,
                            doc=None,
                            module=None):
     result = ""
     checker_title = f"{self.name.replace('_', ' ').title()} checker"
     if module:
         # Provide anchor to link against
         result += f".. _{module}:\n\n"
     result += f"{get_rst_title(checker_title, '~')}\n"
     if module:
         result += f"This checker is provided by ``{module}``.\n"
     result += f"Verbatim name of the checker is ``{self.name}``.\n\n"
     if doc:
         # Provide anchor to link against
         result += get_rst_title(f"{checker_title} Documentation", "^")
         result += f"{cleandoc(doc)}\n\n"
     # options might be an empty generator and not be False when casted to boolean
     options = list(options)
     if options:
         result += get_rst_title(f"{checker_title} Options", "^")
         result += f"{get_rst_section(None, options)}\n"
     if msgs:
         result += get_rst_title(f"{checker_title} Messages", "^")
         for msgid, msg in sorted(msgs.items(),
                                  key=lambda kv:
                                  (_MSG_ORDER.index(kv[0][0]), kv[1])):
             msg = self.create_message_definition_from_tuple(msgid, msg)
             result += f"{msg.format_help(checkerref=False)}\n"
         result += "\n"
     if reports:
         result += get_rst_title(f"{checker_title} Reports", "^")
         for report in reports:
             result += (
                 ":%s: %s\n" % report[:2]  # pylint: disable=consider-using-f-string
             )
         result += "\n"
     result += "\n"
     return result
Example #5
0
    def get_checkers_documentation(self):
        result = get_rst_title("Pylint global options and switches", "-")
        result += """
Pylint provides global options and switches.

"""
        for checker in self.get_checkers():
            name = checker.name
            if name == MAIN_CHECKER_NAME:
                if checker.options:
                    for section, options in checker.options_by_section():
                        if section is None:
                            title = "General options"
                        else:
                            title = "%s options" % section.capitalize()
                        result += get_rst_title(title, "~")
                        result += "%s\n" % get_rst_section(None, options)
        result += get_rst_title("Pylint checkers' options and switches", "-")
        result += """\

Pylint checkers can provide three set of features:

* options that control their execution,
* messages that they can raise,
* reports that they can generate.

Below is a list of all checkers and their features.

"""
        by_checker = self._get_checkers_infos()
        for checker in sorted(by_checker):
            information = by_checker[checker]
            checker = information["checker"]
            del information["checker"]
            result += checker.get_full_documentation(**information)
        return result
Example #6
0
def builder_inited(app: Optional[Sphinx]) -> None:
    """Output full documentation in ReST format for all extension modules."""
    # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/
    base_path = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    # PACKAGE/ --> PACKAGE/pylint/extensions
    ext_path = os.path.join(base_path, "pylint", "extensions")
    modules = []
    doc_files = {}
    for filename in os.listdir(ext_path):
        name, ext = os.path.splitext(filename)
        if name[0] == "_":
            continue
        if ext == ".py":
            modules.append(f"pylint.extensions.{name}")
        elif ext == ".rst":
            doc_files["pylint.extensions." + name] = os.path.join(
                ext_path, filename)
    modules.sort()
    if not modules:
        sys.exit("No Pylint extensions found?")

    linter = PyLinter()
    linter.load_plugin_modules(modules)

    extensions_doc = os.path.join(base_path, "doc", "technical_reference",
                                  "extensions.rst")
    with open(extensions_doc, "w", encoding="utf-8") as stream:
        stream.write(
            get_rst_title("Optional Pylint checkers in the extensions module",
                          "="))
        stream.write("Pylint provides the following optional plugins:\n\n")
        for module in modules:
            stream.write(f"- :ref:`{module}`\n")
        stream.write("\n")
        stream.write("You can activate any or all of these extensions "
                     "by adding a ``load-plugins`` line to the ``MASTER`` "
                     "section of your ``.pylintrc``, for example::\n")
        stream.write("\n    load-plugins=pylint.extensions.docparams,"
                     "pylint.extensions.docstyle\n\n")

        # Print checker documentation to stream
        by_checker = get_plugins_info(linter, doc_files)
        for checker, information in sorted(by_checker.items()):
            checker = information["checker"]
            del information["checker"]
            print(checker.get_full_documentation(**information)[:-1],
                  file=stream)
Example #7
0
def builder_inited(app: Optional[Sphinx]) -> None:
    # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/
    base_path = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    linter = PyLinter()
    linter.load_default_plugins()
    features = os.path.join(base_path, "doc", "user_guide", "checkers",
                            "features.rst")
    with open(features, "w", encoding="utf-8") as stream:
        stream.write(get_rst_title("Pylint features", "="))
        stream.write("""
.. This file is auto-generated. Make any changes to the associated
.. docs extension in 'doc/exts/pylint_features.py'.

""")
        print_full_documentation(linter, stream, False)
Example #8
0
def builder_inited(app: Optional[Sphinx]) -> None:
    """Output full documentation in ReST format for all extension modules."""
    # PACKAGE/docs/exts/pylint_extensions.py --> PACKAGE/
    base_path = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    )
    # PACKAGE/ --> PACKAGE/pylint/extensions
    ext_path = os.path.join(base_path, "pylint", "extensions")
    modules = []
    doc_files = {}
    for filename in os.listdir(ext_path):
        name, ext = os.path.splitext(filename)
        if name[0] == "_":
            continue
        if ext == ".py":
            modules.append(f"pylint.extensions.{name}")
        elif ext == ".rst":
            doc_files["pylint.extensions." + name] = os.path.join(ext_path, filename)
    modules.sort()
    if not modules:
        sys.exit("No Pylint extensions found?")

    linter = PyLinter()
    linter.load_plugin_modules(modules)

    extensions_doc = os.path.join(
        base_path, "doc", "user_guide", "checkers", "extensions.rst"
    )
    with open(extensions_doc, "w", encoding="utf-8") as stream:
        stream.write(get_rst_title("Optional checkers", "="))
        stream.write(
            """
.. This file is auto-generated. Make any changes to the associated
.. docs extension in 'doc/exts/pylint_extensions.py'.

"""
        )
        stream.write("Pylint provides the following optional plugins:\n\n")
        for module in modules:
            stream.write(f"- :ref:`{module}`\n")
        stream.write("\n")
        stream.write(
            "You can activate any or all of these extensions "
            "by adding a ``load-plugins`` line to the ``MAIN`` "
            "section of your ``.pylintrc``, for example::\n"
        )
        stream.write(
            "\n    load-plugins=pylint.extensions.docparams,"
            "pylint.extensions.docstyle\n\n"
        )

        # Print checker documentation to stream
        by_checker = get_plugins_info(linter, doc_files)
        max_len = len(by_checker)
        for i, checker_information in enumerate(sorted(by_checker.items())):
            checker, information = checker_information
            j = -1
            checker = information["checker"]
            del information["checker"]
            if i == max_len - 1:
                # Remove the \n\n at the end of the file
                j = -3
            print(
                checker.get_full_documentation(**information, show_options=False)[:j],
                file=stream,
            )
Example #9
0
def _create_checker_section(
    checker: str, options: list[OptionsData], linter: PyLinter
) -> str:
    checker_string = f".. _{checker}-options:\n\n"
    checker_string += get_rst_title(f"``{checker.capitalize()}`` **Checker**", "-")

    toml_doc = tomlkit.document()
    pylint_tool_table = tomlkit.table(is_super_table=True)
    toml_doc.add(tomlkit.key(["tool", "pylint"]), pylint_tool_table)

    checker_table = tomlkit.table()

    for option in sorted(options, key=lambda x: x.name):
        checker_string += get_rst_title(f"--{option.name}", '"')
        checker_string += f"*{option.optdict.get('help')}*\n\n"
        if option.optdict.get("default") == "":
            checker_string += '**Default:** ``""``\n\n\n'
        else:
            checker_string += f"**Default:**  ``{option.optdict.get('default')}``\n\n\n"

        # Start adding the option to the toml example
        if option.optdict.get("hide_from_config_file"):
            continue

        # Get current value of option
        value = getattr(linter.config, option.name.replace("-", "_"))

        # Create a comment if the option has no value
        if value is None:
            checker_table.add(tomlkit.comment(f"{option.name} ="))
            checker_table.add(tomlkit.nl())
            continue

        # Tomlkit doesn't support regular expressions
        if isinstance(value, re.Pattern):
            value = value.pattern
        elif (
            isinstance(value, (list, tuple))
            and value
            and isinstance(value[0], re.Pattern)
        ):
            value = [i.pattern for i in value]

        # Add to table
        checker_table.add(option.name, value)
        checker_table.add(tomlkit.nl())

    pylint_tool_table.add(options[0].checker.name.lower(), checker_table)
    toml_string = "\n".join(
        f"   {i}" if i else "" for i in tomlkit.dumps(toml_doc).split("\n")
    )
    checker_string += f"""
.. raw:: html

   <details>
   <summary><a>Example configuration section</a></summary>

**Note:** Only ``pylint.tool`` is required, the section title is not. These are the default values.

.. code-block:: toml

{toml_string}

.. raw:: html

   </details>
"""

    return checker_string