aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml1
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp8
-rw-r--r--sources/pyside6/PySide6/glue/qtgui.cpp5
-rw-r--r--sources/pyside6/libpyside/pysideqflags.cpp5
-rw-r--r--sources/pyside6/libpyside/pysidesignal.cpp2
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp1
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.cpp10
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetaenum.h1
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp231
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.h6
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp38
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.h7
-rw-r--r--sources/shiboken6/libshiboken/CMakeLists.txt3
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp3
-rw-r--r--sources/shiboken6/libshiboken/pep384impl.cpp1
-rw-r--r--sources/shiboken6/libshiboken/sbkconverter.h1
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.cpp1050
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.h128
-rw-r--r--sources/shiboken6/libshiboken/sbkenum_p.h51
-rw-r--r--sources/shiboken6/libshiboken/sbkfeature_base.cpp2
-rw-r--r--sources/shiboken6/libshiboken/shiboken.h1
-rw-r--r--sources/shiboken6/shibokenmodule/typesystem_shiboken.xml6
23 files changed, 484 insertions, 1079 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 646c2f311..b1557af87 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -268,7 +268,6 @@
<add-conversion type="QByteArray" file="../glue/qtcore.cpp" snippet="conversion-qbytearray"/>
<add-conversion type="PyFloat" check="PyFloat_CheckExact(%in)" file="../glue/qtcore.cpp" snippet="conversion-pyfloat"/>
<add-conversion type="PyLong" check="PyLong_CheckExact(%in)" file="../glue/qtcore.cpp" snippet="conversion-qlonglong"/>
- <add-conversion type="SbkEnumType" file="../glue/qtcore.cpp" snippet="conversion-sbkobject"/>
<add-conversion type="SbkObject" file="../glue/qtcore.cpp" snippet="conversion-sbkobject"/>
<add-conversion type="PyDict" check="PyDict_CheckExact(%in)" file="../glue/qtcore.cpp" snippet="conversion-pydict"/>
<add-conversion type="PyList" check="PyList_Check(%in)" file="../glue/qtcore.cpp" snippet="conversion-pylist"/>
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index ddb5a9ffa..f15fb6f8a 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -145,11 +145,7 @@ else {
// @snippet metatype-from-type
// @snippet metatype-from-metatype-type
-Shiboken::AutoDecRef intArg;
-if (usingNewEnum())
- intArg.reset(PyObject_GetAttrString(%PYARG_1, "value"));
-else
- intArg.reset(PyObject_CallMethod(%PYARG_1, "__int__", nullptr));
+Shiboken::AutoDecRef intArg(PyObject_GetAttrString(%PYARG_1, "value"));
%0 = new %TYPE(PyLong_AsLong(intArg));
// @snippet metatype-from-metatype-type
@@ -1187,7 +1183,7 @@ Py_END_ALLOW_THREADS
if (atexit.isNull()) {
qWarning("Module atexit not found for registering __moduleShutdown");
PyErr_Clear();
- }else{
+ } else {
regFunc.reset(PyObject_GetAttrString(atexit, "register"));
if (regFunc.isNull()) {
qWarning("Function atexit.register not found for registering __moduleShutdown");
diff --git a/sources/pyside6/PySide6/glue/qtgui.cpp b/sources/pyside6/PySide6/glue/qtgui.cpp
index d610933ba..38e01f24c 100644
--- a/sources/pyside6/PySide6/glue/qtgui.cpp
+++ b/sources/pyside6/PySide6/glue/qtgui.cpp
@@ -313,10 +313,7 @@ if (_i < 0 || _i >= %CPPSELF.count()) {
return 0;
}
QKeyCombination item = (*%CPPSELF)[_i];
-if (usingNewEnum())
- return %CONVERTTOPYTHON[QKeyCombination](item);
-auto combined = item.toCombined();
-return %CONVERTTOPYTHON[int](combined);
+return %CONVERTTOPYTHON[QKeyCombination](item);
// @snippet qkeysequence-getitem
// @snippet qkeysequence-repr
diff --git a/sources/pyside6/libpyside/pysideqflags.cpp b/sources/pyside6/libpyside/pysideqflags.cpp
index 6c0314e66..bff061bca 100644
--- a/sources/pyside6/libpyside/pysideqflags.cpp
+++ b/sources/pyside6/libpyside/pysideqflags.cpp
@@ -6,7 +6,6 @@
#include <autodecref.h>
#include <sbkenum.h>
#include <sbkconverter.h>
-#include <sbkenum_p.h>
extern "C" {
struct SbkConverter;
@@ -34,9 +33,7 @@ extern "C" {
long val = 0;
if (PyTuple_GET_SIZE(args)) {
PyObject *arg = PyTuple_GET_ITEM(args, 0);
- if (Shiboken::isShibokenEnum(arg)) {// faster call
- val = Shiboken::Enum::getValue(arg);
- } else if (PyNumber_Check(arg)) {
+ if (PyNumber_Check(arg)) {
Shiboken::AutoDecRef number(PyNumber_Long(arg));
val = PyLong_AsLong(number);
} else {
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp
index ad2a42802..fc630153c 100644
--- a/sources/pyside6/libpyside/pysidesignal.cpp
+++ b/sources/pyside6/libpyside/pysidesignal.cpp
@@ -927,8 +927,6 @@ QByteArray getTypeName(PyObject *obType)
return QByteArrayLiteral("QVariantList");
if (type == &PyDict_Type)
return QByteArrayLiteral("QVariantMap");
- if (Py_TYPE(type) == SbkEnumType_TypeF())
- return Shiboken::Enum::getCppName(type);
return QByteArrayLiteral("PyObject");
}
if (obType == Py_None) // Must be checked before as Shiboken::String::check accepts Py_None
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index aa20c23d6..d0f7fb383 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -20,7 +20,6 @@
#include <sbkstring.h>
#include <sbkstaticstrings.h>
#include <sbkerrors.h>
-#include <sbkenum_p.h>
#include <QtCore/QByteArrayView>
#include <QtCore/QDebug>
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index b5f951490..7e292f9b2 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -914,7 +914,7 @@ std::optional<AbstractMetaEnum>
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
// PYSIDE-2088, MSVC signedness issue in Qt
const bool castToUnsigned = enumItem->isSigned()
- && enumTypeEntry->cppType().contains(u"unsigned");
+ && enumTypeEntry->cppType().contains(u"unsigned"_s);
const EnumeratorList &enums = enumItem->enumerators();
for (const EnumeratorModelItem &valueItem : enums) {
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
index 8947bffd5..dd208f452 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.cpp
@@ -129,6 +129,16 @@ const AbstractMetaEnumValueList &AbstractMetaEnum::values() const
return d->m_enumValues;
}
+AbstractMetaEnumValueList AbstractMetaEnum::nonRejectedValues() const
+{
+ auto te = d->m_typeEntry;
+ AbstractMetaEnumValueList result = d->m_enumValues;
+ auto pred = [te](const AbstractMetaEnumValue &v) {
+ return te->isEnumValueRejected(v.name()); };
+ result.erase(std::remove_if(result.begin(), result.end(), pred), result.end());
+ return result;
+}
+
void AbstractMetaEnum::addEnumValue(const AbstractMetaEnumValue &enumValue)
{
d->m_enumValues << enumValue;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetaenum.h b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
index da371b31b..b99dbee57 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetaenum.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetaenum.h
@@ -62,6 +62,7 @@ public:
~AbstractMetaEnum();
const AbstractMetaEnumValueList &values() const;
+ AbstractMetaEnumValueList nonRejectedValues() const;
void addEnumValue(const AbstractMetaEnumValue &enumValue);
std::optional<AbstractMetaEnumValue> findEnumValue(QStringView value) const;
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 1f1c6b2fd..9f5cabd4b 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -2129,13 +2129,11 @@ void CppGenerator::writeConverterRegister(TextStream &s, const AbstractMetaClass
<< classContext.wrapperName() << ").name());\n";
}
- s << '\n';
-
if (!typeEntry->isValue() && !typeEntry->isSmartPointer())
return;
// Python to C++ copy (value, not pointer neither reference) conversion.
- s << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter.\n";
+ s << "\n// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter.\n";
sourceTypeName = metaClass->name();
targetTypeName = sourceTypeName + u"_COPY"_s;
QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName);
@@ -3681,8 +3679,6 @@ void CppGenerator::writePythonToCppConversionFunctions(TextStream &s,
QString pyTypeName = toNative.sourceTypeName();
if (pyTypeName == u"Py_None" || pyTypeName == u"PyNone")
typeCheck = u"%in == Py_None"_s;
- else if (pyTypeName == u"SbkEnumType")
- typeCheck = u"Shiboken::isShibokenEnum(%in)"_s;
else if (pyTypeName == u"SbkObject")
typeCheck = u"Shiboken::Object::checkType(%in)"_s;
}
@@ -5665,13 +5661,14 @@ void CppGenerator::writeSignatureInfo(TextStream &s, const OverloadData &overloa
}
}
-void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums,
- ErrorReturn errorReturn) const
+void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums) const
{
if (enums.isEmpty())
return;
bool preambleWrittenE = false;
bool preambleWrittenF = false;
+ bool etypeUsed = false;
+
for (const AbstractMetaEnum &cppEnum : std::as_const(enums)) {
if (cppEnum.isPrivate())
continue;
@@ -5686,12 +5683,13 @@ void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList
preambleWrittenF = true;
}
ConfigurableScope configScope(s, cppEnum.typeEntry());
- writeEnumInitialization(s, cppEnum, errorReturn);
+ etypeUsed |= writeEnumInitialization(s, cppEnum);
}
+ if (preambleWrittenE && !etypeUsed)
+ s << sbkUnusedVariableCast(u"EType"_s);
}
-void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum &cppEnum,
- ErrorReturn errorReturn) const
+bool CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum &cppEnum) const
{
const auto enclosingClass = cppEnum.targetLangEnclosingClass();
const bool hasUpperEnclosingClass = enclosingClass
@@ -5709,6 +5707,137 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
s << (cppEnum.isAnonymous() ? "anonymous enum identified by enum value" : "enum");
s << " '" << cppEnum.name() << "'.\n";
+ const bool isSigned = cppEnum.isSigned()
+ && !cppEnum.typeEntry()->cppType().contains(u"unsigned"_s);
+ const bool isAccessible = !avoidProtectedHack() || !cppEnum.isProtected();
+ const auto enumValues = cppEnum.nonRejectedValues();
+
+ const QString prefix = cppEnum.name();
+
+ QString tmp;
+ if (const auto userType = cppEnum.typeEntry()->cppType(); !userType.isEmpty()) {
+ tmp = userType;
+ } else {
+ if (!isSigned && !cppEnum.underlyingType().contains(u"unsigned"_s))
+ tmp += u"unsigned "_s;
+ tmp += cppEnum.underlyingType();
+ }
+ const QString simpleIntType = getSimplifiedIntTypeName(tmp);
+ QStringList pythonEnumNames;
+
+ // Create a list of values
+ const QString initializerValues = prefix + u"_InitializerValues"_s;
+ const QString initializerName = prefix + u"_Initializer"_s;
+
+ // Build maybe array of enum names.
+ if (cppEnum.enumKind() != AnonymousEnum) {
+ s << "const char *" << initializerName << "[] = {\n" << indent;
+ for (const auto &enumValue : enumValues) {
+ QString name = mangleName(enumValue.name());
+ s << '\"' << name << "\",\n";
+ }
+ s << "nullptr};\n" << outdent;
+ }
+
+ // Calculate formatting and record used number range.
+ int maxNameLen = 0;
+ unsigned long long valueMaskPos = 0;
+ long long valueMaskNeg = 0;
+
+ for (const auto &enumValue : enumValues) {
+ QString name = mangleName(enumValue.name());
+
+ // calculate formatting
+ if (name.length() > maxNameLen)
+ maxNameLen = name.length();
+
+ // calculate used number range
+ QString numStr = enumValue.value().toString();
+ if (numStr.startsWith(u"-"_s)) {
+ auto val = numStr.toLongLong();
+ if (val < valueMaskNeg)
+ valueMaskNeg = val;
+ } else {
+ auto val = numStr.toULongLong();
+ if (val > valueMaskPos)
+ valueMaskPos = val;
+ }
+ }
+
+ // update signedness for the reduced number type.
+ const bool isSignedShort = valueMaskNeg < 0;
+ const QString usedIntType = calcMinimalIntTypeName(valueMaskPos, valueMaskNeg);
+ const int targetHexLen = calcUsedBits(valueMaskPos, valueMaskNeg) / 4;
+
+ if (usedIntType != simpleIntType)
+ s << "// " << usedIntType << " used instead of " << simpleIntType << "\n";
+
+ // Calculating formatting columns
+ QString enumValuePrefix;
+ if (isAccessible) {
+ enumValuePrefix = usedIntType + u"("_s;
+ if (cppEnum.enclosingClass())
+ enumValuePrefix += cppEnum.enclosingClass()->qualifiedCppName() + u"::"_s;
+ if (!cppEnum.isAnonymous())
+ enumValuePrefix += cppEnum.name() + u"::"_s;
+ }
+ const int needSpace = enumValuePrefix.length() + 2; // braces
+
+ // Build array of enum values
+ if (enumValues.isEmpty()) {
+ s << usedIntType << " *" << initializerValues << "{};\n";
+ } else {
+ s << usedIntType << ' ' << initializerValues << "[] = {\n" << indent;
+ for (qsizetype idx = 0, last = enumValues.size() - 1; idx <= last; ++idx) {
+ const auto &enumValue = enumValues[idx];
+
+ QString valueStr = enumValue.value().toString();
+
+ QString enumValueText = enumValuePrefix;
+ if (isAccessible)
+ enumValueText += enumValue.name() + u')';
+ else
+ enumValueText += valueStr;
+
+ bool hasSign = valueStr.startsWith(u"-"_s);
+ if (hasSign)
+ valueStr.removeFirst();
+ auto val = valueStr.toULongLong();
+ QString valueHex = QString(u"0x%1"_s).arg(val, targetHexLen, 16, QChar(u'0'));
+ if (hasSign)
+ valueStr = u'-' + valueHex + u" -"_s + valueStr;
+ else
+ valueStr = u' ' + valueHex + u" "_s + valueStr;
+ if (idx != last)
+ enumValueText += u',';
+ int targetCol = needSpace + maxNameLen - enumValueText.length();
+ s << enumValueText << QByteArray(targetCol, ' ') << " // " << valueStr << "\n";
+ }
+ s << "};\n" << outdent;
+ }
+
+ // Build initialization of anonymous enums
+ if (cppEnum.enumKind() == AnonymousEnum) {
+ int idx = 0;
+ for (const auto &enumValue : enumValues) {
+ const QString mangledName = mangleName(enumValue.name());
+ const QString pyValue = initializerValues + u'[' + QString::number(idx++) + u']';
+ if (enclosingClass || hasUpperEnclosingClass) {
+ s << "PyDict_SetItemString(reinterpret_cast<PyTypeObject *>("
+ << enclosingObjectVariable
+ << ")->tp_dict, \"" << mangledName << "\",\n" << indent
+ << (isSignedShort ? "PyLong_FromLongLong" : "PyLong_FromUnsignedLongLong") << "("
+ << pyValue << "));\n" << outdent;
+ } else {
+ s << "PyModule_AddObject(module, \"" << mangledName << "\",\n" << indent
+ << (isSignedShort ? "PyLong_FromLongLong" : "PyLong_FromUnsignedLongLong") << "("
+ << pyValue << "));\n" << outdent;
+ }
+ }
+ }
+
+ bool etypeUsed = false;
+
QString enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
if (!cppEnum.isAnonymous()) {
int packageLevel = packageName().count(u'.') + 1;
@@ -5725,73 +5854,14 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
}
s << "EType = Shiboken::Enum::"
- << ((enclosingClass
- || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum")
- << '(' << enclosingObjectVariable << ',' << '\n' << indent
- << '"' << cppEnum.name() << "\",\n"
- << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n"
- << '"' << cppEnum.qualifiedCppName() << '"';
- if (flags)
- s << ",\nFType";
- s << ");\n" << outdent
- << "if (!EType)\n"
- << indent << errorReturn << outdent << '\n';
- }
-
- for (const AbstractMetaEnumValue &enumValue : cppEnum.values()) {
- if (enumTypeEntry->isEnumValueRejected(enumValue.name()))
- continue;
-
- QString enumValueText;
- if (!avoidProtectedHack() || !cppEnum.isProtected()) {
- enumValueText = cppEnum.typeEntry()->cppType();
- if (enumValueText.isEmpty())
- enumValueText = u"Shiboken::Enum::EnumValueType"_s;
- enumValueText += u'(';
- if (cppEnum.enclosingClass())
- enumValueText += cppEnum.enclosingClass()->qualifiedCppName() + u"::"_s;
- // Fully qualify the value which is required for C++ 11 enum classes.
- if (!cppEnum.isAnonymous())
- enumValueText += cppEnum.name() + u"::"_s;
- enumValueText += enumValue.name();
- enumValueText += u')';
- } else {
- enumValueText += enumValue.value().toString();
- }
-
- const QString mangledName = mangleName(enumValue.name());
- switch (cppEnum.enumKind()) {
- case AnonymousEnum:
- if (enclosingClass || hasUpperEnclosingClass) {
- s << "{\n" << indent
- << "PyObject *anonEnumItem = PyLong_FromLong(" << enumValueText << ");\n"
- << "if (PyDict_SetItemString(reinterpret_cast<PyTypeObject *>("
- << enclosingObjectVariable
- << ")->tp_dict, \"" << mangledName << "\", anonEnumItem) < 0)\n"
- << indent << errorReturn << outdent
- << "Py_DECREF(anonEnumItem);\n" << outdent
- << "}\n";
- } else {
- s << "if (PyModule_AddIntConstant(module, \"" << mangledName << "\", ";
- s << enumValueText << ") < 0)\n" << indent << errorReturn << outdent;
- }
- break;
- case CEnum:
- case EnumClass:
- s << "if (!Shiboken::Enum::createEnumItemOld(EType,\n" << indent
- << "\"" << mangledName << "\", " << enumValueText << "))\n" << errorReturn
- << outdent;
- break;
- }
- }
- if (cppEnum.enumKind() != AnonymousEnum) {
- s << "// PYSIDE-1735: Resolving the whole enum class at the end for API compatibility.\n"
- << "EType = morphLastEnumToPython();\n"
- << enumVarTypeObj << " = EType;\n";
- } else {
- s << "// PYSIDE-1735: Skip an Anonymous enum class for Python coercion.\n"
+ << "createPythonEnum"
+ << '(' << enclosingObjectVariable << ",\n" << indent
+ << '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n"
+ << initializerName << ", " << initializerValues << ");\n" << outdent
<< enumVarTypeObj << " = EType;\n";
+ etypeUsed = true;
}
+
if (cppEnum.typeEntry()->flags()) {
s << "// PYSIDE-1735: Mapping the flags class to the same enum class.\n"
<< cpythonTypeNameExt(cppEnum.typeEntry()->flags()) << " =\n"
@@ -5803,6 +5873,8 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
if (cppEnum.typeEntry()->flags())
s << "/flags";
s << ".\n\n";
+
+ return etypeUsed;
}
void CppGenerator::writeSignalInitialization(TextStream &s, const AbstractMetaClassCPtr &metaClass)
@@ -6159,8 +6231,9 @@ void CppGenerator::writeClassRegister(TextStream &s,
// Set typediscovery struct or fill the struct of another one
if (needsTypeDiscoveryFunction(metaClass)) {
- s << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(" << cpythonTypeName(metaClass)
- << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);\n\n";
+ s << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(\n" << indent
+ << cpythonTypeName(metaClass)
+ << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << outdent << "\n\n";
}
AbstractMetaEnumList classEnums = metaClass->enums();
@@ -6170,7 +6243,7 @@ void CppGenerator::writeClassRegister(TextStream &s,
s << "// Pass the ..._EnumFlagInfo to the class.\n"
<< "SbkObjectType_SetEnumFlagInfo(pyType, " << chopType(pyTypeName)
<< "_EnumFlagInfo);\n\n";
- writeEnumsInitialization(s, classEnums, ErrorReturn::Void);
+ writeEnumsInitialization(s, classEnums);
if (metaClass->hasSignals())
writeSignalInitialization(s, metaClass);
@@ -6997,7 +7070,7 @@ bool CppGenerator::finishGeneration()
}
}
- writeEnumsInitialization(s, globalEnums, ErrorReturn::Default);
+ writeEnumsInitialization(s, globalEnums);
s << "// Register primitive types converters.\n";
const PrimitiveTypeEntryCList &primitiveTypeList = primitiveTypes();
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h
index 9f07529d9..f88c846ed 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.h
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.h
@@ -448,10 +448,8 @@ private:
void writeRichCompareFunction(TextStream &s, const GeneratorContext &context) const;
void writeSmartPointerRichCompareFunction(TextStream &s, const GeneratorContext &context) const;
- void writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums,
- ErrorReturn errorReturn) const;
- void writeEnumInitialization(TextStream &s, const AbstractMetaEnum &metaEnum,
- ErrorReturn errorReturn) const;
+ void writeEnumsInitialization(TextStream &s, AbstractMetaEnumList &enums) const;
+ bool writeEnumInitialization(TextStream &s, const AbstractMetaEnum &metaEnum) const;
static void writeSignalInitialization(TextStream &s, const AbstractMetaClassCPtr &metaClass);
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index fde07ef80..c9e95e2c8 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -1883,6 +1883,44 @@ QString ShibokenGenerator::getPrivateModuleHeaderFileName(const QString &moduleN
return getModuleHeaderFileBaseName(moduleName) + QStringLiteral("_p.h");
}
+QString ShibokenGenerator::getSimplifiedIntTypeName(const QString &name)
+
+{
+ bool isSigned = !name.contains(u"unsigned"_s);
+ if (name.contains(u"long"_s)) {
+ if (name.contains(u"long long"_s))
+ return isSigned ? u"int64_t"_s : u"uint64_t"_s;
+ return isSigned ? u"int32_t"_s : u"uint32_t"_s;
+ }
+ if (name.contains(u"short"_s))
+ return isSigned ? u"int16_t"_s : u"uint16_t"_s;
+ if (name.contains(u"char"_s))
+ return isSigned ? u"int8_t"_s : u"uint8_t"_s;
+ return isSigned ? u"int32_t"_s : u"uint32_t"_s;
+}
+
+QString ShibokenGenerator::calcMinimalIntTypeName(uint64_t maxNumber, int64_t minNumber)
+{
+ // Calculate the really needed bits.
+ // Note: By the minimization, it depends on the real data if the result is
+ // signed or unsigned. The underlying type is no longer relevant.
+ assert(minNumber <= 0);
+ unsigned long long valueMask = maxNumber - minNumber;
+ int usedBits = (valueMask >> 32) ? 64 : (valueMask >> 16) ? 32 : (valueMask >> 8) ? 16 : 8;
+ return (minNumber < 0 ? u"int"_s : u"uint"_s) + QString::number(usedBits) + u"_t"_s;
+}
+
+int ShibokenGenerator::calcUsedBits(uint64_t maxNumber, int64_t minNumber)
+{
+ // Calculate the really needed bits.
+ // Note: By the minimization, it depends on the real data if the result is
+ // signed or unsigned. The underlying type is no longer relevant.
+ assert(minNumber <= 0);
+ unsigned long long valueMask = maxNumber - minNumber;
+ int usedBits = (valueMask >> 32) ? 64 : (valueMask >> 16) ? 32 : (valueMask >> 8) ? 16 : 8;
+ return usedBits;
+}
+
IncludeGroupList ShibokenGenerator::classIncludes(const AbstractMetaClassCPtr &metaClass) const
{
IncludeGroupList result;
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.h b/sources/shiboken6/generator/shiboken/shibokengenerator.h
index 4189753cc..12d908ddb 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.h
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.h
@@ -272,6 +272,13 @@ protected:
static QString getModuleHeaderFileName(const QString &moduleName = QString());
static QString getPrivateModuleHeaderFileName(const QString &moduleName = QString());
+ /// Turn "unsigned? long? (long|int|short|char)" into "u?int(8|16|32|64)_t""
+ static QString getSimplifiedIntTypeName(const QString &typeName);
+
+ /// Determine the minimal needed data type for a given number range.
+ static QString calcMinimalIntTypeName(uint64_t maxNumber, int64_t minNumber);
+ static int calcUsedBits(uint64_t maxNumber, int64_t minNumber);
+
/// Includes for header (native wrapper class) or binding source
QList<IncludeGroup> classIncludes(const AbstractMetaClassCPtr &metaClass) const;
diff --git a/sources/shiboken6/libshiboken/CMakeLists.txt b/sources/shiboken6/libshiboken/CMakeLists.txt
index 69a0af5ca..2e558a39d 100644
--- a/sources/shiboken6/libshiboken/CMakeLists.txt
+++ b/sources/shiboken6/libshiboken/CMakeLists.txt
@@ -70,7 +70,7 @@ sbkarrayconverter.cpp sbkarrayconverter.h sbkarrayconverter_p.h
sbkcontainer.cpp sbkcontainer.h
sbkconverter.cpp sbkconverter.h sbkconverter_p.h
sbkcppstring.cpp sbkcppstring.h sbkcpptonumpy.h
-sbkenum.cpp sbkenum.h sbkenum_p.h
+sbkenum.cpp sbkenum.h
sbkerrors.cpp sbkerrors.h
sbkfeature_base.cpp sbkfeature_base.h
sbkmodule.cpp sbkmodule.h
@@ -158,7 +158,6 @@ install(FILES
sbkconverter.h
sbkcpptonumpy.h
sbkenum.h
- sbkenum_p.h
sbkerrors.h
sbkfeature_base.h
sbkmodule.h
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index b01d01685..9e5d1b89e 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -721,9 +721,6 @@ void init()
//Init private data
Pep384_Init();
- if (PyType_Ready(SbkEnumType_TypeF()) < 0)
- Py_FatalError("[libshiboken] Failed to initialize Shiboken.SbkEnumType metatype.");
-
if (PyType_Ready(SbkObjectType_TypeF()) < 0)
Py_FatalError("[libshiboken] Failed to initialize Shiboken.BaseWrapperType metatype.");
diff --git a/sources/shiboken6/libshiboken/pep384impl.cpp b/sources/shiboken6/libshiboken/pep384impl.cpp
index e3b8904a5..9616712f6 100644
--- a/sources/shiboken6/libshiboken/pep384impl.cpp
+++ b/sources/shiboken6/libshiboken/pep384impl.cpp
@@ -8,7 +8,6 @@
#include "basewrapper.h"
#include "basewrapper_p.h"
#include "sbkenum.h"
-#include "sbkenum_p.h"
#include "sbkconverter.h"
#include "voidptr.h"
diff --git a/sources/shiboken6/libshiboken/sbkconverter.h b/sources/shiboken6/libshiboken/sbkconverter.h
index c4a99a818..dd8d01379 100644
--- a/sources/shiboken6/libshiboken/sbkconverter.h
+++ b/sources/shiboken6/libshiboken/sbkconverter.h
@@ -7,7 +7,6 @@
#include "sbkpython.h"
#include "shibokenmacros.h"
#include "sbkenum.h"
-#include "sbkenum_p.h"
#include "basewrapper_p.h"
#include <limits>
diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp
index 1b83e8a84..502b6c669 100644
--- a/sources/shiboken6/libshiboken/sbkenum.cpp
+++ b/sources/shiboken6/libshiboken/sbkenum.cpp
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "sbkenum.h"
-#include "sbkenum_p.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
@@ -16,377 +15,23 @@
#include <vector>
#include <sstream>
-#define SbkEnumType_Check(o) (Py_TYPE(Py_TYPE(o)) == SbkEnumType_TypeF())
-using enum_func = PyObject *(*)(PyObject *, PyObject *);
-
using namespace Shiboken;
extern "C"
{
-// forward
-struct lastEnumCreated;
-
-// forward
-static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
- const char *name,
- PyTypeObject *enumType,
- PyTypeObject *flagsType);
-
struct SbkEnumType
{
PyTypeObject type;
};
-static void cleanupEnumTypes();
-
-struct SbkEnumObject
-{
- PyObject_HEAD
- Enum::EnumValueType ob_value;
- PyObject *ob_name;
-};
-
-static PyTypeObject *SbkEnum_TypeF(); // forward
-
-static PyObject *SbkEnumObject_repr(PyObject *self)
-{
- const SbkEnumObject *enumObj = reinterpret_cast<SbkEnumObject *>(self);
- auto name = Py_TYPE(self)->tp_name;
- if (enumObj->ob_name) {
- return String::fromFormat("%s.%s", name, PyBytes_AS_STRING(enumObj->ob_name));
- }
- return String::fromFormat("%s(%ld)", name, enumObj->ob_value);
-}
-
-static PyObject *SbkEnumObject_name(PyObject *self, void *)
-{
- auto *enum_self = reinterpret_cast<SbkEnumObject *>(self);
-
- if (enum_self->ob_name == nullptr)
- Py_RETURN_NONE;
-
- Py_INCREF(enum_self->ob_name);
- return enum_self->ob_name;
-}
-
-static PyObject *SbkEnum_tp_new(PyTypeObject *type, PyObject *args, PyObject *)
-{
- long itemValue = 0;
- if (!PyArg_ParseTuple(args, "|l:__new__", &itemValue))
- return nullptr;
-
- if (type == SbkEnum_TypeF()) {
- PyErr_Format(PyExc_TypeError, "You cannot use %s directly", type->tp_name);
- return nullptr;
- }
-
- SbkEnumObject *self = PyObject_New(SbkEnumObject, type);
- if (!self)
- return nullptr;
- self->ob_value = itemValue;
- AutoDecRef item(Enum::getEnumItemFromValue(type, itemValue));
- self->ob_name = item.object() ? SbkEnumObject_name(item, nullptr) : nullptr;
- return reinterpret_cast<PyObject *>(self);
-}
-
-static const char *SbkEnum_SignatureStrings[] = {
- "Shiboken.Enum(self,itemValue:int=0)",
- nullptr}; // Sentinel
-
-static void enum_object_dealloc(PyObject *ob)
-{
- auto *self = reinterpret_cast<SbkEnumObject *>(ob);
- Py_XDECREF(self->ob_name);
- Sbk_object_dealloc(ob);
-}
-
-static PyObject *_enum_op(enum_func f, PyObject *a, PyObject *b) {
- PyObject *valA = a;
- PyObject *valB = b;
- PyObject *result = nullptr;
- bool enumA = false;
- bool enumB = false;
-
- // We are not allowing floats
- if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) {
- // Check if both variables are SbkEnumObject
- if (SbkEnumType_Check(valA)) {
- valA = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valA)->ob_value);
- enumA = true;
- }
- if (SbkEnumType_Check(valB)) {
- valB = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valB)->ob_value);
- enumB = true;
- }
- }
-
- // Without an enum we are not supporting the operation
- if (!(enumA || enumB)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- result = f(valA, valB);
-
- // Decreasing the reference of the used variables a and b.
- if (enumA)
- Py_DECREF(valA);
- if (enumB)
- Py_DECREF(valB);
- return result;
-}
-
-/* Notes:
- * On Py3k land we use long type when using integer numbers. However, on older
- * versions of Python (version 2) we need to convert it to int type,
- * respectively.
- *
- * Thus calling PyLong_FromLong() will result in calling PyLong_FromLong in
- * Py3k.
- */
-static PyObject *enum_int(PyObject *v)
-{
- return PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(v)->ob_value);
-}
-
-static PyObject *enum_and(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_And, self, b);
-}
-
-static PyObject *enum_or(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_Or, self, b);
-}
-
-static PyObject *enum_xor(PyObject *self, PyObject *b)
-{
- return _enum_op(PyNumber_Xor, self, b);
-}
-
-static int enum_bool(PyObject *v)
-{
- return (reinterpret_cast<SbkEnumObject *>(v)->ob_value > 0);
-}
-
-static PyObject *enum_add(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Add, self, v);
-}
-
-static PyObject *enum_subtract(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Subtract, self, v);
-}
-
-static PyObject *enum_multiply(PyObject *self, PyObject *v)
-{
- return _enum_op(PyNumber_Multiply, self, v);
-}
-
-static PyObject *enum_richcompare(PyObject *self, PyObject *other, int op)
-{
- PyObject *valA = self;
- PyObject *valB = other;
- PyObject *result = nullptr;
- bool enumA = false;
- bool enumB = false;
-
- // We are not allowing floats
- if (!PyFloat_Check(valA) && !PyFloat_Check(valB)) {
-
- // Check if both variables are SbkEnumObject
- if (SbkEnumType_Check(valA)) {
- valA = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valA)->ob_value);
- enumA = true;
- }
- if (SbkEnumType_Check(valB)) {
- valB = PyLong_FromLong(reinterpret_cast<SbkEnumObject *>(valB)->ob_value);
- enumB =true;
- }
- }
-
- // Without an enum we are not supporting the operation
- if (!(enumA || enumB)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- result = PyObject_RichCompare(valA, valB, op);
-
- // Decreasing the reference of the used variables a and b.
- if (enumA)
- Py_DECREF(valA);
- if (enumB)
- Py_DECREF(valB);
-
- return result;
-}
-
-static Py_hash_t enum_hash(PyObject *pyObj)
-{
- Py_hash_t val = reinterpret_cast<SbkEnumObject *>(pyObj)->ob_value;
- if (val == -1)
- val = -2;
- return val;
-}
-
-static PyGetSetDef SbkEnumGetSetList[] = {
- {const_cast<char *>("name"), SbkEnumObject_name, nullptr, nullptr, nullptr},
- {nullptr, nullptr, nullptr, nullptr, nullptr} // Sentinel
-};
-
-static void SbkEnumTypeDealloc(PyObject *pyObj);
-static PyTypeObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds);
-
-static PyType_Slot SbkEnumType_Type_slots[] = {
- {Py_tp_dealloc, reinterpret_cast<void *>(SbkEnumTypeDealloc)},
- {Py_tp_base, reinterpret_cast<void *>(&PyType_Type)},
- {Py_tp_alloc, reinterpret_cast<void *>(PyType_GenericAlloc)},
- {Py_tp_new, reinterpret_cast<void *>(SbkEnumTypeTpNew)},
- {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)},
- {0, nullptr}
-};
-
-// PYSIDE-535: The tp_itemsize field is inherited and does not need to be set.
-// In PyPy, it _must_ not be set, because it would have the meaning that a
-// `__len__` field must be defined. Not doing so creates a hard-to-find crash.
-static PyType_Spec SbkEnumType_Type_spec = {
- "1:Shiboken.EnumMeta",
- 0,
- 0, // sizeof(PyMemberDef), not for PyPy without a __len__ defined
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- SbkEnumType_Type_slots,
-};
-
-PyTypeObject *SbkEnumType_TypeF(void)
-{
- static auto *type = SbkType_FromSpec(&SbkEnumType_Type_spec);
- return type;
-}
-
-static void SbkEnumTypeDealloc(PyObject *pyObj)
-{
- auto *enumType = reinterpret_cast<SbkEnumType *>(pyObj);
- auto *setp = PepType_SETP(enumType);
-
- PyObject_GC_UnTrack(pyObj);
-#ifndef Py_LIMITED_API
-# if PY_VERSION_HEX >= 0x030A0000
- Py_TRASHCAN_BEGIN(pyObj, 1);
-# else
- Py_TRASHCAN_SAFE_BEGIN(pyObj);
-# endif
-#endif
- if (setp->converter)
- Conversions::deleteConverter(setp->converter);
- PepType_SETP_delete(enumType);
-#ifndef Py_LIMITED_API
-# if PY_VERSION_HEX >= 0x030A0000
- Py_TRASHCAN_END;
-# else
- Py_TRASHCAN_SAFE_END(pyObj);
-# endif
-#endif
- if (PepRuntime_38_flag) {
- // PYSIDE-939: Handling references correctly.
- // This was not needed before Python 3.8 (Python issue 35810)
- Py_DECREF(Py_TYPE(pyObj));
- }
-}
-
-PyTypeObject *SbkEnumTypeTpNew(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
-{
- init_enum();
- return PepType_Type_tp_new(metatype, args, kwds);
-}
-
-} // extern "C"
-
-///////////////////////////////////////////////////////////////
-//
-// PYSIDE-15: Pickling Support for Qt Enum objects
-// This works very well and fixes the issue.
-//
-extern "C" {
-
-static PyObject *enum_unpickler = nullptr;
-
-// Pickling: reduce the Qt Enum object
-static PyObject *enum___reduce__(PyObject *obj)
-{
- init_enum();
- return Py_BuildValue("O(Ni)",
- enum_unpickler,
- Py_BuildValue("s", Py_TYPE(obj)->tp_name),
- PyLong_AS_LONG(obj));
-}
-
-} // extern "C"
-
-namespace Shiboken { namespace Enum {
-
-// Unpickling: rebuild the Qt Enum object
-PyObject *unpickleEnum(PyObject *enum_class_name, PyObject *value)
-{
- AutoDecRef parts(PyObject_CallMethod(enum_class_name,
- "split", "s", "."));
- if (parts.isNull())
- return nullptr;
- PyObject *top_name = PyList_GetItem(parts, 0); // borrowed ref
- if (top_name == nullptr)
- return nullptr;
- PyObject *module = PyImport_GetModule(top_name);
- if (module == nullptr) {
- PyErr_Format(PyExc_ImportError, "could not import module %.200s",
- String::toCString(top_name));
- return nullptr;
- }
- AutoDecRef cur_thing(module);
- int len = PyList_Size(parts);
- for (int idx = 1; idx < len; ++idx) {
- PyObject *name = PyList_GetItem(parts, idx); // borrowed ref
- PyObject *thing = PyObject_GetAttr(cur_thing, name);
- if (thing == nullptr) {
- PyErr_Format(PyExc_ImportError, "could not import Qt Enum type %.200s",
- String::toCString(enum_class_name));
- return nullptr;
- }
- cur_thing.reset(thing);
- }
- PyObject *klass = cur_thing;
- return PyObject_CallFunctionObjArgs(klass, value, nullptr);
-}
-
-int enumOption{};
-
-} // namespace Enum
-} // namespace Shiboken
-
-extern "C" {
-
// Initialization
static bool _init_enum()
{
AutoDecRef shibo(PyImport_ImportModule("shiboken6.Shiboken"));
- auto mod = shibo.object();
- // publish Shiboken.Enum so that the signature gets initialized
- if (PyObject_SetAttrString(mod, "Enum", reinterpret_cast<PyObject *>(SbkEnum_TypeF())) < 0)
- return false;
- if (InitSignatureStrings(SbkEnum_TypeF(), SbkEnum_SignatureStrings) < 0)
- return false;
- enum_unpickler = PyObject_GetAttrString(mod, "_unpickle_enum");
- if (enum_unpickler == nullptr)
- return false;
- return true;
+ return !shibo.isNull();
}
-static PyMethodDef SbkEnumObject_Methods[] = {
- {"__reduce__", reinterpret_cast<PyCFunction>(enum___reduce__),
- METH_NOARGS, nullptr},
- {nullptr, nullptr, 0, nullptr} // Sentinel
-};
-
static PyObject *PyEnumModule{};
static PyObject *PyEnumMeta{};
static PyObject *PyEnum{};
@@ -433,15 +78,14 @@ void init_enum()
static bool isInitialized = false;
if (isInitialized)
return;
- if (!(isInitialized || enum_unpickler || _init_enum()))
- Py_FatalError("could not load enum pickling helper function");
- Py_AtExit(cleanupEnumTypes);
+ if (!(isInitialized || _init_enum()))
+ Py_FatalError("could not init enum");
// PYSIDE-1735: Determine whether we should use the old or the new enum implementation.
static PyObject *option = PySys_GetObject("pyside6_option_python_enum");
if (!option || !PyLong_Check(option)) {
PyErr_Clear();
- option = PyLong_FromLong(0);
+ option = PyLong_FromLong(1);
}
int ignoreOver{};
Enum::enumOption = PyLong_AsLongAndOverflow(option, &ignoreOver);
@@ -467,460 +111,6 @@ int enumIsFlag(PyObject *ob_type)
return 0;
}
-// PYSIDE-1735: Helper function to ask what enum we are using
-bool usingNewEnum()
-{
- return true;
-}
-
-} // extern "C"
-
-//
-///////////////////////////////////////////////////////////////
-
-namespace Shiboken {
-
-class DeclaredEnumTypes
-{
-public:
- struct EnumEntry
- {
- char *name; // full name as allocated. type->tp_name might be a substring.
- PyTypeObject *type;
- };
-
- DeclaredEnumTypes(const DeclaredEnumTypes &) = delete;
- DeclaredEnumTypes(DeclaredEnumTypes &&) = delete;
- DeclaredEnumTypes &operator=(const DeclaredEnumTypes &) = delete;
- DeclaredEnumTypes &operator=(DeclaredEnumTypes &&) = delete;
-
- DeclaredEnumTypes();
- ~DeclaredEnumTypes();
- static DeclaredEnumTypes &instance();
- void addEnumType(const EnumEntry &e) { m_enumTypes.push_back(e); }
-
- void cleanup();
-
-private:
- std::vector<EnumEntry> m_enumTypes;
-};
-
-namespace Enum {
-
-// forward
-static PyObject *newItemOld(PyTypeObject *enumType, EnumValueType itemValue,
- const char *itemName);
-
-// forward
-static PyTypeObject * newTypeWithNameOld(const char *name,
- const char *cppName,
- PyTypeObject *numbers_fromFlag);
-
-bool check(PyObject *pyObj)
-{
- init_enum();
-
- static PyTypeObject *meta = getPyEnumMeta();
- return Py_TYPE(Py_TYPE(pyObj)) == reinterpret_cast<PyTypeObject *>(meta);
-}
-
-PyObject *getEnumItemFromValue(PyTypeObject *enumType, EnumValueType itemValue)
-{
- init_enum();
-
- auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
- AutoDecRef val2members(PyObject_GetAttrString(obEnumType, "_value2member_map_"));
- if (val2members.isNull()) {
- PyErr_Clear();
- return nullptr;
- }
- AutoDecRef ob_value(PyLong_FromLongLong(itemValue));
- auto *result = PyDict_GetItem(val2members, ob_value);
- Py_XINCREF(result);
- return result;
-}
-
-static PyTypeObject *createEnum(const char *fullName, const char *cppName,
- PyTypeObject *flagsType)
-{
- init_enum();
- PyTypeObject *enumType = newTypeWithNameOld(fullName, cppName, flagsType);
- if (PyType_Ready(enumType) < 0) {
- Py_XDECREF(enumType);
- return nullptr;
- }
- return enumType;
-}
-
-PyTypeObject *createGlobalEnum(PyObject *module, const char *name, const char *fullName,
- const char *cppName, PyTypeObject *flagsType)
-{
- PyTypeObject *enumType = createEnum(fullName, cppName, flagsType);
- if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- flagsType = recordCurrentEnum(module, name, enumType, flagsType);
- if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType),
- reinterpret_cast<PyObject *>(flagsType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- return enumType;
-}
-
-PyTypeObject *createScopedEnum(PyTypeObject *scope, const char *name, const char *fullName,
- const char *cppName, PyTypeObject *flagsType)
-{
- PyTypeObject *enumType = createEnum(fullName, cppName, flagsType);
- if (enumType && PyDict_SetItemString(scope->tp_dict, name,
- reinterpret_cast<PyObject *>(enumType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- auto *obScope = reinterpret_cast<PyObject *>(scope);
- flagsType = recordCurrentEnum(obScope, name, enumType, flagsType);
- if (flagsType && PyDict_SetItemString(scope->tp_dict,
- PepType_GetNameStr(flagsType),
- reinterpret_cast<PyObject *>(flagsType)) < 0) {
- Py_DECREF(enumType);
- return nullptr;
- }
- return enumType;
-}
-
-static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName,
- EnumValueType itemValue)
-{
- init_enum();
- PyObject *enumItem = newItemOld(enumType, itemValue, itemName);
- if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) {
- Py_DECREF(enumItem);
- return nullptr;
- }
- return enumItem;
-}
-
-bool createEnumItemOld(PyTypeObject *enumType, const char *itemName, EnumValueType itemValue)
-{
- Shiboken::AutoDecRef enumItem(createEnumItem(enumType, itemName, itemValue));
- return !enumItem.isNull();
-}
-
-// This exists temporary as the old way to create an enum item.
-// For the public interface, we use a new function
-static PyObject *newItemOld(PyTypeObject *enumType,
- EnumValueType itemValue, const char *itemName)
-{
- bool newValue = true;
- SbkEnumObject *enumObj;
- if (!itemName) {
- enumObj = reinterpret_cast<SbkEnumObject *>(
- getEnumItemFromValue(enumType, itemValue));
- if (enumObj)
- return reinterpret_cast<PyObject *>(enumObj);
-
- newValue = false;
- }
-
- enumObj = PyObject_New(SbkEnumObject, enumType);
- if (!enumObj)
- return nullptr;
-
- enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : nullptr;
- enumObj->ob_value = itemValue;
-
- if (newValue) {
- auto dict = enumType->tp_dict; // Note: 'values' is borrowed
- PyObject *values = PyDict_GetItemWithError(dict, PyName::values());
- if (values == nullptr) {
- if (PyErr_Occurred())
- return nullptr;
- AutoDecRef new_values(values = PyDict_New());
- if (values == nullptr)
- return nullptr;
- if (PyDict_SetItem(dict, PyName::values(), values) < 0)
- return nullptr;
- }
- PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject *>(enumObj));
- }
-
- return reinterpret_cast<PyObject *>(enumObj);
-}
-
-PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
- const char *itemName)
-{
- init_enum();
-
- auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
- if (!itemName)
- return PyObject_CallFunction(obEnumType, "L", itemValue);
-
- static PyObject *const _member_map_ = String::createStaticString("_member_map_");
- auto *member_map = PyDict_GetItem(enumType->tp_dict, _member_map_);
- if (!(member_map && PyDict_Check(member_map)))
- return nullptr;
- auto *result = PyDict_GetItemString(member_map, itemName);
- Py_XINCREF(result);
- return result;
-}
-
-} // namespace Shiboken
-} // namespace Enum
-
-static PyType_Slot SbkNewEnum_slots[] = {
- {Py_tp_repr, reinterpret_cast<void *>(SbkEnumObject_repr)},
- {Py_tp_str, reinterpret_cast<void *>(SbkEnumObject_repr)},
- {Py_tp_getset, reinterpret_cast<void *>(SbkEnumGetSetList)},
- {Py_tp_methods, reinterpret_cast<void *>(SbkEnumObject_Methods)},
- {Py_tp_new, reinterpret_cast<void *>(SbkEnum_tp_new)},
- {Py_nb_add, reinterpret_cast<void *>(enum_add)},
- {Py_nb_subtract, reinterpret_cast<void *>(enum_subtract)},
- {Py_nb_multiply, reinterpret_cast<void *>(enum_multiply)},
- {Py_nb_positive, reinterpret_cast<void *>(enum_int)},
- {Py_nb_bool, reinterpret_cast<void *>(enum_bool)},
- {Py_nb_and, reinterpret_cast<void *>(enum_and)},
- {Py_nb_xor, reinterpret_cast<void *>(enum_xor)},
- {Py_nb_or, reinterpret_cast<void *>(enum_or)},
- {Py_nb_int, reinterpret_cast<void *>(enum_int)},
- {Py_nb_index, reinterpret_cast<void *>(enum_int)},
- {Py_tp_richcompare, reinterpret_cast<void *>(enum_richcompare)},
- {Py_tp_hash, reinterpret_cast<void *>(enum_hash)},
- {Py_tp_dealloc, reinterpret_cast<void *>(enum_object_dealloc)},
- {0, nullptr}
-};
-static PyType_Spec SbkNewEnum_spec = {
- "1:Shiboken.Enum",
- sizeof(SbkEnumObject),
- 0,
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- SbkNewEnum_slots,
-};
-
-static PyTypeObject *SbkEnum_TypeF()
-{
- static auto type = SbkType_FromSpecWithMeta(&SbkNewEnum_spec, SbkEnumType_TypeF());
- return type;
-}
-
-namespace Shiboken { namespace Enum {
-
-static void
-copyNumberMethods(PyTypeObject *flagsType,
- PyType_Slot number_slots[],
- int *pidx)
-{
- int idx = *pidx;
-#define PUT_SLOT(name) \
- number_slots[idx].slot = (name); \
- number_slots[idx].pfunc = PyType_GetSlot(flagsType, (name)); \
- ++idx;
-
- PUT_SLOT(Py_nb_absolute);
- PUT_SLOT(Py_nb_add);
- PUT_SLOT(Py_nb_and);
- PUT_SLOT(Py_nb_bool);
- PUT_SLOT(Py_nb_divmod);
- PUT_SLOT(Py_nb_float);
- PUT_SLOT(Py_nb_floor_divide);
- PUT_SLOT(Py_nb_index);
- PUT_SLOT(Py_nb_inplace_add);
- PUT_SLOT(Py_nb_inplace_and);
- PUT_SLOT(Py_nb_inplace_floor_divide);
- PUT_SLOT(Py_nb_inplace_lshift);
- PUT_SLOT(Py_nb_inplace_multiply);
- PUT_SLOT(Py_nb_inplace_or);
- PUT_SLOT(Py_nb_inplace_power);
- PUT_SLOT(Py_nb_inplace_remainder);
- PUT_SLOT(Py_nb_inplace_rshift);
- PUT_SLOT(Py_nb_inplace_subtract);
- PUT_SLOT(Py_nb_inplace_true_divide);
- PUT_SLOT(Py_nb_inplace_xor);
- PUT_SLOT(Py_nb_int);
- PUT_SLOT(Py_nb_invert);
- PUT_SLOT(Py_nb_lshift);
- PUT_SLOT(Py_nb_multiply);
- PUT_SLOT(Py_nb_negative);
- PUT_SLOT(Py_nb_or);
- PUT_SLOT(Py_nb_positive);
- PUT_SLOT(Py_nb_power);
- PUT_SLOT(Py_nb_remainder);
- PUT_SLOT(Py_nb_rshift);
- PUT_SLOT(Py_nb_subtract);
- PUT_SLOT(Py_nb_true_divide);
- PUT_SLOT(Py_nb_xor);
-#undef PUT_SLOT
- *pidx = idx;
-}
-
-static PyTypeObject * newTypeWithNameOld(const char *name,
- const char *cppName,
- PyTypeObject *numbers_fromFlag)
-{
- // Careful: SbkType_FromSpec does not allocate the string.
- PyType_Slot newslots[99] = {}; // enough but not too big for the stack
- PyType_Spec newspec;
- DeclaredEnumTypes::EnumEntry entry{strdup(name), nullptr};
- newspec.name = entry.name; // Note that SbkType_FromSpec might use a substring.
- newspec.basicsize = SbkNewEnum_spec.basicsize;
- newspec.itemsize = SbkNewEnum_spec.itemsize;
- newspec.flags = SbkNewEnum_spec.flags;
- // we must append all the number methods, so rebuild everything:
- int idx = 0;
- while (SbkNewEnum_slots[idx].slot) {
- newslots[idx].slot = SbkNewEnum_slots[idx].slot;
- newslots[idx].pfunc = SbkNewEnum_slots[idx].pfunc;
- ++idx;
- }
- if (numbers_fromFlag)
- copyNumberMethods(numbers_fromFlag, newslots, &idx);
- newspec.slots = newslots;
- AutoDecRef bases(PyTuple_New(1));
- static auto basetype = reinterpret_cast<PyObject *>(SbkEnum_TypeF());
- Py_INCREF(basetype);
- PyTuple_SetItem(bases, 0, basetype);
- auto *type = SbkType_FromSpecBasesMeta(&newspec, bases, SbkEnumType_TypeF());
- entry.type = type;
-
- auto *enumType = reinterpret_cast<SbkEnumType *>(type);
- auto *setp = PepType_SETP(enumType);
- setp->cppName = cppName;
- DeclaredEnumTypes::instance().addEnumType(entry);
- return entry.type;
-}
-
-// PySIDE-1735: This function is in the API and should be removed in 6.4 .
-// Python enums are created differently.
-PyTypeObject *newTypeWithName([[maybe_unused]] const char *name,
- [[maybe_unused]] const char *cppName,
- [[maybe_unused]] PyTypeObject *numbers_fromFlag)
-{
- // old enums are gone, remove completely?
- PyErr_Format(PyExc_RuntimeError, "function `%s` can no longer be used because old "
- "Enums are no longer supported", __FUNCTION__);
- return nullptr;
-}
-
-const char *getCppName(PyTypeObject *enumType)
-{
- assert(Py_TYPE(enumType) == SbkEnumType_TypeF());
- auto *type = reinterpret_cast<SbkEnumType *>(enumType);
- auto *setp = PepType_SETP(type);
- return setp->cppName;
-}
-
-EnumValueType getValue(PyObject *enumItem)
-{
- init_enum();
-
- assert(Enum::check(enumItem));
-
- AutoDecRef pyValue(PyObject_GetAttrString(enumItem, "value"));
- return PyLong_AsLongLong(pyValue);
-}
-
-void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag)
-{
- if (isFlag) {
- auto *flagsType = reinterpret_cast<PySideQFlagsType *>(type);
- PepType_PFTP(flagsType)->converter = converter;
- }
- else {
- auto *enumType = reinterpret_cast<SbkEnumType *>(type);
- PepType_SETP(enumType)->converter = converter;
- }
-}
-
-} // namespace Enum
-
-DeclaredEnumTypes &DeclaredEnumTypes::instance()
-{
- static DeclaredEnumTypes me;
- return me;
-}
-
-DeclaredEnumTypes::DeclaredEnumTypes() = default;
-
-DeclaredEnumTypes::~DeclaredEnumTypes()
-{
- cleanup();
-}
-
-void DeclaredEnumTypes::cleanup()
-{
- static bool was_called = false;
- if (was_called)
- return;
-
- for (const auto &e : m_enumTypes) {
- std::free(e.name);
- }
- m_enumTypes.clear();
- was_called = true;
-}
-
-} // namespace Shiboken
-
-static void cleanupEnumTypes()
-{
- DeclaredEnumTypes::instance().cleanup();
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// PYSIDE-1735: Re-implementation of Enums using Python
-// ====================================================
-//
-// This is a very simple, first implementation of a replacement
-// for the Qt-like Enums using the Python Enum module.
-//
-// The basic idea:
-// ---------------
-// * We create the Enums as always
-// * After creation of each enum, a special function is called that
-// * grabs the last generated enum
-// * reads all Enum items
-// * generates a class statement for the Python Enum
-// * creates a new Python Enum class
-// * replaces the already inserted Enum with the new one.
-//
-// There are lots of ways to optimize that. Will be added later.
-//
-extern "C" {
-
-struct lastEnumCreated {
- PyObject *scopeOrModule;
- const char *name;
- PyTypeObject *enumType;
- PyTypeObject *flagsType;
-};
-
-static lastEnumCreated lec{};
-
-static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
- const char *name,
- PyTypeObject *enumType,
- PyTypeObject *flagsType)
-{
- lec.scopeOrModule = scopeOrModule;
- lec.name = name;
- lec.enumType = enumType;
- lec.flagsType = flagsType;
-
- // We return nullptr as flagsType to disable flag creation.
- return nullptr;
-}
-
-static bool is_old_version()
-{
- auto *version = PySys_GetObject("version_info");
- auto *major = PyTuple_GetItem(version, 0);
- auto *minor = PyTuple_GetItem(version, 1);
- auto number = PyLong_AsLong(major) * 1000 + PyLong_AsLong(minor);
- return number <= 3008;
-}
-
///////////////////////////////////////////////////////////////////////
//
// Support for Missing Values
@@ -942,6 +132,7 @@ static bool is_old_version()
// We create each constant only once and keep the result in a dict
// "_sbk_missing_". This is similar to a competitor's "_sip_missing_".
//
+
static PyObject *missing_func(PyObject * /* self */ , PyObject *args)
{
// In order to relax matters to be more compatible with C++, we need
@@ -1017,16 +208,100 @@ static PyObject *create_missing_func(PyObject *klass)
//
////////////////////////////////////////////////////////////////////////
-PyTypeObject *morphLastEnumToPython()
+} // extern "C"
+
+namespace Shiboken {
+
+namespace Enum {
+
+int enumOption{};
+
+bool check(PyObject *pyObj)
+{
+ init_enum();
+
+ static PyTypeObject *meta = getPyEnumMeta();
+ return Py_TYPE(Py_TYPE(pyObj)) == reinterpret_cast<PyTypeObject *>(meta);
+}
+
+PyObject *getEnumItemFromValue(PyTypeObject *enumType, EnumValueType itemValue)
+{
+ init_enum();
+
+ auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
+ AutoDecRef val2members(PyObject_GetAttrString(obEnumType, "_value2member_map_"));
+ if (val2members.isNull()) {
+ PyErr_Clear();
+ return nullptr;
+ }
+ AutoDecRef ob_value(PyLong_FromLongLong(itemValue));
+ auto *result = PyDict_GetItem(val2members, ob_value);
+ Py_XINCREF(result);
+ return result;
+}
+
+PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
+ const char *itemName)
+{
+ init_enum();
+
+ auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
+ if (!itemName)
+ return PyObject_CallFunction(obEnumType, "L", itemValue);
+
+ static PyObject *const _member_map_ = String::createStaticString("_member_map_");
+ auto *member_map = PyDict_GetItem(enumType->tp_dict, _member_map_);
+ if (!(member_map && PyDict_Check(member_map)))
+ return nullptr;
+ auto *result = PyDict_GetItemString(member_map, itemName);
+ Py_XINCREF(result);
+ return result;
+}
+
+EnumValueType getValue(PyObject *enumItem)
+{
+ init_enum();
+
+ assert(Enum::check(enumItem));
+
+ AutoDecRef pyValue(PyObject_GetAttrString(enumItem, "value"));
+ return PyLong_AsLongLong(pyValue);
+}
+
+void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag)
+{
+ if (isFlag) {
+ auto *flagsType = reinterpret_cast<PySideQFlagsType *>(type);
+ PepType_PFTP(flagsType)->converter = converter;
+ }
+ else {
+ auto *enumType = reinterpret_cast<SbkEnumType *>(type);
+ PepType_SETP(enumType)->converter = converter;
+ }
+}
+
+static PyTypeObject *createEnumForPython(PyObject *scopeOrModule,
+ const char *fullName,
+ PyObject *pyEnumItems)
{
- /// The Python Enum internal structure is way too complicated.
- /// It is much easier to generate Python code and execute it.
+ const char *colon = strchr(fullName, ':');
+ assert(colon);
+ int package_level = atoi(fullName);
+ const char *mod = colon + 1;
- // Pick up the last generated Enum and convert it into a PyEnum
- auto *enumType = lec.enumType;
- // This is temporary; SbkEnumType will be removed, soon.
+ const char *qual = mod;
+ for (int idx = package_level; idx > 0; --idx) {
+ const char *dot = strchr(qual, '.');
+ if (!dot)
+ break;
+ qual = dot + 1;
+ }
+ int mlen = qual - mod - 1;
+ AutoDecRef module(Shiboken::String::fromCString(mod, mlen));
+ AutoDecRef qualname(Shiboken::String::fromCString(qual));
+ const char *dot = strrchr(qual, '.');
+ AutoDecRef name(Shiboken::String::fromCString(dot ? dot + 1 : qual));
- auto *scopeOrModule = lec.scopeOrModule;
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.
@@ -1034,15 +309,9 @@ PyTypeObject *morphLastEnumToPython()
auto *sotp = PepType_SOTP(type);
if (!sotp->enumFlagsDict)
initEnumFlagsDict(type);
- enumName = PyDict_GetItem(sotp->enumTypeDict, String::fromCString(lec.name));
+ enumName = PyDict_GetItem(sotp->enumTypeDict, name);
}
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- PyObject *values = PyDict_GetItem(enumType->tp_dict, PyName::values());
- if (!values)
- return nullptr;
-
AutoDecRef PyEnumType(PyObject_GetAttr(PyEnumModule, enumName));
assert(PyEnumType.object());
bool isFlag = PyObject_IsSubclass(PyEnumType, PyFlag);
@@ -1055,24 +324,13 @@ PyTypeObject *morphLastEnumToPython()
PyEnumType.reset(surrogate);
}
- // Walk the values dict and create a Python enum type.
- AutoDecRef name(PyUnicode_FromString(lec.name));
- AutoDecRef args(PyList_New(0));
+ // Walk the enumItemStrings and create a Python enum type.
auto *pyName = name.object();
- auto *pyArgs = args.object();
- while (PyDict_Next(values, &pos, &key, &value)) {
- auto *key_value = PyTuple_New(2);
- PyTuple_SET_ITEM(key_value, 0, key);
- Py_INCREF(key);
- auto *obj = reinterpret_cast<SbkEnumObject *>(value);
- auto *num = PyLong_FromLongLong(obj->ob_value);
- PyTuple_SET_ITEM(key_value, 1, num);
- PyList_Append(pyArgs, key_value);
- }
+
// We now create the new type. Since Python 3.11, we need to pass in
// `boundary=KEEP` because the default STRICT crashes on us.
// See QDir.Filter.Drives | QDir.Filter.Files
- AutoDecRef callArgs(Py_BuildValue("(OO)", pyName, pyArgs));
+ AutoDecRef callArgs(Py_BuildValue("(OO)", pyName, pyEnumItems));
AutoDecRef callDict(PyDict_New());
static PyObject *boundary = String::createStaticString("boundary");
if (PyFlag_KEEP)
@@ -1091,31 +349,111 @@ PyTypeObject *morphLastEnumToPython()
}
auto *newType = reinterpret_cast<PyTypeObject *>(obNewType);
- auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
- AutoDecRef qual_name(PyObject_GetAttr(obEnumType, PyMagicName::qualname()));
- PyObject_SetAttr(obNewType, PyMagicName::qualname(), qual_name);
- AutoDecRef module(PyObject_GetAttr(obEnumType, PyMagicName::module()));
+ PyObject_SetAttr(obNewType, PyMagicName::qualname(), qualname);
PyObject_SetAttr(obNewType, PyMagicName::module(), module);
// See if we should re-introduce shortcuts in the enclosing object.
const bool useGlobalShortcut = (Enum::enumOption & Enum::ENOPT_GLOBAL_SHORTCUT) != 0;
const bool useScopedShortcut = (Enum::enumOption & Enum::ENOPT_SCOPED_SHORTCUT) != 0;
if (useGlobalShortcut || useScopedShortcut) {
+ // We have to use the iterator protokol because the values dict is a mappingproxy.
+ AutoDecRef values(PyObject_GetAttr(obNewType, PyMagicName::members()));
+ AutoDecRef mapIterator(PyObject_GetIter(values));
+ AutoDecRef mapKey{};
bool isModule = PyModule_Check(scopeOrModule);
- pos = 0;
- while (PyDict_Next(values, &pos, &key, &value)) {
- AutoDecRef entry(PyObject_GetAttr(obNewType, key));
- if ((useGlobalShortcut && isModule) || (useScopedShortcut && !isModule))
- if (PyObject_SetAttr(scopeOrModule, key, entry) < 0)
+ while ((mapKey.reset(PyIter_Next(mapIterator))), mapKey.object()) {
+ if ((useGlobalShortcut && isModule) || (useScopedShortcut && !isModule)) {
+ AutoDecRef value(PyObject_GetItem(values, mapKey));
+ if (PyObject_SetAttr(scopeOrModule, mapKey, value) < 0)
return nullptr;
+ }
}
}
- // PYSIDE-1735: Old Python versions can't stand the early enum deallocation.
- static bool old_python_version = is_old_version();
- if (old_python_version)
- Py_INCREF(obEnumType);
return newType;
}
-} // extern "C"
+template <typename IntT>
+static PyObject *toPyObject(IntT v)
+{
+ if constexpr (sizeof(IntT) == 8) {
+ if constexpr (std::is_unsigned_v<IntT>)
+ return PyLong_FromUnsignedLongLong(v);
+ return PyLong_FromLongLong(v);
+ }
+ if constexpr (std::is_unsigned_v<IntT>)
+ return PyLong_FromUnsignedLong(v);
+ return PyLong_FromLong(v);
+}
+
+template <typename IntT>
+static PyTypeObject *createPythonEnumHelper(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], IntT enumValues[])
+{
+ AutoDecRef args(PyList_New(0));
+ auto *pyEnumItems = args.object();
+ for (size_t idx = 0; enumItemStrings[idx] != nullptr; ++idx) {
+ const char *kv = enumItemStrings[idx];
+ auto *key = PyUnicode_FromString(kv);
+ auto *value = toPyObject(enumValues[idx]);
+ auto *key_value = PyTuple_New(2);
+ PyTuple_SET_ITEM(key_value, 0, key);
+ PyTuple_SET_ITEM(key_value, 1, value);
+ PyList_Append(pyEnumItems, key_value);
+ }
+ return createEnumForPython(module, fullName, pyEnumItems);
+}
+
+// Now we have to concretize these functions explicitly,
+// otherwise templates will not work across modules.
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int64_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint64_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int32_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint32_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int16_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint16_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int8_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint8_t enumValues[])
+{
+ return createPythonEnumHelper(module, fullName, enumItemStrings, enumValues);
+}
+
+} // namespace Enum
+} // namespace Shiboken
diff --git a/sources/shiboken6/libshiboken/sbkenum.h b/sources/shiboken6/libshiboken/sbkenum.h
index b14e6dd42..4f21d3338 100644
--- a/sources/shiboken6/libshiboken/sbkenum.h
+++ b/sources/shiboken6/libshiboken/sbkenum.h
@@ -15,71 +15,89 @@ LIBSHIBOKEN_API bool PyEnumMeta_Check(PyObject *ob);
/// exposed for the signature module
LIBSHIBOKEN_API void init_enum();
-extern LIBSHIBOKEN_API PyTypeObject *SbkEnumType_TypeF(void);
struct SbkConverter;
struct SbkEnumType;
-struct SbkEnumTypePrivate;
-} // extern "C"
-
-namespace Shiboken
+struct SbkEnumTypePrivate
{
+ SbkConverter *converter;
+};
+
+/// PYSIDE-1735: Pass on the Python enum/flag information.
+LIBSHIBOKEN_API void initEnumFlagsDict(PyTypeObject *type);
+
+/// 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);
-inline bool isShibokenEnum(PyObject *pyObj)
-{
- return Py_TYPE(Py_TYPE(pyObj)) == SbkEnumType_TypeF();
}
-namespace Enum
+namespace Shiboken { namespace Enum {
+
+enum : int {
+ ENOPT_OLD_ENUM = 0x00, // PySide 6.6: no longer supported
+ ENOPT_NEW_ENUM = 0x01,
+ ENOPT_INHERIT_INT = 0x02,
+ ENOPT_GLOBAL_SHORTCUT = 0x04,
+ ENOPT_SCOPED_SHORTCUT = 0x08,
+ ENOPT_NO_FAKESHORTCUT = 0x10,
+ ENOPT_NO_FAKERENAMES = 0x20,
+ ENOPT_NO_ZERODEFAULT = 0x40,
+ ENOPT_NO_MISSING = 0x80,
+};
+
+LIBSHIBOKEN_API extern int enumOption;
+
+using EnumValueType = long long;
+
+LIBSHIBOKEN_API bool check(PyObject *obj);
+
+LIBSHIBOKEN_API PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
+ const char *itemName = nullptr);
+
+LIBSHIBOKEN_API EnumValueType getValue(PyObject *enumItem);
+LIBSHIBOKEN_API PyObject *getEnumItemFromValue(PyTypeObject *enumType,
+ EnumValueType itemValue);
+
+/// Sets the enum/flag's type converter.
+LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag);
+
+/// Creating Python enums for different types.
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int64_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint64_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int32_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint32_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int16_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint16_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], int8_t enumValues[]);
+
+LIBSHIBOKEN_API PyTypeObject *createPythonEnum(PyObject *module,
+ const char *fullName, const char *enumItemStrings[], uint8_t enumValues[]);
+
+/// This template removes duplication by inlining necessary type casts.
+template <typename IntT>
+inline PyTypeObject *createPythonEnum(PyTypeObject *scope,
+ const char *fullName, const char *enumItemStrings[], IntT enumValues[])
{
- using EnumValueType = long long;
-
- LIBSHIBOKEN_API bool check(PyObject *obj);
- /**
- * Creates a new enum type (and its flags type, if any is given)
- * and registers it to Python and adds it to \p module.
- * \param module Module to where the new enum type will be added.
- * \param name Name of the enum.
- * \param fullName Name of the enum that includes all scope information (e.g.: "module.Enum").
- * \param cppName Full qualified C++ name of the enum.
- * \param flagsType Optional Python type for the flags associated with the enum.
- * \return The new enum type or NULL if it fails.
- */
- LIBSHIBOKEN_API PyTypeObject *createGlobalEnum(PyObject *module,
- const char *name,
- const char *fullName,
- const char *cppName,
- PyTypeObject *flagsType = nullptr);
- /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace.
- LIBSHIBOKEN_API PyTypeObject *createScopedEnum(PyTypeObject *scope,
- const char *name,
- const char *fullName,
- const char *cppName,
- PyTypeObject *flagsType = nullptr);
-
- /// Creates a new enum item for a given enum type.
- LIBSHIBOKEN_API bool createEnumItemOld(PyTypeObject *enumType,
- const char *itemName,
- EnumValueType itemValue);
-
- LIBSHIBOKEN_API PyObject *newItem(PyTypeObject *enumType, EnumValueType itemValue,
- const char *itemName = nullptr);
-
- LIBSHIBOKEN_API PyTypeObject *newTypeWithName(const char *name, const char *cppName,
- PyTypeObject *numbers_fromFlag=nullptr);
- LIBSHIBOKEN_API const char *getCppName(PyTypeObject *type);
- LIBSHIBOKEN_API PyObject *getCppNameNew(PyTypeObject *type);
-
- LIBSHIBOKEN_API EnumValueType getValue(PyObject *enumItem);
- LIBSHIBOKEN_API PyObject *getEnumItemFromValue(PyTypeObject *enumType,
- EnumValueType itemValue);
-
- /// Sets the enum/flag's type converter.
- LIBSHIBOKEN_API void setTypeConverter(PyTypeObject *type, SbkConverter *converter, bool isFlag);
-
- LIBSHIBOKEN_API PyObject *unpickleEnum(PyObject *, PyObject *);
+ auto *obScope = reinterpret_cast<PyObject *>(scope);
+ return createPythonEnum(obScope, fullName, enumItemStrings, enumValues);
}
+} // namespace Enum
} // namespace Shiboken
#endif // SKB_PYENUM_H
diff --git a/sources/shiboken6/libshiboken/sbkenum_p.h b/sources/shiboken6/libshiboken/sbkenum_p.h
deleted file mode 100644
index 3e3640b93..000000000
--- a/sources/shiboken6/libshiboken/sbkenum_p.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef SBKENUM_P_H
-#define SBKENUM_P_H
-
-#include "sbkpython.h"
-#include "shibokenmacros.h"
-
-struct SbkEnumTypePrivate
-{
- SbkConverter *converter;
- const char *cppName;
-};
-
-extern "C" {
-
-/// PYSIDE-1735: Pass on the Python enum/flag information.
-LIBSHIBOKEN_API void initEnumFlagsDict(PyTypeObject *type);
-
-/// PYSIDE-1735: Patching the Enum / Flags implementation. Remove in 6.4
-LIBSHIBOKEN_API PyTypeObject *morphLastEnumToPython();
-
-/// 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);
-/// PYSIDE-1735: Helper function to ask what enum we are using
-LIBSHIBOKEN_API bool usingNewEnum();
-
-}
-
-namespace Shiboken { namespace Enum {
-
-enum : int {
- ENOPT_OLD_ENUM = 0x00, // no longer supported
- ENOPT_NEW_ENUM = 0x01,
- ENOPT_INHERIT_INT = 0x02,
- ENOPT_GLOBAL_SHORTCUT = 0x04,
- ENOPT_SCOPED_SHORTCUT = 0x08,
- ENOPT_NO_FAKESHORTCUT = 0x10,
- ENOPT_NO_FAKERENAMES = 0x20,
- ENOPT_NO_ZERODEFAULT = 0x40,
- ENOPT_NO_MISSING = 0x80,
-};
-
-LIBSHIBOKEN_API extern int enumOption;
-
-}}
-
-#endif // SBKENUM_P_H
diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.cpp b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
index 1242cbda4..fb2fb95aa 100644
--- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp
+++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
@@ -4,7 +4,7 @@
#include "basewrapper.h"
#include "basewrapper_p.h"
#include "autodecref.h"
-#include "sbkenum_p.h"
+#include "sbkenum.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
#include "sbkstaticstrings_p.h"
diff --git a/sources/shiboken6/libshiboken/shiboken.h b/sources/shiboken6/libshiboken/shiboken.h
index 13a15e1f4..6c0ecbe30 100644
--- a/sources/shiboken6/libshiboken/shiboken.h
+++ b/sources/shiboken6/libshiboken/shiboken.h
@@ -14,7 +14,6 @@
#include "sbkarrayconverter.h"
#include "sbkconverter.h"
#include "sbkenum.h"
-#include "sbkenum_p.h" // PYSIDE-1735: This is during the migration, only.
#include "sbkerrors.h"
#include "sbkmodule.h"
#include "sbkstring.h"
diff --git a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
index 81919d6c3..de5003d5b 100644
--- a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
+++ b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
@@ -114,12 +114,6 @@
</inject-code>
</add-function>
- <add-function signature="_unpickle_enum(PyObject*, PyObject*)" return-type="PyObject*">
- <inject-code>
- %PYARG_0 = Shiboken::Enum::unpickleEnum(%1, %2);
- </inject-code>
- </add-function>
-
<extra-includes>
<include file-name="sbkversion.h" location="local"/>
<include file-name="voidptr.h" location="local"/>