diff options
| author | Christian Tismer <tismer@stackless.com> | 2022-08-25 11:54:56 +0200 |
|---|---|---|
| committer | Christian Tismer <tismer@stackless.com> | 2022-09-01 11:47:09 +0200 |
| commit | edbee6b65aeafc0fb9a5cdb8d53e04e15a94edbe (patch) | |
| tree | 4597195b0eff909167dde939805bb656031840d8 | |
| parent | 24b86d11921c70029c1b1b75f8a20c83dbc8a88c (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
Pick-to: 6.3
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
| -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 51f3129cf..7921f6865 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -401,6 +401,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, @@ -459,12 +460,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 b96db47e0..9f163836d 100644 --- a/sources/shiboken6/libshiboken/basewrapper_p.h +++ b/sources/shiboken6/libshiboken/basewrapper_p.h @@ -115,7 +115,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 4a5f50dce..afc78a38f 100644 --- a/sources/shiboken6/libshiboken/sbkenum.cpp +++ b/sources/shiboken6/libshiboken/sbkenum.cpp @@ -394,6 +394,7 @@ static PyMethodDef SbkEnumObject_Methods[] = { {nullptr, nullptr, 0, nullptr} // Sentinel }; +static PyObject *PyEnumModule{}; static PyObject *PyEnumMeta{}; static PyObject *PyEnum{}; static PyObject *PyIntEnum{}; @@ -408,6 +409,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"); @@ -994,16 +996,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; @@ -1012,9 +1012,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 1db7ae681..08b92e35c 100644 --- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp +++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp @@ -175,14 +175,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)); @@ -193,12 +193,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) |
