diff options
Diffstat (limited to 'sources')
5 files changed, 132 insertions, 31 deletions
diff --git a/sources/pyside2/PySide2/support/signature/mapping.py b/sources/pyside2/PySide2/support/signature/mapping.py index 96afd3c7a..d56d97454 100644 --- a/sources/pyside2/PySide2/support/signature/mapping.py +++ b/sources/pyside2/PySide2/support/signature/mapping.py @@ -98,7 +98,6 @@ def init_QtCore(): "unsigned long long": int, "unsigned short": int, "QStringList": StringList, - "QList": list, "QChar": Char, "signed char": Char, "QVariant": Variant, @@ -106,11 +105,8 @@ def init_QtCore(): "QStringRef": str, "QString()": "", "QModelIndexList": ModelIndexList, - "QPair": Pair, "unsigned char": Char, - "QSet": set, # seems _not_ to work - "QVector": list, - "QJsonObject": dict, # seems to work + "QJsonObject": typing.Dict[str, PySide2.QtCore.QJsonValue], "QStringList()": [], "ULONG_MAX": ulong_max, "quintptr": int, @@ -120,12 +116,12 @@ def init_QtCore(): "qptrdiff": int, "true": True, "Qt.HANDLE": int, # be more explicit with some consts? - "list of QAbstractState": list, # how to use typing.List when we don't have QAbstractState? - "list of QAbstractAnimation": list, # dto. + "list of QAbstractState": typing.List[PySide2.QtCore.QAbstractState], + "list of QAbstractAnimation": typing.List[PySide2.QtCore.QAbstractAnimation], "QVariant()": Invalid(Variant), - "QMap": dict, + "QMap": typing.Dict, "PySide2.QtCore.bool": bool, - "QHash": dict, + "QHash": typing.Dict, "PySide2.QtCore.QChar": Char, "PySide2.QtCore.qreal": float, "PySide2.QtCore.float": float, @@ -159,7 +155,6 @@ def init_QtCore(): "signed long": int, "PySide2.QtCore.int": int, "PySide2.QtCore.char": StringList, # A 'char **' is a list of strings. - "char[]": StringList, # 5.9 "unsigned long int": int, # 5.6, RHEL 6.6 "unsigned short int": int, # 5.6, RHEL 6.6 "4294967295UL": 4294967295, # 5.6, RHEL 6.6 @@ -169,7 +164,6 @@ def init_QtCore(): "nullptr": None, # 5.9 "uint64_t": int, # 5.9 "PySide2.QtCore.uint32_t": int, # 5.9 - "float[][]": FloatMatrix, # 5.9 "PySide2.QtCore.unsigned int": int, # 5.9 Ubuntu "PySide2.QtCore.long long": int, # 5.9, MSVC 15 "QGenericArgument(nullptr)": ellipsis, # 5.10 @@ -202,7 +196,7 @@ def init_QtCore(): "zero(PySide2.QtCore.QEvent.Type)": None, "CheckIndexOption.NoOption": Instance( "PySide2.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11 - "QVariantMap": dict, + "QVariantMap": typing.Dict[str, Variant], "PySide2.QtCore.QCborStreamReader.StringResult": typing.AnyStr, "PySide2.QtCore.double": float, }) @@ -249,8 +243,6 @@ def init_QtGui(): def init_QtWidgets(): from PySide2.QtWidgets import QWidget, QMessageBox, QStyleOption, QStyleHintReturn, QStyleOptionComplex from PySide2.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem # 5.9 - GraphicsItemList = typing.List[QGraphicsItem] - StyleOptionGraphicsItemList = typing.List[QStyleOptionGraphicsItem] type_map.update({ "QMessageBox.StandardButtons(Yes | No)": Instance( "QMessageBox.StandardButtons(QMessageBox.Yes | QMessageBox.No)"), @@ -265,8 +257,6 @@ def init_QtWidgets(): "SO_Default": QStyleOption.SO_Default, "SH_Default": QStyleHintReturn.SH_Default, "SO_Complex": QStyleOptionComplex.SO_Complex, - "QGraphicsItem[]": GraphicsItemList, - "QStyleOptionGraphicsItem[]": StyleOptionGraphicsItemList, "zero(PySide2.QtWidgets.QWidget)": None, "zero(PySide2.QtWidgets.QGraphicsItem)": None, "zero(PySide2.QtCore.QEvent)": None, @@ -286,7 +276,7 @@ def init_QtSql(): from PySide2.QtSql import QSqlDatabase type_map.update({ "QLatin1String(defaultConnection)": QSqlDatabase.defaultConnection, - "QVariant.Invalid": Invalid("PySide2.QtCore.QVariant"), # not sure what I should create, here... + "QVariant.Invalid": Invalid("Variant"), # not sure what I should create, here... }) return locals() @@ -342,7 +332,7 @@ def init_QtQml(): "QJSValueList()": [], "PySide2.QtQml.bool volatile": bool, # from 5.9 - "QVariantHash()": {}, + "QVariantHash()": typing.Dict[str, Variant], # XXX sorted? "zero(PySide2.QtQml.QQmlContext)": None, "zero(PySide2.QtQml.QQmlEngine)": None, }) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index d15f3a951..56f53f304 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -4573,7 +4573,11 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction QStringList args; const AbstractMetaArgumentList &arguments = f->arguments(); for (const AbstractMetaArgument *arg : arguments) { + AbstractMetaType *argType = getTypeWithoutContainer(arg->type()); QString strArg = resolveRetOrArgType(arg->type()); + // PYSIDE-921: Handle container returntypes correctly. + if (argType != arg->type()) + strArg += QLatin1Char('[') + resolveRetOrArgType(argType) + QLatin1Char(']'); if (!arg->defaultValueExpression().isEmpty()) { strArg += QLatin1Char('='); QString e = arg->defaultValueExpression(); @@ -4587,10 +4591,12 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction // mark the multiple signatures as such, to make it easier to generate different code if (multiple) s << idx-- << ':'; - // now calculate the return type. s << funcName << '(' << args.join(QLatin1Char(',')) << ')'; AbstractMetaType *returnType = getTypeWithoutContainer(f->type()); - if (returnType) + // PYSIDE-921: Handle container returntypes correctly. + if (returnType != f->type()) + s << "->" << resolveRetOrArgType(f->type()) << '[' << resolveRetOrArgType(returnType) << ']'; + else if (returnType) s << "->" << resolveRetOrArgType(returnType); s << endl; } diff --git a/sources/shiboken2/shibokenmodule/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/loader.py index 8c7739d9a..40ad95bdd 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/support/signature/loader.py @@ -148,6 +148,15 @@ with ensure_import_support(): namespace = inspect.__dict__ from support.signature import typing27 as typing typing.__name__ = "typing" + # Fix the module names in typing if possible. This is important since + # the typing names should be I/O compatible, so that typing.Dict + # shows itself as "typing.Dict". + for name, obj in typing.__dict__.items(): + if hasattr(obj, "__module__"): + try: + obj.__module__ = "typing" + except (TypeError, AttributeError): + pass from support.signature import backport_inspect as inspect _doc = inspect.__doc__ inspect.__dict__.update(namespace) diff --git a/sources/shiboken2/shibokenmodule/support/signature/mapping.py b/sources/shiboken2/shibokenmodule/support/signature/mapping.py index 40db43729..d4c630aca 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/mapping.py +++ b/sources/shiboken2/shibokenmodule/support/signature/mapping.py @@ -55,12 +55,13 @@ import os import pkgutil from signature_loader import typing +from signature_loader.typing import TypeVar, Generic class ellipsis(object): def __repr__(self): return "..." + ellipsis = ellipsis() -Char = typing.Union[str, int] # how do I model the limitation to 1 char? StringList = typing.List[str] IntList = typing.List[int] Point = typing.Tuple[float, float] @@ -69,10 +70,72 @@ IntMatrix = typing.List[IntList] Variant = typing.Any ModelIndexList = typing.List[int] QImageCleanupFunction = typing.Callable -FloatList = typing.List[float] -FloatMatrix = typing.List[FloatList] -# Pair could be more specific, but we loose the info in the generator. -Pair = typing.Tuple[typing.Any, typing.Any] + +# First time installing our own Pair type into typing. +T = TypeVar('T') +S = TypeVar('S') + +class Pair(Generic[T, S]): + __module__ = "typing" + +typing.Pair = Pair + + +# Building our own Char type, which is much nicer than +# Char = typing.Union[str, int] # how do I model the limitation to 1 char? + +# Copied from the six module: +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + +class _CharMeta(type): + def __repr__(self): + return '%s.%s' % (self.__module__, self.__name__) + + +class Char(with_metaclass(_CharMeta)): + """ + From http://doc.qt.io/qt-5/qchar.html : + + In Qt, Unicode characters are 16-bit entities without any markup or + structure. This class represents such an entity. It is lightweight, + so it can be used everywhere. Most compilers treat it like an + unsigned short. + + Here, we provide a simple implementation just to avoid long aliases. + """ + __module__ = "typing" + + def __init__(self, code): + if isinstance(code, int): + self.code = code & 0xffff + else: + self.code = ord(code) + + def __add__(self, other): + return chr(self.code) + other + + def __radd__(self, other): + return other + chr(self.code) + + def __repr__(self): + return "typing.Char({})".format(self.code) + +typing.Char = Char + + MultiMap = typing.DefaultDict[str, typing.List[str]] # ulong_max is only 32 bit on windows. @@ -205,6 +268,13 @@ update_mapping = Reloader().update type_map = {} namespace = globals() # our module's __dict__ +type_map.update({ + "QList": typing.List, + "QVector": typing.List, + "QSet": typing.Set, + "QPair": Pair, + }) + def init_Shiboken(): type_map.update({ @@ -225,18 +295,16 @@ def init_minimal(): def init_sample(): import datetime type_map.update({ + "double": float, "sample.int": int, "Complex": complex, "sample.OddBool": bool, "sample.bool": bool, "sample.PStr": str, - "double[]": FloatList, "OddBool": bool, "PStr": str, + "char": Char, "sample.char": Char, - "double[][]": FloatMatrix, - "int[]": IntList, - "int[][]": IntMatrix, "sample.Point": Point, "sample.ObjectType": object, "std.string": str, @@ -257,7 +325,6 @@ def init_sample(): "zero(sample.bool)": False, "PyDate": datetime.date, "ZeroIn": 0, - "Point[]": PointList, }) return locals() diff --git a/sources/shiboken2/shibokenmodule/support/signature/parser.py b/sources/shiboken2/shibokenmodule/support/signature/parser.py index 2f6e6e3f5..3b09dd4f7 100644 --- a/sources/shiboken2/shibokenmodule/support/signature/parser.py +++ b/sources/shiboken2/shibokenmodule/support/signature/parser.py @@ -45,7 +45,8 @@ import warnings import types import keyword import functools -from signature_loader.mapping import type_map, update_mapping, namespace +from signature_loader.mapping import (type_map, update_mapping, namespace, + typing, Missing) _DEBUG = False LIST_KEYWORDS = False @@ -191,7 +192,35 @@ def _resolve_value(thing, valtype, line): """.format(thing, line), RuntimeWarning) return thing +def _resolve_arraytype(thing, line): + thing = thing[:-2] + if thing.endswith("[]"): + thing = _resolve_arraytype(thing, line) + # this mapping is in shiboken + thing = "QList[" + thing + "]" + return thing + +def to_string(thing): + if isinstance(thing, str): + return thing + if hasattr(thing, "__name__"): + dot = "." in str(type(thing)) + return thing.__module__ + "." + thing.__name__ if dot else thing.__name__ + # Note: This captures things from the typing module: + return str(thing) + def _resolve_type(thing, line): + if thing.endswith("[]"): + thing = _resolve_arraytype(thing, line) + if "[" in thing: + # Handle a container return type. (see PYSIDE-921 in cppgenerator.cpp) + contr, thing = re.match(r"(.*?)\[(.*?)\]$", thing).groups() + contr = to_string(_resolve_type(contr, line)) + thing = to_string(_resolve_type(thing, line)) + result = "{contr}[{thing}]".format(**locals()) + if not isinstance(thing, Missing): + result = eval(result, namespace) + return result return _resolve_value(thing, None, line) def calculate_props(line): |