aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/shibokenmodule
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2019-08-13 11:15:52 +0200
committerChristian Tismer <tismer@stackless.com>2019-08-21 03:30:23 +0200
commit01b43dc3d93e632c3c42fb8e1105f200b9cee2ae (patch)
treef4431f927b267835f940a761ee1bcfb76ac4a580 /sources/shiboken2/shibokenmodule
parent86f56c1ea0846540b082c67d0dc3e942fd311208 (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/shiboken2/shibokenmodule')
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py38
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py20
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py6
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py14
4 files changed, 61 insertions, 17 deletions
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index bd827f1e..af8ada06 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 e6f6dc37..42b12304 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 36b13710..10d0f16a 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 6109bcee..3d14ec7b 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)