mirror of
https://github.com/python/cpython.git
synced 2025-08-11 04:19:06 +00:00
bpo-47115: Document which parts of structs are in limited API/stable ABI (GH-32196)
Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
This commit is contained in:
parent
14a9b4895b
commit
d79f118d04
7 changed files with 969 additions and 893 deletions
|
@ -7,10 +7,12 @@ Frame Objects
|
||||||
|
|
||||||
The C structure of the objects used to describe frame objects.
|
The C structure of the objects used to describe frame objects.
|
||||||
|
|
||||||
The structure is not part of the C API.
|
There are no public members in this structure.
|
||||||
|
|
||||||
.. versionchanged:: 3.11
|
.. versionchanged:: 3.11
|
||||||
The structure moved to the internal C API headers.
|
The members of this structure were removed from the public C API.
|
||||||
|
Refer to the :ref:`What's New entry <pyframeobject-3.11-hiding>`
|
||||||
|
for details.
|
||||||
|
|
||||||
The :c:func:`PyEval_GetFrame` and :c:func:`PyThreadState_GetFrame` functions
|
The :c:func:`PyEval_GetFrame` and :c:func:`PyThreadState_GetFrame` functions
|
||||||
can be used to get a frame object.
|
can be used to get a frame object.
|
||||||
|
|
1766
Doc/data/stable_abi.dat
generated
1766
Doc/data/stable_abi.dat
generated
File diff suppressed because it is too large
Load diff
|
@ -36,6 +36,7 @@ REST_ROLE_MAP = {
|
||||||
'type': 'type',
|
'type': 'type',
|
||||||
'macro': 'macro',
|
'macro': 'macro',
|
||||||
'type': 'type',
|
'type': 'type',
|
||||||
|
'member': 'member',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,6 +101,12 @@ class Annotations:
|
||||||
# Stable ABI annotation. These have two forms:
|
# Stable ABI annotation. These have two forms:
|
||||||
# Part of the [Stable ABI](link).
|
# Part of the [Stable ABI](link).
|
||||||
# Part of the [Stable ABI](link) since version X.Y.
|
# Part of the [Stable ABI](link) since version X.Y.
|
||||||
|
# For structs, there's some more info in the message:
|
||||||
|
# Part of the [Limited API](link) (as an opaque struct).
|
||||||
|
# Part of the [Stable ABI](link) (including all members).
|
||||||
|
# Part of the [Limited API](link) (Only some members are part
|
||||||
|
# of the stable ABI.).
|
||||||
|
# ... all of which can have "since version X.Y" appended.
|
||||||
record = self.stable_abi_data.get(name)
|
record = self.stable_abi_data.get(name)
|
||||||
if record:
|
if record:
|
||||||
if record['role'] != objtype:
|
if record['role'] != objtype:
|
||||||
|
@ -113,15 +120,27 @@ class Annotations:
|
||||||
ref_node = addnodes.pending_xref(
|
ref_node = addnodes.pending_xref(
|
||||||
'Stable ABI', refdomain="std", reftarget='stable',
|
'Stable ABI', refdomain="std", reftarget='stable',
|
||||||
reftype='ref', refexplicit="False")
|
reftype='ref', refexplicit="False")
|
||||||
|
struct_abi_kind = record['struct_abi_kind']
|
||||||
|
if struct_abi_kind in {'opaque', 'members'}:
|
||||||
|
ref_node += nodes.Text('Limited API')
|
||||||
|
else:
|
||||||
ref_node += nodes.Text('Stable ABI')
|
ref_node += nodes.Text('Stable ABI')
|
||||||
emph_node += ref_node
|
emph_node += ref_node
|
||||||
|
if struct_abi_kind == 'opaque':
|
||||||
|
emph_node += nodes.Text(' (as an opaque struct)')
|
||||||
|
elif struct_abi_kind == 'full-abi':
|
||||||
|
emph_node += nodes.Text(' (including all members)')
|
||||||
if record['ifdef_note']:
|
if record['ifdef_note']:
|
||||||
emph_node += nodes.Text(' ' + record['ifdef_note'])
|
emph_node += nodes.Text(' ' + record['ifdef_note'])
|
||||||
if stable_added == '3.2':
|
if stable_added == '3.2':
|
||||||
# Stable ABI was introduced in 3.2.
|
# Stable ABI was introduced in 3.2.
|
||||||
emph_node += nodes.Text('.')
|
pass
|
||||||
else:
|
else:
|
||||||
emph_node += nodes.Text(f' since version {stable_added}.')
|
emph_node += nodes.Text(f' since version {stable_added}')
|
||||||
|
emph_node += nodes.Text('.')
|
||||||
|
if struct_abi_kind == 'members':
|
||||||
|
emph_node += nodes.Text(
|
||||||
|
' (Only some members are part of the stable ABI.)')
|
||||||
node.insert(0, emph_node)
|
node.insert(0, emph_node)
|
||||||
|
|
||||||
# Return value annotation
|
# Return value annotation
|
||||||
|
|
|
@ -1214,8 +1214,10 @@ Porting to Python 3.11
|
||||||
which are not available in the limited C API.
|
which are not available in the limited C API.
|
||||||
(Contributed by Victor Stinner in :issue:`46007`.)
|
(Contributed by Victor Stinner in :issue:`46007`.)
|
||||||
|
|
||||||
* The :c:type:`PyFrameObject` structure member has been moved to the internal C
|
.. _pyframeobject-3.11-hiding:
|
||||||
API headers.
|
|
||||||
|
* The :c:type:`PyFrameObject` structure members have been removed from the
|
||||||
|
public C API.
|
||||||
|
|
||||||
While the documentation notes that the :c:type:`PyFrameObject` fields are
|
While the documentation notes that the :c:type:`PyFrameObject` fields are
|
||||||
subject to change at any time, they have been stable for a long time and were
|
subject to change at any time, they have been stable for a long time and were
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
The documentation now lists which members of C structs are part of the
|
||||||
|
:ref:`Limited API/Stable ABI <stable>`.
|
|
@ -42,6 +42,15 @@
|
||||||
# - a combination of the above (functions that were called by macros that
|
# - a combination of the above (functions that were called by macros that
|
||||||
# were public in the past)
|
# were public in the past)
|
||||||
|
|
||||||
|
# For structs, one of the following must be set:
|
||||||
|
# - opaque: The struct name is available in the Limited API, but its members
|
||||||
|
# are not. Users must manipulate it via pointers.
|
||||||
|
# - members: Space-separated list of members which are part of the
|
||||||
|
# Limited API and Stable ABI.
|
||||||
|
# Members that aren't listed are not accessible to applications.
|
||||||
|
# - full-abi: The entire struct -- all its members and its size -- is part of
|
||||||
|
# the Stable ABI, and must not change.
|
||||||
|
|
||||||
# Removing items from this file is generally not allowed, and additions should
|
# Removing items from this file is generally not allowed, and additions should
|
||||||
# be considered with that in mind. See the devguide for exact rules:
|
# be considered with that in mind. See the devguide for exact rules:
|
||||||
# https://devguide.python.org/c-api/#limited-api
|
# https://devguide.python.org/c-api/#limited-api
|
||||||
|
@ -54,40 +63,58 @@
|
||||||
|
|
||||||
struct PyObject
|
struct PyObject
|
||||||
added 3.2
|
added 3.2
|
||||||
|
members ob_refcnt ob_type
|
||||||
struct PyVarObject
|
struct PyVarObject
|
||||||
added 3.2
|
added 3.2
|
||||||
|
members ob_base ob_size
|
||||||
struct PyMethodDef
|
struct PyMethodDef
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyMemberDef
|
struct PyMemberDef
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyGetSetDef
|
struct PyGetSetDef
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyModuleDef_Base
|
struct PyModuleDef_Base
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyModuleDef
|
struct PyModuleDef
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyStructSequence_Field
|
struct PyStructSequence_Field
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyStructSequence_Desc
|
struct PyStructSequence_Desc
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyType_Slot
|
struct PyType_Slot
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyType_Spec
|
struct PyType_Spec
|
||||||
added 3.2
|
added 3.2
|
||||||
|
full-abi
|
||||||
struct PyThreadState
|
struct PyThreadState
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct PyInterpreterState
|
struct PyInterpreterState
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct PyFrameObject
|
struct PyFrameObject
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct symtable
|
struct symtable
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct PyWeakReference
|
struct PyWeakReference
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct PyLongObject
|
struct PyLongObject
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
struct PyTypeObject
|
struct PyTypeObject
|
||||||
added 3.2
|
added 3.2
|
||||||
|
opaque
|
||||||
|
|
||||||
function PyType_FromSpec
|
function PyType_FromSpec
|
||||||
added 3.2
|
added 3.2
|
||||||
|
@ -299,11 +326,11 @@ typedef newfunc
|
||||||
added 3.2
|
added 3.2
|
||||||
typedef allocfunc
|
typedef allocfunc
|
||||||
added 3.2
|
added 3.2
|
||||||
struct PyCFunction
|
typedef PyCFunction
|
||||||
added 3.2
|
added 3.2
|
||||||
struct PyCFunctionWithKeywords
|
typedef PyCFunctionWithKeywords
|
||||||
added 3.2
|
added 3.2
|
||||||
struct PyCapsule_Destructor
|
typedef PyCapsule_Destructor
|
||||||
added 3.2
|
added 3.2
|
||||||
typedef getter
|
typedef getter
|
||||||
added 3.2
|
added 3.2
|
||||||
|
@ -2194,6 +2221,7 @@ data PyStructSequence_UnnamedField
|
||||||
# Add stable Py_buffer API in Python 3.11 (https://bugs.python.org/issue45459)
|
# Add stable Py_buffer API in Python 3.11 (https://bugs.python.org/issue45459)
|
||||||
struct Py_buffer
|
struct Py_buffer
|
||||||
added 3.11
|
added 3.11
|
||||||
|
full-abi
|
||||||
function PyObject_CheckBuffer
|
function PyObject_CheckBuffer
|
||||||
added 3.11
|
added 3.11
|
||||||
function PyObject_GetBuffer
|
function PyObject_GetBuffer
|
||||||
|
|
|
@ -118,6 +118,8 @@ class ABIItem:
|
||||||
contents: list = dataclasses.field(default_factory=list)
|
contents: list = dataclasses.field(default_factory=list)
|
||||||
abi_only: bool = False
|
abi_only: bool = False
|
||||||
ifdef: str = None
|
ifdef: str = None
|
||||||
|
struct_abi_kind: str = None
|
||||||
|
members: list = None
|
||||||
|
|
||||||
KINDS = frozenset({
|
KINDS = frozenset({
|
||||||
'struct', 'function', 'macro', 'data', 'const', 'typedef',
|
'struct', 'function', 'macro', 'data', 'const', 'typedef',
|
||||||
|
@ -172,6 +174,15 @@ def parse_manifest(file):
|
||||||
if parent.kind not in {'function', 'data'}:
|
if parent.kind not in {'function', 'data'}:
|
||||||
raise_error(f'{kind} cannot go in {parent.kind}')
|
raise_error(f'{kind} cannot go in {parent.kind}')
|
||||||
parent.abi_only = True
|
parent.abi_only = True
|
||||||
|
elif kind in {'members', 'full-abi', 'opaque'}:
|
||||||
|
if parent.kind not in {'struct'}:
|
||||||
|
raise_error(f'{kind} cannot go in {parent.kind}')
|
||||||
|
if prev := getattr(parent, 'struct_abi_kind', None):
|
||||||
|
raise_error(
|
||||||
|
f'{parent.name} already has {prev}, cannot add {kind}')
|
||||||
|
parent.struct_abi_kind = kind
|
||||||
|
if kind == 'members':
|
||||||
|
parent.members = content.split()
|
||||||
else:
|
else:
|
||||||
raise_error(f"unknown kind {kind!r}")
|
raise_error(f"unknown kind {kind!r}")
|
||||||
# When adding more, update the comment in stable_abi.txt.
|
# When adding more, update the comment in stable_abi.txt.
|
||||||
|
@ -246,7 +257,9 @@ REST_ROLES = {
|
||||||
def gen_doc_annotations(manifest, args, outfile):
|
def gen_doc_annotations(manifest, args, outfile):
|
||||||
"""Generate/check the stable ABI list for documentation annotations"""
|
"""Generate/check the stable ABI list for documentation annotations"""
|
||||||
writer = csv.DictWriter(
|
writer = csv.DictWriter(
|
||||||
outfile, ['role', 'name', 'added', 'ifdef_note'], lineterminator='\n')
|
outfile,
|
||||||
|
['role', 'name', 'added', 'ifdef_note', 'struct_abi_kind'],
|
||||||
|
lineterminator='\n')
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
for item in manifest.select(REST_ROLES.keys(), include_abi_only=False):
|
for item in manifest.select(REST_ROLES.keys(), include_abi_only=False):
|
||||||
if item.ifdef:
|
if item.ifdef:
|
||||||
|
@ -257,7 +270,13 @@ def gen_doc_annotations(manifest, args, outfile):
|
||||||
'role': REST_ROLES[item.kind],
|
'role': REST_ROLES[item.kind],
|
||||||
'name': item.name,
|
'name': item.name,
|
||||||
'added': item.added,
|
'added': item.added,
|
||||||
'ifdef_note': ifdef_note})
|
'ifdef_note': ifdef_note,
|
||||||
|
'struct_abi_kind': item.struct_abi_kind})
|
||||||
|
for member_name in item.members or ():
|
||||||
|
writer.writerow({
|
||||||
|
'role': 'member',
|
||||||
|
'name': f'{item.name}.{member_name}',
|
||||||
|
'added': item.added})
|
||||||
|
|
||||||
@generator("ctypes_test", 'Lib/test/test_stable_abi_ctypes.py')
|
@generator("ctypes_test", 'Lib/test/test_stable_abi_ctypes.py')
|
||||||
def gen_ctypes_test(manifest, args, outfile):
|
def gen_ctypes_test(manifest, args, outfile):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue