diff options
author | Christian Tismer <tismer@stackless.com> | 2019-08-13 11:15:52 +0200 |
---|---|---|
committer | Christian Tismer <tismer@stackless.com> | 2019-08-21 03:30:23 +0200 |
commit | 01b43dc3d93e632c3c42fb8e1105f200b9cee2ae (patch) | |
tree | f4431f927b267835f940a761ee1bcfb76ac4a580 /sources | |
parent | 86f56c1ea0846540b082c67d0dc3e942fd311208 (diff) |
Add QtCore.Slot.__signature__ and much more manually
The signature of QtCore.Slot and other classes could not automatically
be generated because the function is not generated by cppgenerator.cpp .
We add it manually in the C++ code into the generation process.
The case of QtCore.Slot had diverse follow-up issues to be solved:
- Classes which did not inherit from Shiboken were not generated.
This is a long-standing omission and creates very many new
simple types.
- The arity of Slot has default arguments after the varargs parameter
"*types". This needed an extended Python parser analysis that fixes
the arguments given to the inspect module, accordingly.
- The signature generation was completely new implemented and
relies no longer on the restricted syntax of a Python (2) function
but generates signatures directly as Parameter instances.
Implemented classes with hand-made signatures:
QtCore.ClassInfo
QtCore.MetaFunction,
QtCore.MetaSignal
QtCore.Property
QtCore.Signal
QtCore.SignalInstance
QtCore.Slot
QtQml.ListProperty
QtQml.VolatileBool
As a side effect, many more subtypes were published.
Enums are done, which concludes this work.
Fixes: PYSIDE-945
Fixes: PYSIDE-1052
Change-Id: Ic09f02ece3a90325519e42e4e39719beb0c27ae9
Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources')
12 files changed, 164 insertions, 65 deletions
diff --git a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp index db297db7c..6427e5198 100644 --- a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp +++ b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp @@ -41,6 +41,7 @@ // shiboken #include <shiboken.h> +#include <signature.h> // pyside #include <pyside.h> @@ -469,12 +470,22 @@ PyTypeObject *QtQml_VolatileBoolTypeF(void) return type; } +static const char *PropertyList_SignatureStrings[] = { + "PySide2.QtQml.ListProperty(type:type,append:typing.Callable," + "at:typing.Callable=None,clear:typing.Callable=None,count:typing.Callable=None)", + nullptr}; // Sentinel + +static const char *VolatileBool_SignatureStrings[] = { + "PySide2.QtQml.VolatileBool.get()->bool", + "PySide2.QtQml.VolatileBool.set(a:object)", + nullptr}; // Sentinel + void PySide::initQmlSupport(PyObject *module) { ElementFactory<PYSIDE_MAX_QML_TYPES - 1>::init(); // Export QmlListProperty type - if (PyType_Ready(PropertyListTypeF()) < 0) { + if (SbkSpecial_Type_Ready(module, PropertyListTypeF(), PropertyList_SignatureStrings) < 0) { PyErr_Print(); qWarning() << "Error initializing PropertyList type."; return; @@ -484,7 +495,7 @@ void PySide::initQmlSupport(PyObject *module) PyModule_AddObject(module, PepType_GetNameStr(PropertyListTypeF()), reinterpret_cast<PyObject *>(PropertyListTypeF())); - if (PyType_Ready(QtQml_VolatileBoolTypeF()) < 0) { + if (SbkSpecial_Type_Ready(module, QtQml_VolatileBoolTypeF(), VolatileBool_SignatureStrings) < 0) { PyErr_Print(); qWarning() << "Error initializing VolatileBool type."; return; diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py index c732227f4..8aa69c983 100644 --- a/sources/pyside2/PySide2/support/generate_pyi.py +++ b/sources/pyside2/PySide2/support/generate_pyi.py @@ -141,7 +141,7 @@ class Formatter(Writer): self.outfile.seek(here) self.outfile.truncate() # Note: we cannot use class_str when we have no body. - self.print("{spaces}class {class_name}: ...".format(**locals())) + self.print("{spaces}class {class_str}: ...".format(**locals())) if "<" in class_name: # This is happening in QtQuick for some reason: ## class QSharedPointer<QQuickItemGrabResult >: @@ -168,6 +168,13 @@ class Formatter(Writer): self.print('{spaces}@staticmethod'.format(**locals())) self.print('{spaces}def {func_name}{signature}: ...'.format(**locals())) + @contextmanager + def enum(self, class_name, enum_name, value): + spaces = self.spaces + hexval = hex(value) + self.print("{spaces}{enum_name:20}: {class_name} = ... # {hexval}".format(**locals())) + yield + def get_license_text(): with io.open(sourcepath) as f: @@ -247,10 +254,10 @@ def generate_all_pyi(outpath, options): os.environ["PYTHONPATH"] = pypath # now we can import - global PySide2, inspect, HintingEnumerator + global PySide2, inspect, HintingEnumerator, EnumType import PySide2 from PySide2.support.signature import inspect - from PySide2.support.signature.lib.enum_sig import HintingEnumerator + from PySide2.support.signature.lib.enum_sig import HintingEnumerator, EnumType # propagate USE_PEP563 to the mapping module. # Perhaps this can be automated? diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp index 288e7f97c..fe5ca8765 100644 --- a/sources/pyside2/libpyside/pysideclassinfo.cpp +++ b/sources/pyside2/libpyside/pysideclassinfo.cpp @@ -45,8 +45,7 @@ #include "dynamicqmetaobject.h" #include <shiboken.h> - -#define CLASSINFO_CLASS_NAME "ClassInfo" +#include <signature.h> extern "C" { @@ -65,7 +64,7 @@ static PyType_Slot PySideClassInfoType_slots[] = { {0, 0} }; static PyType_Spec PySideClassInfoType_spec = { - "PySide2.QtCore." CLASSINFO_CLASS_NAME, + "PySide2.QtCore.ClassInfo", sizeof(PySideClassInfo), 0, Py_TPFLAGS_DEFAULT, @@ -179,13 +178,17 @@ void classInfoFree(void *self) namespace PySide { namespace ClassInfo { +static const char *ClassInfo_SignatureStrings[] = { + "PySide2.QtCore.ClassInfo(**info:typing.Dict[str,str])", + nullptr}; // Sentinel + void init(PyObject *module) { - if (PyType_Ready(PySideClassInfoTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideClassInfoTypeF(), ClassInfo_SignatureStrings) < 0) return; Py_INCREF(PySideClassInfoTypeF()); - PyModule_AddObject(module, CLASSINFO_CLASS_NAME, reinterpret_cast<PyObject *>(PySideClassInfoTypeF())); + PyModule_AddObject(module, "ClassInfo", reinterpret_cast<PyObject *>(PySideClassInfoTypeF())); } bool checkType(PyObject *pyObj) diff --git a/sources/pyside2/libpyside/pysideclassinfo_p.h b/sources/pyside2/libpyside/pysideclassinfo_p.h index 426aee133..c0038a71a 100644 --- a/sources/pyside2/libpyside/pysideclassinfo_p.h +++ b/sources/pyside2/libpyside/pysideclassinfo_p.h @@ -44,7 +44,7 @@ #include <QMetaObject> #include "pysideclassinfo.h" -#define __INFO_ATTR_NAME__ "__classInfo__" +#define __INFO_ATTR_NAME__ "__classInfo__" // not used! ??? struct PySideClassInfo; diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp index 346117201..e0e0c439b 100644 --- a/sources/pyside2/libpyside/pysidemetafunction.cpp +++ b/sources/pyside2/libpyside/pysidemetafunction.cpp @@ -41,6 +41,7 @@ #include "pysidemetafunction_p.h" #include <shiboken.h> +#include <signature.h> #include <QtCore/QMetaMethod> @@ -65,7 +66,7 @@ static PyType_Slot PySideMetaFunctionType_slots[] = { {0, 0} }; static PyType_Spec PySideMetaFunctionType_spec = { - "PySide.MetaFunction", + "PySide2.QtCore.MetaFunction", sizeof(PySideMetaFunction), 0, Py_TPFLAGS_DEFAULT, @@ -101,11 +102,16 @@ PyObject *functionCall(PyObject *self, PyObject *args, PyObject * /* kw */) namespace PySide { namespace MetaFunction { +static const char *MetaFunction_SignatureStrings[] = { + "PySide2.QtCore.MetaFunction.__call__(*args:typing.Any)->typing.Any", + nullptr}; // Sentinel + void init(PyObject *module) { - if (PyType_Ready(PySideMetaFunctionTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideMetaFunctionTypeF(), MetaFunction_SignatureStrings) < 0) return; + Py_INCREF(PySideMetaFunctionTypeF()); PyModule_AddObject(module, "MetaFunction", reinterpret_cast<PyObject *>(PySideMetaFunctionTypeF())); } diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp index a9cacf869..d9d15eb3b 100644 --- a/sources/pyside2/libpyside/pysideproperty.cpp +++ b/sources/pyside2/libpyside/pysideproperty.cpp @@ -45,8 +45,7 @@ #include "pysidesignal_p.h" #include <shiboken.h> - -#define QPROPERTY_CLASS_NAME "Property" +#include <signature.h> extern "C" { @@ -82,7 +81,7 @@ static PyType_Slot PySidePropertyType_slots[] = { }; // Dotted modulename is crucial for PyType_FromSpec to work. Is this name right? static PyType_Spec PySidePropertyType_spec = { - "PySide2.QtCore." QPROPERTY_CLASS_NAME, + "PySide2.QtCore.Property", sizeof(PySideProperty), 0, Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE, @@ -321,13 +320,24 @@ static PyObject *getFromType(PyTypeObject *type, PyObject *name) namespace PySide { namespace Property { +static const char *Property_SignatureStrings[] = { + "PySide2.QtCore.Property(type:type,fget:typing.Callable=None,fset:typing.Callable=None," + "freset:typing.Callable=None,fdel:typing.Callable=None,doc:str=None," + "notify:typing.Callable=None,designable:bool=True,scriptable:bool=True," + "stored:bool=True,user:bool=False,constant:bool=False,final:bool=False)", + "PySide2.QtCore.Property.getter(func:typing.Callable)", + "PySide2.QtCore.Property.read(func:typing.Callable)", + "PySide2.QtCore.Property.setter(func:typing.Callable)", + "PySide2.QtCore.Property.write(func:typing.Callable)", + nullptr}; // Sentinel + void init(PyObject *module) { - if (PyType_Ready(PySidePropertyTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySidePropertyTypeF(), Property_SignatureStrings) < 0) return; Py_INCREF(PySidePropertyTypeF()); - PyModule_AddObject(module, QPROPERTY_CLASS_NAME, reinterpret_cast<PyObject *>(PySidePropertyTypeF())); + PyModule_AddObject(module, "Property", reinterpret_cast<PyObject *>(PySidePropertyTypeF())); } bool checkType(PyObject *pyObj) diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp index 434ef6ac3..a09c17a24 100644 --- a/sources/pyside2/libpyside/pysidesignal.cpp +++ b/sources/pyside2/libpyside/pysidesignal.cpp @@ -47,12 +47,11 @@ #include <QtCore/QObject> #include <QtCore/QMetaMethod> #include <QtCore/QMetaObject> +#include <signature.h> #include <algorithm> #include <utility> -#define SIGNAL_CLASS_NAME "Signal" -#define SIGNAL_INSTANCE_NAME "SignalInstance" #define QT_SIGNAL_SENTINEL '2' namespace PySide { @@ -101,35 +100,35 @@ static PyObject *signalCall(PyObject *, PyObject *, PyObject *); static PyObject *metaSignalCheck(PyObject *, PyObject *); -static PyMethodDef Signal_methods[] = { - {"__instancecheck__", (PyCFunction)metaSignalCheck, METH_O, NULL}, +static PyMethodDef MetaSignal_methods[] = { + {"__instancecheck__", (PyCFunction)metaSignalCheck, METH_O|METH_STATIC, NULL}, {0, 0, 0, 0} }; -static PyType_Slot PySideSignalMetaType_slots[] = { - {Py_tp_methods, (void *)Signal_methods}, +static PyType_Slot PySideMetaSignalType_slots[] = { + {Py_tp_methods, (void *)MetaSignal_methods}, {Py_tp_base, (void *)&PyType_Type}, {Py_tp_free, (void *)PyObject_GC_Del}, {Py_tp_dealloc, (void *)object_dealloc}, {0, 0} }; -static PyType_Spec PySideSignalMetaType_spec = { +static PyType_Spec PySideMetaSignalType_spec = { "PySide2.QtCore.MetaSignal", 0, // sizeof(PyHeapTypeObject) is filled in by PyType_FromSpecWithBases // which calls PyType_Ready which calls inherit_special. 0, Py_TPFLAGS_DEFAULT, - PySideSignalMetaType_slots, + PySideMetaSignalType_slots, }; -PyTypeObject *PySideSignalMetaTypeF(void) +PyTypeObject *PySideMetaSignalTypeF(void) { static PyTypeObject *type = nullptr; if (!type) { PyObject *bases = Py_BuildValue("(O)", &PyType_Type); - type = (PyTypeObject *)PyType_FromSpecWithBases(&PySideSignalMetaType_spec, bases); + type = (PyTypeObject *)PyType_FromSpecWithBases(&PySideMetaSignalType_spec, bases); Py_XDECREF(bases); } return type; @@ -146,7 +145,7 @@ static PyType_Slot PySideSignalType_slots[] = { {0, 0} }; static PyType_Spec PySideSignalType_spec = { - "PySide2.QtCore." SIGNAL_CLASS_NAME, + "PySide2.QtCore.Signal", sizeof(PySideSignal), 0, Py_TPFLAGS_DEFAULT, @@ -160,7 +159,7 @@ PyTypeObject *PySideSignalTypeF(void) if (!type) { type = (PyTypeObject *)PyType_FromSpec(&PySideSignalType_spec); PyTypeObject *hold = Py_TYPE(type); - Py_TYPE(type) = PySideSignalMetaTypeF(); + Py_TYPE(type) = PySideMetaSignalTypeF(); Py_INCREF(Py_TYPE(type)); Py_DECREF(hold); } @@ -185,7 +184,7 @@ static PyType_Slot PySideSignalInstanceType_slots[] = { {0, 0} }; static PyType_Spec PySideSignalInstanceType_spec = { - "PySide2.QtCore." SIGNAL_INSTANCE_NAME, + "PySide2.QtCore.SignalInstance", sizeof(PySideSignalInstance), 0, Py_TPFLAGS_DEFAULT, @@ -211,7 +210,7 @@ int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds) emptyTuple = PyTuple_New(0); if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds, - "|sO:QtCore." SIGNAL_CLASS_NAME, const_cast<char **>(kwlist), &argName, &argArguments)) + "|sO:QtCore.Signal", const_cast<char **>(kwlist), &argName, &argArguments)) return -1; bool tupledArgs = false; @@ -317,7 +316,7 @@ PyObject *signalInstanceConnect(PyObject *self, PyObject *args, PyObject *kwds) static const char *kwlist[] = {"slot", "type", nullptr}; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|O:" SIGNAL_INSTANCE_NAME, const_cast<char **>(kwlist), &slot, &type)) + "O|O:SignalInstance", const_cast<char **>(kwlist), &slot, &type)) return 0; PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self); @@ -585,9 +584,9 @@ PyObject *signalInstanceCall(PyObject *self, PyObject *args, PyObject *kw) return PyCFunction_Call(homonymousMethod, args, kw); } -static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject *args) +static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject *arg) { - if (PyType_IsSubtype(Py_TYPE(args), PySideSignalInstanceTypeF())) + if (PyType_IsSubtype(Py_TYPE(arg), PySideSignalInstanceTypeF())) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -598,21 +597,36 @@ static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject *args) namespace PySide { namespace Signal { +static const char *MetaSignal_SignatureStrings[] = { + "PySide2.QtCore.MetaSignal.__instancecheck__(object:object)->bool", + nullptr}; // Sentinel + +static const char *Signal_SignatureStrings[] = { + "PySide2.QtCore.Signal(*types:type,name:str=nullptr,arguments:str=nullptr)", + nullptr}; // Sentinel + +static const char *SignalInstance_SignatureStrings[] = { + "PySide2.QtCore.SignalInstance.connect(slot:object,type:type=nullptr)", + "PySide2.QtCore.SignalInstance.disconnect(slot:object=nullptr)", + "PySide2.QtCore.SignalInstance.emit(*args:typing.Any)", + nullptr}; // Sentinel + void init(PyObject *module) { - if (PyType_Ready(PySideSignalMetaTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideMetaSignalTypeF(), MetaSignal_SignatureStrings) < 0) return; + Py_INCREF(PySideSignalTypeF()); + PyModule_AddObject(module, "MetaSignal", reinterpret_cast<PyObject *>(PySideMetaSignalTypeF())); - if (PyType_Ready(PySideSignalTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideSignalTypeF(), Signal_SignatureStrings) < 0) return; - Py_INCREF(PySideSignalTypeF()); - PyModule_AddObject(module, SIGNAL_CLASS_NAME, reinterpret_cast<PyObject *>(PySideSignalTypeF())); + PyModule_AddObject(module, "Signal", reinterpret_cast<PyObject *>(PySideSignalTypeF())); - if (PyType_Ready(PySideSignalInstanceTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideSignalInstanceTypeF(), SignalInstance_SignatureStrings) < 0) return; - Py_INCREF(PySideSignalInstanceTypeF()); + PyModule_AddObject(module, "SignalInstance", reinterpret_cast<PyObject *>(PySideSignalInstanceTypeF())); } bool checkType(PyObject *pyObj) diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp index 2f8e69e8f..204253aa2 100644 --- a/sources/pyside2/libpyside/pysideslot.cpp +++ b/sources/pyside2/libpyside/pysideslot.cpp @@ -45,8 +45,7 @@ #include <QtCore/QMetaObject> #include <QtCore/QString> - -#define SLOT_DEC_NAME "Slot" +#include <signature.h> struct SlotData { @@ -76,7 +75,7 @@ static PyType_Slot PySideSlotType_slots[] = { {0, 0} }; static PyType_Spec PySideSlotType_spec = { - "PySide2.QtCore." SLOT_DEC_NAME, + "PySide2.QtCore.Slot", sizeof(PySideSlot), 0, Py_TPFLAGS_DEFAULT, @@ -102,7 +101,7 @@ int slotTpInit(PyObject *self, PyObject *args, PyObject *kw) if (emptyTuple == 0) emptyTuple = PyTuple_New(0); - if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sO:QtCore." SLOT_DEC_NAME, + if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sO:QtCore.Slot", const_cast<char **>(kwlist), &argName, &argResult)) { return -1; } @@ -177,15 +176,20 @@ PyObject *slotCall(PyObject *self, PyObject *args, PyObject * /* kw */) } // extern "C" -namespace PySide { namespace Slot { +namespace PySide { +namespace Slot { + +static const char *Slot_SignatureStrings[] = { + "PySide2.QtCore.Slot(*types:type,name:str=nullptr,result:str=nullptr)->typing.Callable[...,typing.Optional[str]]", + nullptr}; // Sentinel void init(PyObject *module) { - if (PyType_Ready(PySideSlotTypeF()) < 0) + if (SbkSpecial_Type_Ready(module, PySideSlotTypeF(), Slot_SignatureStrings) < 0) return; Py_INCREF(PySideSlotTypeF()); - PyModule_AddObject(module, SLOT_DEC_NAME, reinterpret_cast<PyObject *>(PySideSlotTypeF())); + PyModule_AddObject(module, "Slot", reinterpret_cast<PyObject *>(PySideSlotTypeF())); } } // namespace Slot diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py index bd827f1ee..af8ada065 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py @@ -174,6 +174,13 @@ def make_signature_nameless(signature): signature.parameters[key].__class__ = NamelessParameter +_POSITIONAL_ONLY = inspect._POSITIONAL_ONLY +_POSITIONAL_OR_KEYWORD = inspect._POSITIONAL_OR_KEYWORD +_VAR_POSITIONAL = inspect._VAR_POSITIONAL +_KEYWORD_ONLY = inspect._KEYWORD_ONLY +_VAR_KEYWORD = inspect._VAR_KEYWORD +_empty = inspect._empty + def create_signature(props, key): if not props: # empty signatures string @@ -204,8 +211,8 @@ def create_signature(props, key): elif sig_kind == "classmethod": varnames = ("klass",) + varnames else: - raise SystemError("Methods must be function, method, staticmethod or " - "classmethod") + raise SystemError("Methods must be function, method, staticmethod" + " or classmethod") # calculate the modifications defaults = props["defaults"][:] if not layout.defaults: @@ -216,14 +223,25 @@ def create_signature(props, key): if not layout.return_annotation and "return" in annotations: del annotations["return"] - # attach parameters to a fake function and build a signature - argstr = ", ".join(varnames) - fakefunc = eval("lambda {}: None".format(argstr)) - fakefunc.__name__ = props["name"] - fakefunc.__defaults__ = defaults - fakefunc.__kwdefaults__ = props["kwdefaults"] - fakefunc.__annotations__ = annotations - sig = inspect._signature_from_function(inspect.Signature, fakefunc) + # Build a signature. + kind = inspect._POSITIONAL_OR_KEYWORD + params = [] + for idx, name in enumerate(varnames): + if name.startswith("**"): + kind = _VAR_KEYWORD + elif name.startswith("*"): + kind = _VAR_POSITIONAL + ann = annotations.get(name, _empty) + name = name.lstrip("*") + defpos = idx - len(varnames) + len(defaults) + default = defaults[defpos] if defpos >= 0 else _empty + param = inspect.Parameter(name, kind, annotation=ann, default=default) + params.append(param) + if kind == _VAR_POSITIONAL: + kind = _KEYWORD_ONLY + sig = inspect.Signature(params, + return_annotation=annotations.get('return', _empty), + __validate_parameters__=False) # the special case of nameless parameters if not layout.parameter_names: diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py index e6f6dc379..42b123046 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py @@ -52,6 +52,11 @@ by producing a lot of clarity. import sys from shibokensupport.signature import inspect from shibokensupport.signature import get_signature +try: + from PySide2.QtCore import Qt + EnumType = type(Qt.Key) +except ImportError: + EnumType = None class ExactEnumerator(object): @@ -82,7 +87,8 @@ class ExactEnumerator(object): return ret def klass(self, class_name, klass): - if not "Shiboken" in repr(klass.mro()): + modname = klass.__module__ + if not (modname.startswith("PySide2") or modname.startswith("shiboken2")): # don't look into any foreign classes! ret = self.result_type() return ret @@ -111,6 +117,8 @@ class ExactEnumerator(object): ret.update(self.function(func_name, thing)) for subclass_name, subclass in subclasses: ret.update(self.klass(subclass_name, subclass)) + if isinstance(subclass, EnumType): + self.enum(subclass) return ret def function(self, func_name, func): @@ -121,6 +129,16 @@ class ExactEnumerator(object): ret[key] = signature return ret + def enum(self, subclass): + if not hasattr(self.fmt, "enum"): + # this is an optional feature + return + class_name = subclass.__name__ + for enum_name, value in subclass.__dict__.items(): + if type(type(value)) is EnumType: + with self.fmt.enum(class_name, enum_name, int(value)): + pass + def stringify(signature): if isinstance(signature, list): diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index 36b137104..10d0f16ad 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -67,6 +67,10 @@ ModelIndexList = typing.List[int] QImageCleanupFunction = typing.Callable StringList = typing.List[str] +# unfortunately, typing.Optional[t] expands to typing.Union[t, NoneType] +# Until we can force it to create Optional[t] again, we use this. +NoneType = type(None) + _S = TypeVar("_S") # Building our own Char type, which is much nicer than @@ -316,6 +320,7 @@ type_map.update({ "zero(int)": 0, "zero(object)": None, "zero(str)": "", + "...": "...", }) @@ -345,6 +350,7 @@ def init_sample(): "Foo.HANDLE": int, "HANDLE": int, "Null": None, + "nullptr": None, "ObjectType.Identifier": Missing("sample.ObjectType.Identifier"), "OddBool": bool, "PStr": str, diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py index 6109bceee..3d14ec7b3 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -116,7 +116,7 @@ def _parse_line(line): print("KEYWORD", ret) name = name + "_" if "=" in ann: - ann, default = ann.split("=") + ann, default = ann.split("=", 1) tup = name, ann, default else: tup = name, ann @@ -167,9 +167,11 @@ def try_to_guess(thing, valtype): def _resolve_value(thing, valtype, line): if thing in ("0", "None") and valtype: - if valtype.startswith("PySide2."): + if valtype.startswith("PySide2.") or valtype.startswith("typing."): return None - name = type_map[valtype].__name__ + mapped = type_map[valtype] + # typing.Any: '_SpecialForm' object has no attribute '__name__' + name = mapped.__name__ if hasattr(mapped, "__name__") else str(mapped) thing = "zero({})".format(name) if thing in type_map: return type_map[thing] @@ -275,9 +277,9 @@ def calculate_props(line): for idx, tup in enumerate(arglist): name, ann = tup[:2] if ann == "...": - name = "*args" - # copy the fields back :() - ann = 'NULL' # maps to None + name = "*args" if name.startswith("arg_") else "*" + name + # copy the pathed fields back + ann = 'nullptr' # maps to None tup = name, ann arglist[idx] = tup annotations[name] = _resolve_type(ann, line, 0) |