blob: 387f7f13b4c293c33e64fbee212863d6a741bb3f [file] [log] [blame]
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}