"""Support for including Misc/NEWS.""" from __future__ import annotations import re from pathlib import Path from typing import TYPE_CHECKING from docutils import nodes from sphinx.locale import _ as sphinx_gettext from sphinx.util.docutils import SphinxDirective if TYPE_CHECKING: from typing import Final from docutils.nodes import Node from sphinx.application import Sphinx from sphinx.util.typing import ExtensionMetadata BLURB_HEADER = """\ +++++++++++ Python News +++++++++++ """ bpo_issue_re: Final[re.Pattern[str]] = re.compile( "(?:issue #|bpo-)([0-9]+)", re.ASCII ) gh_issue_re: Final[re.Pattern[str]] = re.compile( "gh-(?:issue-)?([0-9]+)", re.ASCII | re.IGNORECASE ) whatsnew_re: Final[re.Pattern[str]] = re.compile( r"^what's new in (.*?)\??$", re.ASCII | re.IGNORECASE | re.MULTILINE ) class MiscNews(SphinxDirective): has_content = False required_arguments = 1 optional_arguments = 0 final_argument_whitespace = False option_spec = {} def run(self) -> list[Node]: # Get content of NEWS file source, _ = self.get_source_info() news_file = Path(source).resolve().parent / self.arguments[0] self.env.note_dependency(news_file) try: news_text = news_file.read_text(encoding="utf-8") except (OSError, UnicodeError): text = sphinx_gettext("The NEWS file is not available.") return [nodes.strong(text, text)] # remove first 3 lines as they are the main heading news_text = news_text.removeprefix(BLURB_HEADER) news_text = bpo_issue_re.sub(r":issue:`\1`", news_text) # Fallback handling for GitHub issues news_text = gh_issue_re.sub(r":gh:`\1`", news_text) news_text = whatsnew_re.sub(r"\1", news_text) self.state_machine.insert_input(news_text.splitlines(), str(news_file)) return [] def setup(app: Sphinx) -> ExtensionMetadata: app.add_directive("miscnews", MiscNews) return { "version": "1.0", "parallel_read_safe": True, "parallel_write_safe": True, }