diff options
author | Christian Tismer <tismer@stackless.com> | 2022-08-25 11:54:56 +0200 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2022-09-02 12:15:39 +0200 |
commit | d012c19a3113d10aab1c0abcce3b51d7fa1d6a76 (patch) | |
tree | 7049e3835eec1f55e707b72489f33557c3e2264f | |
parent | 9b41055fe043a1f190a06e0cc8b4fc82398261b9 (diff) |
PyEnum: Finish the flexible Enum/Flag assignment and correct
The former fixed coupling between flags and the Enum/Flag decision
is no longer correct, because there are rare cases which deviate
heavily from the default.
One example is Qt.Modifier: This class is equivalent to
Qt.KeyboardModifier, which is a Python Flag type.
This patch implements the full flexibility of redefining enum
and flag and corrects the Qt.Modifier case.
Task-number: PYSIDE-1735
Change-Id: I7947e722f72b4d7b821bce57586e1793a1089606
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit edbee6b65aeafc0fb9a5cdb8d53e04e15a94edbe)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 9 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/basewrapper_p.h | 2 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkenum.cpp | 13 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkfeature_base.cpp | 12 |
4 files changed, 16 insertions, 20 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index b165b6076..61d5de7cc 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -416,6 +416,7 @@ static QSet<QString> useIntSet() /* IntEnum */ u"PySide6.QtCore.Qt.GestureType"_s, /* IntEnum */ u"PySide6.QtCore.Qt.ItemDataRole"_s, /* IntEnum */ u"PySide6.QtCore.Qt.Key"_s, + /* Flag */ u"PySide6.QtCore.Qt.Modifier"_s, // note: "Qt::TextFlag" is set as IntFlag without flags /* IntFlag */ u"PySide6.QtCore.Qt.TextFlag"_s, /* IntFlag */ u"PySide6.QtCore.Qt.WindowType"_s, @@ -474,12 +475,8 @@ static QString BuildEnumFlagInfo(const AbstractMetaEnum &cppEnum) if (decision != TypeSystem::PythonEnumType::Unspecified) { _int = decision == TypeSystem::PythonEnumType::IntEnum || decision == TypeSystem::PythonEnumType::IntFlag; - if (!flags && decision == TypeSystem::PythonEnumType::IntFlag) { - qWarning() << "\nnote: " << enumType->name() << "is set as IntFlag without flags\n"; - _flag = true; - } - if (flags && decision == TypeSystem::PythonEnumType::IntEnum) - qWarning() << "\n*** The expression " << enumType->name() << "should be a flag!\n"; + _flag = decision == TypeSystem::PythonEnumType::Flag || + decision == TypeSystem::PythonEnumType::IntFlag; } result += _flag ? (_int ? u":IntFlag"_s : u":Flag"_s) : (_int ? u":IntEnum"_s : u":Enum"_s); diff --git a/sources/shiboken6/libshiboken/basewrapper_p.h b/sources/shiboken6/libshiboken/basewrapper_p.h index 3e9ff17b0..8d7e0b7a9 100644 --- a/sources/shiboken6/libshiboken/basewrapper_p.h +++ b/sources/shiboken6/libshiboken/basewrapper_p.h @@ -151,7 +151,7 @@ struct SbkObjectTypePrivate const char **propertyStrings; const char **enumFlagInfo; PyObject *enumFlagsDict; - PyObject *enumIntSet; + PyObject *enumTypeDict; }; diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp index 58dafa497..3de052236 100644 --- a/sources/shiboken6/libshiboken/sbkenum.cpp +++ b/sources/shiboken6/libshiboken/sbkenum.cpp @@ -430,6 +430,7 @@ static PyMethodDef SbkEnumObject_Methods[] = { {nullptr, nullptr, 0, nullptr} // Sentinel }; +static PyObject *PyEnumModule{}; static PyObject *PyEnumMeta{}; static PyObject *PyEnum{}; static PyObject *PyIntEnum{}; @@ -444,6 +445,7 @@ PyTypeObject *getPyEnumMeta() static auto *mod = PyImport_ImportModule("enum"); if (mod) { + PyEnumModule = mod; PyEnumMeta = PyObject_GetAttrString(mod, "EnumMeta"); if (PyEnumMeta && PyType_Check(PyEnumMeta)) PyEnum = PyObject_GetAttrString(mod, "Enum"); @@ -1030,16 +1032,14 @@ PyTypeObject *morphLastEnumToPython() } auto *scopeOrModule = lec.scopeOrModule; - bool useInt = true; - + static PyObject *enumName = String::createStaticString("IntEnum"); if (PyType_Check(scopeOrModule)) { // For global objects, we have no good solution, yet where to put the int info. auto type = reinterpret_cast<PyTypeObject *>(scopeOrModule); auto *sotp = PepType_SOTP(type); if (!sotp->enumFlagsDict) initEnumFlagsDict(type); - if (!PySet_Contains(sotp->enumIntSet, String::fromCString(lec.name))) - useInt = false; + enumName = PyDict_GetItem(sotp->enumTypeDict, String::fromCString(lec.name)); } PyObject *key, *value; @@ -1048,9 +1048,10 @@ PyTypeObject *morphLastEnumToPython() if (!values) return nullptr; + AutoDecRef PyEnumType(PyObject_GetAttr(PyEnumModule, enumName)); + assert(PyEnumType.object()); + // Walk the values dict and create a Python enum type. - auto *PyEnumType = lec.flagsType ? (useInt ? PyIntFlag : PyFlag) - : (useInt ? PyIntEnum : PyEnum); AutoDecRef name(PyUnicode_FromString(lec.name)); AutoDecRef args(PyList_New(0)); auto *pyName = name.object(); diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.cpp b/sources/shiboken6/libshiboken/sbkfeature_base.cpp index 096568f4e..797780b48 100644 --- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp +++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp @@ -211,14 +211,14 @@ static bool currentOpcode_Is_CallMethNoArgs() void initEnumFlagsDict(PyTypeObject *type) { - // We create a dict for all flag enums that holds the original C++ name. - // We create a set for all int enums or flags. + // We create a dict for all flag enums that holds the original C++ name + // and a dict that gives every enum/flag type name. static PyObject *const split = Shiboken::String::createStaticString("split"); static PyObject *const colon = Shiboken::String::createStaticString(":"); auto sotp = PepType_SOTP(type); auto **enumFlagInfo = sotp->enumFlagInfo; auto *dict = PyDict_New(); - auto *set = PySet_New(nullptr); + auto *typeDict = PyDict_New(); for (; *enumFlagInfo; ++enumFlagInfo) { AutoDecRef line(PyUnicode_FromString(*enumFlagInfo)); AutoDecRef parts(PyObject_CallMethodObjArgs(line, split, colon, nullptr)); @@ -229,12 +229,10 @@ void initEnumFlagsDict(PyTypeObject *type) PyDict_SetItem(dict, key, value); } auto *typeName = PyList_GetItem(parts, 1); - bool intFlag = strncmp(String::toCString(typeName), "Int", 3) == 0; - if (intFlag) - PySet_Add(set, name); + PyDict_SetItem(typeDict, name, typeName); } sotp->enumFlagsDict = dict; - sotp->enumIntSet = set; + sotp->enumTypeDict = typeDict; } static PyObject *replaceNoArgWithZero(PyObject *callable) |