]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] GH-121970: Extract ``changes`` into a new extension (GH-129105) (#129110)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 20 Jan 2025 23:59:59 +0000 (00:59 +0100)
committerGitHub <noreply@github.com>
Mon, 20 Jan 2025 23:59:59 +0000 (23:59 +0000)
GH-121970: Extract ``changes`` into a new extension (GH-129105)
(cherry picked from commit e54ac3b69edacf4149988150591226df1397d127)

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Doc/conf.py
Doc/tools/extensions/changes.py [new file with mode: 0644]
Doc/tools/extensions/pyspecific.py

index 4c74040976959c26e894279fdf31e848eb733436..e2988604c9b0b50d661668147535937e7ec4e8ee 100644 (file)
@@ -25,6 +25,7 @@ extensions = [
     'audit_events',
     'availability',
     'c_annotations',
+    'changes',
     'glossary_search',
     'lexers',
     'pyspecific',
diff --git a/Doc/tools/extensions/changes.py b/Doc/tools/extensions/changes.py
new file mode 100644 (file)
index 0000000..8de5e7f
--- /dev/null
@@ -0,0 +1,90 @@
+"""Support for documenting version of changes, additions, deprecations."""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from sphinx.domains.changeset import (
+    VersionChange,
+    versionlabel_classes,
+    versionlabels,
+)
+from sphinx.locale import _ as sphinx_gettext
+
+if TYPE_CHECKING:
+    from docutils.nodes import Node
+    from sphinx.application import Sphinx
+    from sphinx.util.typing import ExtensionMetadata
+
+
+def expand_version_arg(argument: str, release: str) -> str:
+    """Expand "next" to the current version"""
+    if argument == "next":
+        return sphinx_gettext("{} (unreleased)").format(release)
+    return argument
+
+
+class PyVersionChange(VersionChange):
+    def run(self) -> list[Node]:
+        # Replace the 'next' special token with the current development version
+        self.arguments[0] = expand_version_arg(
+            self.arguments[0], self.config.release
+        )
+        return super().run()
+
+
+class DeprecatedRemoved(VersionChange):
+    required_arguments = 2
+
+    _deprecated_label = sphinx_gettext(
+        "Deprecated since version %s, will be removed in version %s"
+    )
+    _removed_label = sphinx_gettext(
+        "Deprecated since version %s, removed in version %s"
+    )
+
+    def run(self) -> list[Node]:
+        # Replace the first two arguments (deprecated version and removed version)
+        # with a single tuple of both versions.
+        version_deprecated = expand_version_arg(
+            self.arguments[0], self.config.release
+        )
+        version_removed = self.arguments.pop(1)
+        if version_removed == "next":
+            raise ValueError(
+                "deprecated-removed:: second argument cannot be `next`"
+            )
+        self.arguments[0] = version_deprecated, version_removed
+
+        # Set the label based on if we have reached the removal version
+        current_version = tuple(map(int, self.config.version.split(".")))
+        removed_version = tuple(map(int, version_removed.split(".")))
+        if current_version < removed_version:
+            versionlabels[self.name] = self._deprecated_label
+            versionlabel_classes[self.name] = "deprecated"
+        else:
+            versionlabels[self.name] = self._removed_label
+            versionlabel_classes[self.name] = "removed"
+        try:
+            return super().run()
+        finally:
+            # reset versionlabels and versionlabel_classes
+            versionlabels[self.name] = ""
+            versionlabel_classes[self.name] = ""
+
+
+def setup(app: Sphinx) -> ExtensionMetadata:
+    # Override Sphinx's directives with support for 'next'
+    app.add_directive("versionadded", PyVersionChange, override=True)
+    app.add_directive("versionchanged", PyVersionChange, override=True)
+    app.add_directive("versionremoved", PyVersionChange, override=True)
+    app.add_directive("deprecated", PyVersionChange, override=True)
+
+    # Register the ``.. deprecated-removed::`` directive
+    app.add_directive("deprecated-removed", DeprecatedRemoved)
+
+    return {
+        "version": "1.0",
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
+    }
index f09574d1ad34a41b6cc2a4353f3ae15192ef70e1..7e4b452aca7d53dfa845e83a034c576a7dde6296 100644 (file)
@@ -21,7 +21,6 @@ from docutils.parsers.rst import directives
 from docutils.utils import new_document, unescape
 from sphinx import addnodes
 from sphinx.builders import Builder
-from sphinx.domains.changeset import VersionChange, versionlabels, versionlabel_classes
 from sphinx.domains.python import PyFunction, PyMethod, PyModule
 from sphinx.locale import _ as sphinx_gettext
 from sphinx.util.docutils import SphinxDirective
@@ -184,57 +183,6 @@ class PyAbstractMethod(PyMethod):
         return PyMethod.run(self)
 
 
-# Support for documenting version of changes, additions, deprecations
-
-def expand_version_arg(argument, release):
-    """Expand "next" to the current version"""
-    if argument == 'next':
-        return sphinx_gettext('{} (unreleased)').format(release)
-    return argument
-
-
-class PyVersionChange(VersionChange):
-    def run(self):
-        # Replace the 'next' special token with the current development version
-        self.arguments[0] = expand_version_arg(self.arguments[0],
-                                               self.config.release)
-        return super().run()
-
-
-class DeprecatedRemoved(VersionChange):
-    required_arguments = 2
-
-    _deprecated_label = sphinx_gettext('Deprecated since version %s, will be removed in version %s')
-    _removed_label = sphinx_gettext('Deprecated since version %s, removed in version %s')
-
-    def run(self):
-        # Replace the first two arguments (deprecated version and removed version)
-        # with a single tuple of both versions.
-        version_deprecated = expand_version_arg(self.arguments[0],
-                                                self.config.release)
-        version_removed = self.arguments.pop(1)
-        if version_removed == 'next':
-            raise ValueError(
-                'deprecated-removed:: second argument cannot be `next`')
-        self.arguments[0] = version_deprecated, version_removed
-
-        # Set the label based on if we have reached the removal version
-        current_version = tuple(map(int, self.config.version.split('.')))
-        removed_version = tuple(map(int,  version_removed.split('.')))
-        if current_version < removed_version:
-            versionlabels[self.name] = self._deprecated_label
-            versionlabel_classes[self.name] = 'deprecated'
-        else:
-            versionlabels[self.name] = self._removed_label
-            versionlabel_classes[self.name] = 'removed'
-        try:
-            return super().run()
-        finally:
-            # reset versionlabels and versionlabel_classes
-            versionlabels[self.name] = ''
-            versionlabel_classes[self.name] = ''
-
-
 # Support for including Misc/NEWS
 
 issue_re = re.compile('(?:[Ii]ssue #|bpo-)([0-9]+)', re.I)
@@ -417,11 +365,6 @@ def setup(app):
     app.add_role('issue', issue_role)
     app.add_role('gh', gh_issue_role)
     app.add_directive('impl-detail', ImplementationDetail)
-    app.add_directive('versionadded', PyVersionChange, override=True)
-    app.add_directive('versionchanged', PyVersionChange, override=True)
-    app.add_directive('versionremoved', PyVersionChange, override=True)
-    app.add_directive('deprecated', PyVersionChange, override=True)
-    app.add_directive('deprecated-removed', DeprecatedRemoved)
     app.add_builder(PydocTopicsBuilder)
     app.add_object_type('opcode', 'opcode', '%s (opcode)', parse_opcode_signature)
     app.add_object_type('pdbcommand', 'pdbcmd', '%s (pdb command)', parse_pdb_command)