aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py73
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp7
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp26
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py37
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py45
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py19
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py15
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py17
8 files changed, 161 insertions, 78 deletions
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
index 8aa69c983..d5bbe5d7c 100644
--- a/sources/pyside2/PySide2/support/generate_pyi.py
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -100,6 +100,38 @@ class Formatter(Writer):
The separation in formatter and enumerator is done to keep the
unrelated tasks of enumeration and formatting apart.
"""
+ def __init__(self, *args):
+ Writer.__init__(self, *args)
+ # 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__
+ typing.TypeVar.__repr__ = _typevar__repr__
+
+ # Adding a pattern to substitute "Union[T, NoneType]" by "Optional[T]"
+ # I tried hard to replace typing.Optional by a simple override, but
+ # this became _way_ too much.
+ # See also the comment in layout.py .
+ brace_pat = build_brace_pattern(3)
+ pattern = (r"\b Union \s* \[ \s* {brace_pat} \s*, \s* NoneType \s* \]"
+ .format(**locals()))
+ replace = r"Optional[\1]"
+ optional_searcher = re.compile(pattern, flags=re.VERBOSE)
+ def optional_replacer(source):
+ return optional_searcher.sub(replace, str(source))
+ self.optional_replacer = optional_replacer
+ # self.level is maintained by enum_sig.py
+ # self.after_enum() is a one-shot set by enum_sig.py .
+
@contextmanager
def module(self, mod_name):
self.mod_name = mod_name
@@ -121,26 +153,21 @@ class Formatter(Writer):
@contextmanager
def klass(self, class_name, class_str):
- self.class_name = class_name
- spaces = ""
+ spaces = indent * self.level
while "." in class_name:
- spaces += indent
class_name = class_name.split(".", 1)[-1]
class_str = class_str.split(".", 1)[-1]
self.print()
- if not spaces:
+ if self.level == 0:
self.print()
here = self.outfile.tell()
self.print("{spaces}class {class_str}:".format(**locals()))
- self.print()
pos = self.outfile.tell()
- self.spaces = spaces
yield
if pos == self.outfile.tell():
# we have not written any function
self.outfile.seek(here)
self.outfile.truncate()
- # Note: we cannot use class_str when we have no body.
self.print("{spaces}class {class_str}: ...".format(**locals()))
if "<" in class_name:
# This is happening in QtQuick for some reason:
@@ -150,29 +177,32 @@ class Formatter(Writer):
self.outfile.truncate()
@contextmanager
- def function(self, func_name, signature):
+ def function(self, func_name, signature, modifier=None):
+ if self.after_enum() or func_name == "__init__":
+ self.print()
key = func_name
- spaces = indent + self.spaces if self.class_name else ""
+ spaces = indent * self.level
if type(signature) == type([]):
for sig in signature:
self.print('{spaces}@typing.overload'.format(**locals()))
- self._function(func_name, sig, spaces)
+ self._function(func_name, sig, modifier, spaces)
else:
- self._function(func_name, signature, spaces)
+ self._function(func_name, signature, modifier, spaces)
+ if func_name == "__init__":
+ self.print()
yield key
- def _function(self, func_name, signature, spaces):
- # this would be nicer to get somehow together with the signature
- is_meth = re.match(r"\((\w*)", str(signature)).group(1) == "self"
- if self.class_name and not is_meth:
- self.print('{spaces}@staticmethod'.format(**locals()))
+ def _function(self, func_name, signature, modifier, spaces):
+ if modifier:
+ self.print('{spaces}@{modifier}'.format(**locals()))
+ signature = self.optional_replacer(signature)
self.print('{spaces}def {func_name}{signature}: ...'.format(**locals()))
@contextmanager
def enum(self, class_name, enum_name, value):
- spaces = self.spaces
+ spaces = indent * self.level
hexval = hex(value)
- self.print("{spaces}{enum_name:20}: {class_name} = ... # {hexval}".format(**locals()))
+ self.print("{spaces}{enum_name:25}: {class_name} = ... # {hexval}".format(**locals()))
yield
@@ -254,10 +284,11 @@ def generate_all_pyi(outpath, options):
os.environ["PYTHONPATH"] = pypath
# now we can import
- global PySide2, inspect, HintingEnumerator, EnumType
+ global PySide2, inspect, typing, HintingEnumerator, build_brace_pattern
import PySide2
- from PySide2.support.signature import inspect
- from PySide2.support.signature.lib.enum_sig import HintingEnumerator, EnumType
+ from PySide2.support.signature import inspect, typing
+ from PySide2.support.signature.lib.enum_sig import HintingEnumerator
+ from PySide2.support.signature.lib.tool import build_brace_pattern
# propagate USE_PEP563 to the mapping module.
# Perhaps this can be automated?
diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp
index 71fcf5f64..2dc785884 100644
--- a/sources/shiboken2/libshiboken/sbkenum.cpp
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -412,6 +412,13 @@ PyTypeObject *createScopedEnum(SbkObjectType *scope, const char *name, const cha
static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue)
{
+ char mangled[20];
+ if (strcmp(itemName, "None") == 0
+ || strcmp(itemName, "False") == 0 || strcmp(itemName, "True") == 0) {
+ strcpy(mangled, itemName);
+ strcat(mangled, "_");
+ itemName = mangled;
+ }
PyObject *enumItem = newItem(enumType, itemValue, itemName);
if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0)
return nullptr;
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index 2cade65e0..0afdbcdc9 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -99,7 +99,7 @@ CreateSignature(PyObject *props, PyObject *key)
{
/*
* Here is the new function to create all signatures. It simply calls
- * into Python and creates a signature object for a dummy-function.
+ * into Python and creates a signature object directly.
* This is so much simpler than using all the attributes explicitly
* to support '_signature_is_functionlike()'.
*/
@@ -313,7 +313,7 @@ pyside_tp_get___signature__(PyObject *obtype_mod, const char *modifier)
// forward
static PyObject *
-GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier);
+GetSignature_Cached(PyObject *props, const char *func_kind, const char *modifier);
static PyObject *
GetTypeKey(PyObject *ob)
@@ -381,16 +381,16 @@ GetSignature_Function(PyObject *obfunc, const char *modifier)
Py_RETURN_NONE;
int flags = PyCFunction_GET_FLAGS(obfunc);
- const char *sig_kind;
+ const char *func_kind;
if (PyModule_Check(obtype_mod))
- sig_kind = "function";
+ func_kind = "function";
else if (flags & METH_CLASS)
- sig_kind = "classmethod";
+ func_kind = "classmethod";
else if (flags & METH_STATIC)
- sig_kind = "staticmethod";
+ func_kind = "staticmethod";
else
- sig_kind = "method";
- return GetSignature_Cached(props, sig_kind, modifier);
+ func_kind = "method";
+ return GetSignature_Cached(props, func_kind, modifier);
}
static PyObject *
@@ -427,11 +427,15 @@ GetSignature_TypeMod(PyObject *ob, const char *modifier)
}
static PyObject *
-GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier)
+GetSignature_Cached(PyObject *props, const char *func_kind, const char *modifier)
{
+ // Special case: We want to know the func_kind.
+ if (modifier && strcmp(modifier, "__func_kind__") == 0)
+ return Py_BuildValue("s", func_kind);
+
Shiboken::AutoDecRef key(modifier == nullptr
- ? Py_BuildValue("s", sig_kind)
- : Py_BuildValue("(ss)", sig_kind, modifier));
+ ? Py_BuildValue("s", func_kind)
+ : Py_BuildValue("(ss)", func_kind, modifier));
PyObject *value = PyDict_GetItem(props, key);
if (value == nullptr) {
// we need to compute a signature object
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index af8ada065..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):
"""
@@ -217,8 +246,6 @@ def create_signature(props, key):
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"]
@@ -235,6 +262,10 @@ def create_signature(props, key):
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:
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 42b123046..b026a5d20 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
@@ -71,6 +71,13 @@ class ExactEnumerator(object):
def __init__(self, formatter, result_type=dict):
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)
@@ -80,10 +87,12 @@ class ExactEnumerator(object):
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):
+ self.enum(klass)
+ for func_name, func in functions:
+ ret.update(self.function(func_name, func))
return ret
def klass(self, class_name, klass):
@@ -95,7 +104,7 @@ class ExactEnumerator(object):
bases_list = []
for base in klass.__bases__:
name = base.__name__
- if name == "object":
+ if name in ("object", "type"):
pass
else:
modname = base.__module__
@@ -103,30 +112,41 @@ class ExactEnumerator(object):
bases_list.append(name)
class_str = "{}({})".format(class_name, ", ".join(bases_list))
with self.fmt.klass(class_name, class_str):
- ret = self.function("__init__", klass)
+ ret = self.result_type()
# class_members = inspect.getmembers(klass)
# gives us also the inherited things.
class_members = sorted(list(klass.__dict__.items()))
subclasses = []
+ functions = []
for thing_name, thing in class_members:
if inspect.isclass(thing):
subclass_name = ".".join((class_name, thing_name))
subclasses.append((subclass_name, thing))
- else:
+ elif inspect.isroutine(thing):
func_name = thing_name.split(".")[0] # remove ".overload"
- ret.update(self.function(func_name, thing))
+ functions.append((func_name, thing))
+ self.fmt.level += 1
for subclass_name, subclass in subclasses:
ret.update(self.klass(subclass_name, subclass))
if isinstance(subclass, EnumType):
self.enum(subclass)
- return ret
+ ret = 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)
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
def enum(self, subclass):
@@ -138,6 +158,7 @@ class ExactEnumerator(object):
if type(type(value)) is EnumType:
with self.fmt.enum(class_name, enum_name, int(value)):
pass
+ self._after_enum = True
def stringify(signature):
@@ -160,7 +181,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
@@ -177,11 +198,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 8192f9bca..8eff19d77 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.
@@ -171,7 +157,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
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 10d0f16ad..163aac851 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):
@@ -76,22 +77,6 @@ _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__)