Skip to content

Commit 0a7db33

Browse files
[3.13] gh-155095: Fix docs changes builder for our custom directives (GH-155100) (GH-157357) (#157358)
(cherry picked from commit 94dc051) Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent cdc4849 commit 0a7db33

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

.github/workflows/reusable-docs.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ jobs:
8686
--fail-if-regression \
8787
--fail-if-improved \
8888
--fail-if-new-news-nit
89+
- name: 'Build list of changes'
90+
run: |
91+
make -C Doc/ PYTHON=../python changes
8992
9093
# Run "doctest" on HEAD as new syntax doesn't exist in the latest stable release
9194
doctest:

Doc/tools/extensions/changes.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from docutils import nodes
88
from sphinx import addnodes
9+
from sphinx.builders.changes import ChangesBuilder
910
from sphinx.domains.changeset import (
1011
VersionChange,
1112
versionlabel_classes,
@@ -17,6 +18,7 @@
1718
if TYPE_CHECKING:
1819
from docutils.nodes import Node
1920
from sphinx.application import Sphinx
21+
from sphinx.environment import BuildEnvironment
2022
from sphinx.util.typing import ExtensionMetadata
2123

2224

@@ -146,6 +148,32 @@ def _add_glossary_link(cls, inline: nodes.inline) -> None:
146148
break
147149

148150

151+
def _fixup_changesets(app: Sphinx, env: BuildEnvironment) -> None:
152+
changesets = env.get_domain("changeset").changesets
153+
154+
# The changeset domain records each entry's plain text before SoftDeprecated
155+
# replaces the :term:, so strip the markup before the changes builder renders it.
156+
for entries in changesets.values():
157+
for i, entry in enumerate(entries):
158+
if entry.type == "soft-deprecated":
159+
entries[i] = entry._replace(
160+
content=SoftDeprecated._TERM_RE.sub(r"\1", entry.content)
161+
)
162+
163+
# DeprecatedRemoved entries are recorded under their (deprecated,
164+
# removed) version tuple, which the changes builder ignores.
165+
# Re-file them under both versions.
166+
for versions in [v for v in changesets if isinstance(v, tuple)]:
167+
deprecated, removed = versions
168+
for entry in changesets.pop(versions):
169+
changesets.setdefault(deprecated, []).append(
170+
entry._replace(type="deprecated")
171+
)
172+
changesets.setdefault(removed, []).append(
173+
entry._replace(type="versionremoved")
174+
)
175+
176+
149177
def setup(app: Sphinx) -> ExtensionMetadata:
150178
# Override Sphinx's directives with support for 'next'
151179
app.add_directive("versionadded", PyVersionChange, override=True)
@@ -155,9 +183,15 @@ def setup(app: Sphinx) -> ExtensionMetadata:
155183

156184
# Register the ``.. deprecated-removed::`` directive
157185
app.add_directive("deprecated-removed", DeprecatedRemoved)
186+
# _fixup_changesets() changes these entries to 'deprecated'/'versionremoved'
187+
ChangesBuilder.typemap["deprecated-removed"] = "deprecated-removed"
158188

159189
# Register the ``.. soft-deprecated::`` directive
160190
app.add_directive("soft-deprecated", SoftDeprecated)
191+
ChangesBuilder.typemap["soft-deprecated"] = "soft deprecated"
192+
193+
# Repair the recorded changesets for the couple of custom directives above
194+
app.connect("env-updated", _fixup_changesets)
161195

162196
return {
163197
"version": "1.0",

0 commit comments

Comments
 (0)