-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
/
Copy pathchanges.py
90 lines (73 loc) · 3.07 KB
/
changes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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,
}