aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2018-07-14 15:10:56 +0200
committerChristian Tismer <tismer@stackless.com>2018-11-24 10:31:02 +0000
commitb92fb6e81be252a2ffae26768434028c5029ddc7 (patch)
tree88338bea02faff38ac986ba9d39c24d17670f795
parent4413f505ebcc39882ab7052488b37e38300b5219 (diff)
Split The Signature Module After The Project Split
The PySide project has been split into three pieces, including Shiboken. This had far-reaching consequences for the signature project. Shiboken can be run together with PySide or alone, with tests or without. In every configuration, the signature module has to work correctly. During tests, the shiboken binary also hides the shiboken module, and we had to use extra efforts to always guarantee the accessibility of all signature modules. This commit is the preparation for typeerrors implemented with the signature module. It has been split off because the splitting is not directly related, besides these unawaited consequences. I re-added and corrected voidptr_test and simplified the calls. Remark.. We should rename shiboken to Shiboken in all imports. I also simplified initialization. After "from PySide2 import QtCore", now a simple access like "type.__signature__" triggers initialization. Further, I removed all traces of "signature_loader" and allowed loading everything from PySide2.support.signature, again. The loader is now needed internally, only. Also, moved the type patching into FinishSignatureInitialization to support modules with no classes at all. The "testbinding" problem was finally identified as a name clash when the same function is also a signal. A further investigation showed that there exists also a regular PySide method with that problem. The test was extended to all methods, and it maps now all these cases to "{name}.overload". Updated the included typing27.py from https://pypi.org/project/typing/ from version 3.6.2 to version 3.6.6 . Task-number: PYSIDE-749 Change-Id: Ie33b8c6b0df5640212f8991539088593a041a05c Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--sources/pyside2/PySide2/CMakeLists.txt35
-rw-r--r--sources/pyside2/PySide2/support/__init__.py10
-rw-r--r--sources/pyside2/PySide2/support/signature/__init__.py10
-rw-r--r--sources/pyside2/PySide2/support/signature/layout.py205
-rw-r--r--sources/pyside2/PySide2/support/signature/lib/enum_sig.py129
-rw-r--r--sources/pyside2/PySide2/support/signature/mapping.py125
-rw-r--r--sources/pyside2/tests/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtWidgets/qlabel_test.py9
-rw-r--r--sources/pyside2/tests/QtWidgets/qstandarditemmodel_test.py9
-rw-r--r--sources/pyside2/tests/registry/existence_test.py2
-rw-r--r--sources/pyside2/tests/registry/init_platform.py1
-rw-r--r--sources/pyside2/tests/support/voidptr_test.py4
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.cpp26
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h2
-rw-r--r--sources/shiboken2/libshiboken/pep384impl_doc.rst4
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp101
-rw-r--r--sources/shiboken2/shibokenmodule/CMakeLists.txt27
-rw-r--r--sources/shiboken2/shibokenmodule/support/__init__.py40
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/PSF-3.7.0.txt (renamed from sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt)0
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/__init__.py (renamed from sources/pyside2/PySide2/support/signature/loader.py)51
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/backport_inspect.py (renamed from sources/pyside2/PySide2/support/signature/backport_inspect.py)0
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py (renamed from sources/pyside2/PySide2/support/signature/fix-complaints.py)0
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/layout.py245
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/lib/__init__.py40
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py135
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/loader.py176
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/mapping.py199
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/parser.py (renamed from sources/pyside2/PySide2/support/signature/parser.py)3
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/qt_attribution.json (renamed from sources/pyside2/PySide2/support/signature/qt_attribution.json)0
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/typing27.py (renamed from sources/pyside2/PySide2/support/signature/typing27.py)117
30 files changed, 1063 insertions, 643 deletions
diff --git a/sources/pyside2/PySide2/CMakeLists.txt b/sources/pyside2/PySide2/CMakeLists.txt
index 4709dd073..a101538e3 100644
--- a/sources/pyside2/PySide2/CMakeLists.txt
+++ b/sources/pyside2/PySide2/CMakeLists.txt
@@ -6,9 +6,21 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/global.h.in"
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in"
"${CMAKE_CURRENT_BINARY_DIR}/__init__.py" @ONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/layout.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/layout.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/mapping.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/mapping.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/enum_sig.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/enum_sig.py" COPYONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/_config.py.in"
- "${CMAKE_CURRENT_BINARY_DIR}/_config.py" @ONLY)
+ "${CMAKE_CURRENT_BINARY_DIR}/_config.py" @ONLY)
# Use absolute path instead of relative path, to avoid ninja build errors due to
# duplicate file dependency inconsistency.
@@ -38,27 +50,6 @@ endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/__init__.py"
"${CMAKE_CURRENT_BINARY_DIR}/support/__init__.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/__init__.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/__init__.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/layout.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/layout.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/loader.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/loader.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/mapping.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/mapping.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/parser.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/parser.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/__init__.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/__init__.py" COPYONLY)
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/enum_sig.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/enum_sig.py" COPYONLY)
-if (PYTHON_VERSION_MAJOR EQUAL 3)
-else()
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/backport_inspect.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/backport_inspect.py" COPYONLY)
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/typing27.py"
- "${CMAKE_CURRENT_BINARY_DIR}/support/signature/typing.py" COPYONLY)
-endif()
# now compile all modules.
file(READ "${CMAKE_CURRENT_BINARY_DIR}/pyside2_global.h" pyside2_global_contents)
diff --git a/sources/pyside2/PySide2/support/__init__.py b/sources/pyside2/PySide2/support/__init__.py
index 18abd9d0e..dda01474d 100644
--- a/sources/pyside2/PySide2/support/__init__.py
+++ b/sources/pyside2/PySide2/support/__init__.py
@@ -37,12 +37,4 @@
##
#############################################################################
-# Import VoidPtr type to expose it under PySide2.support.VoidPtr
-try:
- # The normal import statement when PySide2 is installed.
- from PySide2.shiboken2 import VoidPtr
-except ImportError:
- # When running make test in shiboken build dir, or when running testrunner.py,
- # shiboken2 is not part of the PySide2 module, so it needs to be imported as a standalone
- # module.
- from shiboken2 import VoidPtr
+from shiboken2 import VoidPtr
diff --git a/sources/pyside2/PySide2/support/signature/__init__.py b/sources/pyside2/PySide2/support/signature/__init__.py
index 49224bf92..d587a4d62 100644
--- a/sources/pyside2/PySide2/support/signature/__init__.py
+++ b/sources/pyside2/PySide2/support/signature/__init__.py
@@ -39,8 +39,8 @@
from __future__ import print_function, absolute_import
-from .loader import inspect
-from PySide2 import QtCore
-if QtCore.QProcess.__signature__:
- pass # trigger initialization phase 2, so we can import:
-from signature_loader import get_signature
+# Trigger initialization phase 2.
+_ = type.__signature__
+from signature_loader import get_signature, inspect
+
+__all__ = "get_signature inspect layout mapping lib".split()
diff --git a/sources/pyside2/PySide2/support/signature/layout.py b/sources/pyside2/PySide2/support/signature/layout.py
index e18cb2172..c8a4062cb 100644
--- a/sources/pyside2/PySide2/support/signature/layout.py
+++ b/sources/pyside2/PySide2/support/signature/layout.py
@@ -39,207 +39,4 @@
from __future__ import print_function, absolute_import
-"""
-layout.py
-
-The signature module now has the capability to configure
-differently formatted versions of signatures. The default
-layout is known from the "__signature__" attribute.
-
-The function "get_signature(ob, modifier=None)" produces the same
-signatures by default. By passing different modifiers, you
-can select different layouts.
-
-This module configures the different layouts which can be used.
-It also implements them in this file. The configurations are
-used literally as strings like "signature", "existence", etc.
-"""
-
-from textwrap import dedent
-from .loader import inspect
-
-
-class SimpleNamespace(object):
- # From types.rst, because the builtin is implemented in Python 3, only.
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
-
- def __repr__(self):
- keys = sorted(self.__dict__)
- items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
- return "{}({})".format(type(self).__name__, ", ".join(items))
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
-
-class SignatureLayout(SimpleNamespace):
- """
- Configure a signature.
-
- The layout of signatures can have different layouts which are
- controlled by keyword arguments:
-
- definition=True Determines if self will generated.
- defaults=True
- ellipsis=False Replaces defaults by "...".
- return_annotation=True
- parameter_names=True False removes names before ":".
- """
- allowed_keys = SimpleNamespace(definition=True,
- defaults=True,
- ellipsis=False,
- return_annotation=True,
- parameter_names=True)
- allowed_values = True, False
-
- def __init__(self, **kwds):
- args = SimpleNamespace(**self.allowed_keys.__dict__)
- args.__dict__.update(kwds)
- self.__dict__.update(args.__dict__)
- err_keys = list(set(self.__dict__) - set(self.allowed_keys.__dict__))
- if err_keys:
- self._attributeerror(err_keys)
- err_values = list(set(self.__dict__.values()) - set(self.allowed_values))
- if err_values:
- self._valueerror(err_values)
-
- def __setattr__(self, key, value):
- if key not in self.allowed_keys.__dict__:
- self._attributeerror([key])
- if value not in self.allowed_values:
- self._valueerror([value])
- self.__dict__[key] = value
-
- def _attributeerror(self, err_keys):
- err_keys = ", ".join(err_keys)
- allowed_keys = ", ".join(self.allowed_keys.__dict__.keys())
- raise AttributeError(dedent("""\
- Not allowed: '{err_keys}'.
- The only allowed keywords are '{allowed_keys}'.
- """.format(**locals())))
-
- def _valueerror(self, err_values):
- err_values = ", ".join(map(str, err_values))
- allowed_values = ", ".join(map(str, self.allowed_values))
- raise ValueError(dedent("""\
- Not allowed: '{err_values}'.
- The only allowed values are '{allowed_values}'.
- """.format(**locals())))
-
-# The following names are used literally in this module.
-# This way, we avoid the dict hashing problem.
-signature = SignatureLayout()
-
-existence = SignatureLayout(definition=False,
- defaults=False,
- return_annotation=False,
- parameter_names=False)
-
-hintingstub = SignatureLayout(ellipsis=True)
-
-typeerror = SignatureLayout(definition=False,
- return_annotation=False,
- parameter_names=False)
-
-
-def define_nameless_parameter():
- """
- Create Nameless Parameters
-
- A nameless parameter has a reduced string representation.
- This is done by cloning the parameter type and overwriting its
- __str__ method. The inner structure is still a valid parameter.
- """
- def __str__(self):
- # for Python 2, we must change self to be an instance of P
- klass = self.__class__
- self.__class__ = P
- txt = P.__str__(self)
- self.__class__ = klass
- txt = txt[txt.index(":") + 1:].strip() if ":" in txt else txt
- return txt
-
- P = inspect.Parameter
- newname = "NamelessParameter"
- bases = P.__bases__
- body = dict(P.__dict__) # get rid of mappingproxy
- if "__slots__" in body:
- # __slots__ would create duplicates
- for name in body["__slots__"]:
- del body[name]
- body["__str__"] = __str__
- return type(newname, bases, body)
-
-
-NamelessParameter = define_nameless_parameter()
-
-
-def make_signature_nameless(signature):
- """
- Make a Signature Nameless
-
- We use an existing signature and change the type of its parameters.
- The signature looks different, but is totally intact.
- """
- for key in signature.parameters.keys():
- signature.parameters[key].__class__ = NamelessParameter
-
-
-def create_signature(props, key):
- if not props:
- # empty signatures string
- return
- if isinstance(props["multi"], list):
- # multi sig: call recursively
- return list(create_signature(elem, key)
- for elem in props["multi"])
- if type(key) is tuple:
- sig_kind, modifier = key
- else:
- sig_kind, modifier = key, "signature"
-
- layout = globals()[modifier] # lookup of the modifier in this module
- if not isinstance(layout, SignatureLayout):
- raise SystemError("Modifiers must be names of a SignatureLayout "
- "instance")
-
- # this is the basic layout of a signature
- varnames = props["varnames"]
- if layout.definition:
- if sig_kind == "function":
- pass
- elif sig_kind == "method":
- varnames = ("self",) + varnames
- elif sig_kind == "staticmethod":
- pass
- elif sig_kind == "classmethod":
- varnames = ("klass",) + varnames
- else:
- 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 = ("...",) * 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)
-
- # the special case of nameless parameters
- if not layout.parameter_names:
- make_signature_nameless(sig)
- return sig
-
-# end of file
+from signature_loader.layout import *
diff --git a/sources/pyside2/PySide2/support/signature/lib/enum_sig.py b/sources/pyside2/PySide2/support/signature/lib/enum_sig.py
index c043f04f8..1d19ad5e4 100644
--- a/sources/pyside2/PySide2/support/signature/lib/enum_sig.py
+++ b/sources/pyside2/PySide2/support/signature/lib/enum_sig.py
@@ -39,131 +39,4 @@
from __future__ import print_function, absolute_import
-import sys
-from PySide2.support.signature import inspect, get_signature
-
-
-class ExactEnumerator(object):
- """
- ExactEnumerator enumerates all signatures in a module as they are.
-
- This class is used for generating complete listings of all signatures.
- An appropriate formatter should be supplied, if printable output
- is desired.
- """
- def __init__(self, formatter, result_type=dict):
- self.fmt = formatter
- self.result_type = result_type
-
- def module(self, mod_name):
- __import__(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))
- return ret
-
- def klass(self, class_name, klass):
- bases_list = []
- for base in klass.__bases__:
- name = base.__name__
- if name == "object":
- pass
- else:
- modname = base.__module__
- name = modname + "." + base.__name__
- 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)
- # 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:
- ret.update(self.function(thing_name, thing))
- for subclass_name, subclass in subclasses:
- ret.update(self.klass(subclass_name, subclass))
- return ret
-
- def function(self, func_name, func):
- ret = self.result_type()
- signature = getattr(func, '__signature__', None)
- if signature is not None:
- with self.fmt.function(func_name, signature) as key:
- ret[key] = signature
- return ret
-
-
-def simplify(signature):
- if isinstance(signature, list):
- # remove duplicates which still sometimes occour:
- ret = set(simplify(sig) for sig in signature)
- return sorted(ret) if len(ret) > 1 else list(ret)[0]
- ret = []
- for pv in signature.parameters.values():
- txt = str(pv)
- if ":" not in txt: # 'self' or '*args'
- continue
- txt = txt[txt.index(":") + 1:]
- if "=" in txt:
- txt = txt[:txt.index("=")]
- quote = txt[0]
- if quote in ("'", '"') and txt[-1] == quote:
- txt = txt[1:-1]
- ret.append(txt.strip())
- return tuple(ret)
-
-
-### disabled for now:
-class SimplifyingEnumerator(ExactEnumerator):
- """
- SimplifyingEnumerator enumerates all signatures in a module filtered.
-
- There are no default values, no variable
- names and no self parameter. Only types are present after simplification.
- The functions 'next' resp. '__next__' are removed
- to make the output identical for Python 2 and 3.
- An appropriate formatter should be supplied, if printable output
- is desired.
- """
-
- def function(self, func_name, func):
- ret = self.result_type()
- signature = get_signature(func, 'existence')
- if signature is not None and func_name not in ("next", "__next__"):
- with self.fmt.function(func_name, signature) as key:
- ret[key] = str(signature)
- return ret
-
-
-class SimplifyingEnumerator(ExactEnumerator):
- """
- SimplifyingEnumerator enumerates all signatures in a module filtered.
-
- There are no default values, no variable
- names and no self parameter. Only types are present after simplification.
- The functions 'next' resp. '__next__' are removed
- to make the output identical for Python 2 and 3.
- An appropriate formatter should be supplied, if printable output
- is desired.
- """
-
- def function(self, func_name, func):
- ret = self.result_type()
- signature = getattr(func, '__signature__', None)
- sig = simplify(signature) if signature is not None else None
- if sig is not None and func_name not in ("next", "__next__", "__div__"):
- with self.fmt.function(func_name, sig) as key:
- ret[key] = sig
- return ret
+from signature_loader.enum_sig import *
diff --git a/sources/pyside2/PySide2/support/signature/mapping.py b/sources/pyside2/PySide2/support/signature/mapping.py
index 23ba6a7f1..15727cb6a 100644
--- a/sources/pyside2/PySide2/support/signature/mapping.py
+++ b/sources/pyside2/PySide2/support/signature/mapping.py
@@ -47,115 +47,23 @@ to the Python representation.
The PySide modules are not loaded in advance, but only after they appear
in sys.modules. This minimizes the loading overhead.
-In principle, we need to re-load the module, when the imports change.
-But it is much easier to do it on demand, when we get an exception.
-See _resolve_value() in singature.py
"""
-import sys
-import struct
import PySide2
-try:
- import sample
-except ImportError:
- pass
-
-try:
- from . import typing
-except ImportError:
- 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]
-IntMatrix = typing.List[IntList]
-Variant = typing.Any
-ModelIndexList = typing.List[int]
-QImageCleanupFunction = typing.Callable
-FloatList = typing.List[float]
-FloatMatrix = typing.List[FloatList]
-# 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]]
-
-# 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
-
-GL_COLOR_BUFFER_BIT = 0x00004000
-GL_NEAREST = 0x2600
-
-WId = int
-# from 5.9
-GL_TEXTURE_2D = 0x0DE1
-GL_RGBA = 0x1908
-
-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):
- 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(_NotCalled):
- pass
-
-class Invalid(_NotCalled):
- pass
+from signature_loader.sbk_mapping import *
-# Helper types
-class Default(_NotCalled):
- pass
+Sbk_Reloader = Reloader
-class Instance(_NotCalled):
- pass
-
-
-class Reloader(object):
- def __init__(self):
- self.sys_module_count = 0
- self.uninitialized = PySide2.__all__[:] + ["sample"]
+class Reloader(Sbk_Reloader):
+ _uninitialized = Sbk_Reloader._uninitialized + PySide2.__all__
+ _prefixes = Sbk_Reloader._prefixes + ["PySide2."]
def update(self):
- if self.sys_module_count == len(sys.modules):
- return
- self.sys_module_count = len(sys.modules)
- g = globals()
- for mod_name in self.uninitialized[:]:
- if "PySide2." + mod_name in sys.modules or mod_name == "sample":
- self.uninitialized.remove(mod_name)
- proc_name = "init_" + mod_name
- if proc_name in g:
- g.update(g[proc_name]())
-
+ Sbk_Reloader.update(self, globals())
update_mapping = Reloader().update
-type_map = {}
+
def init_QtCore():
import PySide2.QtCore
@@ -490,23 +398,4 @@ def init_QtWinExtras():
})
return locals()
-def init_sample():
- type_map.update({
- "sample.int": int,
- "Complex": complex,
- "sample.OddBool": bool,
- "sample.bool": bool,
- "sample.PStr": str,
- "double[]": FloatList,
- "OddBool": bool,
- "PStr": str,
- "sample.char": Char,
- "double[][]": FloatMatrix,
- "int[]": IntList,
- "int[][]": IntMatrix,
- })
- return locals()
-
-# Here was testbinding, actually the source of all evil.
-
# end of file
diff --git a/sources/pyside2/tests/CMakeLists.txt b/sources/pyside2/tests/CMakeLists.txt
index 2386950e9..4289012a8 100644
--- a/sources/pyside2/tests/CMakeLists.txt
+++ b/sources/pyside2/tests/CMakeLists.txt
@@ -54,6 +54,7 @@ else()
endif()
add_subdirectory(registry)
add_subdirectory(signals)
+ add_subdirectory(support)
foreach(shortname IN LISTS all_module_shortnames)
message(STATUS "preparing tests for module 'Qt${shortname}'")
diff --git a/sources/pyside2/tests/QtWidgets/qlabel_test.py b/sources/pyside2/tests/QtWidgets/qlabel_test.py
index 2c5616001..9d84b5c17 100644
--- a/sources/pyside2/tests/QtWidgets/qlabel_test.py
+++ b/sources/pyside2/tests/QtWidgets/qlabel_test.py
@@ -32,14 +32,7 @@ import unittest
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QLabel
-try:
- # The normal import statement when PySide2 is installed.
- from PySide2 import shiboken2 as shiboken
-except ImportError:
- # When running make test in shiboken build dir, or when running
- # testrunner.py, shiboken2 is not part of the PySide2 module,
- # so it needs to be imported as a standalone module.
- import shiboken2 as shiboken
+import shiboken2 as shiboken
from helper import UsesQApplication
diff --git a/sources/pyside2/tests/QtWidgets/qstandarditemmodel_test.py b/sources/pyside2/tests/QtWidgets/qstandarditemmodel_test.py
index 7a34cf238..c07bd8705 100644
--- a/sources/pyside2/tests/QtWidgets/qstandarditemmodel_test.py
+++ b/sources/pyside2/tests/QtWidgets/qstandarditemmodel_test.py
@@ -31,14 +31,7 @@ import sys
from PySide2.QtGui import QStandardItemModel, QStandardItem
from PySide2.QtWidgets import QWidget
-try:
- # The normal import statement when PySide2 is installed.
- from PySide2 import shiboken2 as shiboken
-except ImportError:
- # When running make test in shiboken build dir, or when running testrunner.py,
- # shiboken2 is not part of the PySide2 module, so it needs to be imported as a standalone
- # module.
- import shiboken2 as shiboken
+import shiboken2 as shiboken
from helper import UsesQApplication
diff --git a/sources/pyside2/tests/registry/existence_test.py b/sources/pyside2/tests/registry/existence_test.py
index 6e870385d..0d8014ad8 100644
--- a/sources/pyside2/tests/registry/existence_test.py
+++ b/sources/pyside2/tests/registry/existence_test.py
@@ -130,7 +130,7 @@ class TestSignaturesExists(unittest.TestCase):
warn(msgMultiSignatureCount(key, found_sigs[key], value))
self.assertTrue(check_warnings())
-tested_versions = (5, 6), (5, 9), (5, 11)
+tested_versions = (5, 6), (5, 9), (5, 11) #, (5, 12) # activate this, soon!
if not have_refmodule and is_ci and qtVersion()[:2] in tested_versions:
class TestFor_CI_Init(unittest.TestCase):
diff --git a/sources/pyside2/tests/registry/init_platform.py b/sources/pyside2/tests/registry/init_platform.py
index 66ec6f566..ded8ba81c 100644
--- a/sources/pyside2/tests/registry/init_platform.py
+++ b/sources/pyside2/tests/registry/init_platform.py
@@ -56,7 +56,6 @@ from textwrap import dedent
all_modules = list("PySide2." + x for x in PySide2.__all__)
from PySide2.QtCore import __version__
-
from PySide2.support.signature.lib.enum_sig import SimplifyingEnumerator
is_py3 = sys.version_info[0] == 3
diff --git a/sources/pyside2/tests/support/voidptr_test.py b/sources/pyside2/tests/support/voidptr_test.py
index 8179407e5..330788c63 100644
--- a/sources/pyside2/tests/support/voidptr_test.py
+++ b/sources/pyside2/tests/support/voidptr_test.py
@@ -27,7 +27,7 @@
#############################################################################
import unittest
-from PySide2 import shiboken2
+import shiboken2 as shiboken
from PySide2.support import VoidPtr
from PySide2.QtCore import QByteArray
@@ -40,7 +40,7 @@ class PySide2Support(unittest.TestCase):
# or another VoidPtr object.
ba = QByteArray(b"Hello world")
voidptr = VoidPtr(ba)
- self.assertIsInstance(voidptr, shiboken2.VoidPtr)
+ self.assertIsInstance(voidptr, shiboken.VoidPtr)
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken2/libshiboken/pep384impl.cpp b/sources/shiboken2/libshiboken/pep384impl.cpp
index 869d09529..7cca03c84 100644
--- a/sources/shiboken2/libshiboken/pep384impl.cpp
+++ b/sources/shiboken2/libshiboken/pep384impl.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "pep384impl.h"
-#include <autodecref.h>
+#include "autodecref.h"
extern "C"
{
@@ -502,7 +502,8 @@ static PyTypeObject *getFunctionType(void)
PyTypeObject *PepStaticMethod_TypePtr = NULL;
-static PyTypeObject *getStaticMethodType(void)
+static PyTypeObject *
+getStaticMethodType(void)
{
// this works for Python 3, only
// "StaticMethodType = type(str.__dict__['maketrans'])\n";
@@ -511,12 +512,31 @@ static PyTypeObject *getStaticMethodType(void)
"StaticMethod_Type = type(spamlist.__dict__['staticmeth'])\n";
return (PyTypeObject *) PepRun_GetResult(prog, "StaticMethod_Type");
}
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *sm_callable;
+ PyObject *sm_dict;
+} staticmethod;
+
+PyObject *
+PyStaticMethod_New(PyObject *callable)
+{
+ staticmethod *sm = (staticmethod *)
+ PyType_GenericAlloc(PepStaticMethod_TypePtr, 0);
+ if (sm != NULL) {
+ Py_INCREF(callable);
+ sm->sm_callable = callable;
+ }
+ return (PyObject *)sm;
+}
#endif // Py_LIMITED_API
#if PY_VERSION_HEX < 0x03000000
PyTypeObject *PepMethodDescr_TypePtr = NULL;
-static PyTypeObject *getMethodDescrType(void)
+static PyTypeObject *
+getMethodDescrType(void)
{
static const char prog[] =
"MethodDescr_Type = type(str.split)\n";
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
index 6649fa95e..78b9defb5 100644
--- a/sources/shiboken2/libshiboken/pep384impl.h
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -63,6 +63,7 @@ extern "C"
*/
#ifdef Py_LIMITED_API
// Why the hell is this useful debugging function not allowed?
+// BTW: When used, it breaks on Windows, intentionally!
LIBSHIBOKEN_API void _PyObject_Dump(PyObject *);
#endif
@@ -467,6 +468,7 @@ LIBSHIBOKEN_API PyObject *_Pep_PrivateMangle(PyObject *self, PyObject *name);
#ifdef Py_LIMITED_API
extern LIBSHIBOKEN_API PyTypeObject *PepStaticMethod_TypePtr;
+LIBSHIBOKEN_API PyObject *PyStaticMethod_New(PyObject *callable);
#else
#define PepStaticMethod_TypePtr &PyStaticMethod_Type
#endif
diff --git a/sources/shiboken2/libshiboken/pep384impl_doc.rst b/sources/shiboken2/libshiboken/pep384impl_doc.rst
index 2844249ad..ab286dd3e 100644
--- a/sources/shiboken2/libshiboken/pep384impl_doc.rst
+++ b/sources/shiboken2/libshiboken/pep384impl_doc.rst
@@ -283,7 +283,9 @@ written that skips over dotted name parts.
Finally, the function ``_PyObject_Dump`` was excluded from the limited API.
This is a useful debugging aid that we always want to have available,
-so it is added back, again.
+so it is added back, again. Anyway, we did not reimplement it, and so
+Windows is not supported.
+Therefore, a forgotten debugging call of this functions will break COIN. :-)
Using The New Type API
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index 962e50d46..92ce3e50a 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -111,12 +111,14 @@ CreateSignature(PyObject *props, PyObject *key)
static PyObject *
pyside_cf_get___signature__(PyObject *func, const char *modifier)
{
+ init_module_2();
return GetSignature_Function(func, modifier);
}
static PyObject *
pyside_sm_get___signature__(PyObject *sm, const char *modifier)
{
+ init_module_2();
Shiboken::AutoDecRef func(PyObject_GetAttrString(sm, "__func__"));
return GetSignature_Function(func, modifier);
}
@@ -239,6 +241,7 @@ name_key_to_func(PyObject *ob)
static PyObject *
pyside_md_get___signature__(PyObject *ob_md, const char *modifier)
{
+ init_module_2();
Shiboken::AutoDecRef func(name_key_to_func(ob_md));
if (func.object() == Py_None)
return Py_None;
@@ -250,12 +253,14 @@ pyside_md_get___signature__(PyObject *ob_md, const char *modifier)
static PyObject *
pyside_wd_get___signature__(PyObject *ob, const char *modifier)
{
+ init_module_2();
return GetSignature_Wrapper(ob, modifier);
}
static PyObject *
pyside_tp_get___signature__(PyObject *typemod, const char *modifier)
{
+ init_module_2();
return GetSignature_TypeMod(typemod, modifier);
}
@@ -407,14 +412,23 @@ GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier)
static const char PySide_PythonCode[] =
"from __future__ import print_function, absolute_import\n" R"~(if True:
+ # This is becoming the 'signature_loader' module.
+
import sys, os, traceback
# We avoid imports in phase 1 that could fail. "import shiboken" of the
# binary would even crash in FinishSignatureInitialization.
def bootstrap():
global __file__
- import PySide2 as root
+ try:
+ import shiboken2 as root
+ except ImportError:
+ # uninstalled case without ctest, try only this one which has __init__:
+ from shibokenmodule import shiboken2 as root
rp = os.path.realpath(os.path.dirname(root.__file__))
+ # This can be the shiboken2 directory or the binary module, so search.
+ while len(rp) > 3 and not os.path.exists(os.path.join(rp, 'support')):
+ rp = os.path.abspath(os.path.join(rp, '..'))
__file__ = os.path.join(rp, 'support', 'signature', 'loader.py')
try:
with open(__file__) as _f:
@@ -493,6 +507,7 @@ init_phase_2(safe_globals_struc *p, PyMethodDef *methods)
error:
Py_XDECREF(v);
+ PyErr_Print();
PyErr_SetString(PyExc_SystemError, "could not initialize part 2");
return -1;
}
@@ -569,7 +584,6 @@ get_signature(PyObject *self, PyObject *args)
const char *modifier = nullptr;
init_module_1();
- init_module_2();
if (!PyArg_ParseTuple(args, "O|s", &ob, &modifier))
return NULL;
@@ -618,7 +632,7 @@ void handler(int sig) {
#endif // _WIN32
static int
-PySideType_Ready(PyTypeObject *type)
+PySide_PatchTypes(void)
{
static int init_done = 0;
@@ -642,7 +656,7 @@ PySideType_Ready(PyTypeObject *type)
#endif // _WIN32
init_done = 1;
}
- return PyType_Ready(type);
+ return 0;
}
static void
@@ -672,14 +686,7 @@ PySide_BuildSignatureArgs(PyObject *module, PyObject *type,
* We can ignore the EnclosingObject since we get full name info
* from the type.
*/
- if (PyModule_Check(module)) {
- const char *name = PyModule_GetName(module);
- if (name == NULL)
- return -1;
- if (strcmp(name, "testbinding") == 0)
- return 0;
- }
- else
+ if (!PyModule_Check(module))
assert(PyDict_Check(module));
/*
* Normally, we would now just call the Python function with the
@@ -758,7 +765,7 @@ SbkSpecial_Type_Ready(PyObject *module, PyTypeObject *type,
const char *signatures)
{
int ret;
- if (PySideType_Ready(type) < 0)
+ if (PyType_Ready(type) < 0)
return -1;
ret = PySide_BuildSignatureArgs(module, (PyObject *)type, signatures);
if (ret < 0) {
@@ -778,13 +785,9 @@ PySide_FinishSignatures(PyObject *module, const char *signatures)
* Initialization of module functions and resolving of static methods.
*/
- // CRUCIAL: Do not call this on "testbinding":
- // The module is different and should not get signatures, anyway.
const char *name = PyModule_GetName(module);
if (name == NULL)
return -1;
- if (strcmp(name, "testbinding") == 0)
- return 0;
// we abuse the call for types, since they both have a __name__ attribute.
if (PySide_BuildSignatureArgs(module, module, signatures) < 0)
@@ -846,7 +849,8 @@ _build_func_to_type(PyObject *obtype)
* mapping from function to type.
*
* We walk through the method list of the type
- * and record the mapping from function to this type in a dict.
+ * and record the mapping from static method to this type in a dict.
+ * We also check for hidden methods, see below.
*/
PyTypeObject *type = reinterpret_cast<PyTypeObject *>(obtype);
PyObject *dict = type->tp_dict;
@@ -856,13 +860,51 @@ _build_func_to_type(PyObject *obtype)
return 0;
for (; meth->ml_name != NULL; meth++) {
- if (meth->ml_flags & METH_STATIC) {
- PyObject *descr = PyDict_GetItemString(dict, meth->ml_name);
- if (descr == NULL)
+ /*
+ * It is possible that a method is overwritten by another
+ * attribute with the same name. This case was obviously provoked
+ * explicitly in "testbinding.TestObject.staticMethodDouble",
+ * where instead of the method a "PySide2.QtCore.Signal" object
+ * was in the dict.
+ * This overlap is also found in regular PySide under
+ * "PySide2.QtCore.QProcess.error" where again a signal object is
+ * returned. These hidden methods will be opened for the
+ * signature module by adding them under the name
+ * "{name}.overload".
+ */
+ PyObject *descr = PyDict_GetItemString(dict, meth->ml_name);
+ const char *look_attr = meth->ml_flags & METH_STATIC ? "__func__" : "__name__";
+ int check_name = meth->ml_flags & METH_STATIC ? 0 : 1;
+ if (descr == NULL)
+ return -1;
+
+ // We first check all methods if one is hidden by something else.
+ Shiboken::AutoDecRef look(PyObject_GetAttrString(descr, look_attr));
+ Shiboken::AutoDecRef given(Py_BuildValue("s", meth->ml_name));
+ if (look.isNull()
+ || (check_name && PyObject_RichCompareBool(look, given, Py_EQ) != 1)) {
+ PyErr_Clear();
+ Shiboken::AutoDecRef cfunc(PyCFunction_NewEx(meth, (PyObject*)type, NULL));
+ if (cfunc.isNull())
+ return -1;
+ if (meth->ml_flags & METH_STATIC)
+ descr = PyStaticMethod_New(cfunc);
+ else
+ descr = PyDescr_NewMethod(type, meth);
+ if (descr == nullptr)
return -1;
- Shiboken::AutoDecRef func(PyObject_GetAttrString(descr, "__func__"));
- if (func.isNull() ||
- PyDict_SetItem(pyside_globals->map_dict, func, obtype) < 0)
+ char mangled_name[200];
+ strcpy(mangled_name, meth->ml_name);
+ strcat(mangled_name, ".overload");
+ if (PyDict_SetItemString(dict, mangled_name, descr) < 0)
+ return -1;
+ if (PyDict_SetItemString(pyside_globals->map_dict, mangled_name, obtype) < 0)
+ return -1;
+ continue;
+ }
+ // Then we insert the mapping for static methods.
+ if (meth->ml_flags & METH_STATIC) {
+ if (PyDict_SetItem(pyside_globals->map_dict, look, obtype) < 0)
return -1;
}
}
@@ -873,11 +915,14 @@ void
FinishSignatureInitialization(PyObject *module, const char *signatures)
{
/*
- * This function is called at the very end of a module
- * initialization. SbkSpecial_Type_Ready has already been run
- * with all the types.
- * We now initialize module functions and resolve static methods.
+ * This function is called at the very end of a module initialization.
+ * We now patch certain types to support the __signature__ attribute,
+ * initialize module functions and resolve static methods.
+ *
+ * Still, it is not possible to call init phase 2 from here,
+ * because the import is still running. Do it from Python!
*/
+ PySide_PatchTypes();
if (PySide_FinishSignatures(module, signatures) < 0) {
PyErr_Print();
PyErr_SetNone(PyExc_ImportError);
diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt
index 20baf9f7e..342b6d908 100644
--- a/sources/shiboken2/shibokenmodule/CMakeLists.txt
+++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt
@@ -52,6 +52,33 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/_config.py"
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in"
"${CMAKE_CURRENT_BINARY_DIR}/__init__.py" @ONLY)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/layout.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/layout.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/loader.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/loader.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/mapping.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/mapping.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/parser.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/parser.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/__init__.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/__init__.py" COPYONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/lib/enum_sig.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/lib/enum_sig.py" COPYONLY)
+if (PYTHON_VERSION_MAJOR EQUAL 3)
+else()
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/backport_inspect.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/backport_inspect.py" COPYONLY)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/support/signature/typing27.py"
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/typing.py" COPYONLY)
+endif()
+install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/support"
+ DESTINATION "${PYTHON_SITE_PACKAGES}/shiboken2")
+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/__init__.py"
DESTINATION "${PYTHON_SITE_PACKAGES}/shiboken2")
diff --git a/sources/shiboken2/shibokenmodule/support/__init__.py b/sources/shiboken2/shibokenmodule/support/__init__.py
new file mode 100644
index 000000000..760d89571
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/__init__.py
@@ -0,0 +1,40 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# this file intentionally left blank
diff --git a/sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt b/sources/shiboken2/shibokenmodule/support/signature/PSF-3.7.0.txt
index be42010dd..be42010dd 100644
--- a/sources/pyside2/PySide2/support/signature/PSF-3.7.0.txt
+++ b/sources/shiboken2/shibokenmodule/support/signature/PSF-3.7.0.txt
diff --git a/sources/pyside2/PySide2/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/__init__.py
index 21ecebcc8..f639f1ad0 100644
--- a/sources/pyside2/PySide2/support/signature/loader.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/__init__.py
@@ -39,51 +39,6 @@
from __future__ import print_function, absolute_import
-"""
-loader.py
-
-The loader has to lazy-load the signature module and also provides a few
-Python modules to support Python 2.7 .
-
-This file was originally directly embedded into the C source.
-After it grew more and more, I now prefer to have it as Python file.
-The remaining stub loader in the C source is now only a short string.
-
-This version does no longer use an embedded .zip file but is a package.
-The old code without a package but with zip compression can still be found
-at https://codereview.qt-project.org/#/c/203533/ for reference.
-"""
-
-import sys
-import os
-
-# Make sure that we always have the PySide containing package first.
-# This is crucial for the mapping during reload in the tests.
-package_dir = __file__
-for _ in "four":
- package_dir = os.path.dirname(package_dir)
-sys.path.insert(0, package_dir)
-if sys.version_info >= (3,):
- import inspect
-else:
- import inspect
- namespace = inspect.__dict__
- from PySide2.support.signature import backport_inspect as inspect
- _doc = inspect.__doc__
- inspect.__dict__.update(namespace)
- 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("_"))
-
-# name used in signature.cpp
-from PySide2.support.signature.parser import pyside_type_init
-sys.path.pop(0)
-# Note also that during the tests we have a different encoding that would
-# break the Python license decorated files without an encoding line.
-from PySide2.support.signature import layout
-
-# name used in signature.cpp
-def create_signature(props, key):
- return layout.create_signature(props, key)
-
-# end of file
+# Trigger initialization phase 2.
+_ = type.__signature__
+from signature_loader import get_signature, inspect
diff --git a/sources/pyside2/PySide2/support/signature/backport_inspect.py b/sources/shiboken2/shibokenmodule/support/signature/backport_inspect.py
index 0eafe9caa..0eafe9caa 100644
--- a/sources/pyside2/PySide2/support/signature/backport_inspect.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/backport_inspect.py
diff --git a/sources/pyside2/PySide2/support/signature/fix-complaints.py b/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py
index e078ef1ab..e078ef1ab 100644
--- a/sources/pyside2/PySide2/support/signature/fix-complaints.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/fix-complaints.py
diff --git a/sources/shiboken2/shibokenmodule/support/signature/layout.py b/sources/shiboken2/shibokenmodule/support/signature/layout.py
new file mode 100644
index 000000000..47f97fc2b
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/signature/layout.py
@@ -0,0 +1,245 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+"""
+layout.py
+
+The signature module now has the capability to configure
+differently formatted versions of signatures. The default
+layout is known from the "__signature__" attribute.
+
+The function "get_signature(ob, modifier=None)" produces the same
+signatures by default. By passing different modifiers, you
+can select different layouts.
+
+This module configures the different layouts which can be used.
+It also implements them in this file. The configurations are
+used literally as strings like "signature", "existence", etc.
+"""
+
+from textwrap import dedent
+from signature_loader import inspect
+
+
+class SimpleNamespace(object):
+ # From types.rst, because the builtin is implemented in Python 3, only.
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
+
+ def __repr__(self):
+ keys = sorted(self.__dict__)
+ items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
+ return "{}({})".format(type(self).__name__, ", ".join(items))
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+
+class SignatureLayout(SimpleNamespace):
+ """
+ Configure a signature.
+
+ The layout of signatures can have different layouts which are
+ controlled by keyword arguments:
+
+ definition=True Determines if self will generated.
+ defaults=True
+ ellipsis=False Replaces defaults by "...".
+ return_annotation=True
+ parameter_names=True False removes names before ":".
+ """
+ allowed_keys = SimpleNamespace(definition=True,
+ defaults=True,
+ ellipsis=False,
+ return_annotation=True,
+ parameter_names=True)
+ allowed_values = True, False
+
+ def __init__(self, **kwds):
+ args = SimpleNamespace(**self.allowed_keys.__dict__)
+ args.__dict__.update(kwds)
+ self.__dict__.update(args.__dict__)
+ err_keys = list(set(self.__dict__) - set(self.allowed_keys.__dict__))
+ if err_keys:
+ self._attributeerror(err_keys)
+ err_values = list(set(self.__dict__.values()) - set(self.allowed_values))
+ if err_values:
+ self._valueerror(err_values)
+
+ def __setattr__(self, key, value):
+ if key not in self.allowed_keys.__dict__:
+ self._attributeerror([key])
+ if value not in self.allowed_values:
+ self._valueerror([value])
+ self.__dict__[key] = value
+
+ def _attributeerror(self, err_keys):
+ err_keys = ", ".join(err_keys)
+ allowed_keys = ", ".join(self.allowed_keys.__dict__.keys())
+ raise AttributeError(dedent("""\
+ Not allowed: '{err_keys}'.
+ The only allowed keywords are '{allowed_keys}'.
+ """.format(**locals())))
+
+ def _valueerror(self, err_values):
+ err_values = ", ".join(map(str, err_values))
+ allowed_values = ", ".join(map(str, self.allowed_values))
+ raise ValueError(dedent("""\
+ Not allowed: '{err_values}'.
+ The only allowed values are '{allowed_values}'.
+ """.format(**locals())))
+
+# The following names are used literally in this module.
+# This way, we avoid the dict hashing problem.
+signature = SignatureLayout()
+
+existence = SignatureLayout(definition=False,
+ defaults=False,
+ return_annotation=False,
+ parameter_names=False)
+
+hintingstub = SignatureLayout(ellipsis=True)
+
+typeerror = SignatureLayout(definition=False,
+ return_annotation=False,
+ parameter_names=False)
+
+
+def define_nameless_parameter():
+ """
+ Create Nameless Parameters
+
+ A nameless parameter has a reduced string representation.
+ This is done by cloning the parameter type and overwriting its
+ __str__ method. The inner structure is still a valid parameter.
+ """
+ def __str__(self):
+ # for Python 2, we must change self to be an instance of P
+ klass = self.__class__
+ self.__class__ = P
+ txt = P.__str__(self)
+ self.__class__ = klass
+ txt = txt[txt.index(":") + 1:].strip() if ":" in txt else txt
+ return txt
+
+ P = inspect.Parameter
+ newname = "NamelessParameter"
+ bases = P.__bases__
+ body = dict(P.__dict__) # get rid of mappingproxy
+ if "__slots__" in body:
+ # __slots__ would create duplicates
+ for name in body["__slots__"]:
+ del body[name]
+ body["__str__"] = __str__
+ return type(newname, bases, body)
+
+
+NamelessParameter = define_nameless_parameter()
+
+
+def make_signature_nameless(signature):
+ """
+ Make a Signature Nameless
+
+ We use an existing signature and change the type of its parameters.
+ The signature looks different, but is totally intact.
+ """
+ for key in signature.parameters.keys():
+ signature.parameters[key].__class__ = NamelessParameter
+
+
+def create_signature(props, key):
+ if not props:
+ # empty signatures string
+ return
+ if isinstance(props["multi"], list):
+ # multi sig: call recursively
+ return list(create_signature(elem, key)
+ for elem in props["multi"])
+ if type(key) is tuple:
+ sig_kind, modifier = key
+ else:
+ sig_kind, modifier = key, "signature"
+
+ layout = globals()[modifier] # lookup of the modifier in this module
+ if not isinstance(layout, SignatureLayout):
+ raise SystemError("Modifiers must be names of a SignatureLayout "
+ "instance")
+
+ # this is the basic layout of a signature
+ varnames = props["varnames"]
+ if layout.definition:
+ if sig_kind == "function":
+ pass
+ elif sig_kind == "method":
+ varnames = ("self",) + varnames
+ elif sig_kind == "staticmethod":
+ pass
+ elif sig_kind == "classmethod":
+ varnames = ("klass",) + varnames
+ else:
+ 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 = ("...",) * 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)
+
+ # the special case of nameless parameters
+ if not layout.parameter_names:
+ make_signature_nameless(sig)
+ return sig
+
+# end of file
diff --git a/sources/shiboken2/shibokenmodule/support/signature/lib/__init__.py b/sources/shiboken2/shibokenmodule/support/signature/lib/__init__.py
new file mode 100644
index 000000000..2d640cb89
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/signature/lib/__init__.py
@@ -0,0 +1,40 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# this file intentionally left blank
diff --git a/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py
new file mode 100644
index 000000000..2ec14d62b
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py
@@ -0,0 +1,135 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+import sys
+from signature_loader import get_signature, inspect
+
+
+class ExactEnumerator(object):
+ """
+ ExactEnumerator enumerates all signatures in a module as they are.
+
+ This class is used for generating complete listings of all signatures.
+ An appropriate formatter should be supplied, if printable output
+ is desired.
+ """
+ def __init__(self, formatter, result_type=dict):
+ self.fmt = formatter
+ self.result_type = result_type
+
+ def module(self, mod_name):
+ __import__(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))
+ return ret
+
+ def klass(self, class_name, klass):
+ bases_list = []
+ for base in klass.__bases__:
+ name = base.__name__
+ if name == "object":
+ pass
+ else:
+ modname = base.__module__
+ name = modname + "." + base.__name__
+ 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)
+ # 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:
+ ret.update(self.function(thing_name, thing))
+ for subclass_name, subclass in subclasses:
+ ret.update(self.klass(subclass_name, subclass))
+ return ret
+
+ def function(self, func_name, func):
+ ret = self.result_type()
+ signature = getattr(func, '__signature__', None)
+ if signature is not None:
+ with self.fmt.function(func_name, signature) as key:
+ ret[key] = str(signature)
+ return ret
+
+
+def stringify(signature):
+ if isinstance(signature, list):
+ # remove duplicates which still sometimes occour:
+ ret = set(stringify(sig) for sig in signature)
+ return sorted(ret) if len(ret) > 1 else list(ret)[0]
+ return tuple(str(pv) for pv in signature.parameters.values())
+
+
+class SimplifyingEnumerator(ExactEnumerator):
+ """
+ SimplifyingEnumerator enumerates all signatures in a module filtered.
+
+ There are no default values, no variable
+ names and no self parameter. Only types are present after simplification.
+ The functions 'next' resp. '__next__' are removed
+ to make the output identical for Python 2 and 3.
+ An appropriate formatter should be supplied, if printable output
+ is desired.
+ """
+
+ def function(self, func_name, func):
+ ret = self.result_type()
+ signature = get_signature(func, 'existence')
+ sig = stringify(signature) if signature is not None else None
+ if sig is not None and func_name not in ("next", "__next__", "__div__"):
+ with self.fmt.function(func_name, sig) as key:
+ ret[key] = sig
+ return ret
diff --git a/sources/shiboken2/shibokenmodule/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/loader.py
new file mode 100644
index 000000000..83493e511
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/signature/loader.py
@@ -0,0 +1,176 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+"""
+loader.py
+
+The loader has to lazy-load the signature module and also provides a few
+Python modules to support Python 2.7 .
+
+This file was originally directly embedded into the C source.
+After it grew more and more, I now prefer to have it as Python file.
+The remaining stub loader in the C source is now only a short string.
+
+This version does no longer use an embedded .zip file but is a package.
+The old code without a package but with zip compression can still be found
+at https://codereview.qt-project.org/#/c/203533/ for reference.
+"""
+
+import sys
+import os
+import traceback
+import types
+from contextlib import contextmanager
+from distutils.sysconfig import get_python_lib
+
+"""
+A note on the import problem (solved):
+
+During the tests, the shiboken build structure has the layout
+
+ shiboken2/shibokenmodule/shiboken2.abi3.so
+
+and the name "shiboken2" in sys.modules points directly to the binary
+file, hiding the outer shiboken2 module.
+
+To fix that, we temporarily remove the binary from sys.path,
+do the needed imports and then restore the binary.
+This action was put into a context manager for readability.
+"""
+
+# On Python 2, we only have ImportError, which is way too coarse.
+# When problems occour, please use Python 3, because it has the finer
+# ModuleNotFoundError.
+
+try:
+ ModuleNotFoundError
+except NameError:
+ ModuleNotFoundError = ImportError
+
+@contextmanager
+def ensure_import_support():
+ # Make sure that we always have the shiboken containing package first.
+ # This is sometimes hidden by the ctest paths.
+ # We adjust the path in a way that the support folder comes first.
+ # This can be in "shiboken2/support" or in "shibokenmodule/support",
+ # so we use the "support" folder as toplevel.
+ sbk_support_dir = os.path.abspath(os.path.join(__file__, "..", "..", ".."))
+ sys.path.insert(0, sbk_support_dir)
+ sbk = "shiboken2"
+ save_sbk = sys.modules.pop(sbk) if sbk in sys.modules else None
+ # make sure that we get at the support folder
+ try:
+ import support
+ yield
+ except Exception as e:
+ print("Problem importing support:")
+ print(e)
+ traceback.print_exc()
+ sys.stdout.flush()
+ sys.exit(-1)
+ if save_sbk:
+ sys.modules[sbk] = save_sbk
+ sys.path.pop(0)
+
+
+with ensure_import_support():
+ # We store all needed modules in signature_loader.
+ # This way, they are always accessible.
+ import signature_loader
+
+ if sys.version_info >= (3,):
+ import typing
+ import inspect
+ else:
+ import inspect
+ namespace = inspect.__dict__
+ from support.signature import typing
+ from support.signature import backport_inspect as inspect
+ _doc = inspect.__doc__
+ inspect.__dict__.update(namespace)
+ 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("_"))
+
+ def put_into_loader_package(module, loader=signature_loader):
+ # Note: the "with" statement hides that we are no longer in a
+ # global context, but inside ensure_import_support. Therefore,
+ # we need to explicitly pass the signature_loader in.
+
+ # take the last component of the module name
+ name = module.__name__.rsplit(".", 1)[-1]
+ # allow access as signature_loader.typing
+ setattr(loader, name, module)
+ # put into sys.modules as a package to allow all import options
+ fullname = "{}.{}".format(loader.__name__, name)
+ sys.modules[fullname] = module
+
+ put_into_loader_package(typing)
+ put_into_loader_package(inspect)
+ from support.signature import mapping as sbk_mapping
+ sbk_mapping.__name__ = "sbk_mapping"
+ put_into_loader_package(sbk_mapping)
+ # We may or may not use PySide.
+ try:
+ from PySide2.support.signature import mapping
+ except ModuleNotFoundError:
+ mapping = sbk_mapping
+ mapping.__name__ = "mapping"
+ put_into_loader_package(mapping)
+ from support.signature import layout
+ put_into_loader_package(layout)
+ from support.signature.lib import enum_sig
+ put_into_loader_package(enum_sig)
+ from support.signature.parser import pyside_type_init
+
+
+# Note also that during the tests we have a different encoding that would
+# break the Python license decorated files without an encoding line.
+
+# name used in signature.cpp
+def create_signature(props, key):
+ return layout.create_signature(props, key)
+
+# name used in signature.cpp
+def seterror_argument(args, func_name):
+ return errorhandler.seterror_argument(args, func_name)
+
+# end of file
diff --git a/sources/shiboken2/shibokenmodule/support/signature/mapping.py b/sources/shiboken2/shibokenmodule/support/signature/mapping.py
new file mode 100644
index 000000000..724b0c751
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/support/signature/mapping.py
@@ -0,0 +1,199 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function, absolute_import
+
+"""
+mapping.py
+
+This module has the mapping from the pyside C-modules view of signatures
+to the Python representation.
+
+The PySide modules are not loaded in advance, but only after they appear
+in sys.modules. This minimizes the loading overhead.
+"""
+
+import sys
+import struct
+import os
+import pkgutil
+
+from signature_loader 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]
+Point = typing.Tuple[float, float]
+PointList = typing.List[Point]
+IntMatrix = typing.List[IntList]
+Variant = typing.Any
+ModelIndexList = typing.List[int]
+QImageCleanupFunction = typing.Callable
+FloatList = typing.List[float]
+FloatMatrix = typing.List[FloatList]
+# 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]]
+
+# 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
+
+GL_COLOR_BUFFER_BIT = 0x00004000
+GL_NEAREST = 0x2600
+
+WId = int
+
+# from 5.9
+GL_TEXTURE_2D = 0x0DE1
+GL_RGBA = 0x1908
+
+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):
+ 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 signature_loader.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(_NotCalled):
+ pass
+
+class Invalid(_NotCalled):
+ pass
+
+# Helper types
+class Default(_NotCalled):
+ pass
+
+class Instance(_NotCalled):
+ pass
+
+
+class Reloader(object):
+ _uninitialized = ["sample"]
+ _prefixes = [""]
+
+ def __init__(self):
+ self.sys_module_count = 0
+ self.uninitialized = self._uninitialized
+
+ def update(self, g=None):
+ if self.sys_module_count == len(sys.modules):
+ return
+ self.sys_module_count = len(sys.modules)
+ if g is None:
+ g = globals()
+ for mod_name in self.uninitialized[:]:
+ for prefix in self._prefixes:
+ if prefix + mod_name in sys.modules:
+ self.uninitialized.remove(mod_name)
+ proc_name = "init_" + mod_name
+ if proc_name in g:
+ g.update(g[proc_name]())
+
+
+update_mapping = Reloader().update
+type_map = {}
+
+
+def init_sample():
+ import sample
+ import datetime
+ type_map.update({
+ "sample.int": int,
+ "Complex": complex,
+ "sample.OddBool": bool,
+ "sample.bool": bool,
+ "sample.PStr": str,
+ "double[]": FloatList,
+ "OddBool": bool,
+ "PStr": str,
+ "sample.char": Char,
+ "double[][]": FloatMatrix,
+ "int[]": IntList,
+ "int[][]": IntMatrix,
+ "sample.Point": Point,
+ "sample.ObjectType": object,
+ "std.string": str,
+ "HANDLE": int,
+ "Foo.HANDLE": int,
+ "sample.Photon.TemplateBase": Missing("sample.Photon.TemplateBase"),
+ "ObjectType.Identifier": Missing("sample.ObjectType.Identifier"),
+ "zero(HANDLE)": 0,
+ "Null": None,
+ "zero(sample.ObjectType)": None,
+ "std.size_t": int,
+ 'Str("<unknown>")': "<unknown>",
+ 'Str("<unk")': "<unk",
+ 'Str("nown>")': "nown>",
+ "zero(sample.ObjectModel)": None,
+ "sample.unsigned char": Char,
+ "sample.double": float,
+ "zero(sample.bool)": False,
+ "PyDate": datetime.date,
+ "ZeroIn": 0,
+ "Point[]": PointList,
+ })
+ return locals()
+
+# end of file
diff --git a/sources/pyside2/PySide2/support/signature/parser.py b/sources/shiboken2/shibokenmodule/support/signature/parser.py
index dd6640fde..82cd9aab3 100644
--- a/sources/pyside2/PySide2/support/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/parser.py
@@ -45,7 +45,8 @@ import warnings
import types
import keyword
import functools
-from .mapping import type_map, update_mapping, __dict__ as namespace
+from signature_loader.mapping import (
+ type_map, update_mapping, __dict__ as namespace)
_DEBUG = False
LIST_KEYWORDS = False
diff --git a/sources/pyside2/PySide2/support/signature/qt_attribution.json b/sources/shiboken2/shibokenmodule/support/signature/qt_attribution.json
index 491ae8054..491ae8054 100644
--- a/sources/pyside2/PySide2/support/signature/qt_attribution.json
+++ b/sources/shiboken2/shibokenmodule/support/signature/qt_attribution.json
diff --git a/sources/pyside2/PySide2/support/signature/typing27.py b/sources/shiboken2/shibokenmodule/support/signature/typing27.py
index ae1d6ba27..5d1c6058b 100644
--- a/sources/pyside2/PySide2/support/signature/typing27.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/typing27.py
@@ -95,6 +95,7 @@ import functools
import re as stdlib_re # Avoid confusion with the re we export.
import sys
import types
+import copy
try:
import collections.abc as collections_abc
except ImportError:
@@ -160,6 +161,7 @@ __all__ = [
'NewType',
'no_type_check',
'no_type_check_decorator',
+ 'NoReturn',
'overload',
'Text',
'TYPE_CHECKING',
@@ -445,7 +447,7 @@ def _type_check(arg, msg):
if (
type(arg).__name__ in ('_Union', '_Optional') and
not getattr(arg, '__origin__', None) or
- isinstance(arg, TypingMeta) and _gorg(arg) in (Generic, _Protocol)
+ isinstance(arg, TypingMeta) and arg._gorg in (Generic, _Protocol)
):
raise TypeError("Plain %s is not valid as type argument" % arg)
return arg
@@ -1033,29 +1035,6 @@ class _Optional(_FinalTypingBase):
Optional = _Optional(_root=True)
-def _gorg(a):
- """Return the farthest origin of a generic class (internal helper)."""
- assert isinstance(a, GenericMeta)
- while a.__origin__ is not None:
- a = a.__origin__
- return a
-
-
-def _geqv(a, b):
- """Return whether two generic classes are equivalent (internal helper).
-
- The intention is to consider generic class X and any of its
- parameterized forms (X[T], X[int], etc.) as equivalent.
-
- However, X is not equivalent to a subclass of X.
-
- The relation is reflexive, symmetric and transitive.
- """
- assert isinstance(a, GenericMeta) and isinstance(b, GenericMeta)
- # Reduce each to its origin.
- return _gorg(a) is _gorg(b)
-
-
def _next_in_mro(cls):
"""Helper for Generic.__new__.
@@ -1065,7 +1044,7 @@ def _next_in_mro(cls):
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
- if isinstance(c, GenericMeta) and _gorg(c) is Generic:
+ if isinstance(c, GenericMeta) and c._gorg is Generic:
next_in_mro = cls.__mro__[i + 1]
return next_in_mro
@@ -1166,13 +1145,15 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
extra = namespace.get('__extra__')
if extra is not None and type(extra) is abc.ABCMeta and extra not in bases:
bases = (extra,) + bases
- bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b for b in bases)
+ bases = tuple(b._gorg if isinstance(b, GenericMeta) else b for b in bases)
# remove bare Generic from bases if there are other generic bases
if any(isinstance(b, GenericMeta) and b is not Generic for b in bases):
bases = tuple(b for b in bases if b is not Generic)
namespace.update({'__origin__': origin, '__extra__': extra})
self = super(GenericMeta, cls).__new__(cls, name, bases, namespace)
+ super(GenericMeta, self).__setattr__('_gorg',
+ self if not origin else origin._gorg)
self.__parameters__ = tvars
# Be prepared that GenericMeta will be subclassed by TupleMeta
@@ -1219,7 +1200,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def _abc_negative_cache(self):
if isinstance(self.__extra__, abc.ABCMeta):
return self.__extra__._abc_negative_cache
- return _gorg(self)._abc_generic_negative_cache
+ return self._gorg._abc_generic_negative_cache
@_abc_negative_cache.setter
def _abc_negative_cache(self, value):
@@ -1233,7 +1214,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def _abc_negative_cache_version(self):
if isinstance(self.__extra__, abc.ABCMeta):
return self.__extra__._abc_negative_cache_version
- return _gorg(self)._abc_generic_negative_cache_version
+ return self._gorg._abc_generic_negative_cache_version
@_abc_negative_cache_version.setter
def _abc_negative_cache_version(self, value):
@@ -1283,7 +1264,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
if self.__origin__ is None:
return self
tree_args = _subs_tree(self, tvars, args)
- return (_gorg(self),) + tuple(tree_args)
+ return (self._gorg,) + tuple(tree_args)
def __eq__(self, other):
if not isinstance(other, GenericMeta):
@@ -1299,7 +1280,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def __getitem__(self, params):
if not isinstance(params, tuple):
params = (params,)
- if not params and not _gorg(self) is Tuple:
+ if not params and self._gorg is not Tuple:
raise TypeError(
"Parameter list to %s[...] cannot be empty" % _qualname(self))
msg = "Parameters to generic types must be types."
@@ -1343,7 +1324,11 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def __subclasscheck__(self, cls):
if self.__origin__ is not None:
- if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
+ # This should only be modules within the standard
+ # library. singledispatch is the only exception, because
+ # it's a Python 2 backport of functools.singledispatch.
+ if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools',
+ 'singledispatch']:
raise TypeError("Parameterized generics cannot be used with class "
"or instance checks")
return False
@@ -1362,11 +1347,6 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
return issubclass(instance.__class__, self)
return False
- def __copy__(self):
- return self.__class__(self.__name__, self.__bases__, dict(self.__dict__),
- self.__parameters__, self.__args__, self.__origin__,
- self.__extra__, self.__orig_bases__)
-
def __setattr__(self, attr, value):
# We consider all the subscripted genrics as proxies for original class
if (
@@ -1375,7 +1355,17 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
):
super(GenericMeta, self).__setattr__(attr, value)
else:
- super(GenericMeta, _gorg(self)).__setattr__(attr, value)
+ super(GenericMeta, self._gorg).__setattr__(attr, value)
+
+
+def _copy_generic(self):
+ """Hack to work around https://bugs.python.org/issue11480 on Python 2"""
+ return self.__class__(self.__name__, self.__bases__, dict(self.__dict__),
+ self.__parameters__, self.__args__, self.__origin__,
+ self.__extra__, self.__orig_bases__)
+
+
+copy._copy_dispatch[GenericMeta] = _copy_generic
# Prevent checks for Generic to crash when defining Generic.
@@ -1386,10 +1376,18 @@ def _generic_new(base_cls, cls, *args, **kwds):
# Assure type is erased on instantiation,
# but attempt to store it in __orig_class__
if cls.__origin__ is None:
- return base_cls.__new__(cls)
+ if (base_cls.__new__ is object.__new__ and
+ cls.__init__ is not object.__init__):
+ return base_cls.__new__(cls)
+ else:
+ return base_cls.__new__(cls, *args, **kwds)
else:
- origin = _gorg(cls)
- obj = base_cls.__new__(origin)
+ origin = cls._gorg
+ if (base_cls.__new__ is object.__new__ and
+ cls.__init__ is not object.__init__):
+ obj = base_cls.__new__(origin)
+ else:
+ obj = base_cls.__new__(origin, *args, **kwds)
try:
obj.__orig_class__ = cls
except AttributeError:
@@ -1423,7 +1421,7 @@ class Generic(object):
__slots__ = ()
def __new__(cls, *args, **kwds):
- if _geqv(cls, Generic):
+ if cls._gorg is Generic:
raise TypeError("Type Generic cannot be instantiated; "
"it can be used only as a base class")
return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
@@ -1445,7 +1443,7 @@ class TupleMeta(GenericMeta):
@_tp_cache
def __getitem__(self, parameters):
- if self.__origin__ is not None or not _geqv(self, Tuple):
+ if self.__origin__ is not None or self._gorg is not Tuple:
# Normal generic rules apply if this is not the first subscription
# or a subscription of a subclass.
return super(TupleMeta, self).__getitem__(parameters)
@@ -1474,6 +1472,9 @@ class TupleMeta(GenericMeta):
"with issubclass().")
+copy._copy_dispatch[TupleMeta] = _copy_generic
+
+
class Tuple(tuple):
"""Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
@@ -1489,7 +1490,7 @@ class Tuple(tuple):
__slots__ = ()
def __new__(cls, *args, **kwds):
- if _geqv(cls, Tuple):
+ if cls._gorg is Tuple:
raise TypeError("Type Tuple cannot be instantiated; "
"use tuple() instead")
return _generic_new(tuple, cls, *args, **kwds)
@@ -1504,7 +1505,7 @@ class CallableMeta(GenericMeta):
return self._tree_repr(self._subs_tree())
def _tree_repr(self, tree):
- if _gorg(self) is not Callable:
+ if self._gorg is not Callable:
return super(CallableMeta, self)._tree_repr(tree)
# For actual Callable (not its subclass) we override
# super(CallableMeta, self)._tree_repr() for nice formatting.
@@ -1524,7 +1525,7 @@ class CallableMeta(GenericMeta):
with hashable arguments to improve speed.
"""
- if self.__origin__ is not None or not _geqv(self, Callable):
+ if self.__origin__ is not None or self._gorg is not Callable:
return super(CallableMeta, self).__getitem__(parameters)
if not isinstance(parameters, tuple) or len(parameters) != 2:
raise TypeError("Callable must be used as "
@@ -1552,6 +1553,9 @@ class CallableMeta(GenericMeta):
return super(CallableMeta, self).__getitem__(parameters)
+copy._copy_dispatch[CallableMeta] = _copy_generic
+
+
class Callable(object):
"""Callable type; Callable[[int], str] is a function of (int) -> str.
@@ -1568,7 +1572,7 @@ class Callable(object):
__slots__ = ()
def __new__(cls, *args, **kwds):
- if _geqv(cls, Callable):
+ if cls._gorg is Callable:
raise TypeError("Type Callable cannot be instantiated; "
"use a non-abstract subclass instead")
return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
@@ -1618,7 +1622,7 @@ def no_type_check(arg):
if isinstance(arg, type):
arg_attrs = arg.__dict__.copy()
for attr, val in arg.__dict__.items():
- if val in arg.__bases__:
+ if val in arg.__bases__ + (arg,):
arg_attrs.pop(attr)
for obj in arg_attrs.values():
if isinstance(obj, types.FunctionType):
@@ -1735,6 +1739,7 @@ class _ProtocolMeta(GenericMeta):
if (not attr.startswith('_abc_') and
attr != '__abstractmethods__' and
attr != '_is_protocol' and
+ attr != '_gorg' and
attr != '__dict__' and
attr != '__args__' and
attr != '__slots__' and
@@ -1886,7 +1891,7 @@ class List(list, MutableSequence[T]):
__extra__ = list
def __new__(cls, *args, **kwds):
- if _geqv(cls, List):
+ if cls._gorg is List:
raise TypeError("Type List cannot be instantiated; "
"use list() instead")
return _generic_new(list, cls, *args, **kwds)
@@ -1897,7 +1902,7 @@ class Deque(collections.deque, MutableSequence[T]):
__extra__ = collections.deque
def __new__(cls, *args, **kwds):
- if _geqv(cls, Deque):
+ if cls._gorg is Deque:
return collections.deque(*args, **kwds)
return _generic_new(collections.deque, cls, *args, **kwds)
@@ -1907,7 +1912,7 @@ class Set(set, MutableSet[T]):
__extra__ = set
def __new__(cls, *args, **kwds):
- if _geqv(cls, Set):
+ if cls._gorg is Set:
raise TypeError("Type Set cannot be instantiated; "
"use set() instead")
return _generic_new(set, cls, *args, **kwds)
@@ -1918,7 +1923,7 @@ class FrozenSet(frozenset, AbstractSet[T_co]):
__extra__ = frozenset
def __new__(cls, *args, **kwds):
- if _geqv(cls, FrozenSet):
+ if cls._gorg is FrozenSet:
raise TypeError("Type FrozenSet cannot be instantiated; "
"use frozenset() instead")
return _generic_new(frozenset, cls, *args, **kwds)
@@ -1975,7 +1980,7 @@ class Dict(dict, MutableMapping[KT, VT]):
__extra__ = dict
def __new__(cls, *args, **kwds):
- if _geqv(cls, Dict):
+ if cls._gorg is Dict:
raise TypeError("Type Dict cannot be instantiated; "
"use dict() instead")
return _generic_new(dict, cls, *args, **kwds)
@@ -1986,7 +1991,7 @@ class DefaultDict(collections.defaultdict, MutableMapping[KT, VT]):
__extra__ = collections.defaultdict
def __new__(cls, *args, **kwds):
- if _geqv(cls, DefaultDict):
+ if cls._gorg is DefaultDict:
return collections.defaultdict(*args, **kwds)
return _generic_new(collections.defaultdict, cls, *args, **kwds)
@@ -1996,7 +2001,7 @@ class Counter(collections.Counter, Dict[T, int]):
__extra__ = collections.Counter
def __new__(cls, *args, **kwds):
- if _geqv(cls, Counter):
+ if cls._gorg is Counter:
return collections.Counter(*args, **kwds)
return _generic_new(collections.Counter, cls, *args, **kwds)
@@ -2015,7 +2020,7 @@ class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]):
__extra__ = _G_base
def __new__(cls, *args, **kwds):
- if _geqv(cls, Generator):
+ if cls._gorg is Generator:
raise TypeError("Type Generator cannot be instantiated; "
"create a subclass instead")
return _generic_new(_G_base, cls, *args, **kwds)
@@ -2144,7 +2149,7 @@ class IO(Generic[AnyStr]):
def close(self):
pass
- @abstractmethod
+ @abstractproperty
def closed(self):
pass