| from __future__ import annotations |
| |
| import json |
| import os |
| import textwrap |
| from pathlib import Path |
| from typing import Any |
| |
| from sphinx.addnodes import document |
| from sphinx.application import Sphinx |
| from sphinx.builders.html import StandaloneHTMLBuilder |
| from sphinx.environment import BuildEnvironment |
| |
| from mypy.main import define_options |
| |
| |
| class MypyHTMLBuilder(StandaloneHTMLBuilder): |
| strict_file: Path |
| |
| def __init__(self, app: Sphinx, env: BuildEnvironment) -> None: |
| super().__init__(app, env) |
| self._ref_to_doc = {} |
| self.strict_file = Path(self.srcdir) / "strict_list.rst" |
| self._add_strict_list() |
| |
| def write_doc(self, docname: str, doctree: document) -> None: |
| super().write_doc(docname, doctree) |
| self._ref_to_doc.update({_id: docname for _id in doctree.ids}) |
| |
| def _add_strict_list(self) -> None: |
| strict_flags: list[str] |
| _, strict_flags, _ = define_options() |
| strict_part = ", ".join(f":option:`{s} <mypy {s}>`" for s in strict_flags) |
| if ( |
| not strict_part |
| or strict_part.isspace() |
| or len(strict_part) < 20 |
| or len(strict_part) > 2000 |
| ): |
| raise ValueError(f"{strict_part=}, which doesn't look right (by a simple heuristic).") |
| self.strict_file.write_text( |
| "For this version of mypy, the list of flags enabled by strict is: " + strict_part |
| ) |
| |
| def _verify_error_codes(self) -> None: |
| from mypy.errorcodes import error_codes |
| |
| missing_error_codes = {c for c in error_codes if f"code-{c}" not in self._ref_to_doc} |
| if missing_error_codes: |
| raise ValueError( |
| f"Some error codes are not documented: {', '.join(sorted(missing_error_codes))}" |
| ) |
| |
| def _write_ref_redirector(self) -> None: |
| if os.getenv("VERIFY_MYPY_ERROR_CODES"): |
| self._verify_error_codes() |
| p = Path(self.outdir) / "_refs.html" |
| data = f""" |
| <html> |
| <body> |
| <script> |
| const ref_to_doc = {json.dumps(self._ref_to_doc)}; |
| const hash = window.location.hash.substring(1); |
| const doc = ref_to_doc[hash]; |
| if (doc) {{ |
| window.location.href = doc + '.html' + '#' + hash; |
| }} else {{ |
| window.document.innerText = 'Unknown reference: ' + hash; |
| }} |
| </script> |
| </body> |
| </html> |
| """ |
| p.write_text(textwrap.dedent(data)) |
| |
| def finish(self) -> None: |
| super().finish() |
| self._write_ref_redirector() |
| self.strict_file.unlink() |
| |
| |
| def setup(app: Sphinx) -> dict[str, Any]: |
| app.add_builder(MypyHTMLBuilder, override=True) |
| |
| return {"version": "0.1", "parallel_read_safe": True, "parallel_write_safe": True} |