@@ -249,18 +249,17 @@ def _stable_abi_annotation(
249249 reftype = "ref" ,
250250 refexplicit = "False" ,
251251 )
252- struct_abi_kind = record .struct_abi_kind
253- if struct_abi_kind in {"opaque" , "members" }:
254- ref_node += nodes .Text (sphinx_gettext ("Limited API" ))
255- else :
256- ref_node += nodes .Text (sphinx_gettext ("Stable ABI" ))
252+ ref_node += nodes .Text (sphinx_gettext ("Stable ABI" ))
257253 emph_node += ref_node
254+ struct_abi_kind = record .struct_abi_kind
258255 if struct_abi_kind == "opaque" :
259256 emph_node += nodes .Text (" " + sphinx_gettext ("(as an opaque struct)" ))
260257 elif struct_abi_kind == "full-abi" :
261258 emph_node += nodes .Text (
262259 " " + sphinx_gettext ("(including all members)" )
263260 )
261+ elif struct_abi_kind in {"members" , "abi3t-opaque" }:
262+ emph_node += nodes .Text (" " + sphinx_gettext ("(see below)" ))
264263 if record .ifdef_note :
265264 emph_node += nodes .Text (f" { record .ifdef_note } " )
266265 if stable_added == "3.2" :
@@ -271,11 +270,7 @@ def _stable_abi_annotation(
271270 " " + sphinx_gettext ("since version %s" ) % stable_added
272271 )
273272 emph_node += nodes .Text ("." )
274- if struct_abi_kind == "members" :
275- msg = " " + sphinx_gettext (
276- "(Only some members are part of the stable ABI.)"
277- )
278- emph_node += nodes .Text (msg )
273+
279274 return emph_node
280275
281276
@@ -378,6 +373,33 @@ def run(self) -> list[nodes.Node]:
378373 return [node ]
379374
380375
376+ class VersionHexCheatsheet (SphinxDirective ):
377+ """Show results of Py_PACK_VERSION(3, x) for a few relevant Python versions
378+
379+ This is useful for defining version before Python.h is included.
380+ It should auto-update with the version being documented, so it must be an
381+ extension.
382+ """
383+
384+ has_content = False
385+ required_arguments = 0
386+ optional_arguments = 0
387+ final_argument_whitespace = True
388+
389+ def run (self ) -> list [nodes .Node ]:
390+ content = [
391+ ".. code-block:: c" ,
392+ "" ,
393+ ]
394+ current_minor = int (self .config .version .removeprefix ('3.' ))
395+ for minor in range (current_minor - 5 , current_minor + 1 ):
396+ value = (3 << 24 ) | (minor << 16 )
397+ content .append (f' { value :#x} /* Py_PACK_VERSION(3.{ minor } ) */' )
398+ node = nodes .paragraph ()
399+ self .state .nested_parse (StringList (content ), 0 , node )
400+ return [node ]
401+
402+
381403class CorrespondingTypeSlot (SphinxDirective ):
382404 """Type slot annotations
383405
@@ -443,6 +465,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
443465 app .add_config_value ("stable_abi_file" , "" , "env" , types = {str })
444466 app .add_config_value ("threadsafety_file" , "" , "env" , types = {str })
445467 app .add_directive ("limited-api-list" , LimitedAPIList )
468+ app .add_directive ("version-hex-cheatsheet" , VersionHexCheatsheet )
446469 app .add_directive ("corresponding-type-slot" , CorrespondingTypeSlot )
447470 app .connect ("builder-inited" , init_annotations )
448471 app .connect ("doctree-read" , add_annotations )
0 commit comments