CPython’s Limited C-API and Stable ABI, introduced in PEP 384, will be formalized in a single definitive file, tested, and documented.
MotivationPEP 384 defined a Limited API and Stable ABI, which allow extenders and embedders of CPython to compile extension modules that are binary-compatible with any subsequent version of 3.x. In theory, this brings several advantages:
However, in hindsight, PEP 384 and its implementation has several issues:
#define
that should make only the Stable ABI available, but there is no process that ensures it is kept up-to date. Neither is there a process for updating the documentation.This PEP defines the Limited API more clearly and introducess process designed to make the Stable ABI and Limited API more useful and robust.
RationaleThis PEP contains a lot of clarifications and definitions, but just one big technical change: the Stable ABI will be explicitly listed in a human-maintained “manifest” file.
There have been efforts to collect such lists automatically, e.g. by scanning the symbols exported from Python. Such automation might seem easier to maintain than a handcrafted file, but has major issues: for example, the set exported symbols has platform-specific variations. Also, the cost of updating an explicit manifest is small compared to the overall work that should go into changing API that will need to be supported forever (or until Python 3 reaches end of life, if that comes sooner).
This PEP proposes automatically generating things from the manifest: initially documentation and DLL contents, with later possibilities for also automating tests.
Stable ABI vs. Limited APIPEP 384 and this document deal with the Limited API and the Stable ABI, two related but distinct concepts. In short:
This section clarifies these terms and defines some of their semantics (either pre-existing or newly proposed here).
The word “Extensions” is used as a shorthand for all code that uses the Python API, e.g. extension modules or software that embeds Python.
Stable ABIThe CPython Stable ABI is a promise that extensions built against a specific Stable ABI version will be compatible with any newer interpreter of the same major version.
The Stable ABI does not define a complete binary interface: important details like the layout of structures in memory or function calling conventions are determined by the platform and the compiler and its settings. The Stable ABI promise only applies if these lower-details are also stable.
For example, an extension built with the CPython 3.10 Stable ABI will be usable with CPython 3.11, 3.12, etc. It will not necessarily be compatible with CPython 4.0, nor with CPython 3.10 on a different platform.
The Stable ABI is not generally forward-compatible: an extension built and tested with CPython 3.10 will not generally be compatible with CPython 3.9.
Note
For example, starting in Python 3.10, the Py_tp_doc
slot may be set to NULL
, while in older versions, a NULL
value will likely crash the interpreter.
The Stable ABI trades performance for its stability. For example, extensions built for a specific CPython version will automatically use faster macros instead of functions in the Stable ABI.
Future Python versions may deprecate some members of the Stable ABI. Deprecated members will still work, but may suffer from issues like reduced performance or, in the most extreme cases, memory/resource leaks.
Limited APIThe Stable ABI promise holds for extensions compiled from code that restricts itself to the Limited API (application programming interface). The Limited API is a subset of CPython’s C API.
Extensions that target the Limited API should define the preprocessor macro Py_LIMITED_API
to either 3
or the current PYTHON_API_VERSION
. This will enable Stable ABI versions of several functions and limit definitions to the Limited API. (However, note that the macro is not perfect: due to technical issues or oversights, some non-limited API might be exposed even with it defined.)
The Limited API is not guaranteed to be stable. In the future, parts of the Limited API may be deprecated. They may even be removed, as long as the Stable ABI is kept stable and Python’s general backwards compatibility policy, PEP 387, is followed.
Note
For example, a function declaration might be removed from public header files but kept in the library. This is currently a possibility for the future; this PEP does not to propose a concrete process for deprecations and removals.
The goal for the Limited API is to cover everything needed to interact with the interpreter. The main reason to not include a public API in the Limited subset should be that it needs implementation details that change between CPython versions (like struct memory layouts) – usually for performance reasons.
The Limited API is not limited to CPython. Other implementations are encouraged to implement it and help drive its design.
SpecificationTo make the Stable ABI more useful and robust, the following changes are proposed.
Stable ABI ManifestAll members of the Stable ABI – functions, typedefs, structs, data, macros, and constants – will be explicitly listed in a single “manifest” file, Misc/stable_abi.txt
.
For structs, any fields that users of the Stable ABI are allowed to access will be listed explicitly.
The manifest will also serve as the definitive list of the Limited API. Members that are not part of the Limited API, but are part of the Stable ABI (e.g. PyObject.ob_type
, which is accessible by the Py_TYPE
macro), will be annotated as such.
For items that are only available on some systems, the manifest will record the feature macro that determines their presence (such as MS_WINDOWS
or HAVE_FORK
). To make the implementation (and usage from non-C languages) easier, all such macros will be simple names. If a future item needs a “negative” macro or complex expression (such as a hypothetical #ifndef MACOSX
or #if defined(POSIX) && !defined(LINUX)
), a new feature macro will be derived.
The format of the manifest will be subject to change whenever needed. It should be consumed only by scripts in the CPython repository. If a stable list is needed, a script can be added to generate it.
The following will be generated from the ABI manifest:
PC/python3dll.c
.The following will be checked against the Stable ABI manifest as part of continuous integration:
Doc/data/refcounts.txt
, includes all function in the Stable ABI (among others).Python.h
is included with Py_LIMITED_API
set. (Initially Linux only; checks on other systems may be added in the future.)After the initial implementation, details such as function arguments will be added and the manifest will be checked for internal consistency (e.g. all types used in function signatures are part of the API).
Contents of the Stable ABIThe initial Stable ABI manifest will include:
PC/python3dll.c
.Py_am_aiter
.Py_TPFLAGS_DEFAULT
, Py_TPFLAGS_BASETYPE
, Py_TPFLAGS_HAVE_GC
, Py_TPFLAGS_METHOD_DESCRIPTOR
.METH_*
(except deprecated ones).Items that are no longer in CPython when this PEP is accepted will be removed from the list.
Additional items may be added to the initial manifest according to the checklist below.
Documenting the Limited APINotes saying “Part of the Limited API” will be added to Python’s documentation automatically, in a way similar to the notes on functions that return borrowed references.
A complete list of all members of the Limited API will also be added to the documentation.
Testing the Stable ABIAn automatically generated test module will be added to ensure that all symbols included in the Stable ABI are available at compile time.
Changing the Limited APIA checklist for changing the Limited API, including adding new items to it and removing existing ones, will be added to the Devguide. The checklist will 1) mention best practices and common pitfalls in Python C API design and 2) guide the developer around the files that need changing and scripts that need running when the Limited API is changed.
Below is the initial proposal for the checklist. (After the PEP is accepted, see the Devguide for the current version.)
Note that the checklist applies to new changes; several items in the existing Limited API are grandfathered and couldn’t be added today.
Design considerations:
void*
(a data pointer) or vice versa.NULL
is passed in).
- The GIL
- Garbage collection
- Memory layout of PyObject, lists/tuples and other structures
If following these guidelines would hurt performance, add a fast function (or macro) to the non-limited API and a stable equivalent to the Limited API.
If anything is unclear, or you have a good reason to break the guidelines, consider discussing the change at the capi-sig mailing list.
Procedure:
Include/
, into a #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03yy0000
block (with the yy
corresponding to the target CPython version).Misc/stable_abi.txt
.make regen-all
. (or the alternative for non-make
platforms)make check-abi
. (or the alternative for non-make
platforms)The following notes will be added to documentation, along with better information regarding this topic and what guarantees do we offer:
Extension authors should test with all Python versions they support, and preferably build with the lowest such version.
Compiling with Py_LIMITED_API
defined is not a guarantee that your code conforms to the Limited API or the Stable ABI. Py_LIMITED_API
only covers definitions, but an API also includes other issues, such as expected semantics.
Examples of issues that Py_LIMITED_API
does not guard against are:
NULL
values for an argument in Python 3.9 will fail if NULL
is passed to it under Python 3.8. Only testing with 3.8 (or lower versions) will uncover this issue.Py_LIMITED_API
does not filter out such “private” fields.Py_LIMITED_API
defined, may break in the future. Despite the team’s best efforts, such issues may happen.The Stable ABI promise relies on stable underlying ABI details, such as the layout of structures in memory and function calling conventions, which are affected by the compiler and its settings. For the promise to hold, these details must not change between CPython 3.x releases on a particular platform.
Backwards CompatibilityBackwards compatibility is one honking great idea!
This PEP aims at full compatibility with the existing Stable ABI and Limited API, but defines them terms more explicitly. It might not be consistent with some interpretations of what the existing Stable ABI/Limited API is.
Security ImplicationsNone known.
How to Teach ThisTechnical documentation will be provided in Doc/c-api/stable
and linked from the What’s New document. Docs for CPython core developers will be added to the devguide.
See issue 43795.
Ideas for the FutureThe following issues are out of scope of this PEP, but show possible future directions.
Defining a process for deprecations/removalsWhile this PEP acknowledges that parts of the Limited API might be deprecated or removed in the future, a process to do this is not in scope, and is left to a possible future PEP.
C syntax for the ABI manifestIt might be useful to have the ABI manifest be a C header file, or to generate header files from the manifest. Again, either are options for the future.
Open IssuesNone so far.
CopyrightThis document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4