“Minimum target version” is a lovely name.
Yeah. Get options from the config file and feed them to the compiler. That’s how it should work.
There’s a mismatch between what’s in the setuptools config file and what CPython accepts (and also what’s in the user’s brain). We should fix that. And it looks like most of the fix should be on the CPython side.
That’s not my intent.
Here’s a strawman proposal, as something concrete (with silly names):
pyproject.toml’s[c]section containsmin_target_python = "3.13": Setuptools takes that, setsPy_MIN_TARGET_PYTHONto 3.13 for the compiler, and generates acp3_13tagpyproject.toml’s[c]section containsforward_compatible = true: Setuptools setsPy_FORWARD_COMPATIBLE, and a wheel tag that indicates 3.14+ compatibilty [1].pyproject.toml’s[c]section containsfree_threading_compatible = true: Setuptools setsPy_FREE_THREADING_COMPATIBLE, and a wheel tag for that.
And if the user calls Py_UseAThreeFourteenFeature() that doesn’t work with the settings, the compiler complains that it’s not available. That error can’t really be clear on its own, but at least the docs for Py_UseAThreeFourteenFeature mention the required min_target_python.
As to “two different numbers that increase in lockstep”, I agree, but the answer is to not increase them in lockstep
That’s what is meant by “that association should be broken.”
That gives us PEP 809 (one of them merges five +1’s into a +5), or the 2000-era PYTHON_API_VERSION. I know your preference on that one ![]()
(I’m being silly here.)
The terminology here is very strange when stable or limited words are attached to it (for my understanding) if I have to put my C programming hat on.
Yes. We should rebrand, and avoid the terms “API” and “ABI”.
(Here I’m being serious.)
I thought, maybe naively, There will be a certain subset of Python C API, this includes the actual functions and data structures we are using such as PyObject and so on will be frozen.
Not only that, but also the ABI is going to be frozen, that means if we compile something against a future version of Python, it will be ABI compatible meaning that since we are using a subset of the C API those functions will communicate using the same binary ordering sizes etc. So if there is an object defined this is always going to allocate same number of bytes, with same structure etc. So we can move one library compiled with one version of Python and use it in another if we stick to this particular subset of the API. So I don’t need to compile the same library 5 times if I am supporting 5 versions of Python (in the future). But no such lunch with a discount apparently.
That is the case. If you use the 3.13 Stable ABI, the functions and the struct memory layouts your extension uses are frozen, and compatible with 3.13, 3.14, 3.15, 3.16, and so on until Python 4we remove non-free-threaded builds.
To use the 3.13 Stable ABI, your source needs to restrict itself to only using the functions and structs that have this forward-capability guarantee. That subset is called the 3.13 Limited API.
(Does that make sense? I’ll expand on that now.)
If your source is compatible with the 3.13 Limited API, it’ll also be compatible with:
- the “full” CPython 3.13-only API (since Limited API is a subset of that)
- most likely, the 3.14 LImited API (since there have been no removals, or very few ones that touched some old niche functions)
So, you can compile your “3.13+” compatible source into a “3.14+” compatible extension, or a “3.13-only” extension. Both might get some performance improvements over the “3.13+” extension – some function might be able to avoid a backwards-compatibility hack, or otherwise use a faster implementation.
There’s compile-time option for choosing the desired “minimum target version” and the “forward compatibility? y/n”. The option’s name is… extremely confusing.
Let’s name it Py_MIN_TARGET_VERSION instead.
not being concrete here: options for a short tag currently have bagage ;) ↩︎