From f456e6fbc34d184e322b2a88665e7bd6f0685019 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 25 Oct 2024 15:34:20 +0200 Subject: [PATCH 1/4] [3.11] gh-121277: Allow `.. versionadded:: next` in docs (GH-121278) (#124718) Make `versionchanged:: next`` expand to current (unreleased) version. When a new CPython release is cut, the release manager will replace all such occurences of "next" with the just-released version. (See the issue for release-tools and devguide PRs.) Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> (cherry picked from commit 7d24ea9db3e8fdca52058629c9ba577aba3d8e5c) gh-121277: Raise nice error on `next` as second argument to deprecated-removed (GH-124623) (cherry-picked from e349f73a5ad2856b0a7cbe4aef7cc081c7aed777) --- Doc/tools/extensions/pyspecific.py | 29 +++++++++++++++++-- ...-07-19-12-22-48.gh-issue-121277.wF_zKd.rst | 2 ++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Documentation/2024-07-19-12-22-48.gh-issue-121277.wF_zKd.rst diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index c849a4d3875029..b102382dec6916 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -414,7 +414,22 @@ def run(self): return PyMethod.run(self) -# Support for documenting version of removal in deprecations +# 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(Directive): has_content = True @@ -430,7 +445,13 @@ def run(self): node = addnodes.versionmodified() node.document = self.state.document node['type'] = 'deprecated-removed' - version = (self.arguments[0], self.arguments[1]) + version = ( + expand_version_arg(self.arguments[0], self.config.release), + self.arguments[1], + ) + if version[1] == 'next': + raise ValueError( + 'deprecated-removed:: second argument cannot be `next`') node['version'] = version env = self.state.document.settings.env current_version = tuple(int(e) for e in env.config.version.split('.')) @@ -713,6 +734,10 @@ def setup(app): app.add_directive('availability', Availability) app.add_directive('audit-event', AuditEvent) app.add_directive('audit-event-table', AuditEventListDirective) + 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_builder(suspicious.CheckSuspiciousMarkupBuilder) diff --git a/Misc/NEWS.d/next/Documentation/2024-07-19-12-22-48.gh-issue-121277.wF_zKd.rst b/Misc/NEWS.d/next/Documentation/2024-07-19-12-22-48.gh-issue-121277.wF_zKd.rst new file mode 100644 index 00000000000000..60f75ae0c21326 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2024-07-19-12-22-48.gh-issue-121277.wF_zKd.rst @@ -0,0 +1,2 @@ +Writers of CPython's documentation can now use ``next`` as the version for +the ``versionchanged``, ``versionadded``, ``deprecated`` directives. From 4b97d2bc8d4fb81318173d426cf366a9f323d66e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 11 Dec 2024 15:16:18 +0100 Subject: [PATCH 2/4] Import VersionChange sphinx.domains.changeset.VersionChange exists at least since Sphinx 2.1, according to: https://www.sphinx-doc.org/en/master/extdev/deprecated.html --- Doc/tools/extensions/pyspecific.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index b102382dec6916..6cad6b5f68edaf 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -22,6 +22,7 @@ from sphinx import addnodes from sphinx.builders import Builder from sphinx.domains.python import PyFunction, PyMethod +from sphinx.domains.changeset import VersionChange from sphinx.errors import NoUri from sphinx.locale import _ as sphinx_gettext from sphinx.util import logging From f94480737e795b837b7d2916ef904d252ef5ae37 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 11 Dec 2024 15:24:46 +0100 Subject: [PATCH 3/4] Get config from env --- Doc/tools/extensions/pyspecific.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 6cad6b5f68edaf..7a118663fd35e4 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -446,15 +446,15 @@ def run(self): node = addnodes.versionmodified() node.document = self.state.document node['type'] = 'deprecated-removed' + env = self.state.document.settings.env version = ( - expand_version_arg(self.arguments[0], self.config.release), + expand_version_arg(self.arguments[0], env.config.release), self.arguments[1], ) if version[1] == 'next': raise ValueError( 'deprecated-removed:: second argument cannot be `next`') node['version'] = version - env = self.state.document.settings.env current_version = tuple(int(e) for e in env.config.version.split('.')) removed_version = tuple(int(e) for e in self.arguments[1].split('.')) if current_version < removed_version: From ba0529bdae2b17d5bbbc887f1778619cbcbd4d37 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 11 Dec 2024 15:30:13 +0100 Subject: [PATCH 4/4] Use version, not arguments directly --- Doc/tools/extensions/pyspecific.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 7a118663fd35e4..c71ad641d7c07b 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -456,13 +456,13 @@ def run(self): 'deprecated-removed:: second argument cannot be `next`') node['version'] = version current_version = tuple(int(e) for e in env.config.version.split('.')) - removed_version = tuple(int(e) for e in self.arguments[1].split('.')) + removed_version = tuple(int(e) for e in version[1].split('.')) if current_version < removed_version: label = self._deprecated_label else: label = self._removed_label - text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) + text = label.format(deprecated=version[0], removed=version[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], self.lineno+1)