[3.11] gh-121277: Allow .. versionadded:: next in docs (GH-121278) (#124718) (#127827)

* [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 7d24ea9db3)

gh-121277: Raise nice error on `next` as second argument to deprecated-removed (GH-124623)

(cherry-picked from e349f73a5a)

* 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

* Get config from env

* Use version, not arguments directly
This commit is contained in:
Petr Viktorin 2024-12-11 15:58:46 +01:00 committed by GitHub
parent 976c4f2a9d
commit f0895aa9c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 5 deletions

View File

@ -22,6 +22,7 @@
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.domains.python import PyFunction, PyMethod from sphinx.domains.python import PyFunction, PyMethod
from sphinx.domains.changeset import VersionChange
from sphinx.errors import NoUri from sphinx.errors import NoUri
from sphinx.locale import _ as sphinx_gettext from sphinx.locale import _ as sphinx_gettext
from sphinx.util import logging from sphinx.util import logging
@ -414,7 +415,22 @@ def run(self):
return PyMethod.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): class DeprecatedRemoved(Directive):
has_content = True has_content = True
@ -430,17 +446,23 @@ def run(self):
node = addnodes.versionmodified() node = addnodes.versionmodified()
node.document = self.state.document node.document = self.state.document
node['type'] = 'deprecated-removed' node['type'] = 'deprecated-removed'
version = (self.arguments[0], self.arguments[1])
node['version'] = version
env = self.state.document.settings.env env = self.state.document.settings.env
version = (
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
current_version = tuple(int(e) for e in env.config.version.split('.')) 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: if current_version < removed_version:
label = self._deprecated_label label = self._deprecated_label
else: else:
label = self._removed_label 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: if len(self.arguments) == 3:
inodes, messages = self.state.inline_text(self.arguments[2], inodes, messages = self.state.inline_text(self.arguments[2],
self.lineno+1) self.lineno+1)
@ -713,6 +735,10 @@ def setup(app):
app.add_directive('availability', Availability) app.add_directive('availability', Availability)
app.add_directive('audit-event', AuditEvent) app.add_directive('audit-event', AuditEvent)
app.add_directive('audit-event-table', AuditEventListDirective) 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_directive('deprecated-removed', DeprecatedRemoved)
app.add_builder(PydocTopicsBuilder) app.add_builder(PydocTopicsBuilder)
app.add_builder(suspicious.CheckSuspiciousMarkupBuilder) app.add_builder(suspicious.CheckSuspiciousMarkupBuilder)

View File

@ -0,0 +1,2 @@
Writers of CPython's documentation can now use ``next`` as the version for
the ``versionchanged``, ``versionadded``, ``deprecated`` directives.