aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2018-11-25 15:55:45 +0100
committerCristian Maureira-Fredes <cristian.maureira-fredes@qt.io>2018-12-03 20:31:58 +0000
commit14af709e10fa8a2e3c84094c13ebdda9833be124 (patch)
treef6be857ed5d6502e4073a395b21e22cce278da75
parent5778103f5c86dc7f95bd79eabc24de4021eb2734 (diff)
Generate Hinting Stubs Automatically
The script is now automatically called in the cmake build, as part of the create_pyside_module macro. The script runs after every module build and tries to generate .pyi files. This does not need to succeed, but will generate all files in the end. The script has been prepared to allow partial runs without overhead. After integration of the .pyi generation into cmake, these files are also installed into the install directory by cmake. For wheel building, setup.py has entries, too. Building a full project with all modules revealed a bug in the signature module that allowed unsupported function objects. Module enum_sig had to be changed to suppress types which have no ancestry in shiboken. PYTHONPATH was avoided because it was not Windows compatible. Instead, the script was changed to accept "--sys-path" and "--lib-path" parameters. The latter evaluates either to PATH or LD_LIBRARY_PATH. The necessity to create .pyi files while the project is in the build process showed a hard to track down error condition in PySide_BuildSignatureProps. Simple logging was added as a start of introducing logging everywhere. Task-number: PYSIDE-735 Change-Id: I6b3eec4b823d026583e902023badedeb06fe0961 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--build_scripts/platforms/unix.py8
-rw-r--r--build_scripts/platforms/windows_desktop.py8
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py198
-rw-r--r--sources/pyside2/PySide2/support/signature/mapping.py4
-rw-r--r--sources/pyside2/cmake/Macros/PySideModules.cmake15
-rw-r--r--sources/shiboken2/libshiboken/pep384impl.h7
-rw-r--r--sources/shiboken2/libshiboken/signature.cpp95
-rw-r--r--sources/shiboken2/shibokenmodule/CMakeLists.txt2
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/__init__.py5
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py4
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/loader.py3
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/mapping.py14
-rw-r--r--sources/shiboken2/shibokenmodule/support/signature/parser.py1
13 files changed, 252 insertions, 112 deletions
diff --git a/build_scripts/platforms/unix.py b/build_scripts/platforms/unix.py
index fc56992f4..d3767976f 100644
--- a/build_scripts/platforms/unix.py
+++ b/build_scripts/platforms/unix.py
@@ -184,6 +184,14 @@ def prepare_packages_posix(self, vars):
"{st_build_dir}/{st_package_name}/support",
vars=vars)
+ # <source>/pyside2/{st_package_name}/*.pyi ->
+ # <setup>/{st_package_name}/*.pyi
+ copydir(
+ "{build_dir}/pyside2/{st_package_name}",
+ "{st_build_dir}/{st_package_name}",
+ filter=["*.pyi"],
+ vars=vars)
+
if not OPTION_NOEXAMPLES:
# examples/* -> <setup>/{st_package_name}/examples
copydir(os.path.join(self.script_dir, "examples"),
diff --git a/build_scripts/platforms/windows_desktop.py b/build_scripts/platforms/windows_desktop.py
index c61bbbc99..c98ef3959 100644
--- a/build_scripts/platforms/windows_desktop.py
+++ b/build_scripts/platforms/windows_desktop.py
@@ -207,6 +207,14 @@ def prepare_packages_win32(self, vars):
"{st_build_dir}/{st_package_name}/support",
vars=vars)
+ # <source>/pyside2/{st_package_name}/*.pyi ->
+ # <setup>/{st_package_name}/*.pyi
+ copydir(
+ "{build_dir}/pyside2/{st_package_name}",
+ "{st_build_dir}/{st_package_name}",
+ filter=["*.pyi"],
+ vars=vars)
+
copydir(
"{build_dir}/pyside2/libpyside",
"{st_build_dir}/{st_package_name}",
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
index adece0776..7a2c79ba2 100644
--- a/sources/pyside2/PySide2/support/generate_pyi.py
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -1,3 +1,4 @@
+# This Python file uses the following encoding: utf-8
#############################################################################
##
## Copyright (C) 2018 The Qt Company Ltd.
@@ -49,14 +50,15 @@ import sys
import os
import io
import re
-import PySide2
import subprocess
import argparse
from contextlib import contextmanager
from textwrap import dedent
-from PySide2.support.signature import inspect
-from PySide2.support.signature.lib.enum_sig import HintingEnumerator
+
+import logging
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger("generate_pyi")
# Make sure not to get .pyc in Python2.
@@ -101,8 +103,9 @@ class Formatter(Writer):
self.print("# Module", mod_name)
self.print("import shiboken2 as Shiboken")
from PySide2.support.signature import typing
- typing_str = "from PySide2.support.signature import typing"
- self.print(typing_str)
+ self.print("from PySide2.support.signature import typing")
+ self.print("from PySide2.support.signature.mapping import (")
+ self.print(" Virtual, Missing, Invalid, Default, Instance)")
self.print()
self.print("class Object(object): pass")
self.print()
@@ -174,68 +177,151 @@ def find_imports(text):
return [imp for imp in PySide2.__all__ if imp + "." in text]
+def safe_create(filename):
+ pid = os.getpid()
+ locname = "{filename}.{pid}".format(**locals())
+ f = io.open(locname, "w") # do not close for atomic rename on Linux
+ if sys.platform == "win32":
+ f.close()
+ try:
+ os.rename(locname, filename)
+ logger.debug("{pid}:File {filename} created".format(**locals()))
+ if sys.platform == "win32":
+ f = io.open(filename, "w")
+ return f
+ except OSError:
+ logger.debug("{pid}:Could not rename {locname} to {filename}"
+ .format(**locals()))
+ try:
+ os.remove(locname)
+ except OSError as e:
+ logger.warning("{pid}: unexpected os.remove error in safe_create: {e}"
+ .format(**locals()))
+ return None
+
+
def generate_pyi(import_name, outpath, options):
+ """
+ Generates a .pyi file.
+
+ Returns 1 If the result is valid, else 0.
+ """
+ pid = os.getpid()
plainname = import_name.split(".")[-1]
if not outpath:
outpath = os.path.dirname(PySide2.__file__)
outfilepath = os.path.join(outpath, plainname + ".pyi")
if options.skip and os.path.exists(outfilepath):
- return
+ logger.debug("{pid}:Skipped existing: {outfilepath}".format(**locals()))
+ return 1
+ workpath = outfilepath + ".working"
+ if os.path.exists(workpath):
+ return 0
+ realfile = safe_create(workpath)
+ if not realfile:
+ return 0
+
try:
- __import__(import_name)
- except ImportError:
- return
-
- module = sys.modules[import_name]
- mod_fullname = module.__file__
- outfile = io.StringIO()
- fmt = Formatter(outfile)
- enu = HintingEnumerator(fmt)
- fmt.print(get_license_text())
- need_imports = not USE_PEP563
- if USE_PEP563:
- fmt.print("from __future__ import annotations")
+ top = __import__(import_name)
+ obj = getattr(top, plainname)
+ if not getattr(obj, "__file__", None) or os.path.isdir(obj.__file__):
+ raise ImportError("We do not accept a namespace as module {plainname}"
+ .format(**locals()))
+ module = sys.modules[import_name]
+
+ outfile = io.StringIO()
+ fmt = Formatter(outfile)
+ enu = HintingEnumerator(fmt)
+ fmt.print(get_license_text()) # which has encoding, already
+ need_imports = not USE_PEP563
+ if USE_PEP563:
+ fmt.print("from __future__ import annotations")
+ fmt.print()
+ fmt.print(dedent('''\
+ """
+ This file contains the exact signatures for all functions in module
+ {import_name}, except for defaults which are replaced by "...".
+ """
+ '''.format(**locals())))
+ enu.module(import_name)
fmt.print()
- fmt.print(dedent('''\
- """
- This file contains the exact signatures for all functions in PySide
- for module '{mod_fullname}',
- except for defaults which are replaced by "...".
- """
- '''.format(**locals())))
- enu.module(import_name)
- fmt.print("# eof")
- with io.open(outfilepath, "w") as realfile:
- wr = Writer(realfile)
- outfile.seek(0)
- while True:
- line = outfile.readline()
- if not line:
- break
- line = line.rstrip()
- # we remove the IMPORTS marker and insert imports if needed
- if line == "IMPORTS":
- if need_imports:
- for mod_name in find_imports(outfile.getvalue()):
- imp = "PySide2." + mod_name
- if imp != import_name:
- wr.print("import " + imp)
- wr.print("import " + import_name)
- wr.print()
- wr.print()
- else:
- wr.print(line)
+ fmt.print("# eof")
+
+ except ImportError as e:
+ logger.debug("{pid}:Import problem with module {plainname}: {e}".format(**locals()))
+ try:
+ os.remove(workpath)
+ except OSError as e:
+ logger.warning("{pid}: unexpected os.remove error in generate_pyi: {e}"
+ .format(**locals()))
+ return 0
+
+ wr = Writer(realfile)
+ outfile.seek(0)
+ while True:
+ line = outfile.readline()
+ if not line:
+ break
+ line = line.rstrip()
+ # we remove the IMPORTS marker and insert imports if needed
+ if line == "IMPORTS":
+ if need_imports:
+ for mod_name in find_imports(outfile.getvalue()):
+ imp = "PySide2." + mod_name
+ if imp != import_name:
+ wr.print("import " + imp)
+ wr.print("import " + import_name)
+ wr.print()
+ wr.print()
+ else:
+ wr.print(line)
+ realfile.close()
- print(outfilepath, file=sys.stderr)
+ if os.path.exists(outfilepath):
+ os.remove(outfilepath)
+ try:
+ os.rename(workpath, outfilepath)
+ except OSError:
+ logger.warning("{pid}: probable duplicate generated: {outfilepath}"#
+ .format(**locals()))
+ return 0
+ logger.info("Generated: {outfilepath}".format(**locals()))
if sys.version_info[0] == 3:
# Python 3: We can check the file directly if the syntax is ok.
subprocess.check_output([sys.executable, outfilepath])
+ return 1
def generate_all_pyi(outpath, options):
+ ps = os.pathsep
+ if options.sys_path:
+ # make sure to propagate the paths from sys_path to subprocesses
+ sys_path = [os.path.normpath(_) for _ in options.sys_path]
+ sys.path[0:0] = sys_path
+ pypath = ps.join(sys_path)
+ os.environ["PYTHONPATH"] = pypath
+ if options.lib_path:
+ # the path changes are automatically propagated to subprocesses
+ ospath_var = "PATH" if sys.platform == "win32" else "LD_LIBRARY_PATH"
+ old_val = os.environ.get(ospath_var, "")
+ lib_path = [os.path.normpath(_) for _ in options.lib_path]
+ ospath = ps.join(lib_path + old_val.split(ps))
+ os.environ[ospath_var] = ospath
+
+ # now we can import
+ global PySide2, inspect, HintingEnumerator
+ import PySide2
+ from PySide2.support.signature import inspect
+ from PySide2.support.signature.lib.enum_sig import HintingEnumerator
+
+ valid = 0
for mod_name in PySide2.__all__:
import_name = "PySide2." + mod_name
- generate_pyi(import_name, outpath, options)
+ valid += generate_pyi(import_name, outpath, options)
+
+ npyi = len(PySide2.__all__)
+ if valid == npyi:
+ logger.info("+++ All {npyi} .pyi files have been created.".format(**locals()))
if __name__ == "__main__":
@@ -245,14 +331,20 @@ if __name__ == "__main__":
parser_run = subparsers.add_parser("run",
help="run the generation",
description="This script generates the .pyi file for all PySide modules.")
- parser_run.add_argument("--skip", action="store_true", help="skip already generated files")
- parser_run.add_argument("--outpath", help="the outout folder. Default = location of binaries.")
+ parser_run.add_argument("--skip", action="store_true",
+ help="skip existing files")
+ parser_run.add_argument("--outpath",
+ help="the output directory (default = binary location)")
+ parser_run.add_argument("--sys-path", nargs="+",
+ help="a list of strings prepended to sys.path")
+ parser_run.add_argument("--lib-path", nargs="+",
+ help="a list of strings prepended to LD_LIBRARY_PATH (unix) or PATH (windows)")
options = parser.parse_args()
if options.command == "run":
outpath = options.outpath
if outpath and not os.path.exists(outpath):
os.makedirs(outpath)
- print("+++ Created path {outpath}".format(**locals()))
+ logger.info("+++ Created path {outpath}".format(**locals()))
generate_all_pyi(outpath, options=options)
else:
parser_run.print_help()
diff --git a/sources/pyside2/PySide2/support/signature/mapping.py b/sources/pyside2/PySide2/support/signature/mapping.py
index cf5857c65..1a769484d 100644
--- a/sources/pyside2/PySide2/support/signature/mapping.py
+++ b/sources/pyside2/PySide2/support/signature/mapping.py
@@ -315,8 +315,7 @@ def init_QtXmlPatterns():
return locals()
-def init_QtMultimedia():
- import PySide2.QtMultimedia
+def init_QtMultimediaWidgets():
import PySide2.QtMultimediaWidgets
type_map.update({
"QGraphicsVideoItem": PySide2.QtMultimediaWidgets.QGraphicsVideoItem,
@@ -386,7 +385,6 @@ def init_QtTest():
def init_QtWebEngineWidgets():
import PySide2.QtWebEngineWidgets
type_map.update({
- "PySide2.QtTest.QTouchEventSequence": PySide2.QtTest.QTest.QTouchEventSequence,
"zero(PySide2.QtWebEngineWidgets.QWebEnginePage.FindFlags)": 0,
})
return locals()
diff --git a/sources/pyside2/cmake/Macros/PySideModules.cmake b/sources/pyside2/cmake/Macros/PySideModules.cmake
index 88c7a5044..dd4845033 100644
--- a/sources/pyside2/cmake/Macros/PySideModules.cmake
+++ b/sources/pyside2/cmake/Macros/PySideModules.cmake
@@ -125,8 +125,21 @@ macro(create_pyside_module
endif()
create_generator_target(${module_name})
+ # build type hinting stubs
+ add_custom_command( TARGET ${module_name} POST_BUILD
+ COMMAND "${SHIBOKEN_PYTHON_INTERPRETER}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/../support/generate_pyi.py" run --skip
+ --sys-path "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/../shiboken2/shibokenmodule"
+ --lib-path "${CMAKE_BINARY_DIR}/libpyside" "${CMAKE_BINARY_DIR}/../shiboken2/libshiboken"
+ )
# install
- install(TARGETS ${module_name} LIBRARY DESTINATION ${PYTHON_SITE_PACKAGES}/PySide2)
+ install(TARGETS ${module_name} LIBRARY DESTINATION "${PYTHON_SITE_PACKAGES}/PySide2")
+
+ install(DIRECTORY "${CMAKE_BINARY_DIR}/" DESTINATION "${PYTHON_SITE_PACKAGES}"
+ OPTIONAL
+ FILES_MATCHING PATTERN "*.pyi")
+
+ string(TOLOWER ${module_name} lower_module_name)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PySide2/${module_name}/pyside2_${lower_module_name}_python.h
DESTINATION include/PySide2${pyside2_SUFFIX}/${module_name}/)
file(GLOB typesystem_files ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_*.xml ${typesystem_path})
diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h
index 78b9defb5..bfa8f38a7 100644
--- a/sources/shiboken2/libshiboken/pep384impl.h
+++ b/sources/shiboken2/libshiboken/pep384impl.h
@@ -333,10 +333,11 @@ LIBSHIBOKEN_API PyObject *PepFunction_Get(PyObject *, const char *);
#define PyFunction_Check(op) (Py_TYPE(op) == PepFunction_TypePtr)
#define PyFunction_GET_CODE(func) PyFunction_GetCode(func)
-#define PyFunction_GetCode(func) PepFunction_Get((PyObject *)func, "__code__")
-#define PepFunction_GetName(func) PepFunction_Get((PyObject *)func, "__name__")
+#define PyFunction_GetCode(func) PepFunction_Get((PyObject *)func, "__code__")
+#define PepFunction_GetName(func) PepFunction_Get((PyObject *)func, "__name__")
#else
-#define PepFunction_GetName(func) (((PyFunctionObject *)func)->func_name)
+#define PepFunction_TypePtr (&PyFunction_Type)
+#define PepFunction_GetName(func) (((PyFunctionObject *)func)->func_name)
#endif
/*****************************************************************************
diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp
index 92ce3e50a..922f85906 100644
--- a/sources/shiboken2/libshiboken/signature.cpp
+++ b/sources/shiboken2/libshiboken/signature.cpp
@@ -120,6 +120,8 @@ pyside_sm_get___signature__(PyObject *sm, const char *modifier)
{
init_module_2();
Shiboken::AutoDecRef func(PyObject_GetAttrString(sm, "__func__"));
+ if (Py_TYPE(func) == PepFunction_TypePtr)
+ Py_RETURN_NONE;
return GetSignature_Function(func, modifier);
}
@@ -299,28 +301,38 @@ GetClassKey(PyObject *ob)
return Py_BuildValue("O", class_name.object());
}
+static PyObject *empty_dict = nullptr;
+
+static PyObject *
+TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype)
+{
+ PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, type_key);
+ if (dict == nullptr) {
+ if (empty_dict == nullptr)
+ empty_dict = PyDict_New();
+ dict = empty_dict;
+ }
+ if (PyTuple_Check(dict))
+ dict = PySide_BuildSignatureProps(obtype);
+ return dict;
+}
+
static PyObject *
GetSignature_Function(PyObject *ob_func, const char *modifier)
{
+ // make sure that we look into PyCFunction, only...
+ if (Py_TYPE(ob_func) == PepFunction_TypePtr)
+ Py_RETURN_NONE;
Shiboken::AutoDecRef typemod(GetClassOfFunc(ob_func));
Shiboken::AutoDecRef type_key(GetClassKey(typemod));
if (type_key.isNull())
Py_RETURN_NONE;
- PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, type_key);
- if (dict == NULL)
- Py_RETURN_NONE;
- if (PyTuple_Check(dict)) {
- /*
- * We do the initialization lazily.
- * This has also the advantage that we can freely import PySide.
- */
- dict = PySide_BuildSignatureProps(typemod);
- if (dict == NULL)
- Py_RETURN_NONE;
- }
+ PyObject *dict = TypeKey_to_PropsDict(type_key, typemod);
+ if (dict == nullptr)
+ return nullptr;
Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob_func, "__name__"));
PyObject *props = !func_name.isNull() ? PyDict_GetItem(dict, func_name) : nullptr;
- if (props == NULL)
+ if (props == nullptr)
Py_RETURN_NONE;
int flags = PyCFunction_GET_FLAGS(ob_func);
@@ -333,8 +345,7 @@ GetSignature_Function(PyObject *ob_func, const char *modifier)
sig_kind = "staticmethod";
else
sig_kind = "method";
- PyObject *ret = GetSignature_Cached(props, sig_kind, modifier);
- return ret;
+ return GetSignature_Cached(props, sig_kind, modifier);
}
static PyObject *
@@ -346,20 +357,11 @@ GetSignature_Wrapper(PyObject *ob, const char *modifier)
if (func_name.isNull() || objclass.isNull() || class_key.isNull())
return nullptr;
- PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, class_key);
- if (dict == NULL)
- Py_RETURN_NONE;
- if (PyTuple_Check(dict)) {
- /*
- * We do the initialization lazily.
- * This has also the advantage that we can freely import PySide.
- */
- dict = PySide_BuildSignatureProps(objclass);
- if (dict == NULL)
- Py_RETURN_NONE;
- }
+ PyObject *dict = TypeKey_to_PropsDict(class_key, objclass);
+ if (dict == nullptr)
+ return nullptr;
PyObject *props = PyDict_GetItem(dict, func_name);
- if (props == NULL)
+ if (props == nullptr)
Py_RETURN_NONE;
return GetSignature_Cached(props, "method", modifier);
}
@@ -370,18 +372,11 @@ GetSignature_TypeMod(PyObject *ob, const char *modifier)
Shiboken::AutoDecRef ob_name(PyObject_GetAttrString(ob, "__name__"));
Shiboken::AutoDecRef ob_key(GetClassKey(ob));
- PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, ob_key);
- if (dict == NULL)
- Py_RETURN_NONE;
-
- if (PyTuple_Check(dict)) {
- dict = PySide_BuildSignatureProps(ob);
- if (dict == NULL) {
- Py_RETURN_NONE;
- }
- }
+ PyObject *dict = TypeKey_to_PropsDict(ob_key, ob);
+ if (dict == nullptr)
+ return nullptr;
PyObject *props = PyDict_GetItem(dict, ob_name);
- if (props == NULL)
+ if (props == nullptr)
Py_RETURN_NONE;
return GetSignature_Cached(props, "method", modifier);
}
@@ -587,6 +582,9 @@ get_signature(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O|s", &ob, &modifier))
return NULL;
+ if (Py_TYPE(ob) == PepFunction_TypePtr)
+ Py_RETURN_NONE;
+
if (Py_TYPE(ob) == &PyCFunction_Type)
return pyside_cf_get___signature__(ob, modifier);
if (Py_TYPE(ob) == PepStaticMethod_TypePtr)
@@ -723,14 +721,13 @@ static PyMethodDef signature_methods[] = {
static void
init_module_2(void)
{
- static int init_done = 0, initializing = 0;
+ static int init_done = 0;
if (!init_done) {
- if (initializing)
- Py_FatalError("Init 2 called recursively!");
- init_phase_2(pyside_globals, signature_methods);
+ // Phase 2 will call __init__.py which touches a signature, itself.
+ // Therefore we set init_done prior to init_phase_2().
init_done = 1;
- initializing = 0;
+ init_phase_2(pyside_globals, signature_methods);
}
}
@@ -751,8 +748,14 @@ PySide_BuildSignatureProps(PyObject *classmod)
if (arg_tup == nullptr)
return nullptr;
PyObject *dict = PyObject_CallObject(pyside_globals->sigparse_func, arg_tup);
- if (dict == nullptr)
- return nullptr;
+ if (dict == nullptr) {
+ if (PyErr_Occurred())
+ return nullptr;
+ // No error: return an empty dict.
+ if (empty_dict == nullptr)
+ empty_dict = PyDict_New();
+ return empty_dict;
+ }
// We replace the arguments by the result dict.
if (PyDict_SetItem(pyside_globals->arg_dict, type_key, dict) < 0)
diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt
index 342b6d908..0eba3eaff 100644
--- a/sources/shiboken2/shibokenmodule/CMakeLists.txt
+++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt
@@ -74,7 +74,7 @@ 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)
+ "${CMAKE_CURRENT_BINARY_DIR}/support/signature/typing27.py" COPYONLY)
endif()
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/support"
DESTINATION "${PYTHON_SITE_PACKAGES}/shiboken2")
diff --git a/sources/shiboken2/shibokenmodule/support/signature/__init__.py b/sources/shiboken2/shibokenmodule/support/signature/__init__.py
index 253ba98dc..d0791df04 100644
--- a/sources/shiboken2/shibokenmodule/support/signature/__init__.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/__init__.py
@@ -41,4 +41,7 @@ from __future__ import print_function, absolute_import
# Trigger initialization phase 2.
_ = type.__signature__
-from signature_loader import get_signature, inspect, typing
+
+## from signature_loader import get_signature, inspect, typing
+# This causes a recursion in Python 2!
+# We do everything from signature_loader, instead.
diff --git a/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py
index f79f3266a..013ec36cc 100644
--- a/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/lib/enum_sig.py
@@ -81,6 +81,10 @@ class ExactEnumerator(object):
return ret
def klass(self, class_name, klass):
+ if not "Shiboken" in repr(klass.mro()):
+ # don't look into any foreign classes!
+ ret = self.result_type()
+ return ret
bases_list = []
for base in klass.__bases__:
name = base.__name__
diff --git a/sources/shiboken2/shibokenmodule/support/signature/loader.py b/sources/shiboken2/shibokenmodule/support/signature/loader.py
index 170fb0a2a..de27d441c 100644
--- a/sources/shiboken2/shibokenmodule/support/signature/loader.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/loader.py
@@ -146,7 +146,8 @@ with ensure_import_support():
else:
import inspect
namespace = inspect.__dict__
- from support.signature import typing
+ from support.signature import typing27 as typing
+ typing.__name__ = "typing"
from support.signature import backport_inspect as inspect
_doc = inspect.__doc__
inspect.__dict__.update(namespace)
diff --git a/sources/shiboken2/shibokenmodule/support/signature/mapping.py b/sources/shiboken2/shibokenmodule/support/signature/mapping.py
index bca1ce307..3e76cd94a 100644
--- a/sources/shiboken2/shibokenmodule/support/signature/mapping.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/mapping.py
@@ -104,7 +104,7 @@ class _NotCalled(str):
real object is needed, the wrapper can simply be called.
"""
def __repr__(self):
- suppress = "PySide2.support.signature.typing."
+ suppress = "support.signature.typing."
text = self[len(suppress):] if self.startswith(suppress) else self
return "{}({})".format(type(self).__name__, text)
@@ -119,7 +119,8 @@ class Virtual(_NotCalled):
# Other types I simply could not find.
class Missing(_NotCalled):
- pass
+ def __repr__(self):
+ return '{}("{}")'.format(type(self).__name__, self)
class Invalid(_NotCalled):
pass
@@ -148,7 +149,14 @@ class Reloader(object):
g = globals()
for mod_name in self.uninitialized[:]:
for prefix in self._prefixes:
- if prefix + mod_name in sys.modules:
+ import_name = prefix + mod_name
+ if import_name in sys.modules:
+ # check if this is a real module
+ obj = sys.modules[import_name]
+ if not getattr(obj, "__file__", None) or os.path.isdir(obj.__file__):
+ raise ImportError("Module '{mod_name}' is at most a "
+ "namespace!".format(**locals()))
+ # module is real
self.uninitialized.remove(mod_name)
proc_name = "init_" + mod_name
if proc_name in g:
diff --git a/sources/shiboken2/shibokenmodule/support/signature/parser.py b/sources/shiboken2/shibokenmodule/support/signature/parser.py
index 4bb1bf234..5178d9ef9 100644
--- a/sources/shiboken2/shibokenmodule/support/signature/parser.py
+++ b/sources/shiboken2/shibokenmodule/support/signature/parser.py
@@ -76,6 +76,7 @@ def dprint(*args, **kw):
import pprint
for arg in args:
pprint.pprint(arg)
+ sys.stdout.flush()
def _parse_line(line):
line_re = r"""