diff options
| author | Christian Tismer <tismer@stackless.com> | 2023-10-08 18:20:39 +0200 |
|---|---|---|
| committer | Christian Tismer <tismer@stackless.com> | 2023-10-09 11:32:10 +0200 |
| commit | 8b9d69fac87cb18777e33103512c8592edd05ff4 (patch) | |
| tree | b862eb3fc03a5d4a4fe87087eeff839c8ad83803 /sources/pyside6/libpyside/feature_select.cpp | |
| parent | 65ac5d41a68dac51f85976e22ad2379d659f2f8e (diff) | |
shiboken: Get rid of tp_dict in general
It is a long due task to finally remove the direct access
to type object fields.
With Python 3.12, direct access to tp_dict became
problematic. We use that as a reason to start removing
the direct access in favor of function calls.
Task-number: PYSIDE-2230
Change-Id: I6f8a7479ab0afdbef14d4661f66c3588f3a578aa
Pick-to: 6.2 6.5 6.6
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside/feature_select.cpp')
| -rw-r--r-- | sources/pyside6/libpyside/feature_select.cpp | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp index ec15e6d0a..3f8e38870 100644 --- a/sources/pyside6/libpyside/feature_select.cpp +++ b/sources/pyside6/libpyside/feature_select.cpp @@ -162,7 +162,7 @@ static bool replaceClassDict(PyTypeObject *type) * This is mandatory for all type dicts when they are touched. */ ensureNewDictType(); - auto *dict = type->tp_dict; + AutoDecRef dict(PepType_GetDict(type)); auto *ob_ndt = reinterpret_cast<PyObject *>(new_dict_type); auto *new_dict = PyObject_CallObject(ob_ndt, nullptr); if (new_dict == nullptr || PyDict_Update(new_dict, dict) < 0) @@ -173,8 +173,8 @@ static bool replaceClassDict(PyTypeObject *type) setNextDict(new_dict, new_dict); // We have now an exact copy of the dict with a new type. // Replace `__dict__` which usually has refcount 1 (but see cyclic_test.py) - Py_DECREF(type->tp_dict); - type->tp_dict = new_dict; + Py_DECREF(PepType_GetDict(type)); + PepType_SetDict(type, new_dict); return true; } @@ -184,7 +184,7 @@ static bool addNewDict(PyTypeObject *type, int select_id) * Add a new dict to the ring and set it as `type->tp_dict`. * A 'false' return is fatal. */ - auto *dict = type->tp_dict; + AutoDecRef dict(PepType_GetDict(type)); auto *ob_ndt = reinterpret_cast<PyObject *>(new_dict_type); auto *new_dict = PyObject_CallObject(ob_ndt, nullptr); if (new_dict == nullptr) @@ -194,7 +194,7 @@ static bool addNewDict(PyTypeObject *type, int select_id) auto next_dict = nextInCircle(dict); setNextDict(dict, new_dict); setNextDict(new_dict, next_dict); - type->tp_dict = new_dict; + PepType_SetDict(type, new_dict); return true; } @@ -204,18 +204,19 @@ static inline bool moveToFeatureSet(PyTypeObject *type, int select_id) * Rotate the ring to the given `select_id` and return `true`. * If not found, stay at the current position and return `false`. */ - auto *initial_dict = type->tp_dict; + AutoDecRef tpDict(PepType_GetDict(type)); + auto *initial_dict = tpDict.object(); auto *dict = initial_dict; do { int current_id = getSelectId(dict); // This works because small numbers are singleton objects. if (current_id == select_id) { - type->tp_dict = dict; + PepType_SetDict(type, dict); return true; } dict = nextInCircle(dict); } while (dict != initial_dict); - type->tp_dict = initial_dict; + PepType_SetDict(type, initial_dict); return false; } @@ -234,8 +235,7 @@ static bool createNewFeatureSet(PyTypeObject *type, int select_id) Q_UNUSED(ok); assert(ok); - AutoDecRef prev_dict(type->tp_dict); - Py_INCREF(prev_dict); // keep the first ref unchanged + AutoDecRef prev_dict(PepType_GetDict(type)); if (!addNewDict(type, select_id)) return false; int id = select_id; @@ -245,13 +245,14 @@ static bool createNewFeatureSet(PyTypeObject *type, int select_id) for (int idx = id; *proc != nullptr; ++proc, idx >>= 1) { if (idx & 1) { // clear the tp_dict that will get new content - PyDict_Clear(type->tp_dict); + AutoDecRef tpDict(PepType_GetDict(type)); + PyDict_Clear(tpDict); // let the proc re-fill the tp_dict if (!(*proc)(type, prev_dict, id)) return false; // if there is still a step, prepare `prev_dict` if (idx >> 1) { - prev_dict.reset(PyDict_Copy(type->tp_dict)); + prev_dict.reset(PyDict_Copy(tpDict.object())); if (prev_dict.isNull()) return false; } @@ -267,7 +268,8 @@ static inline void SelectFeatureSetSubtype(PyTypeObject *type, int select_id) * every subclass until no more subclasses or reaching the wanted id. */ static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type); - if (Py_TYPE(type->tp_dict) == Py_TYPE(pyTypeType_tp_dict)) { + AutoDecRef tpDict(PepType_GetDict(type)); + if (Py_TYPE(tpDict.object()) == Py_TYPE(pyTypeType_tp_dict)) { // On first touch, we initialize the dynamic naming. // The dict type will be replaced after the first call. if (!replaceClassDict(type)) { @@ -322,7 +324,8 @@ static inline void SelectFeatureSet(PyTypeObject *type) * Shiboken will assign it via a public hook of `basewrapper.cpp`. */ static const auto *pyTypeType_tp_dict = PepType_GetDict(&PyType_Type); - if (Py_TYPE(type->tp_dict) == Py_TYPE(pyTypeType_tp_dict)) { + AutoDecRef tpDict(PepType_GetDict(type)); + if (Py_TYPE(tpDict.object()) == Py_TYPE(pyTypeType_tp_dict)) { // We initialize the dynamic features by using our own dict type. if (!replaceClassDict(type)) { Py_FatalError("failed to replace class dict!"); @@ -456,7 +459,8 @@ static PyObject *methodWithNewName(PyTypeObject *type, static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, int /* id */) { PyMethodDef *meth = type->tp_methods; - PyObject *lower_dict = type->tp_dict; + AutoDecRef tpDict(PepType_GetDict(type)); + PyObject *lower_dict = tpDict.object(); // PYSIDE-1702: A user-defined class in Python has no internal method list. // We are not going to change anything. @@ -632,7 +636,8 @@ static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, in */ PyMethodDef *meth = type->tp_methods; - PyObject *prop_dict = type->tp_dict; + AutoDecRef tpDict(PepType_GetDict(type)); + PyObject *prop_dict = tpDict.object(); // The empty `tp_dict` gets populated by the previous dict. if (PyDict_Update(prop_dict, prev_dict) < 0) @@ -765,7 +770,8 @@ static bool patch_property_impl() #define SIMILAR_FEATURE(xx) \ static bool feature_##xx##_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int /* id */) \ { \ - PyObject *dict = type->tp_dict; \ + AutoDecRef tpDict(PepType_GetDict(type)); \ + PyObject *dict = tpDict.object(); \ if (PyDict_Update(dict, prev_dict) < 0) \ return false; \ if (PyDict_SetItemString(dict, "fake_feature_" #xx, Py_None) < 0) \ |
