GeezerVison is showing github.com — Request to restore PyWeakref_GetObject() to the v3.15 limited API · Issue #161568 · python/cpython
Request to restore PyWeakref_GetObject() to the v3.15 limited API #161568DescriptionBug report
PyWeakref_GetObject() was deprecated in v3.13 (when PyWeakref_GetRef() was added) and removed in v3.15. This means that extension modules that target older (still supported) versions cannot be built against the v3.15 headers.
#158401 shows the importance of using the latest versions of the headers where possible. Taking this issue into account v3.14 headers are the only ones that can safely be used when targeting all currently supported versions of Python.
I would like to see PyWeakref_GetObject() restored to the v3.15 limited API and only removed in v3.18 when it's replacement is available in all supported versions (ie. when v3.13 is the oldest supported version). If this were the case (and the principle followed for other similar situations) then extension authors could always build using the latest supported headers.
CPython versions tested on:
3.15
Operating systems tested on:
No response Activitypicnixz commented on Nov 7, 2026 If by "supported", you mean 3.13 and lower, those version do not accept regular bug fixes anymore and only accept security patches. Which extensions are affected by it? We didn't get (or at least AFAIR) about that during the alpha, beta, and RC phase for 3.15 and I'm not sure we can change the limited API for 3.15 anymore.
cc @vstinner vstinner commented on Nov 7, 2026 Did you consider updating your code base to PyWeakref_GetRef() using https://pythoncapi-compat.readthedocs.io/ to support Python 3.12 and older?
PyWeakref_GetObject() function is now reliable since it returns a borrowed reference. PyWeakref_GetRef() is safer since it returns a strong reference.
Note: PyWeakref_GetObject() does still exist in Python 3.15 and 3.16 stable ABI, but it's now an ABI-only symbol.
The PyWeakref_GetObject() function was removed from the C API by commit a5e0562 (issue gh-133644). vstinner commented on Nov 7, 2026
#158401 shows the importance of using the latest versions of the headers where possible.
The pythoncapi-compat project is a concrete solution to help C and C++ extensions adopting new APIs and remain compatible with older Python versions. In your case, it allows you using PyWeakref_GetRef() on old Python versions. philthompson10 commented on Nov 7, 2026 So in order to use pythoncapi-compat I make a local copy of the header file in each affected project?
Out of curiosity, why isn't a copy of this distributed with Python? vstinner commented on Nov 7, 2026
So in order to use pythoncapi-compat I make a local copy of the header file in each affected project?
Correct. Once the file is copied, you don't have to update it when it changes upstream. Only update it if you need new functions.
Out of curiosity, why isn't a copy of this distributed with Python?
For me, it's easier to maintain it outside CPython repository. I can more easily support old Python versions (I only removed Python 2.7 support a few months ago!). I can also update it more frequently than Python releases, when issues are discovered. philthompson10 commented on Nov 8, 2026 I wasn't suggesting including it in the CPython repository, just that an installation contained the-latest-copy-at-the-time.
Anyway, using pythoncapi-compat allows me to use PyWeakref_GetRef() in my source code and the compiled extension module has an undefined _PyWeakref_GetObject symbol, so that all seems to work.
However if I build against the v3.15 headers then the module can only be imported by v3.15. If I build against the v3.14 headers then the module can be imported by all supported versions of Python. So there seems to be something else going on, but this is unrelated to my original request. vstinner commented on Nov 8, 2026
However if I build against the v3.15 headers then the module can only be imported by v3.15. If I build against the v3.14 headers then the module can be imported by all supported versions of Python.
- If you build with limited C API 3.15, the binary works on Python >= 3.15
- If you build with limited C API 3.14, the binary works on Python >= 3.14
See the doc: https://docs.python.org/dev/c-api/stable.html.
But there is no guarantee that if you build for limited C API 3.14, it will work on Python < 3.14: maybe it works by luck if you don't call too many functions and these functions didn't change last years. But that's unsafe and out of the stable ABI contract.
For example, if you want to support Python >= 3.11, you must target the limited C API 3.11.
Anyway, using pythoncapi-compat allows me to use PyWeakref_GetRef() in my source code and the compiled extension module has an undefined _PyWeakref_GetObject symbol, so that all seems to work.
Are you sure that _PyWeakref_GetObject symbol is used, and not PyWeakref_GetObject? There is no _PyWeakref_GetObject symbol in libpython, whereas PyWeakref_GetObject is part of the stable ABI and so remains available in Python 3.16 for example (the API was removed, the stable ABI was left unchanged). philthompson10 commented on Nov 8, 2026
Are you sure that _PyWeakref_GetObject symbol is used, and not PyWeakref_GetObject? There is no _PyWeakref_GetObject symbol in libpython, whereas PyWeakref_GetObject is part of the stable ABI and so remains available in Python 3.16 for example (the API was removed, the stable ABI was left unchanged).
Quite sure. That's just the compiler doing its normal thing of prepending an underscore to external symbols.
But there is no guarantee that if you build for limited C API 3.14, it will work on Python < 3.14: maybe it works by luck if you don't call too many functions and these functions didn't change last years. But that's unsafe and out of the stable ABI contract.
As I said right at the start extension modules that target older (still supported) versions. In all cases I'm targeting the v3.11 stable ABI, ie. Py_LIMITED_API=0x030b0000.
To restate:
- v3.15 headers, using pythoncapi-compat, calling PyWeakref_GetRef(), can only be imported by Python v3.15
- v3.14 headers, using pythoncapi-compat, calling PyWeakref_GetRef(), can be imported by Python v3.11 to v3.15
- v3.14 headers, not using pythoncapi-compat, calling PyWeakref_GetObject(), can be imported by Python v3.11 to v3.15
When I get the chance I'll use a debug build of v3.15 to work out exactly why its failing
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|