From 3a01a7302308f30e6fc14f949d7d54aad1abf71d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 2 Feb 2025 12:49:00 +0000 Subject: [PATCH 1/3] Extract ``misc_news`` into a new extension --- Doc/conf.py | 1 + Doc/make.bat | 10 ++--- Doc/tools/extensions/misc_news.py | 68 ++++++++++++++++++++++++++++++ Doc/tools/extensions/pyspecific.py | 41 ------------------ 4 files changed, 73 insertions(+), 47 deletions(-) create mode 100644 Doc/tools/extensions/misc_news.py diff --git a/Doc/conf.py b/Doc/conf.py index 1aeecaeb3073f5..94af54084ee338 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -28,6 +28,7 @@ 'changes', 'glossary_search', 'lexers', + 'misc_news', 'pydoc_topics', 'pyspecific', 'sphinx.ext.coverage', diff --git a/Doc/make.bat b/Doc/make.bat index ede793ed3c6d70..99f0d5c44f0098 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -127,16 +127,14 @@ goto end :build if not exist "%BUILDDIR%" mkdir "%BUILDDIR%" -rem PY_MISC_NEWS_DIR is also used by our Sphinx extension in tools/extensions/pyspecific.py -if not defined PY_MISC_NEWS_DIR set PY_MISC_NEWS_DIR=%BUILDDIR%\%1 -if not exist "%PY_MISC_NEWS_DIR%" mkdir "%PY_MISC_NEWS_DIR%" +if not exist build mkdir build if exist ..\Misc\NEWS ( - echo.Copying Misc\NEWS to %PY_MISC_NEWS_DIR%\NEWS - copy ..\Misc\NEWS "%PY_MISC_NEWS_DIR%\NEWS" > nul + echo.Copying existing Misc\NEWS file to Doc\build\NEWS + copy ..\Misc\NEWS build\NEWS > nul ) else if exist ..\Misc\NEWS.D ( if defined BLURB ( echo.Merging Misc/NEWS with %BLURB% - %BLURB% merge -f "%PY_MISC_NEWS_DIR%\NEWS" + %BLURB% merge -f build\NEWS ) else ( echo.No Misc/NEWS file and Blurb is not available. exit /B 1 diff --git a/Doc/tools/extensions/misc_news.py b/Doc/tools/extensions/misc_news.py new file mode 100644 index 00000000000000..056a42162f0475 --- /dev/null +++ b/Doc/tools/extensions/misc_news.py @@ -0,0 +1,68 @@ +"""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 + + +issue_re: Final[re.Pattern[str]] = re.compile( + "(?:[Ii]ssue #|bpo-)([0-9]+)", re.ASCII | re.IGNORECASE +) +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: + text = sphinx_gettext("The NEWS file is not available.") + return [nodes.strong(text, text)] + + news_text = 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) + + # remove first 3 lines as they are the main heading + lines = [".. default-role:: py:obj", ""] + news_text.splitlines()[3:] + self.state_machine.insert_input(lines, 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, + } diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index f363dfd4216929..57cf80a7e77324 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -141,46 +141,6 @@ def run(self): return PyMethod.run(self) -# Support for including Misc/NEWS - -issue_re = re.compile('(?:[Ii]ssue #|bpo-)([0-9]+)', re.I) -gh_issue_re = re.compile('(?:gh-issue-|gh-)([0-9]+)', re.I) -whatsnew_re = re.compile(r"(?im)^what's new in (.*?)\??$") - - -class MiscNews(SphinxDirective): - has_content = False - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = False - option_spec = {} - - def run(self): - fname = self.arguments[0] - source = self.state_machine.input_lines.source( - self.lineno - self.state_machine.input_offset - 1) - source_dir = getenv('PY_MISC_NEWS_DIR') - if not source_dir: - source_dir = path.dirname(path.abspath(source)) - fpath = path.join(source_dir, fname) - self.env.note_dependency(path.abspath(fpath)) - try: - with io.open(fpath, encoding='utf-8') as fp: - content = fp.read() - except Exception: - text = 'The NEWS file is not available.' - node = nodes.strong(text, text) - return [node] - content = issue_re.sub(r':issue:`\1`', content) - # Fallback handling for the GitHub issue - content = gh_issue_re.sub(r':gh:`\1`', content) - content = whatsnew_re.sub(r'\1', content) - # remove first 3 lines as they are the main heading - lines = ['.. default-role:: obj', ''] + content.splitlines()[3:] - self.state_machine.insert_input(lines, fname) - return [] - - # Support for documenting Opcodes opcode_sig_re = re.compile(r'(\w+(?:\+\d)?)(?:\s*\((.*)\))?') @@ -268,6 +228,5 @@ def setup(app): app.add_directive_to_domain('py', 'awaitablefunction', PyAwaitableFunction) app.add_directive_to_domain('py', 'awaitablemethod', PyAwaitableMethod) app.add_directive_to_domain('py', 'abstractmethod', PyAbstractMethod) - app.add_directive('miscnews', MiscNews) app.connect('env-check-consistency', patch_pairindextypes) return {'version': '1.0', 'parallel_read_safe': True} From 6f3cb21235c41042759d3fc664b4c5e5b2007c05 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:04:53 +0000 Subject: [PATCH 2/3] =?UTF-8?q?B=C3=A9n=C3=A9dikt's=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Doc/tools/extensions/misc_news.py | 8 ++++---- Misc/NEWS.d/3.5.3rc1.rst | 2 +- Misc/NEWS.d/3.6.0a4.rst | 2 +- Misc/NEWS.d/3.6.0b1.rst | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/tools/extensions/misc_news.py b/Doc/tools/extensions/misc_news.py index 056a42162f0475..975cd9dd266773 100644 --- a/Doc/tools/extensions/misc_news.py +++ b/Doc/tools/extensions/misc_news.py @@ -18,8 +18,8 @@ from sphinx.util.typing import ExtensionMetadata -issue_re: Final[re.Pattern[str]] = re.compile( - "(?:[Ii]ssue #|bpo-)([0-9]+)", re.ASCII | re.IGNORECASE +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 @@ -43,11 +43,11 @@ def run(self) -> list[Node]: self.env.note_dependency(news_file) try: news_text = news_file.read_text(encoding="utf-8") - except OSError: + except (OSError, UnicodeError): text = sphinx_gettext("The NEWS file is not available.") return [nodes.strong(text, text)] - news_text = issue_re.sub(r":issue:`\1`", news_text) + 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) diff --git a/Misc/NEWS.d/3.5.3rc1.rst b/Misc/NEWS.d/3.5.3rc1.rst index 2424604249a65c..cfc729dd82556f 100644 --- a/Misc/NEWS.d/3.5.3rc1.rst +++ b/Misc/NEWS.d/3.5.3rc1.rst @@ -1146,7 +1146,7 @@ after a commit. .. section: Library A new version of typing.py from https://github.com/python/typing: -Collection (only for 3.6) (Issue #27598). Add FrozenSet to __all__ +Collection (only for 3.6) (issue #27598). Add FrozenSet to __all__ (upstream #261). Fix crash in _get_type_vars() (upstream #259). Remove the dict constraint in ForwardRef._eval_type (upstream #252). diff --git a/Misc/NEWS.d/3.6.0a4.rst b/Misc/NEWS.d/3.6.0a4.rst index 3abbdecb57038b..6f3f5262e5749d 100644 --- a/Misc/NEWS.d/3.6.0a4.rst +++ b/Misc/NEWS.d/3.6.0a4.rst @@ -177,7 +177,7 @@ Support keyword arguments to zlib.decompress(). Patch by Xiang Zhang. .. section: Library Prevent segfault after interpreter re-initialization due to ref count -problem introduced in code for Issue #27038 in 3.6.0a3. Patch by Xiang +problem introduced in code for issue #27038 in 3.6.0a3. Patch by Xiang Zhang. .. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index bd54cf601d053b..1e2dcdd6c642bb 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -1137,7 +1137,7 @@ chunked transfer-encoding. .. section: Library A new version of typing.py from https://github.com/python/typing: - -Collection (only for 3.6) (Issue #27598) - Add FrozenSet to __all__ +Collection (only for 3.6) (issue #27598) - Add FrozenSet to __all__ (upstream #261) - fix crash in _get_type_vars() (upstream #259) - Remove the dict constraint in ForwardRef._eval_type (upstream #252) From 7b4aa2a960952d1618b4f28b340fda5742ea75d2 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:06:18 +0000 Subject: [PATCH 3/3] Strip blurb "Python News" header --- Doc/tools/extensions/misc_news.py | 13 ++++++++++--- Doc/whatsnew/changelog.rst | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Doc/tools/extensions/misc_news.py b/Doc/tools/extensions/misc_news.py index 975cd9dd266773..a24c440595ee92 100644 --- a/Doc/tools/extensions/misc_news.py +++ b/Doc/tools/extensions/misc_news.py @@ -18,6 +18,12 @@ 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 ) @@ -47,14 +53,15 @@ def run(self) -> list[Node]: 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) - # remove first 3 lines as they are the main heading - lines = [".. default-role:: py:obj", ""] + news_text.splitlines()[3:] - self.state_machine.insert_input(lines, str(news_file)) + self.state_machine.insert_input(news_text.splitlines(), str(news_file)) return [] diff --git a/Doc/whatsnew/changelog.rst b/Doc/whatsnew/changelog.rst index b4356143659031..e796d4157cec76 100644 --- a/Doc/whatsnew/changelog.rst +++ b/Doc/whatsnew/changelog.rst @@ -1,5 +1,7 @@ .. _changelog: +.. default-role:: py:obj + +++++++++ Changelog +++++++++