Skip to content

gh-111506: Add _Py_OPAQUE_PYOBJECT to hide PyObject layout & related API #136505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 12, 2025

Conversation

encukou
Copy link
Member

@encukou encukou commented Jul 10, 2025

Make it so that defining _Py_OPAQUE_PYOBJECT before including <Python.h> will make the PyObject struct opaque, and hide all limited-API structs & functions that need access to it.

Also, allow Py_LIMITED_API with Py_GIL_DISABLED if _Py_OPAQUE_PYOBJECT is defined.

Opaque PyObject will be needed for most alternatives we have of defining a Stable ABI for free-threaded builds. See Discourse thread for discussion. (We may want to either expose this to users as Py_OPAQUE_PYOBJECT, or define it implicitly for limited-API free-threaded builds.)
And if I'm wrong -- this is easy to remove, like like Py_GIL_DISABLED.

As I mentioned, I'd like to put this in main to avoid rebasing a fork and to make it easier to build on top.

encukou added 2 commits July 10, 2025 13:12
API that's removed when _Py_OPAQUE_PYOBJECT is defined:

    - PyObject_HEAD
    - _PyObject_EXTRA_INIT
    - PyObject_HEAD_INIT
    - PyObject_VAR_HEAD
    - struct _object (i.e. PyObject) (opaque)
    - struct PyVarObject (opaque)
    - Py_SIZE
    - Py_SET_TYPE
    - Py_SET_SIZE
    - PyModuleDef_Base (opaque)
    - PyModuleDef_HEAD_INIT
    - PyModuleDef (opaque)
    - _Py_IsImmortal
    - _Py_IsStaticImmortal

Note that the `_Py_IsImmortal` removal means _Py_OPAQUE_PYOBJECT
only works with limited API 3.14+ now.
@encukou
Copy link
Member Author

encukou commented Jul 11, 2025

We can also test this (with a workaround/hack in the test for the missing part).

@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @encukou for commit 33d9ae7 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F136505%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jul 11, 2025
@encukou
Copy link
Member Author

encukou commented Jul 11, 2025

The tests aren't that straightforward, but the workaround can still be removed if we either scrap the “opaque PyObject” idea or implement PEP 793.
@vstinner, are you OK with having this workaround in tests in main, it order to test that Python.h compiles with opaque PyObject (and except for PyModuleDef, it can produce working extensions)?

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the overall approach of the _Py_OPAQUE_PYOBJECT macro. I'm fine with testing it in test_cext.

# Test with _Py_OPAQUE_PYOBJECT
self.check_build('_test_limited_opaque_cext', limited=True, opaque=True)

def check_build(self, extension_name, std=None, limited=False, opaque=False):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to rename "opaque" to "opaque_pyobject" (also in _check_build).

@@ -45,6 +45,9 @@ def main():
std = os.environ.get("CPYTHON_TEST_STD", "")
module_name = os.environ["CPYTHON_TEST_EXT_NAME"]
limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", ""))
opaque = bool(os.environ.get("CPYTHON_TEST_OPAQUE_PYOBJECT", ""))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to rename opaque to opaque_pyobject.

@@ -75,6 +78,12 @@ def main():
version = sys.hexversion
cflags.append(f'-DPy_LIMITED_API={version:#x}')

# Define _Py_OPAQUE_PYOBJECT macro
if opaque:
version = sys.hexversion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

version is not used, it can be removed.

@encukou encukou merged commit c7d24b8 into python:main Jul 12, 2025
39 checks passed
@encukou encukou deleted the opaque-pyobject-priv branch July 12, 2025 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy