summaryrefslogtreecommitdiffstats
path: root/Doc/tools/extensions
diff options
context:
space:
mode:
authorAdam Turner <9087854+AA-Turner@users.noreply.github.com>2024-10-09 20:50:03 (GMT)
committerGitHub <noreply@github.com>2024-10-09 20:50:03 (GMT)
commitcbfd39247983309a9ef0ae6da6c61cc71665b967 (patch)
tree26584db28bf4d8edacdafe4eb09cbb3293b7e5cb /Doc/tools/extensions
parentf2cb39947093feda3ff85b8dc820922cc5e5f954 (diff)
downloadcpython-cbfd39247983309a9ef0ae6da6c61cc71665b967.zip
cpython-cbfd39247983309a9ef0ae6da6c61cc71665b967.tar.gz
cpython-cbfd39247983309a9ef0ae6da6c61cc71665b967.tar.bz2
GH-121970: Extract ``availability`` into a new extension (#125082)
Diffstat (limited to 'Doc/tools/extensions')
-rw-r--r--Doc/tools/extensions/availability.py125
-rw-r--r--Doc/tools/extensions/pyspecific.py76
2 files changed, 125 insertions, 76 deletions
diff --git a/Doc/tools/extensions/availability.py b/Doc/tools/extensions/availability.py
new file mode 100644
index 0000000..47833fd
--- /dev/null
+++ b/Doc/tools/extensions/availability.py
@@ -0,0 +1,125 @@
+"""Support for documenting platform availability"""
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from docutils import nodes
+from sphinx import addnodes
+from sphinx.util import logging
+from sphinx.util.docutils import SphinxDirective
+
+if TYPE_CHECKING:
+ from sphinx.application import Sphinx
+ from sphinx.util.typing import ExtensionMetadata
+
+logger = logging.getLogger("availability")
+
+# known platform, libc, and threading implementations
+_PLATFORMS = frozenset({
+ "AIX",
+ "Android",
+ "BSD",
+ "DragonFlyBSD",
+ "Emscripten",
+ "FreeBSD",
+ "GNU/kFreeBSD",
+ "iOS",
+ "Linux",
+ "macOS",
+ "NetBSD",
+ "OpenBSD",
+ "POSIX",
+ "Solaris",
+ "Unix",
+ "VxWorks",
+ "WASI",
+ "Windows",
+})
+_LIBC = frozenset({
+ "BSD libc",
+ "glibc",
+ "musl",
+})
+_THREADING = frozenset({
+ # POSIX platforms with pthreads
+ "pthreads",
+})
+KNOWN_PLATFORMS = _PLATFORMS | _LIBC | _THREADING
+
+
+class Availability(SphinxDirective):
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 0
+ final_argument_whitespace = True
+
+ def run(self) -> list[nodes.container]:
+ title = "Availability"
+ refnode = addnodes.pending_xref(
+ title,
+ nodes.inline(title, title, classes=["xref", "std", "std-ref"]),
+ refdoc=self.env.docname,
+ refdomain="std",
+ refexplicit=True,
+ reftarget="availability",
+ reftype="ref",
+ refwarn=True,
+ )
+ sep = nodes.Text(": ")
+ parsed, msgs = self.state.inline_text(self.arguments[0], self.lineno)
+ pnode = nodes.paragraph(title, "", refnode, sep, *parsed, *msgs)
+ self.set_source_info(pnode)
+ cnode = nodes.container("", pnode, classes=["availability"])
+ self.set_source_info(cnode)
+ if self.content:
+ self.state.nested_parse(self.content, self.content_offset, cnode)
+ self.parse_platforms()
+
+ return [cnode]
+
+ def parse_platforms(self) -> dict[str, str | bool]:
+ """Parse platform information from arguments
+
+ Arguments is a comma-separated string of platforms. A platform may
+ be prefixed with "not " to indicate that a feature is not available.
+
+ Example::
+
+ .. availability:: Windows, Linux >= 4.2, not WASI
+
+ Arguments like "Linux >= 3.17 with glibc >= 2.27" are currently not
+ parsed into separate tokens.
+ """
+ platforms = {}
+ for arg in self.arguments[0].rstrip(".").split(","):
+ arg = arg.strip()
+ platform, _, version = arg.partition(" >= ")
+ if platform.startswith("not "):
+ version = False
+ platform = platform.removeprefix("not ")
+ elif not version:
+ version = True
+ platforms[platform] = version
+
+ if unknown := set(platforms).difference(KNOWN_PLATFORMS):
+ logger.warning(
+ "Unknown platform%s or syntax '%s' in '.. availability:: %s', "
+ "see %s:KNOWN_PLATFORMS for a set of known platforms.",
+ "s" if len(platforms) != 1 else "",
+ " ".join(sorted(unknown)),
+ self.arguments[0],
+ __file__,
+ )
+
+ return platforms
+
+
+def setup(app: Sphinx) -> ExtensionMetadata:
+ app.add_directive("availability", Availability)
+
+ return {
+ "version": "1.0",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py
index b6623a2..bcb8a42 100644
--- a/Doc/tools/extensions/pyspecific.py
+++ b/Doc/tools/extensions/pyspecific.py
@@ -24,7 +24,6 @@ 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 import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.writers.text import TextWriter, TextTranslator
from sphinx.util.display import status_iterator
@@ -108,80 +107,6 @@ class ImplementationDetail(SphinxDirective):
return [pnode]
-# Support for documenting platform availability
-
-class Availability(SphinxDirective):
-
- has_content = True
- required_arguments = 1
- optional_arguments = 0
- final_argument_whitespace = True
-
- # known platform, libc, and threading implementations
- known_platforms = frozenset({
- "AIX", "Android", "BSD", "DragonFlyBSD", "Emscripten", "FreeBSD",
- "GNU/kFreeBSD", "Linux", "NetBSD", "OpenBSD", "POSIX", "Solaris",
- "Unix", "VxWorks", "WASI", "Windows", "macOS", "iOS",
- # libc
- "BSD libc", "glibc", "musl",
- # POSIX platforms with pthreads
- "pthreads",
- })
-
- def run(self):
- availability_ref = ':ref:`Availability <availability>`: '
- avail_nodes, avail_msgs = self.state.inline_text(
- availability_ref + self.arguments[0],
- self.lineno)
- pnode = nodes.paragraph(availability_ref + self.arguments[0],
- '', *avail_nodes, *avail_msgs)
- self.set_source_info(pnode)
- cnode = nodes.container("", pnode, classes=["availability"])
- self.set_source_info(cnode)
- if self.content:
- self.state.nested_parse(self.content, self.content_offset, cnode)
- self.parse_platforms()
-
- return [cnode]
-
- def parse_platforms(self):
- """Parse platform information from arguments
-
- Arguments is a comma-separated string of platforms. A platform may
- be prefixed with "not " to indicate that a feature is not available.
-
- Example::
-
- .. availability:: Windows, Linux >= 4.2, not WASI
-
- Arguments like "Linux >= 3.17 with glibc >= 2.27" are currently not
- parsed into separate tokens.
- """
- platforms = {}
- for arg in self.arguments[0].rstrip(".").split(","):
- arg = arg.strip()
- platform, _, version = arg.partition(" >= ")
- if platform.startswith("not "):
- version = False
- platform = platform[4:]
- elif not version:
- version = True
- platforms[platform] = version
-
- unknown = set(platforms).difference(self.known_platforms)
- if unknown:
- cls = type(self)
- logger = logging.getLogger(cls.__qualname__)
- logger.warning(
- f"Unknown platform(s) or syntax '{' '.join(sorted(unknown))}' "
- f"in '.. availability:: {self.arguments[0]}', see "
- f"{__file__}:{cls.__qualname__}.known_platforms for a set "
- "known platforms."
- )
-
- return platforms
-
-
# Support for documenting decorators
class PyDecoratorMixin(object):
@@ -492,7 +417,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('availability', Availability)
app.add_directive('versionadded', PyVersionChange, override=True)
app.add_directive('versionchanged', PyVersionChange, override=True)
app.add_directive('versionremoved', PyVersionChange, override=True)