aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2022-04-10 17:22:14 +0200
committerChristian Tismer <tismer@stackless.com>2022-05-23 22:45:33 +0200
commit8472a2b6eb32e6238e82f5778add908652b2cd82 (patch)
tree8fd91deb2d6114c0fcf77807b5c71e43acd206c4
parent79a23bc22ad635531c242280627d942e86fcfd45 (diff)
PyEnum: Prepare to support both implementations
The enum implementation should be switchable between the old and the new version. This switching is possible only before PySide import. This patch prepares the switching capability for the signature module and installs fields that will affect the global header files. The new version can be selected by setting the environment variable PYSIDE63_OPTION_PYTHON_ENUM=1 or setting sys.pyside63_option_python_enum=1 [ChangeLog][PySide6] The signature module was prepared to support both C++ enums and Python enums. This can be selected at startup. Task-number: PYSIDE-1735 Change-Id: I14999e1049fbaaccd00f00d1b7b1257bc9287255 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> (cherry picked from commit 31deae2a0ea3725d038433f6be91119865a8f399) Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--sources/pyside6/libpyside/pysideqflags.cpp1
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetatype.cpp12
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp60
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.cpp88
-rw-r--r--sources/shiboken6/libshiboken/sbkenum_p.h9
-rw-r--r--sources/shiboken6/libshiboken/shiboken.h1
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py5
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py76
8 files changed, 214 insertions, 38 deletions
diff --git a/sources/pyside6/libpyside/pysideqflags.cpp b/sources/pyside6/libpyside/pysideqflags.cpp
index cd57b2bb9..84e87f038 100644
--- a/sources/pyside6/libpyside/pysideqflags.cpp
+++ b/sources/pyside6/libpyside/pysideqflags.cpp
@@ -41,6 +41,7 @@
#include <autodecref.h>
#include <sbkenum.h>
+#include <sbkenum_p.h>
extern "C" {
struct SbkConverter;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
index b5fa4100c..d47b25ef2 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
@@ -668,8 +668,16 @@ QString AbstractMetaTypeData::formatPythonSignature() const
result += TypeInfo::indirectionKeyword(i);
// If it is a flags type, we replace it with the full name:
// "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>"
- if (m_typeEntry->isFlags())
- result = m_typeEntry->qualifiedTargetLangName();
+ if (m_typeEntry->isFlags()) {
+ // PYSIDE-1735: We need to provide both the flags type and the original enum type
+ // as a choice at runtime.
+ auto flagsTypeEntry = static_cast<const FlagsTypeEntry *>(m_typeEntry);
+ auto enumTypeEntry = flagsTypeEntry->originator();
+ result = m_typeEntry->targetLangPackage() + u".^^"_s
+ + flagsTypeEntry->targetLangName() + u"^^"_s
+ + enumTypeEntry->targetLangName() + u"^^"_s;
+ }
+
result.replace(u"::"_s, u"."_s);
return result;
}
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 60f89666e..26a5340b5 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -4193,7 +4193,7 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const TypeEnt
if (!enumType)
return;
QString enumFlagName = enumType->isFlags() ? u"flag"_s : u"enum"_s;
- QString enumPythonType = cpythonTypeNameExt(enumType);
+ QString enumPythonVar = enumType->isFlags() ? u"FType"_s : u"EType"_s;
const FlagsTypeEntry *flags = nullptr;
if (enumType->isFlags())
@@ -4205,7 +4205,7 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const TypeEnt
Indentation indent(s);
QString typeName = fixedCppTypeName(enumType);
s << "SbkConverter *converter = Shiboken::Conversions::createConverter("
- << enumPythonType << ',' << '\n';
+ << enumPythonVar << ',' << '\n';
{
Indentation indent(s);
s << cppToPythonFunctionName(typeName, typeName) << ");\n";
@@ -4228,7 +4228,7 @@ void CppGenerator::writeEnumConverterInitialization(TextStream &s, const TypeEnt
writeAddPythonToCppConversion(s, u"converter"_s, toCpp, isConv);
}
- s << "Shiboken::Enum::setTypeConverter(" << enumPythonType
+ s << "Shiboken::Enum::setTypeConverter(" << enumPythonVar
<< ", converter, " << (enumType->isFlags() ? "true" : "false") << ");\n";
QString signature = enumType->qualifiedCppName();
@@ -5417,10 +5417,21 @@ void CppGenerator::writeEnumsInitialization(TextStream &s, AbstractMetaEnumList
{
if (enums.isEmpty())
return;
- s << "// Initialization of enums.\n\n";
+ bool preambleWrittenE = false;
+ bool preambleWrittenF = false;
for (const AbstractMetaEnum &cppEnum : qAsConst(enums)) {
if (cppEnum.isPrivate())
continue;
+ if (!preambleWrittenE) {
+ s << "// Initialization of enums.\n"
+ << "PyTypeObject *EType{};\n\n";
+ preambleWrittenE = true;
+ }
+ if (!preambleWrittenF && cppEnum.typeEntry()->flags()) {
+ s << "// Initialization of enums, flags part.\n"
+ << "PyTypeObject *FType{};\n\n";
+ preambleWrittenF = true;
+ }
writeEnumInitialization(s, cppEnum, errorReturn);
}
}
@@ -5436,7 +5447,8 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
ErrorReturn errorReturn) const
{
const AbstractMetaClass *enclosingClass = cppEnum.targetLangEnclosingClass();
- bool hasUpperEnclosingClass = enclosingClass && enclosingClass->targetLangEnclosingClass() != nullptr;
+ bool hasUpperEnclosingClass = enclosingClass
+ && enclosingClass->targetLangEnclosingClass() != nullptr;
const EnumTypeEntry *enumTypeEntry = cppEnum.typeEntry();
QString enclosingObjectVariable;
if (enclosingClass)
@@ -5450,7 +5462,7 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
s << (cppEnum.isAnonymous() ? "anonymous enum identified by enum value" : "enum");
s << " '" << cppEnum.name() << "'.\n";
- QString enumVarTypeObj;
+ QString enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
if (!cppEnum.isAnonymous()) {
int packageLevel = packageName().count(u'.') + 1;
FlagsTypeEntry *flags = enumTypeEntry->flags();
@@ -5459,15 +5471,15 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
// We need 'flags->flagsName()' with the full module/class path.
QString fullPath = getClassTargetFullName(cppEnum);
fullPath.truncate(fullPath.lastIndexOf(u'.') + 1);
- s << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\""
- << packageLevel << ':' << fullPath << flags->flagsName() << "\", "
- << cpythonEnumName(cppEnum) << "_number_slots);\n";
+ s << "FType = PySide::QFlags::create(\""
+ << packageLevel << ':' << fullPath << flags->flagsName() << "\", \n" << indent
+ << cpythonEnumName(cppEnum) << "_number_slots);\n" << outdent
+ << cpythonTypeNameExt(flags) << " = FType;\n";
}
- enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry);
-
- s << enumVarTypeObj << " = Shiboken::Enum::"
- << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum")
+ s << "EType = Shiboken::Enum::"
+ << ((enclosingClass
+ || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum")
<< '(' << enclosingObjectVariable << ',' << '\n';
{
Indentation indent(s);
@@ -5475,10 +5487,10 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
<< '"' << packageLevel << ':' << getClassTargetFullName(cppEnum) << "\",\n"
<< '"' << cppEnum.qualifiedCppName() << '"';
if (flags)
- s << ",\n" << cpythonTypeNameExt(flags);
+ s << ",\nFType";
s << ");\n";
}
- s << "if (!" << cpythonTypeNameExt(cppEnum.typeEntry()) << ")\n"
+ s << "if (!EType)\n"
<< indent << errorReturn << outdent << '\n';
}
@@ -5521,8 +5533,9 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
break;
case CEnum: {
s << "if (!Shiboken::Enum::";
- s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem");
- s << '(' << enumVarTypeObj << ',' << '\n';
+ s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem"
+ : "createGlobalEnumItem");
+ s << '(' << "EType" << ',' << '\n';
Indentation indent(s);
s << enclosingObjectVariable << ", \"" << mangledName << "\", "
<< enumValueText << "))\n" << errorReturn;
@@ -5530,15 +5543,22 @@ void CppGenerator::writeEnumInitialization(TextStream &s, const AbstractMetaEnum
break;
case EnumClass: {
s << "if (!Shiboken::Enum::createScopedEnumItem("
- << enumVarTypeObj << ',' << '\n';
+ << "EType" << ",\n";
Indentation indentation(s);
- s << enumVarTypeObj<< ", \"" << mangledName << "\", "
+ s << "EType" << ", \"" << mangledName << "\", "
<< enumValueText << "))\n" << errorReturn;
}
break;
}
}
-
+ s << "// PYSIDE-1735: Resolving the whole enum class at the end for API compatibility.\n"
+ << "EType = morphLastEnumToPython();\n"
+ << enumVarTypeObj << " = EType;\n";
+ if (cppEnum.typeEntry()->flags()) {
+ s << "// PYSIDE-1735: Mapping the flags class to the same enum class.\n"
+ << cpythonTypeNameExt(cppEnum.typeEntry()->flags()) << " =\n"
+ << indent << "mapFlagsToSameEnum(FType, EType);\n" << outdent;
+ }
writeEnumConverterInitialization(s, cppEnum);
s << "// End of '" << cppEnum.name() << "' enum";
diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp
index 211b131a4..1ec21f81e 100644
--- a/sources/shiboken6/libshiboken/sbkenum.cpp
+++ b/sources/shiboken6/libshiboken/sbkenum.cpp
@@ -59,6 +59,17 @@ static void cleanupEnumTypes();
extern "C"
{
+// forward
+struct lastEnumCreated;
+
+// forward
+static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
+ const char *name,
+ const char *fullName,
+ const char *cppName,
+ PyTypeObject *enumType,
+ PyTypeObject *flagsType);
+
struct SbkEnumType
{
PyTypeObject type;
@@ -119,7 +130,7 @@ static const char *SbkEnum_SignatureStrings[] = {
"Shiboken.Enum(self,itemValue:int=0)",
nullptr}; // Sentinel
-void enum_object_dealloc(PyObject *ob)
+static void enum_object_dealloc(PyObject *ob)
{
auto *self = reinterpret_cast<SbkEnumObject *>(ob);
Py_XDECREF(self->ob_name);
@@ -485,13 +496,15 @@ static PyTypeObject *createEnum(const char *fullName, const char *cppName,
return enumType;
}
-PyTypeObject *createGlobalEnum(PyObject *module, const char *name, const char *fullName, const char *cppName, PyTypeObject *flagsType)
+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, fullName, cppName, enumType, flagsType);
if (flagsType && PyModule_AddObject(module, PepType_GetNameStr(flagsType),
reinterpret_cast<PyObject *>(flagsType)) < 0) {
Py_DECREF(enumType);
@@ -500,7 +513,8 @@ PyTypeObject *createGlobalEnum(PyObject *module, const char *name, const char *f
return enumType;
}
-PyTypeObject *createScopedEnum(PyTypeObject *scope, const char *name, const char *fullName, const char *cppName, PyTypeObject *flagsType)
+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,
@@ -508,6 +522,8 @@ PyTypeObject *createScopedEnum(PyTypeObject *scope, const char *name, const char
Py_DECREF(enumType);
return nullptr;
}
+ auto *obScope = reinterpret_cast<PyObject *>(scope);
+ flagsType = recordCurrentEnum(obScope, name, fullName, cppName, enumType, flagsType);
if (flagsType && PyDict_SetItemString(scope->tp_dict,
PepType_GetNameStr(flagsType),
reinterpret_cast<PyObject *>(flagsType)) < 0) {
@@ -516,7 +532,6 @@ PyTypeObject *createScopedEnum(PyTypeObject *scope, const char *name, const char
}
return enumType;
}
-
static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue)
{
PyObject *enumItem = newItem(enumType, itemValue, itemName);
@@ -675,6 +690,8 @@ copyNumberMethods(PyTypeObject *flagsType,
*pidx = idx;
}
+// PySIDE-1735: This function is in the API. Support it with the new enums.
+//
PyTypeObject *
newTypeWithName(const char *name,
const char *cppName,
@@ -769,3 +786,66 @@ static void cleanupEnumTypes()
Shiboken::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;
+ const char *fullName;
+ const char *cppName;
+ PyTypeObject *enumType;
+ PyTypeObject *flagsType;
+};
+
+static lastEnumCreated lec{};
+
+static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
+ const char *name,
+ const char *fullName,
+ const char *cppName,
+ PyTypeObject *enumType,
+ PyTypeObject *flagsType)
+{
+ lec.scopeOrModule = scopeOrModule;
+ lec.name = name;
+ lec.fullName = fullName;
+ lec.cppName = cppName;
+ lec.enumType = enumType;
+ lec.flagsType = flagsType;
+ // We later return nullptr as flagsType to disable flag creation.
+ return flagsType;
+}
+
+PyTypeObject *morphLastEnumToPython()
+{
+ // to be implemented...
+ return lec.enumType;
+}
+
+PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObject *EType)
+{
+ // this will be switchable...
+ return FType;
+}
+
+} // extern "C"
diff --git a/sources/shiboken6/libshiboken/sbkenum_p.h b/sources/shiboken6/libshiboken/sbkenum_p.h
index 895c1ddcb..eeb505b34 100644
--- a/sources/shiboken6/libshiboken/sbkenum_p.h
+++ b/sources/shiboken6/libshiboken/sbkenum_p.h
@@ -47,6 +47,15 @@ struct SbkEnumTypePrivate
{
SbkConverter *converter;
const char *cppName;
+ PyTypeObject *replacementType;
};
+extern "C" {
+
+/// PYSIDE-1735: Patching the Enum / Flags implementation. Remove in 6.4
+LIBSHIBOKEN_API PyTypeObject *morphLastEnumToPython();
+LIBSHIBOKEN_API PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObject *EType);
+
+}
+
#endif // SKB_PYENUM_P_H
diff --git a/sources/shiboken6/libshiboken/shiboken.h b/sources/shiboken6/libshiboken/shiboken.h
index 3e1df5235..283590565 100644
--- a/sources/shiboken6/libshiboken/shiboken.h
+++ b/sources/shiboken6/libshiboken/shiboken.h
@@ -50,6 +50,7 @@
#include "sbkarrayconverter.h"
#include "sbkconverter.h"
#include "sbkenum.h"
+#include "sbkenum_p.h" // PYSIDE-1735: This is during the migration, only.
#include "sbkmodule.h"
#include "sbkstring.h"
#include "sbkstaticstrings.h"
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index d714eb09c..c069d644a 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -417,6 +417,7 @@ def init_sample():
type_map.update({
"char": int,
"char**": typing.List[str],
+ "const char*": str,
"Complex": complex,
"double": float,
"Foo.HANDLE": int,
@@ -426,6 +427,7 @@ def init_sample():
"OddBool": bool,
"PStr": str,
"PyDate": datetime.date,
+ "PyBuffer": bytes,
"sample.bool": bool,
"sample.char": int,
"sample.double": float,
@@ -436,6 +438,7 @@ def init_sample():
"sample.Photon.TemplateBase[Photon.IdentityType]": sample.Photon.ValueIdentity,
"sample.Point": Point,
"sample.PStr": str,
+ "SampleNamespace.InValue.ZeroIn": 0,
"sample.unsigned char": int,
"std.size_t": int,
"std.string": str,
@@ -591,6 +594,8 @@ def init_PySide6_QtWidgets():
"QWidget.RenderFlags(QWidget.DrawWindowBackground | QWidget.DrawChildren)"),
"static_cast<Qt.MatchFlags>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance(
"Qt.MatchFlags(Qt.MatchExactly | Qt.MatchCaseSensitive)"),
+ "static_cast<Qt.MatchFlag>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance(
+ "Qt.MatchFlag(Qt.MatchExactly | Qt.MatchCaseSensitive)"),
"QListWidgetItem.ItemType.Type": PySide6.QtWidgets.QListWidgetItem.Type,
"QTableWidgetItem.ItemType.Type": PySide6.QtWidgets.QTableWidgetItem.Type,
"QTreeWidgetItem.ItemType.Type": PySide6.QtWidgets.QTreeWidgetItem.Type,
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 84c42dd11..4f8bdb8b9 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -37,13 +37,15 @@
##
#############################################################################
-import sys
+import enum
+import functools
+import keyword
+import os
import re
-import warnings
+import sys
import types
import typing
-import keyword
-import functools
+import warnings
from types import SimpleNamespace
from shibokensupport.signature.mapping import (type_map, update_mapping,
@@ -74,6 +76,36 @@ guesses, we provide an entry in 'type_map' that resolves it.
In effect, 'type_map' maps text to real Python objects.
"""
+def _get_flag_enum_option():
+ flag = False # XXX get default out of version number?
+ envname = "PYSIDE63_OPTION_PYTHON_ENUM"
+ sysname = envname.lower()
+ opt = os.environ.get(envname)
+ if opt:
+ opt = opt.lower()
+ if opt in ("yes", "on", "true"):
+ flag = True
+ elif opt in ("no", "off", "false"):
+ flag = False
+ elif opt.isnumeric():
+ flag = bool(int(opt))
+ elif hasattr(sys, sysname):
+ flag = bool(getattr(sys, sysname))
+ # modify the sys attribute to bool
+ setattr(sys, sysname, flag)
+ # modify the env attribute to "0" or "1"
+ os.environ[envname] = str(int(flag))
+ return flag
+
+
+class EnumSelect(enum.Enum):
+ # PYSIDE-1735: Here we could save object.value expressions by using IntEnum.
+ # But it is nice to use just an Enum for selecting Enum version.
+ OLD = 1
+ NEW = 2
+ SELECTION = NEW if _get_flag_enum_option() else OLD
+
+
def dprint(*args, **kw):
if _DEBUG:
import pprint
@@ -189,10 +221,11 @@ def make_good_value(thing, valtype):
if thing.endswith("()"):
thing = f'Default("{thing[:-2]}")'
else:
- ret = eval(thing, namespace)
+ # PYSIDE-1735: Use explicit globals and locals because of a bug in VsCode
+ ret = eval(thing, globals(), namespace)
if valtype and repr(ret).startswith("<"):
thing = f'Instance("{thing}")'
- return eval(thing, namespace)
+ return eval(thing, globals(), namespace)
except Exception:
pass
@@ -264,12 +297,18 @@ def _resolve_arraytype(thing, line):
def to_string(thing):
+ # This function returns a string that creates the same object.
+ # It is absolutely crucial that str(eval(thing)) == str(thing),
+ # i.e. it must be an idempotent mapping.
if isinstance(thing, str):
return thing
if hasattr(thing, "__name__") and thing.__module__ != "typing":
- dot = "." in str(thing)
+ m = thing.__module__
+ dot = "." in str(thing) or m not in (thing.__qualname__, "builtins")
name = get_name(thing)
- return thing.__module__ + "." + name if dot else name
+ ret = m + "." + name if dot else name
+ assert(eval(ret, globals(), namespace))
+ return ret
# Note: This captures things from the typing module:
return str(thing)
@@ -280,7 +319,8 @@ def handle_matrix(arg):
n, m, typstr = tuple(map(lambda x:x.strip(), arg.split(",")))
assert typstr == "float"
result = f"PySide6.QtGui.QMatrix{n}x{m}"
- return eval(result, namespace)
+ return eval(result, globals(), namespace)
+
def _resolve_type(thing, line, level, var_handler, func_name=None):
# manual set of 'str' instead of 'bytes'
@@ -319,7 +359,7 @@ def _resolve_type(thing, line, level, var_handler, func_name=None):
result = f"{contr}[{thing}]"
# PYSIDE-1538: Make sure that the eval does not crash.
try:
- return eval(result, namespace)
+ return eval(result, globals(), namespace)
except Exception as e:
warnings.warn(f"""pyside_type_init:_resolve_type
@@ -370,6 +410,18 @@ def handle_retvar(obj):
def calculate_props(line):
+ # PYSIDE-1735: QFlag is now divided into fields for future Python Enums, like
+ # "PySide.QtCore.^^Qt.ItemFlags^^Qt.ItemFlag^^"
+ # Resolve that until Enum is finally settled.
+ while "^^" in line:
+ parts = line.split("^^", 3)
+ selected = EnumSelect.SELECTION
+ line = parts[0] + parts[selected.value] + parts[3]
+ if selected is EnumSelect.NEW:
+ _old, _new = EnumSelect.OLD.value, EnumSelect.NEW.value
+ line = re.sub(rf"\b{parts[_old]}\b", parts[_new], line)
+ type_map[parts[_old]] = parts[_new]
+
parsed = SimpleNamespace(**_parse_line(line.strip()))
arglist = parsed.arglist
annotations = {}
@@ -378,7 +430,7 @@ def calculate_props(line):
name, ann = tup[:2]
if ann == "...":
name = "*args" if name.startswith("arg_") else "*" + name
- # copy the pathed fields back
+ # copy the patched fields back
ann = 'nullptr' # maps to None
tup = name, ann
arglist[idx] = tup
@@ -455,7 +507,7 @@ def fix_variables(props, line):
else:
retvars_str = ", ".join(map(to_string, retvars))
typestr = f"typing.Tuple[{retvars_str}]"
- returntype = eval(typestr, namespace)
+ returntype = eval(typestr, globals(), namespace)
props.annotations["return"] = returntype
props.varnames = tuple(varnames)
props.defaults = tuple(defaults)