2021-06-08 20:37:55 -04:00
|
|
|
"""Sphinx extensions for performant PEP processing"""
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
2024-06-11 02:23:44 -04:00
|
|
|
import html
|
|
|
|
from pathlib import Path
|
|
|
|
from typing import TYPE_CHECKING, Any
|
2021-06-08 20:37:55 -04:00
|
|
|
|
|
|
|
from docutils.writers.html5_polyglot import HTMLTranslator
|
2022-01-09 13:07:03 -05:00
|
|
|
from sphinx import environment
|
2021-06-08 20:37:55 -04:00
|
|
|
|
2024-06-11 02:23:44 -04:00
|
|
|
from pep_sphinx_extensions.generate_rss import (
|
|
|
|
create_rss_feed,
|
|
|
|
get_from_doctree,
|
|
|
|
pep_abstract,
|
|
|
|
)
|
|
|
|
from pep_sphinx_extensions.pep_processor.html import (
|
|
|
|
pep_html_builder,
|
|
|
|
pep_html_translator,
|
|
|
|
)
|
|
|
|
from pep_sphinx_extensions.pep_processor.parsing import (
|
|
|
|
pep_banner_directive,
|
|
|
|
pep_parser,
|
|
|
|
pep_role,
|
|
|
|
)
|
2022-02-27 17:58:15 -05:00
|
|
|
from pep_sphinx_extensions.pep_processor.transforms import pep_references
|
2021-06-12 13:51:14 -04:00
|
|
|
from pep_sphinx_extensions.pep_zero_generator.pep_index_generator import create_pep_zero
|
2021-06-08 20:37:55 -04:00
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from sphinx.application import Sphinx
|
|
|
|
|
|
|
|
|
2022-03-11 10:34:31 -05:00
|
|
|
def _update_config_for_builder(app: Sphinx) -> None:
|
2022-02-27 17:58:15 -05:00
|
|
|
app.env.document_ids = {} # For PEPReferenceRoleTitleText
|
2023-01-22 05:56:05 -05:00
|
|
|
app.env.settings["builder"] = app.builder.name
|
2021-06-30 15:19:44 -04:00
|
|
|
if app.builder.name == "dirhtml":
|
2023-09-01 00:57:00 -04:00
|
|
|
app.env.settings["pep_url"] = "pep-{:0>4}/"
|
2021-06-30 15:19:44 -04:00
|
|
|
|
2023-08-05 12:22:22 -04:00
|
|
|
app.connect("build-finished", _post_build) # Post-build tasks
|
2022-03-11 10:34:31 -05:00
|
|
|
|
|
|
|
|
|
|
|
def _post_build(app: Sphinx, exception: Exception | None) -> None:
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
from build import create_index_file
|
|
|
|
|
|
|
|
if exception is not None:
|
|
|
|
return
|
2023-08-05 12:22:22 -04:00
|
|
|
|
|
|
|
# internal_builder exists if Sphinx is run by build.py
|
|
|
|
if "internal_builder" not in app.tags:
|
|
|
|
create_index_file(Path(app.outdir), app.builder.name)
|
|
|
|
create_rss_feed(app.doctreedir, app.outdir)
|
2022-03-11 10:34:31 -05:00
|
|
|
|
2021-06-30 15:19:44 -04:00
|
|
|
|
2024-06-11 02:23:44 -04:00
|
|
|
def set_description(
|
|
|
|
app: Sphinx, pagename: str, templatename: str, context: dict[str, Any], doctree
|
|
|
|
) -> None:
|
|
|
|
if not pagename.startswith("pep-"):
|
|
|
|
return
|
|
|
|
|
|
|
|
full_path = Path(app.doctreedir) / f"{pagename}.doctree"
|
|
|
|
abstract = get_from_doctree(full_path, "Abstract")
|
|
|
|
if abstract:
|
|
|
|
if len(abstract) > 256:
|
|
|
|
abstract = abstract[:253] + "..."
|
|
|
|
context["description"] = html.escape(abstract)
|
|
|
|
else:
|
|
|
|
context["description"] = "Python Enhancement Proposals (PEPs)"
|
|
|
|
|
|
|
|
|
2021-06-08 20:37:55 -04:00
|
|
|
def setup(app: Sphinx) -> dict[str, bool]:
|
|
|
|
"""Initialize Sphinx extension."""
|
|
|
|
|
2023-01-22 05:56:05 -05:00
|
|
|
environment.default_settings["pep_url"] = "pep-{:0>4}.html"
|
2022-01-28 18:24:08 -05:00
|
|
|
environment.default_settings["halt_level"] = 2 # Fail on Docutils warning
|
2022-01-09 13:07:03 -05:00
|
|
|
|
2021-06-08 20:37:55 -04:00
|
|
|
# Register plugin logic
|
2022-01-09 13:07:03 -05:00
|
|
|
app.add_builder(pep_html_builder.FileBuilder, override=True)
|
|
|
|
app.add_builder(pep_html_builder.DirectoryBuilder, override=True)
|
2022-01-16 17:33:05 -05:00
|
|
|
|
2021-06-08 20:37:55 -04:00
|
|
|
app.add_source_parser(pep_parser.PEPParser) # Add PEP transforms
|
2022-01-16 17:33:05 -05:00
|
|
|
|
2021-06-30 15:19:44 -04:00
|
|
|
app.set_translator("html", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides (html builder)
|
|
|
|
app.set_translator("dirhtml", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides (dirhtml builder)
|
2022-01-16 17:33:05 -05:00
|
|
|
|
|
|
|
app.add_role("pep", pep_role.PEPRole(), override=True) # Transform PEP references to links
|
|
|
|
|
2022-02-27 17:58:15 -05:00
|
|
|
app.add_post_transform(pep_references.PEPReferenceRoleTitleText)
|
|
|
|
|
2022-08-02 23:48:56 -04:00
|
|
|
# Register custom directives
|
|
|
|
app.add_directive(
|
|
|
|
"pep-banner", pep_banner_directive.PEPBanner)
|
|
|
|
app.add_directive(
|
|
|
|
"canonical-doc", pep_banner_directive.CanonicalDocBanner)
|
|
|
|
app.add_directive(
|
|
|
|
"canonical-pypa-spec", pep_banner_directive.CanonicalPyPASpecBanner)
|
2024-01-12 02:20:09 -05:00
|
|
|
app.add_directive(
|
|
|
|
"canonical-typing-spec", pep_banner_directive.CanonicalTypingSpecBanner)
|
2024-04-14 09:35:25 -04:00
|
|
|
app.add_directive("rejected", pep_banner_directive.RejectedBanner)
|
|
|
|
app.add_directive("superseded", pep_banner_directive.SupersededBanner)
|
|
|
|
app.add_directive("withdrawn", pep_banner_directive.WithdrawnBanner)
|
2022-08-02 23:48:56 -04:00
|
|
|
|
2022-01-16 17:33:05 -05:00
|
|
|
# Register event callbacks
|
2021-06-30 15:19:44 -04:00
|
|
|
app.connect("builder-inited", _update_config_for_builder) # Update configuration values for builder used
|
2022-01-16 17:33:05 -05:00
|
|
|
app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook
|
2024-06-11 02:23:44 -04:00
|
|
|
app.connect('html-page-context', set_description)
|
2021-06-08 20:37:55 -04:00
|
|
|
|
|
|
|
# Mathematics rendering
|
2024-04-23 06:38:09 -04:00
|
|
|
inline_maths = HTMLTranslator.visit_math, None
|
|
|
|
block_maths = HTMLTranslator.visit_math_block, None
|
2021-06-08 20:37:55 -04:00
|
|
|
app.add_html_math_renderer("maths_to_html", inline_maths, block_maths) # Render maths to HTML
|
|
|
|
|
|
|
|
# Parallel safety: https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata
|
|
|
|
return {"parallel_read_safe": True, "parallel_write_safe": True}
|