diff options
author | Christian Tismer <tismer@stackless.com> | 2022-06-14 17:07:58 +0200 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2022-06-15 08:58:56 +0200 |
commit | 4131e4549108bc53149a45b24ccc5b3a40b6cf60 (patch) | |
tree | 7ccc460a29b14824a027585883cef8579401c20e /sources | |
parent | d78151f89b2c374af366bee536c8ceeae3b2ab5e (diff) |
QEnum: Adapt to the new enum implementation
QEnum was implemented with Python enums, as opposed to the
old C++ enums. Now that support for Python enums is built
into PySide, it is necessary to keep the implementing
Python modules always the same.
This patch prepares QEnum and PyEnum compatibility for the
upcoming embedding of old enum implementations.
As a side effect: Python 3.6 and 3.7 had a hard-to-find
refcount error when creating new enums.
Task-number: PYSIDE-1735
Change-Id: Ic44459c8e319d6d0308c7366beafa6fe7df41b79
Pick-to: 6.3
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside6/libpyside/pysideqenum.cpp | 32 | ||||
-rw-r--r-- | sources/pyside6/tests/QtCore/qenum_test.py | 2 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkenum.cpp | 22 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkenum_p.h | 2 |
4 files changed, 28 insertions, 30 deletions
diff --git a/sources/pyside6/libpyside/pysideqenum.cpp b/sources/pyside6/libpyside/pysideqenum.cpp index 3713e3c57..4ccbcbaff 100644 --- a/sources/pyside6/libpyside/pysideqenum.cpp +++ b/sources/pyside6/libpyside/pysideqenum.cpp @@ -111,38 +111,14 @@ int isFlag(PyObject *obType) * The function is called in MetaObjectBuilderPrivate::parsePythonType * again to obtain the flag value. */ - if (!PyType_Check(obType)) { - PyErr_Format(PyExc_TypeError, "a class argument was expected, not a '%.200s' instance", - Py_TYPE(obType)->tp_name); - return -1; - }; - auto *type = reinterpret_cast<PyTypeObject *>(obType); - PyObject *mro = type->tp_mro; - Py_ssize_t i, n = PyTuple_GET_SIZE(mro); - bool right_module = false; - bool have_enum = false; - bool have_flag = false; - bool have_members = PyObject_HasAttr(obType, PyMagicName::members()); - for (i = 0; i < n; i++) { - obType = PyTuple_GET_ITEM(mro, i); - type = reinterpret_cast<PyTypeObject *>(obType); - AutoDecRef mod(PyObject_GetAttr(obType, PyMagicName::module())); - QByteArray cmod = String::toCString(mod); - QByteArray cname = type->tp_name; - if (cmod == "enum") { - right_module = true; - if (cname == "Enum") - have_enum = true; - else if (cname == "Flag") - have_flag = true; - } - } - if (!right_module || !(have_enum || have_flag) || !have_members) { + int res = enumIsFlag(obType); + if (res < 0) { + auto *type = reinterpret_cast<PyTypeObject *>(obType); PyErr_Format(PyExc_TypeError, "type %.200s does not inherit from 'Enum' or 'Flag'", type->tp_name); return -1; } - return bool(have_flag); + return bool(res); } PyObject *QEnumMacro(PyObject *pyenum, bool flag) diff --git a/sources/pyside6/tests/QtCore/qenum_test.py b/sources/pyside6/tests/QtCore/qenum_test.py index 141c48f31..aa9dfbb60 100644 --- a/sources/pyside6/tests/QtCore/qenum_test.py +++ b/sources/pyside6/tests/QtCore/qenum_test.py @@ -184,12 +184,10 @@ class SomeClass(QObject): @unittest.skipUnless(HAVE_ENUM, "requires 'enum' module (use 'pip install enum34' for Python 2)") class TestQEnumMacro(unittest.TestCase): def testTopLevel(self): - self.assertEqual(type(OuterEnum).__module__, "enum") self.assertEqual(type(OuterEnum).__name__, "EnumMeta") self.assertEqual(len(OuterEnum.__members__), 2) def testSomeClass(self): - self.assertEqual(type(SomeClass.SomeEnum).__module__, "enum") self.assertEqual(type(SomeClass.SomeEnum).__name__, "EnumMeta") self.assertEqual(len(SomeClass.SomeEnum.__members__), 3) with self.assertRaises(TypeError): diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp index 17abb43ce..b9427142d 100644 --- a/sources/shiboken6/libshiboken/sbkenum.cpp +++ b/sources/shiboken6/libshiboken/sbkenum.cpp @@ -444,6 +444,24 @@ void init_enum() is_initialized = true; } +// PYSIDE-1735: Helper function supporting QEnum +int enumIsFlag(PyObject *ob_type) +{ + init_enum(); + + auto *metatype = Py_TYPE(ob_type); + if (metatype != reinterpret_cast<PyTypeObject *>(PyEnumMeta)) + return -1; + auto *mro = reinterpret_cast<PyTypeObject *>(ob_type)->tp_mro; + Py_ssize_t idx, n = PyTuple_GET_SIZE(mro); + for (idx = 0; idx < n; idx++) { + auto *sub_type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx)); + if (sub_type == reinterpret_cast<PyTypeObject *>(PyFlag)) + return 1; + } + return 0; +} + } // extern "C" // @@ -986,6 +1004,10 @@ PyTypeObject *morphLastEnumToPython() } // Protect against double initialization setp->replacementType = newType; +#if PY_VERSION_HEX < 0x03080000 + // PYSIDE-1735: Old Python versions can't stand the early enum deallocation. + Py_INCREF(enumType); +#endif return newType; } diff --git a/sources/shiboken6/libshiboken/sbkenum_p.h b/sources/shiboken6/libshiboken/sbkenum_p.h index 77561a232..76d28bc26 100644 --- a/sources/shiboken6/libshiboken/sbkenum_p.h +++ b/sources/shiboken6/libshiboken/sbkenum_p.h @@ -22,6 +22,8 @@ LIBSHIBOKEN_API PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObje /// PYSIDE-1735: Make sure that we can import the Python enum implementation. LIBSHIBOKEN_API PyTypeObject *getPyEnumMeta(); +// PYSIDE-1735: Helper function supporting QEnum +LIBSHIBOKEN_API int enumIsFlag(PyObject *ob_enum); } |