File: availability.py

package info (click to toggle)
python3.13 3.13.6-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 121,256 kB
  • sloc: python: 703,743; ansic: 653,888; xml: 31,250; sh: 5,844; cpp: 4,326; makefile: 1,981; objc: 787; lisp: 502; javascript: 213; asm: 75; csh: 12
file content (126 lines) | stat: -rw-r--r-- 3,595 bytes parent folder | download | duplicates (3)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""Support for documenting platform availability"""

from __future__ import annotations

from typing import TYPE_CHECKING

from docutils import nodes
from sphinx import addnodes
from sphinx.locale import _ as sphinx_gettext
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 = sphinx_gettext("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,
    }