aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature')
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py75
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py100
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py19
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py25
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py27
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py13
6 files changed, 180 insertions, 79 deletions
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index bd827f1ee..384273d92 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -56,7 +56,7 @@ used literally as strings like "signature", "existence", etc.
"""
from textwrap import dedent
-from shibokensupport.signature import inspect
+from shibokensupport.signature import inspect, typing
from shibokensupport.signature.mapping import ellipsis
from shibokensupport.signature.lib.tool import SimpleNamespace
@@ -162,6 +162,35 @@ def define_nameless_parameter():
NamelessParameter = define_nameless_parameter()
+"""
+Note on the "Optional" feature:
+
+When an annotation has a default value that is None, then the
+type has to be wrapped into "typing.Optional".
+
+Note that only the None value creates an Optional expression,
+because the None leaves the domain of the variable.
+Defaults like integer values are ignored: They stay in the domain.
+
+That information would be lost when we use the "..." convention.
+
+Note that the typing module has the remarkable expansion
+
+ Optional[T] is Variant[T, NoneType]
+
+We want to avoid that when generating the .pyi file.
+This is done by a regex in generate_pyi.py .
+The following would work in Python 3, but this is a version-dependent
+hack that also won't work in Python 2 and would be _very_ complex.
+"""
+# import sys
+# if sys.version_info[0] == 3:
+# class hugo(list):pass
+# typing._normalize_alias["hugo"] = "Optional"
+# Optional = typing._alias(hugo, typing.T, inst=False)
+# else:
+# Optional = typing.Optional
+
def make_signature_nameless(signature):
"""
@@ -174,6 +203,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,26 +240,39 @@ 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:
defaults = ()
- if layout.ellipsis:
- defaults = (ellipsis,) * len(defaults)
annotations = props["annotations"].copy()
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
+ if default is None:
+ ann = typing.Optional[ann]
+ if default is not _empty and layout.ellipsis:
+ default = ellipsis
+ 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..f11f3cf3d 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
@@ -64,61 +64,109 @@ class ExactEnumerator(object):
"""
def __init__(self, formatter, result_type=dict):
+ global EnumType
+ try:
+ # Lazy import
+ from PySide2.QtCore import Qt
+ EnumType = type(Qt.Key)
+ except ImportError:
+ EnumType = None
+
self.fmt = formatter
self.result_type = result_type
+ self.fmt.level = 0
+ self.fmt.after_enum = self.after_enum
+ self._after_enum = False
+
+ def after_enum(self):
+ ret = self._after_enum
+ self._after_enum = False
def module(self, mod_name):
__import__(mod_name)
+ self.fmt.mod_name = mod_name
with self.fmt.module(mod_name):
module = sys.modules[mod_name]
members = inspect.getmembers(module, inspect.isclass)
functions = inspect.getmembers(module, inspect.isroutine)
ret = self.result_type()
self.fmt.class_name = None
- for func_name, func in functions:
- ret.update(self.function(func_name, func))
for class_name, klass in members:
ret.update(self.klass(class_name, klass))
+ if isinstance(klass, EnumType):
+ raise SystemError("implement enum instances at module level")
+ for func_name, func in functions:
+ ret.update(self.function(func_name, func))
return ret
def klass(self, class_name, klass):
- if not "Shiboken" in repr(klass.mro()):
- # don't look into any foreign classes!
- ret = self.result_type()
- return ret
bases_list = []
for base in klass.__bases__:
name = base.__name__
- if name == "object":
+ if name in ("object", "type"):
pass
else:
modname = base.__module__
name = modname + "." + base.__name__
bases_list.append(name)
class_str = "{}({})".format(class_name, ", ".join(bases_list))
+ ret = self.result_type()
+ # class_members = inspect.getmembers(klass)
+ # gives us also the inherited things.
+ class_members = sorted(list(klass.__dict__.items()))
+ subclasses = []
+ functions = []
+ enums = []
+
+ for thing_name, thing in class_members:
+ if inspect.isclass(thing):
+ subclass_name = ".".join((class_name, thing_name))
+ subclasses.append((subclass_name, thing))
+ elif inspect.isroutine(thing):
+ func_name = thing_name.split(".")[0] # remove ".overload"
+ signature = getattr(thing, "__signature__", None)
+ if signature is not None:
+ functions.append((func_name, thing))
+ elif type(type(thing)) is EnumType:
+ enums.append((thing_name, thing))
+ init_signature = getattr(klass, "__signature__", None)
+ enums.sort(key=lambda tup: tup[1]) # sort by enum value
+ self.fmt.have_body = bool(subclasses or functions or enums or init_signature)
+
with self.fmt.klass(class_name, class_str):
- ret = self.function("__init__", klass)
- # class_members = inspect.getmembers(klass)
- # gives us also the inherited things.
- class_members = sorted(list(klass.__dict__.items()))
- subclasses = []
- for thing_name, thing in class_members:
- if inspect.isclass(thing):
- subclass_name = ".".join((class_name, thing_name))
- subclasses.append((subclass_name, thing))
- else:
- func_name = thing_name.split(".")[0] # remove ".overload"
- ret.update(self.function(func_name, thing))
+ self.fmt.level += 1
+ self.fmt.class_name = class_name
+ if hasattr(self.fmt, "enum"):
+ # this is an optional feature
+ for enum_name, value in enums:
+ with self.fmt.enum(class_name, enum_name, int(value)):
+ pass
for subclass_name, subclass in subclasses:
+ if klass == subclass:
+ # this is a side effect of the typing module for Python 2.7
+ # via the "._gorg" property, which we can safely ignore.
+ print("Warning: {class_name} points to itself via {subclass_name}, skipped!"
+ .format(**locals()))
+ continue
ret.update(self.klass(subclass_name, subclass))
- return ret
+ self.fmt.class_name = class_name
+ ret.update(self.function("__init__", klass))
+ for func_name, func in functions:
+ func_kind = get_signature(func, "__func_kind__")
+ modifier = func_kind if func_kind in (
+ "staticmethod", "classmethod") else None
+ ret.update(self.function(func_name, func, modifier))
+ self.fmt.level -= 1
+ return ret
- def function(self, func_name, func):
+ def function(self, func_name, func, modifier=None):
+ self.fmt.level += 1
ret = self.result_type()
- signature = getattr(func, '__signature__', None)
+ signature = func.__signature__
if signature is not None:
- with self.fmt.function(func_name, signature) as key:
+ with self.fmt.function(func_name, signature, modifier) as key:
ret[key] = signature
+ self.fmt.level -= 1
return ret
@@ -142,7 +190,7 @@ class SimplifyingEnumerator(ExactEnumerator):
is desired.
"""
- def function(self, func_name, func):
+ def function(self, func_name, func, modifier=None):
ret = self.result_type()
signature = get_signature(func, 'existence')
sig = stringify(signature) if signature is not None else None
@@ -159,11 +207,11 @@ class HintingEnumerator(ExactEnumerator):
hinting stubs. Only default values are replaced by "...".
"""
- def function(self, func_name, func):
+ def function(self, func_name, func, modifier=None):
ret = self.result_type()
signature = get_signature(func, 'hintingstub')
if signature is not None:
- with self.fmt.function(func_name, signature) as key:
+ with self.fmt.function(func_name, signature, modifier) as key:
ret[key] = signature
return ret
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
index b34bfb404..3b0825049 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
@@ -43,6 +43,8 @@ from __future__ import print_function, absolute_import
tool.py
Some useful stuff, see below.
+On the function with_metaclass see the answer from Martijn Pieters on
+https://stackoverflow.com/questions/18513821/python-metaclass-understanding-the-with-metaclass
"""
from textwrap import dedent
@@ -132,4 +134,21 @@ def build_brace_pattern(level, separators=""):
indent = idx * " ", **locals())
return pattern.replace("C", "{").replace("D", "}")
+
+# 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', (), {})
+
# eof
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
index 3d25c5690..a0367883a 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py
@@ -85,20 +85,6 @@ def formatannotation(annotation, base_module=None):
return annotation.__module__ + '.' + annotation.__qualname__
return repr(annotation)
-# patching __repr__ to disable the __repr__ of typing.TypeVar:
-"""
- def __repr__(self):
- if self.__covariant__:
- prefix = '+'
- elif self.__contravariant__:
- prefix = '-'
- else:
- prefix = '~'
- return prefix + self.__name__
-"""
-def _typevar__repr__(self):
- return "typing." + self.__name__
-
# Note also that during the tests we have a different encoding that would
# break the Python license decorated files without an encoding line.
@@ -160,12 +146,18 @@ def list_modules(message):
print(" {:23}".format(name), repr(module)[:70])
+orig_typing = True
if sys.version_info >= (3,):
import typing
import inspect
inspect.formatannotation = formatannotation
else:
- from shibokensupport import typing27 as typing
+ if "typing" not in sys.modules:
+ orig_typing = False
+ from shibokensupport import typing27 as typing
+ sys.modules["typing"] = typing
+ else:
+ import typing
import inspect
namespace = inspect.__dict__
from shibokensupport import backport_inspect as inspect
@@ -174,7 +166,6 @@ else:
inspect.__doc__ += _doc
# force inspect to find all attributes. See "heuristic" in pydoc.py!
inspect.__all__ = list(x for x in dir(inspect) if not x.startswith("_"))
-typing.TypeVar.__repr__ = _typevar__repr__
# Fix the module names in typing if possible. This is important since
# the typing names should be I/O compatible, so that typing.Dict
@@ -206,7 +197,7 @@ def move_into_pyside_package():
put_into_package(PySide2.support.signature, importhandler)
put_into_package(PySide2.support.signature.lib, enum_sig)
- put_into_package(PySide2.support.signature, typing)
+ put_into_package(None if orig_typing else PySide2.support.signature, typing)
put_into_package(PySide2.support.signature, inspect)
from shibokensupport.signature import mapping
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 5d6a24016..2110ebe7a 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -55,6 +55,7 @@ import os
from shibokensupport.signature import typing
from shibokensupport.signature.typing import TypeVar, Generic
+from shibokensupport.signature.lib.tool import with_metaclass
class ellipsis(object):
def __repr__(self):
@@ -66,27 +67,15 @@ Variant = typing.Any
ModelIndexList = typing.List[int]
QImageCleanupFunction = typing.Callable
+# 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
# 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__)
@@ -208,7 +197,7 @@ class _Parameterized(object):
class ResultVariable(_Parameterized):
pass
-# Mark the primitive variables to become Sequence, Iterator or List
+# Mark the primitive variables to become Sequence, Iterable or List
# (decided in the parser).
class ArrayLikeVariable(_Parameterized):
pass
@@ -275,6 +264,7 @@ type_map = {}
namespace = globals() # our module's __dict__
type_map.update({
+ "...": ellipsis,
"bool": bool,
"char": Char,
"char*": str,
@@ -337,6 +327,7 @@ type_map.update({
"unsigned long": int,
"unsigned short int": int, # 5.6, RHEL 6.6
"unsigned short": int,
+ "Unspecified": None,
"ushort": int,
"void": int, # be more specific?
"WId": WId,
@@ -357,6 +348,7 @@ type_map.update({
"array GLuint*" : ArrayLikeVariable(int),
"array int*" : ArrayLikeVariable(int),
"array long long*" : ArrayLikeVariable(int),
+ "array long*" : ArrayLikeVariable(int),
"array short*" : ArrayLikeVariable(int),
"array signed char*" : bytes,
"array unsigned char*" : bytes,
@@ -420,6 +412,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 204f37384..8d970956b 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -106,7 +106,8 @@ def _parse_line(line):
$
"""
ret = SimpleNamespace(**re.match(line_re, line, re.VERBOSE).groupdict())
- argstr = ret.arglist
+ # PYSIDE-1095: Handle arbitrary default expressions
+ argstr = ret.arglist.replace("->", ".deref.")
arglist = _parse_arglist(argstr)
args = []
for arg in arglist:
@@ -116,7 +117,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,7 +168,7 @@ 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
map = type_map[valtype]
# typing.Any: '_SpecialForm' object has no attribute '__name__'
@@ -315,9 +316,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, handle_argvar)