From 477cb4b496f830f51e2eac0a6e7d748c14de252c Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Tue, 2 Aug 2022 11:08:17 -0700 Subject: [PATCH 1/4] Try to update getset_dict APIs for 3.11 --- include/pybind11/detail/class.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index 42720f844d..8e7c487122 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -502,6 +502,7 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) { return (PyObject *) heap_type; } +#if PY_VERSION_HEX < 0x030A0000 /// dynamic_attr: Support for `d = instance.__dict__`. extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) { PyObject *&dict = *_PyObject_GetDictPtr(self); @@ -526,6 +527,7 @@ extern "C" inline int pybind11_set_dict(PyObject *self, PyObject *new_dict, void dict = new_dict; return 0; } +#endif /// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`. extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) { @@ -558,9 +560,17 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { type->tp_traverse = pybind11_traverse; type->tp_clear = pybind11_clear; - static PyGetSetDef getset[] = { - {const_cast("__dict__"), pybind11_get_dict, pybind11_set_dict, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr}}; + static PyGetSetDef getset[] = {{const_cast("__dict__"), +#if PY_VERSION_HEX < 0x030A0000 + pybind11_get_dict, + pybind11_set_dict, +#else + PyObject_GenericGetDict, + PyObject_GenericSetDict, +#endif + nullptr, + nullptr}, + {nullptr, nullptr, nullptr, nullptr, nullptr}}; type->tp_getset = getset; } From 92a47ac19374c6ebe0e4285b5d67006bc3decfb2 Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Thu, 4 Aug 2022 11:18:55 -0700 Subject: [PATCH 2/4] Update API for all Python versions --- include/pybind11/detail/class.h | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index 8e7c487122..f6187e8ede 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -502,33 +502,6 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) { return (PyObject *) heap_type; } -#if PY_VERSION_HEX < 0x030A0000 -/// dynamic_attr: Support for `d = instance.__dict__`. -extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) { - PyObject *&dict = *_PyObject_GetDictPtr(self); - if (!dict) { - dict = PyDict_New(); - } - Py_XINCREF(dict); - return dict; -} - -/// dynamic_attr: Support for `instance.__dict__ = dict()`. -extern "C" inline int pybind11_set_dict(PyObject *self, PyObject *new_dict, void *) { - if (!PyDict_Check(new_dict)) { - PyErr_Format(PyExc_TypeError, - "__dict__ must be set to a dictionary, not a '%.200s'", - get_fully_qualified_tp_name(Py_TYPE(new_dict)).c_str()); - return -1; - } - PyObject *&dict = *_PyObject_GetDictPtr(self); - Py_INCREF(new_dict); - Py_CLEAR(dict); - dict = new_dict; - return 0; -} -#endif - /// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`. extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) { PyObject *&dict = *_PyObject_GetDictPtr(self); @@ -561,13 +534,8 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { type->tp_clear = pybind11_clear; static PyGetSetDef getset[] = {{const_cast("__dict__"), -#if PY_VERSION_HEX < 0x030A0000 - pybind11_get_dict, - pybind11_set_dict, -#else PyObject_GenericGetDict, PyObject_GenericSetDict, -#endif nullptr, nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr}}; From cfdb1830a430d6f717d7b5b982bfec2ffed2cedb Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Mon, 8 Aug 2022 10:39:03 -0700 Subject: [PATCH 3/4] Test ifdef for forward explicit forward compat --- include/pybind11/detail/class.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index f6187e8ede..3a6fa16431 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -533,11 +533,16 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { type->tp_traverse = pybind11_traverse; type->tp_clear = pybind11_clear; - static PyGetSetDef getset[] = {{const_cast("__dict__"), - PyObject_GenericGetDict, - PyObject_GenericSetDict, - nullptr, - nullptr}, + static PyGetSetDef getset[] = {{ +#if PY_VERSION_HEX <= 0x03060000 + const_cast("__dict__"), +#else + "__dict__", +#endif + PyObject_GenericGetDict, + PyObject_GenericSetDict, + nullptr, + nullptr}, {nullptr, nullptr, nullptr, nullptr, nullptr}}; type->tp_getset = getset; } From b8d141d16c835f54b8db8f510d3f6763c5cf967a Mon Sep 17 00:00:00 2001 From: Aaron Gokaslan Date: Mon, 8 Aug 2022 10:45:18 -0700 Subject: [PATCH 4/4] Fix ifdef --- include/pybind11/detail/class.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index 3a6fa16431..a98e5e5414 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -534,7 +534,7 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) { type->tp_clear = pybind11_clear; static PyGetSetDef getset[] = {{ -#if PY_VERSION_HEX <= 0x03060000 +#if PY_VERSION_HEX < 0x03070000 const_cast("__dict__"), #else "__dict__",