aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2022-08-25 11:54:56 +0200
committerChristian Tismer <tismer@stackless.com>2022-09-02 12:15:39 +0200
commitd012c19a3113d10aab1c0abcce3b51d7fa1d6a76 (patch)
tree7049e3835eec1f55e707b72489f33557c3e2264f
parent9b41055fe043a1f190a06e0cc8b4fc82398261b9 (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.cpp9
-rw-r--r--sources/shiboken6/libshiboken/basewrapper_p.h2
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.cpp13
-rw-r--r--sources/shiboken6/libshiboken/sbkfeature_base.cpp12
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)