Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions Doc/c-api/exceptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1117,124 +1117,191 @@ For completeness, here are all the variables:
Exception types
---------------

.. stable-abi-note::

These pointers are part of the :ref:`Stable ABI <stable>` since the
version in the *S.ABI* column (or since 3.2 when *S.ABI* is empty).
Exceptions marked N/A are *not* part of Stable ABI.

.. omit-stable-abi-notes::

.. list-table::
:align: left
:widths: auto
:header-rows: 1

* * C name
* .. stable-abi-note::

S.ABI
* Python name
* * .. c:var:: PyObject *PyExc_BaseException
*
* :exc:`BaseException`
* * .. c:var:: PyObject *PyExc_BaseExceptionGroup
* 3.11
* :exc:`BaseExceptionGroup`
* * .. c:var:: PyObject *PyExc_Exception
*
* :exc:`Exception`
* * .. c:var:: PyObject *PyExc_ArithmeticError
*
* :exc:`ArithmeticError`
* * .. c:var:: PyObject *PyExc_AssertionError
*
* :exc:`AssertionError`
* * .. c:var:: PyObject *PyExc_AttributeError
*
* :exc:`AttributeError`
* * .. c:var:: PyObject *PyExc_BlockingIOError
* 3.7
* :exc:`BlockingIOError`
* * .. c:var:: PyObject *PyExc_BrokenPipeError
* 3.7
* :exc:`BrokenPipeError`
* * .. c:var:: PyObject *PyExc_BufferError
*
* :exc:`BufferError`
* * .. c:var:: PyObject *PyExc_ChildProcessError
* 3.7
* :exc:`ChildProcessError`
* * .. c:var:: PyObject *PyExc_ConnectionAbortedError
* 3.7
* :exc:`ConnectionAbortedError`
* * .. c:var:: PyObject *PyExc_ConnectionError
* 3.7
* :exc:`ConnectionError`
* * .. c:var:: PyObject *PyExc_ConnectionRefusedError
* 3.7
* :exc:`ConnectionRefusedError`
* * .. c:var:: PyObject *PyExc_ConnectionResetError
* 3.7
* :exc:`ConnectionResetError`
* * .. c:var:: PyObject *PyExc_EOFError
*
* :exc:`EOFError`
* * .. c:var:: PyObject *PyExc_FileExistsError
* 3.7
* :exc:`FileExistsError`
* * .. c:var:: PyObject *PyExc_FileNotFoundError
* 3.7
* :exc:`FileNotFoundError`
* * .. c:var:: PyObject *PyExc_FloatingPointError
*
* :exc:`FloatingPointError`
* * .. c:var:: PyObject *PyExc_GeneratorExit
*
* :exc:`GeneratorExit`
* * .. c:var:: PyObject *PyExc_ImportCycleError
* N/A
* :exc:`ImportCycleError`
* * .. c:var:: PyObject *PyExc_ImportError
*
* :exc:`ImportError`
* * .. c:var:: PyObject *PyExc_IndentationError
*
* :exc:`IndentationError`
* * .. c:var:: PyObject *PyExc_IndexError
*
* :exc:`IndexError`
* * .. c:var:: PyObject *PyExc_InterruptedError
* 3.7
* :exc:`InterruptedError`
* * .. c:var:: PyObject *PyExc_IsADirectoryError
* 3.7
* :exc:`IsADirectoryError`
* * .. c:var:: PyObject *PyExc_KeyError
*
* :exc:`KeyError`
* * .. c:var:: PyObject *PyExc_KeyboardInterrupt
*
* :exc:`KeyboardInterrupt`
* * .. c:var:: PyObject *PyExc_LookupError
*
* :exc:`LookupError`
* * .. c:var:: PyObject *PyExc_MemoryError
*
* :exc:`MemoryError`
* * .. c:var:: PyObject *PyExc_ModuleNotFoundError
* 3.6
* :exc:`ModuleNotFoundError`
* * .. c:var:: PyObject *PyExc_NameError
*
* :exc:`NameError`
* * .. c:var:: PyObject *PyExc_NotADirectoryError
* 3.7
* :exc:`NotADirectoryError`
* * .. c:var:: PyObject *PyExc_NotImplementedError
*
* :exc:`NotImplementedError`
* * .. c:var:: PyObject *PyExc_OSError
*
* :exc:`OSError`
* * .. c:var:: PyObject *PyExc_OverflowError
*
* :exc:`OverflowError`
* * .. c:var:: PyObject *PyExc_PermissionError
* 3.7
* :exc:`PermissionError`
* * .. c:var:: PyObject *PyExc_ProcessLookupError
* 3.7
* :exc:`ProcessLookupError`
* * .. c:var:: PyObject *PyExc_PythonFinalizationError
*
* :exc:`PythonFinalizationError`
* * .. c:var:: PyObject *PyExc_RecursionError
* 3.7
* :exc:`RecursionError`
* * .. c:var:: PyObject *PyExc_ReferenceError
*
* :exc:`ReferenceError`
* * .. c:var:: PyObject *PyExc_RuntimeError
*
* :exc:`RuntimeError`
* * .. c:var:: PyObject *PyExc_StopAsyncIteration
* 3.7
* :exc:`StopAsyncIteration`
* * .. c:var:: PyObject *PyExc_StopIteration
*
* :exc:`StopIteration`
* * .. c:var:: PyObject *PyExc_SyntaxError
*
* :exc:`SyntaxError`
* * .. c:var:: PyObject *PyExc_SystemError
*
* :exc:`SystemError`
* * .. c:var:: PyObject *PyExc_SystemExit
*
* :exc:`SystemExit`
* * .. c:var:: PyObject *PyExc_TabError
*
* :exc:`TabError`
* * .. c:var:: PyObject *PyExc_TimeoutError
* 3.7
* :exc:`TimeoutError`
* * .. c:var:: PyObject *PyExc_TypeError
*
* :exc:`TypeError`
* * .. c:var:: PyObject *PyExc_UnboundLocalError
*
* :exc:`UnboundLocalError`
* * .. c:var:: PyObject *PyExc_UnicodeDecodeError
*
* :exc:`UnicodeDecodeError`
* * .. c:var:: PyObject *PyExc_UnicodeEncodeError
*
* :exc:`UnicodeEncodeError`
* * .. c:var:: PyObject *PyExc_UnicodeError
*
* :exc:`UnicodeError`
* * .. c:var:: PyObject *PyExc_UnicodeTranslateError
*
* :exc:`UnicodeTranslateError`
* * .. c:var:: PyObject *PyExc_ValueError
*
* :exc:`ValueError`
* * .. c:var:: PyObject *PyExc_ZeroDivisionError
*
* :exc:`ZeroDivisionError`

.. versionadded:: 3.3
Expand Down Expand Up @@ -1295,36 +1362,58 @@ Notes:
Warning types
-------------

.. stable-abi-note::

These pointers are part of the :ref:`Stable ABI <stable>` since the
version in the *S.ABI* column (or since 3.2 when *S.ABI* is empty).

.. omit-stable-abi-notes::

.. list-table::
:align: left
:widths: auto
:header-rows: 1

* * C name
* .. stable-abi-note::

S.ABI
* Python name
* * .. c:var:: PyObject *PyExc_Warning
*
* :exc:`Warning`
* * .. c:var:: PyObject *PyExc_BytesWarning
*
* :exc:`BytesWarning`
* * .. c:var:: PyObject *PyExc_DeprecationWarning
*
* :exc:`DeprecationWarning`
* * .. c:var:: PyObject *PyExc_EncodingWarning
* 3.10
* :exc:`EncodingWarning`
* * .. c:var:: PyObject *PyExc_FutureWarning
*
* :exc:`FutureWarning`
* * .. c:var:: PyObject *PyExc_ImportWarning
*
* :exc:`ImportWarning`
* * .. c:var:: PyObject *PyExc_PendingDeprecationWarning
*
* :exc:`PendingDeprecationWarning`
* * .. c:var:: PyObject *PyExc_ResourceWarning
* 3.7
* :exc:`ResourceWarning`
* * .. c:var:: PyObject *PyExc_RuntimeWarning
*
* :exc:`RuntimeWarning`
* * .. c:var:: PyObject *PyExc_SyntaxWarning
*
* :exc:`SyntaxWarning`
* * .. c:var:: PyObject *PyExc_UnicodeWarning
*
* :exc:`UnicodeWarning`
* * .. c:var:: PyObject *PyExc_UserWarning
*
* :exc:`UserWarning`

.. versionadded:: 3.2
Expand Down
5 changes: 5 additions & 0 deletions Doc/c-api/iterator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ Builtin Iterator Types
These are built-in iteration types that are included in Python's C API, but
provide no additional functions. They are here for completeness.

.. stable-abi-note::

These pointers are part of the :ref:`Stable ABI <stable>`.

.. omit-stable-abi-notes::

.. list-table::
:widths: auto
Expand Down
55 changes: 55 additions & 0 deletions Doc/tools/extensions/c_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,22 @@ def add_annotations(app: Sphinx, doctree: nodes.document) -> None:
f"{ROLE_TO_OBJECT_TYPE[record.role]!r} != {objtype!r}"
)
raise ValueError(msg)

# Skip the note if any ancestor has 'omit-stable-abi-note'
# in a 'c_annotations' attribute.
ancestor = node
while ancestor:
if 'omit-stable-abi-note' not in ancestor.get(
'c_annotations',
[],
):
break
ancestor = node.parent
else:
# no skip; add the annotation
annotation = _stable_abi_annotation(record)
node.insert(0, annotation)
node.setdefault("classes", []).append('ADDED-HERE')

# Unstable API annotation.
if name.startswith("PyUnstable"):
Expand Down Expand Up @@ -445,6 +459,45 @@ def run(self) -> list[nodes.Node]:
return [node]


class StableABINote(SphinxDirective):
"""A manual Stable ABI note

Normally, notes are auto-generated.
This directive allows adding a similarly styled note manually.
Pair with omit-stable-abi-notes to override the automatic generation.
"""

has_content = True

def run(self) -> list[nodes.Node]:
node = nodes.Element() # Anonymous container for parsing
node.rawsource = '\n'.join(self.content)
self.state.nested_parse(self.content, self.content_offset, node)
for child in node.children:
child.setdefault("classes", []).append('stableabi')
return node.children


class OmitStableABINotes(SphinxDirective):
"""A block where automatic Stable ABI notes are not generated

Normally used for dense lists/tables of definitions, where individual notes
are omitted and the whole block has a common manual note.
"""

has_content = True

def run(self) -> list[nodes.Node]:
node = nodes.Element() # Anonymous container for parsing
node.rawsource = '\n'.join(self.content)
self.state.nested_parse(self.content, self.content_offset, node)
for child in node.children:
child.setdefault("c_annotations", []).append(
'omit-stable-abi-notes',
)
return node.children


def init_annotations(app: Sphinx) -> None:
# Using domaindata is a bit hack-ish,
# but allows storing state without a global variable or closure.
Expand All @@ -467,6 +520,8 @@ def setup(app: Sphinx) -> ExtensionMetadata:
app.add_directive("limited-api-list", LimitedAPIList)
app.add_directive("version-hex-cheatsheet", VersionHexCheatsheet)
app.add_directive("corresponding-type-slot", CorrespondingTypeSlot)
app.add_directive("omit-stable-abi-notes", OmitStableABINotes)
app.add_directive("stable-abi-note", StableABINote)
app.connect("builder-inited", init_annotations)
app.connect("doctree-read", add_annotations)

Expand Down
Loading