diff options
| author | Christian Tismer <tismer@stackless.com> | 2017-10-19 11:27:13 +0200 |
|---|---|---|
| committer | Christian Tismer <tismer@stackless.com> | 2017-11-14 09:39:59 +0000 |
| commit | b825eec459a3d5dcddf14061d578ef89e6ad5ee4 (patch) | |
| tree | 1d01b860a1134fffb31ab0029a4251c939460a4f /sources/pyside2/PySide2/support/signature/mapping.py | |
| parent | fa1c97fc2a7f25fe178b0c180b56f78ac00bc4c9 (diff) | |
Update and complete the signature module
There is now an external typing module for Python 2.7 and Python 3.6
from Guido (PSF license again) that makes the differences between
both versions vanish.
Also, when generating interface files, some types did not show
correctly, and the constant "0" is wrong in almost all cases.
Values in signatures looked often bad since they have no nice
__repr__, and it was almost impossible to create correct .pyi files.
Now, these instances are created as wrapped string types
with a nice __repr__. A call of these objects creates the real
constant. This way, also objects can be rendered which are
dependent from the existence of other objects (i.E. QPixMap).
This patch improves the usability of the signature module.
We can now generate source code or .pyi files without modifications.
Task-number: PYSIDE-510
Change-Id: I55490d76a29fc6c0e4f821c0c77d5e5d1e28976e
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside2/PySide2/support/signature/mapping.py')
| -rw-r--r-- | sources/pyside2/PySide2/support/signature/mapping.py | 189 |
1 files changed, 133 insertions, 56 deletions
diff --git a/sources/pyside2/PySide2/support/signature/mapping.py b/sources/pyside2/PySide2/support/signature/mapping.py index 668ca8df4..33686d4a5 100644 --- a/sources/pyside2/PySide2/support/signature/mapping.py +++ b/sources/pyside2/PySide2/support/signature/mapping.py @@ -53,30 +53,23 @@ See _resolve_value() in singature.py """ import sys -import collections import struct import PySide2 -PY3 = sys.version_info >= (3,) -if PY3: - from . import typing - ellipsis = eval("...") - Char = typing.Union[str, int] # how do I model the limitation to 1 char? - StringList = typing.List[str] - Variant = typing.Union[str, int, float, Char, StringList, type(ellipsis)] - # Much more, do we need that? Do we better kill it? - ModelIndexList = typing.List[int] - QImageCleanupFunction = typing.Callable[[bytes], None] - FloatMatrix = typing.List[typing.List[float]] -else: - ellipsis = "..." - Char = str - StringList = list - Variant = object - ModelIndexList = list - QImageCleanupFunction = object - FloatMatrix = list -Pair = collections.namedtuple('Pair', ['first', 'second']) +from . import typing +ellipsis = "..." +Char = typing.Union[str, int] # how do I model the limitation to 1 char? +StringList = typing.List[str] +IntList = typing.List[int] +Variant = typing.Any +ModelIndexList = typing.List[int] +QImageCleanupFunction = typing.Callable[[bytes], None] +FloatMatrix = typing.List[typing.List[float]] +# Pair could be more specific, but we loose the info in the generator. +Pair = typing.Tuple[typing.Any, typing.Any] +MultiMap = typing.DefaultDict[str, typing.List[str]] +Text = typing.Text + # ulong_max is only 32 bit on windows. ulong_max = 2*sys.maxsize+1 if len(struct.pack("L", 1)) != 4 else 0xffffffff ushort_max = 0xffff @@ -90,15 +83,49 @@ WId = int GL_TEXTURE_2D = 0x0DE1 GL_RGBA = 0x1908 -# Some types are abstract. They just show their name. -class Virtual(str): +class _NotCalled(str): + """ + Wrap some text with semantics + + This class is wrapped around text in order to avoid calling it. + There are three reasons for this: + + - some instances cannot be created since they are abstract, + - some can only be created after qApp was created, + - some have an ugly __repr__ with angle brackets in it. + + By using derived classes, good looking instances can be created + which can be used to generate source code or .pyi files. When the + real object is needed, the wrapper can simply be called. + """ def __repr__(self): - return "Virtual({})".format(self) + suppress = "PySide2.support.signature.typing." + text = self[len(suppress):] if self.startswith(suppress) else self + return "{}({})".format(type(self).__name__, text) + + def __call__(self): + from .mapping import __dict__ as namespace + text = self if self.endswith(")") else self + "()" + return eval(text, namespace) + +# Some types are abstract. They just show their name. +class Virtual(_NotCalled): + pass # Other types I simply could not find. -class Missing(str): - def __repr__(self): - return "Missing({})".format(self) +class Missing(_NotCalled): + pass + +class Invalid(_NotCalled): + pass + +# Helper types +class Default(_NotCalled): + pass + +class Instance(_NotCalled): + pass + class Reloader(object): def __init__(self): @@ -117,13 +144,14 @@ class Reloader(object): if proc_name in g: g.update(g[proc_name]()) + update_mapping = Reloader().update type_map = {} def init_QtCore(): import PySide2.QtCore from PySide2.QtCore import Qt, QUrl, QDir, QGenericArgument - from PySide2.QtCore import QRect, QSize, QPoint + from PySide2.QtCore import QRect, QSize, QPoint, QLocale, QByteArray from PySide2.QtCore import QMarginsF # 5.9 try: # seems to be not generated by 5.9 ATM. @@ -159,7 +187,7 @@ def init_QtCore(): "QVariant": Variant, "QVariant.Type": type, # not so sure here... "QStringRef": str, - "QString()": None, # unclear: "" would be isEmpty(), but not isNull() + "QString()": "", "QModelIndexList": ModelIndexList, "QPair": Pair, "unsigned char": Char, @@ -172,13 +200,13 @@ def init_QtCore(): "PyCallable": callable, "...": ellipsis, # no idea how this should be translated... maybe so? "PyTypeObject": type, - "PySequence": list, # needs to be changed, QApplication for instance! + "PySequence": typing.Sequence, "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. - "QVariant()": (ellipsis,), # no idea what to use here for "invalid Variant"? + "QVariant()": Invalid(Variant), "QMap": dict, "PySide2.QtCore.bool": bool, "QHash": dict, @@ -197,27 +225,25 @@ def init_QtCore(): "PySide2.QtCore.quint64": int, "PySide2.QtCore.quint8": int, "PySide2.QtCore.uchar": Char, - "QGenericArgument(0)": QGenericArgument(None), "PySide2.QtCore.long": int, "PySide2.QtCore.QUrl.ComponentFormattingOptions": PySide2.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why??? - "QUrl.FormattingOptions(PrettyDecoded)": QUrl.FormattingOptions(QUrl.PrettyDecoded), + "QUrl.FormattingOptions(PrettyDecoded)": Instance( + "QUrl.FormattingOptions(QUrl.PrettyDecoded)"), # from 5.9 - "QDir.Filters(AllEntries | NoDotAndDotDot)": QDir.Filters(QDir.AllEntries | - QDir.NoDotAndDotDot), - "QGenericArgument(Q_NULLPTR)": QGenericArgument(None), + "QDir.Filters(AllEntries | NoDotAndDotDot)": Instance( + "QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot)"), "NULL": None, # 5.6, MSVC - "QGenericArgument(NULL)": QGenericArgument(None), # 5.6, MSVC - "QDir.SortFlags(Name | IgnoreCase)": QDir.SortFlags(QDir.Name | QDir.IgnoreCase), + "QDir.SortFlags(Name | IgnoreCase)": Instance( + "QDir.SortFlags(QDir.Name | QDir.IgnoreCase)"), "PyBytes": bytes, - "PyUnicode": str if PY3 else unicode, + "PyUnicode": Text, "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 - "QGenericArgument((0))": None, # 5.6, RHEL 6.6. Is that ok? "4294967295UL": 4294967295, # 5.6, RHEL 6.6 "PySide2.QtCore.int32_t": int, # 5.9 "PySide2.QtCore.int64_t": int, # 5.9 @@ -228,6 +254,33 @@ def init_QtCore(): "float[][]": FloatMatrix, # 5.9 "PySide2.QtCore.unsigned int": int, # 5.9 Ubuntu "PySide2.QtCore.long long": int, # 5.9, MSVC 15 + "QModelIndex()": Invalid("PySide2.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?! + "QGenericArgument((0))": None, # 5.6, RHEL 6.6. Is that ok? + "QGenericArgument()": None, + "QGenericArgument(0)": None, + "QGenericArgument(NULL)": None, # 5.6, MSVC + "QGenericArgument(Q_NULLPTR)": None, + "zero(PySide2.QtCore.QObject)": None, + "zero(PySide2.QtCore.QThread)": None, + "zero(quintptr)": 0, + "zero(str)": "", + "zero(int)": 0, + "zero(PySide2.QtCore.QState)": None, + "zero(PySide2.QtCore.bool)": False, + "zero(PySide2.QtCore.int)": 0, + "zero(void)": None, + "zero(long long)": 0, + "zero(PySide2.QtCore.QAbstractItemModel)": None, + "zero(PySide2.QtCore.QJsonParseError)": None, + "zero(double)": 0.0, + "zero(PySide2.QtCore.qint64)": 0, + "zero(PySide2.QtCore.QTextCodec.ConverterState)": None, + "zero(long long)": 0, + "zero(QImageCleanupFunction)": None, + "zero(unsigned int)": 0, + "zero(PySide2.QtCore.QPoint)": Default("PySide2.QtCore.QPoint"), + "zero(unsigned char)": 0, + "zero(PySide2.QtCore.QEvent.Type)": None, }) try: type_map.update({ @@ -253,8 +306,15 @@ def init_QtGui(): "GL_NEAREST": GL_NEAREST, "WId": WId, "PySide2.QtGui.QPlatformSurface": Virtual("PySide2.QtGui.QPlatformSurface"), # hmm... - "QList< QTouchEvent.TouchPoint >()": list, - "QPixmap()": lambda:QPixmap(), # we cannot create this without qApp + "QList< QTouchEvent.TouchPoint >()": [], # XXX improve? + "QPixmap()": Default("PySide2.QtGui.QPixmap"), # can't create without qApp + "zero(PySide2.QtGui.QWindow)": None, + "zero(PySide2.QtGui.QOpenGLContext)": None, + "zero(PySide2.QtGui.QRegion)": None, + "zero(PySide2.QtGui.QPaintDevice)": None, + "zero(PySide2.QtGui.QTextLayout.FormatRange)": None, + "zero(PySide2.QtGui.QTouchDevice)": None, + "zero(PySide2.QtGui.QScreen)": None, }) return locals() @@ -262,19 +322,15 @@ def init_QtWidgets(): import PySide2.QtWidgets from PySide2.QtWidgets import QWidget, QMessageBox, QStyleOption, QStyleHintReturn, QStyleOptionComplex from PySide2.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem # 5.9 - if PY3: - GraphicsItemList = typing.List[QGraphicsItem] - StyleOptionGraphicsItemList = typing.List[QStyleOptionGraphicsItem] - else: - GraphicsItemList = list - StyleOptionGraphicsItemList = list + GraphicsItemList = typing.List[QGraphicsItem] + StyleOptionGraphicsItemList = typing.List[QStyleOptionGraphicsItem] type_map.update({ - "QMessageBox.StandardButtons(Yes | No)": QMessageBox.StandardButtons( - QMessageBox.Yes | QMessageBox.No), - "QWidget.RenderFlags(DrawWindowBackground | DrawChildren)": QWidget.RenderFlags( - QWidget.DrawWindowBackground | QWidget.DrawChildren), - "static_cast<Qt.MatchFlags>(Qt.MatchExactly|Qt.MatchCaseSensitive)": ( - Qt.MatchFlags(Qt.MatchExactly | Qt.MatchCaseSensitive)), + "QMessageBox.StandardButtons(Yes | No)": Instance( + "QMessageBox.StandardButtons(QMessageBox.Yes | QMessageBox.No)"), + "QWidget.RenderFlags(DrawWindowBackground | DrawChildren)": Instance( + "QWidget.RenderFlags(QWidget.DrawWindowBackground | QWidget.DrawChildren)"), + "static_cast<Qt.MatchFlags>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance( + "Qt.MatchFlags(Qt.MatchExactly | Qt.MatchCaseSensitive)"), "QVector< int >()": [], # from 5.9 "Type": PySide2.QtWidgets.QListWidgetItem.Type, @@ -283,6 +339,16 @@ def init_QtWidgets(): "SO_Complex": QStyleOptionComplex.SO_Complex, "QGraphicsItem[]": GraphicsItemList, "QStyleOptionGraphicsItem[]": StyleOptionGraphicsItemList, + "zero(PySide2.QtWidgets.QWidget)": None, + "zero(PySide2.QtWidgets.QGraphicsItem)": None, + "zero(PySide2.QtCore.QEvent)": None, + "zero(PySide2.QtWidgets.QStyleOption)": None, + "zero(PySide2.QtWidgets.QStyleHintReturn)": None, + "zero(PySide2.QtWidgets.QGraphicsLayoutItem)": None, + "zero(PySide2.QtWidgets.QListWidget)": None, + "zero(PySide2.QtGui.QKeySequence)": None, + "zero(PySide2.QtWidgets.QAction)": None, + "zero(PySide2.QtWidgets.QUndoCommand)": None, }) return locals() @@ -291,14 +357,17 @@ def init_QtSql(): from PySide2.QtSql import QSqlDatabase type_map.update({ "QLatin1String(defaultConnection)": QSqlDatabase.defaultConnection, - "QVariant.Invalid": -1, # not sure what I should create, here... + "QVariant.Invalid": Invalid("PySide2.QtCore.QVariant"), # not sure what I should create, here... }) return locals() def init_QtNetwork(): import PySide2.QtNetwork type_map.update({ - "QMultiMap": typing.DefaultDict(list) if PY3 else {}, + "QMultiMap": MultiMap, + "zero(unsigned short)": 0, + "zero(PySide2.QtCore.QIODevice)": None, + "zero(QList)": [], }) return locals() @@ -331,6 +400,9 @@ def init_QtOpenGL(): "PySide2.QtOpenGL.GLint": int, "PySide2.QtOpenGL.GLuint": int, "GLfloat": float, # 5.6, MSVC 15 + "zero(PySide2.QtOpenGL.QGLContext)": None, + "zero(GLenum)": 0, + "zero(PySide2.QtOpenGL.QGLWidget)": None, }) return locals() @@ -341,6 +413,8 @@ def init_QtQml(): "PySide2.QtQml.bool volatile": bool, # from 5.9 "QVariantHash()": {}, + "zero(PySide2.QtQml.QQmlContext)": None, + "zero(PySide2.QtQml.QQmlEngine)": None, }) return locals() @@ -350,6 +424,8 @@ def init_QtQuick(): "PySide2.QtQuick.QSharedPointer": int, "PySide2.QtCore.uint": int, "T": int, + "zero(PySide2.QtQuick.QQuickItem)": None, + "zero(GLuint)": 0, }) return locals() @@ -372,6 +448,7 @@ def init_QtWebEngineWidgets(): import PySide2.QtWebEngineWidgets type_map.update({ "PySide2.QtTest.QTouchEventSequence": PySide2.QtTest.QTest.QTouchEventSequence, + "zero(PySide2.QtWebEngineWidgets.QWebEnginePage.FindFlags)": 0, }) return locals() |
