aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-10-08 14:21:19 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-10-08 14:21:19 +0200
commit00fa3966dbed373e341710f1145fd23a88f1bdb0 (patch)
tree331be762988f22221b40ed93486b9b05b657f0bd
parente801fdab20ad4f5f47deaf49600af0d5f02ecc51 (diff)
parent2ed45ce8991408de91d7e02a2b80a09a2d9e5083 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
-rw-r--r--build_scripts/build_scripts.pyproject2
-rw-r--r--build_scripts/config.py1
-rw-r--r--build_scripts/main.py449
-rw-r--r--build_scripts/qp5_tool.py2
-rw-r--r--build_scripts/qtinfo.py2
-rw-r--r--build_scripts/setup_runner.py1
-rw-r--r--build_scripts/utils.py16
-rw-r--r--build_scripts/wheel_override.py22
-rw-r--r--build_scripts/wheel_utils.py162
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp19
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h22
-rw-r--r--sources/shiboken2/ApiExtractor/typesystemparser.cpp33
-rw-r--r--sources/shiboken2/generator/generator.cpp3
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp27
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp8
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp5
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp22
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py4
-rw-r--r--testing/wheel_tester.py21
20 files changed, 452 insertions, 371 deletions
diff --git a/build_scripts/build_scripts.pyproject b/build_scripts/build_scripts.pyproject
index 604419c10..80df4d386 100644
--- a/build_scripts/build_scripts.pyproject
+++ b/build_scripts/build_scripts.pyproject
@@ -1,6 +1,6 @@
{
"files": ["main.py", "__init__.py", "config.py", "options.py", "qtinfo.py",
- "setup_runner.py", "utils.py", "wheel_override.py",
+ "setup_runner.py", "utils.py", "wheel_override.py", "wheel_utils.py",
"platforms/__init__.py", "platforms/linux.py",
"platforms/macos.py", "platforms/unix.py",
"platforms/windows_desktop.py",
diff --git a/build_scripts/config.py b/build_scripts/config.py
index 0a6c3bbb2..86482a043 100644
--- a/build_scripts/config.py
+++ b/build_scripts/config.py
@@ -137,7 +137,6 @@ class Config(object):
setup_kwargs['version'] = package_version
setup_kwargs['python_requires'] = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.10"
-
if quiet:
# Tells distutils / setuptools to be quiet, and only print warnings or errors.
# Makes way less noise in the terminal when building.
diff --git a/build_scripts/main.py b/build_scripts/main.py
index c0fa16a51..8429c1fdb 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -41,10 +41,17 @@ from __future__ import print_function
from distutils.version import LooseVersion
import os
+import platform
+import re
+import sys
+from textwrap import dedent
import time
from .config import config
-from .utils import memoize, get_python_dict
+from .utils import get_python_dict
from .options import OPTION
+from .wheel_utils import (get_package_version, get_qt_version,
+ get_package_timestamp, macos_plat_name,
+ macos_pyside_min_deployment_target)
setup_script_dir = os.getcwd()
build_scripts_dir = os.path.join(setup_script_dir, 'build_scripts')
@@ -57,37 +64,6 @@ def elapsed():
return int(time.time()) - start_time
-@memoize
-def get_package_timestamp():
- """ In a Coin CI build the returned timestamp will be the
- Coin integration id timestamp. For regular builds it's
- just the current timestamp or a user provided one."""
- return OPTION["PACKAGE_TIMESTAMP"] if OPTION["PACKAGE_TIMESTAMP"] else start_time
-
-
-@memoize
-def get_package_version():
- """ Returns the version string for the PySide2 package. """
- pyside_version_py = os.path.join(
- setup_script_dir, "sources", "pyside2", "pyside_version.py")
- d = get_python_dict(pyside_version_py)
-
- final_version = "{}.{}.{}".format(
- d['major_version'], d['minor_version'], d['patch_version'])
- release_version_type = d['release_version_type']
- pre_release_version = d['pre_release_version']
- if pre_release_version and release_version_type:
- final_version += release_version_type + pre_release_version
- if release_version_type.startswith("comm"):
- final_version += "." + release_version_type
-
- # Add the current timestamp to the version number, to suggest it
- # is a development snapshot build.
- if OPTION["SNAPSHOT_BUILD"]:
- final_version += ".dev{}".format(get_package_timestamp())
- return final_version
-
-
def get_setuptools_extension_modules():
# Setting py_limited_api on the extension is the "correct" thing
# to do, but it doesn't actually do anything, because we
@@ -101,16 +77,162 @@ def get_setuptools_extension_modules():
return extension_modules
+def _get_make(platform_arch, build_type):
+ """Helper for retrieving the make command and CMake generator name"""
+ makespec = OPTION["MAKESPEC"]
+ if makespec == "make":
+ return ("make", "Unix Makefiles")
+ if makespec == "msvc":
+ nmake_path = find_executable("nmake")
+ if nmake_path is None or not os.path.exists(nmake_path):
+ log.info("nmake not found. Trying to initialize the MSVC env...")
+ init_msvc_env(platform_arch, build_type)
+ nmake_path = find_executable("nmake")
+ if not nmake_path or not os.path.exists(nmake_path):
+ raise DistutilsSetupError('"nmake" could not be found.')
+ if not OPTION["NO_JOM"]:
+ jom_path = find_executable("jom")
+ if jom_path:
+ log.info("jom was found in {}".format(jom_path))
+ return (jom_path, "NMake Makefiles JOM")
+ log.info("nmake was found in {}".format(nmake_path))
+ if OPTION["JOBS"]:
+ msg = "Option --jobs can only be used with 'jom' on Windows."
+ raise DistutilsSetupError(msg)
+ return (nmake_path, "NMake Makefiles")
+ if makespec == "mingw":
+ return ("mingw32-make", "mingw32-make")
+ if makespec == "ninja":
+ return ("ninja", "Ninja")
+ m = 'Invalid option --make-spec "{}".'.format(makespec)
+ raise DistutilsSetupError(m)
+
+
+def get_make(platform_arch, build_type):
+ """Retrieve the make command and CMake generator name"""
+ (make_path, make_generator) = _get_make(platform_arch, build_type)
+ if not os.path.isabs(make_path):
+ make_path = find_executable(make_path)
+ if not make_path or not os.path.exists(make_path):
+ raise DistutilsSetupError("You need the program '{}' on your system path to "
+ "compile PySide2.".format(make_path))
+ return (make_path, make_generator)
+
+
+def _get_py_library_win(build_type, py_version, py_prefix, py_libdir,
+ py_include_dir):
+ """Helper for finding the Python library on Windows"""
+ if py_include_dir is None or not os.path.exists(py_include_dir):
+ py_include_dir = os.path.join(py_prefix, "include")
+ if py_libdir is None or not os.path.exists(py_libdir):
+ # For virtual environments on Windows, the py_prefix will contain a
+ # path pointing to it, instead of the system Python installation path.
+ # Since INCLUDEPY contains a path to the system location, we use the
+ # same base directory to define the py_libdir variable.
+ py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
+ if not os.path.isdir(py_libdir):
+ raise DistutilsSetupError("Failed to locate the 'libs' directory")
+ dbg_postfix = "_d" if build_type == "Debug" else ""
+ if OPTION["MAKESPEC"] == "mingw":
+ static_lib_name = "libpython{}{}.a".format(
+ py_version.replace(".", ""), dbg_postfix)
+ return os.path.join(py_libdir, static_lib_name)
+ v = py_version.replace(".", "")
+ python_lib_name = "python{}{}.lib".format(v, dbg_postfix)
+ return os.path.join(py_libdir, python_lib_name)
+
+
+def _get_py_library_unix(build_type, py_version, py_prefix, py_libdir,
+ py_include_dir):
+ """Helper for finding the Python library on UNIX"""
+ if py_libdir is None or not os.path.exists(py_libdir):
+ py_libdir = os.path.join(py_prefix, "lib")
+ if py_include_dir is None or not os.path.exists(py_include_dir):
+ dir = "include/python{}".format(py_version)
+ py_include_dir = os.path.join(py_prefix, dir)
+ dbg_postfix = "_d" if build_type == "Debug" else ""
+ lib_exts = ['.so']
+ if sys.platform == 'darwin':
+ lib_exts.append('.dylib')
+ if sys.version_info[0] > 2:
+ lib_suff = getattr(sys, 'abiflags', None)
+ else: # Python 2
+ lib_suff = ''
+ lib_exts.append('.so.1')
+ # Suffix for OpenSuSE 13.01
+ lib_exts.append('.so.1.0')
+ # static library as last gasp
+ lib_exts.append('.a')
+
+ if sys.version_info[0] == 2 and dbg_postfix:
+ # For Python2 add a duplicate set of extensions combined with the
+ # dbg_postfix, so we test for both the debug version of the lib
+ # and the normal one. This allows a debug PySide2 to be built with a
+ # non-debug Python.
+ lib_exts = [dbg_postfix + e for e in lib_exts] + lib_exts
+
+ libs_tried = []
+ for lib_ext in lib_exts:
+ lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
+ py_library = os.path.join(py_libdir, lib_name)
+ if os.path.exists(py_library):
+ return py_library
+ libs_tried.append(py_library)
+ # At least on macOS 10.11, the system Python 2.6 does not include a
+ # symlink to the framework file disguised as a .dylib file, thus finding
+ # the library would fail. Manually check if a framework file "Python"
+ # exists in the Python framework bundle.
+ if sys.platform == 'darwin' and sys.version_info[:2] == (2, 6):
+ # These manipulations essentially transform
+ # /System/Library/Frameworks/Python.framework/Versions/2.6/lib
+ # to
+ # /System/Library/Frameworks/Python.framework/Versions/2.6/Python
+ possible_framework_path = os.path.realpath(os.path.join(py_libdir, '..'))
+ possible_framework_version = os.path.basename(possible_framework_path)
+ possible_framework_library = os.path.join(possible_framework_path, 'Python')
+
+ if (possible_framework_version == '2.6'
+ and os.path.exists(possible_framework_library)):
+ return possible_framework_library
+ libs_tried.append(possible_framework_library)
+
+ # Try to find shared libraries which have a multi arch
+ # suffix.
+ py_multiarch = get_config_var("MULTIARCH")
+ if py_multiarch:
+ try_py_libdir = os.path.join(py_libdir, py_multiarch)
+ libs_tried = []
+ for lib_ext in lib_exts:
+ lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
+ py_library = os.path.join(try_py_libdir, lib_name)
+ if os.path.exists(py_library):
+ return py_library
+ libs_tried.append(py_library)
+
+ m = "Failed to locate the Python library with {}".format(", ".join(libs_tried))
+ raise DistutilsSetupError(m)
+
+
+def get_py_library(build_type, py_version, py_prefix, py_libdir, py_include_dir):
+ """Find the Python library"""
+ if sys.platform == "win32":
+ py_library = _get_py_library_win(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
+ else:
+ py_library = _get_py_library_unix(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
+ if py_library.endswith('.a'):
+ # Python was compiled as a static library
+ log.error("Failed to locate a dynamic Python library, using {}".format(py_library))
+ return py_library
+
+
try:
import setuptools
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
-import sys
-import platform
-import re
-
import distutils.log as log
from distutils.errors import DistutilsSetupError
from distutils.sysconfig import get_config_var
@@ -137,8 +259,6 @@ from .platforms.unix import prepare_packages_posix
from .platforms.windows_desktop import prepare_packages_win32
from .wheel_override import wheel_module_exists, get_bdist_wheel_override
-from textwrap import dedent
-
def check_allowed_python_version():
"""
@@ -243,21 +363,6 @@ qtinfo = QtInfo()
qtinfo.setup(OPTION["QMAKE"], OPTION["QT_VERSION"])
-def get_qt_version():
- qt_version = qtinfo.version
-
- if not qt_version:
- log.error("Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command))
- sys.exit(1)
-
- if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
- log.error("Incompatible Qt version detected: {}. A Qt version >= 5.7 is "
- "required.".format(qt_version))
- sys.exit(1)
-
- return qt_version
-
-
def prepare_build():
# Clean up temp build folder.
for n in ["build"]:
@@ -374,7 +479,7 @@ class PysideBuild(_build):
def finalize_options(self):
os_name_backup = os.name
if sys.platform == 'darwin':
- self.plat_name = PysideBuild.macos_plat_name()
+ self.plat_name = macos_plat_name()
# This is a hack to circumvent the dubious check in
# distutils.commands.build -> finalize_options, which only
# allows setting the plat_name for windows NT.
@@ -421,49 +526,7 @@ class PysideBuild(_build):
make_path = None
make_generator = None
if not OPTION["ONLYPACKAGE"]:
- if OPTION["MAKESPEC"] == "make":
- make_name = "make"
- make_generator = "Unix Makefiles"
- elif OPTION["MAKESPEC"] == "msvc":
- nmake_path = find_executable("nmake")
- if nmake_path is None or not os.path.exists(nmake_path):
- log.info("nmake not found. Trying to initialize the MSVC env...")
- init_msvc_env(platform_arch, build_type)
- nmake_path = find_executable("nmake")
- assert(nmake_path is not None and os.path.exists(nmake_path))
- jom_path = None if OPTION["NO_JOM"] else find_executable("jom")
- if jom_path is not None and os.path.exists(jom_path):
- log.info("jom was found in {}".format(jom_path))
- make_name = "jom"
- make_generator = "NMake Makefiles JOM"
- else:
- log.info("nmake was found in {}".format(nmake_path))
- make_name = "nmake"
- make_generator = "NMake Makefiles"
- if OPTION["JOBS"]:
- msg = "Option --jobs can only be used with 'jom' on Windows."
- raise DistutilsSetupError(msg)
- elif OPTION["MAKESPEC"] == "mingw":
- make_name = "mingw32-make"
- make_generator = "MinGW Makefiles"
- elif OPTION["MAKESPEC"] == "ninja":
- make_name = "ninja"
- make_generator = "Ninja"
- else:
- raise DistutilsSetupError("Invalid option --make-spec.")
- make_path = find_executable(make_name)
- if make_path is None or not os.path.exists(make_path):
- raise DistutilsSetupError("You need the program '{}' on your system path to "
- "compile PySide2.".format(make_name))
-
- if OPTION["CMAKE"] is None or not os.path.exists(OPTION["CMAKE"]):
- raise DistutilsSetupError("Failed to find cmake."
- " Please specify the path to cmake with "
- "--cmake parameter.")
-
- if OPTION["QMAKE"] is None or not os.path.exists(OPTION["QMAKE"]):
- raise DistutilsSetupError("Failed to find qmake. "
- "Please specify the path to qmake with --qmake parameter.")
+ (make_path, make_generator) = get_make(platform_arch, build_type)
# Prepare parameters
py_executable = sys.executable
@@ -479,111 +542,6 @@ class PysideBuild(_build):
else:
py_scripts_dir = os.path.join(py_prefix, "bin")
self.py_scripts_dir = py_scripts_dir
- if py_libdir is None or not os.path.exists(py_libdir):
- if sys.platform == "win32":
- # For virtual environments on Windows, the py_prefix will contain a path pointing
- # to it, instead of the system Python installation path.
- # Since INCLUDEPY contains a path to the system location, we use the same base
- # directory to define the py_libdir variable.
- py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
- if not os.path.isdir(py_libdir):
- raise DistutilsSetupError("Failed to locate the 'libs' directory")
- else:
- py_libdir = os.path.join(py_prefix, "lib")
- if py_include_dir is None or not os.path.exists(py_include_dir):
- if sys.platform == "win32":
- py_include_dir = os.path.join(py_prefix, "include")
- else:
- py_include_dir = os.path.join(py_prefix, "include/python{}".format(py_version))
- dbg_postfix = ""
- if build_type == "Debug":
- dbg_postfix = "_d"
- if sys.platform == "win32":
- if OPTION["MAKESPEC"] == "mingw":
- static_lib_name = "libpython{}{}.a".format(
- py_version.replace(".", ""), dbg_postfix)
- py_library = os.path.join(py_libdir, static_lib_name)
- else:
- python_lib_name = "python{}{}.lib".format(
- py_version.replace(".", ""), dbg_postfix)
- py_library = os.path.join(py_libdir, python_lib_name)
- else:
- lib_exts = ['.so']
- if sys.platform == 'darwin':
- lib_exts.append('.dylib')
- if sys.version_info[0] > 2:
- lib_suff = getattr(sys, 'abiflags', None)
- else: # Python 2
- lib_suff = ''
- lib_exts.append('.so.1')
- # Suffix for OpenSuSE 13.01
- lib_exts.append('.so.1.0')
- # static library as last gasp
- lib_exts.append('.a')
-
- if sys.version_info[0] == 2 and dbg_postfix:
- # For Python2 add a duplicate set of extensions
- # combined with the dbg_postfix, so we test for both the
- # debug version of the lib and the normal one.
- # This allows a debug PySide2 to be built with a
- # non-debug Python.
- lib_exts = [dbg_postfix + e for e in lib_exts] + lib_exts
-
- python_library_found = False
- libs_tried = []
- for lib_ext in lib_exts:
- lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
- py_library = os.path.join(py_libdir, lib_name)
- if os.path.exists(py_library):
- python_library_found = True
- break
- libs_tried.append(py_library)
- else:
- # At least on macOS 10.11, the system Python 2.6 does
- # not include a symlink to the framework file disguised
- # as a .dylib file, thus finding the library would
- # fail.
- # Manually check if a framework file "Python" exists in
- # the Python framework bundle.
- if sys.platform == 'darwin' and sys.version_info[:2] == (2, 6):
- # These manipulations essentially transform
- # /System/Library/Frameworks/Python.framework/Versions/2.6/lib
- # to
- # /System/Library/Frameworks/Python.framework/Versions/2.6/Python
- possible_framework_path = os.path.realpath(os.path.join(py_libdir, '..'))
- possible_framework_version = os.path.basename(possible_framework_path)
- possible_framework_library = os.path.join(possible_framework_path, 'Python')
-
- if (possible_framework_version == '2.6'
- and os.path.exists(possible_framework_library)):
- py_library = possible_framework_library
- python_library_found = True
- else:
- libs_tried.append(possible_framework_library)
-
- # Try to find shared libraries which have a multi arch
- # suffix.
- if not python_library_found:
- py_multiarch = get_config_var("MULTIARCH")
- if py_multiarch and not python_library_found:
- try_py_libdir = os.path.join(py_libdir, py_multiarch)
- libs_tried = []
- for lib_ext in lib_exts:
- lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
- py_library = os.path.join(try_py_libdir, lib_name)
- if os.path.exists(py_library):
- py_libdir = try_py_libdir
- python_library_found = True
- break
- libs_tried.append(py_library)
-
- if not python_library_found:
- raise DistutilsSetupError(
- "Failed to locate the Python library with {}".format(", ".join(libs_tried)))
-
- if py_library.endswith('.a'):
- # Python was compiled as a static library
- log.error("Failed to locate a dynamic Python library, using {}".format(py_library))
self.qtinfo = qtinfo
qt_dir = os.path.dirname(OPTION["QMAKE"])
@@ -633,7 +591,8 @@ class PysideBuild(_build):
self.install_dir = install_dir
self.py_executable = py_executable
self.py_include_dir = py_include_dir
- self.py_library = py_library
+ self.py_library = get_py_library(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
self.py_version = py_version
self.build_type = build_type
self.site_packages_dir = get_python_lib(1, 0, prefix=install_dir)
@@ -743,74 +702,12 @@ class PysideBuild(_build):
log.info("OpenSSL dll directory: {}".format(OPTION["OPENSSL"]))
if sys.platform == 'darwin':
pyside_macos_deployment_target = (
- PysideBuild.macos_pyside_min_deployment_target()
+ macos_pyside_min_deployment_target()
)
log.info("MACOSX_DEPLOYMENT_TARGET set to: {}".format(
pyside_macos_deployment_target))
log.info("=" * 30)
- @staticmethod
- def macos_qt_min_deployment_target():
- target = qtinfo.macos_min_deployment_target
-
- if not target:
- raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.")
- return target
-
- @staticmethod
- @memoize
- def macos_pyside_min_deployment_target():
- """
- Compute and validate PySide2 MACOSX_DEPLOYMENT_TARGET value.
- Candidate sources that are considered:
- - setup.py provided value
- - maximum value between minimum deployment target of the
- Python interpreter and the minimum deployment target of
- the Qt libraries.
- If setup.py value is provided, that takes precedence.
- Otherwise use the maximum of the above mentioned two values.
- """
- python_target = get_config_var('MACOSX_DEPLOYMENT_TARGET') or None
- qt_target = PysideBuild.macos_qt_min_deployment_target()
- setup_target = OPTION["MACOS_DEPLOYMENT_TARGET"]
-
- qt_target_split = [int(x) for x in qt_target.split('.')]
- if python_target:
- python_target_split = [int(x) for x in python_target.split('.')]
- if setup_target:
- setup_target_split = [int(x) for x in setup_target.split('.')]
-
- message = ("Can't set MACOSX_DEPLOYMENT_TARGET value to {} because "
- "{} was built with minimum deployment target set to {}.")
- # setup.py provided OPTION["MACOS_DEPLOYMENT_TARGET"] value takes
- # precedence.
- if setup_target:
- if python_target and setup_target_split < python_target_split:
- raise DistutilsSetupError(message.format(setup_target, "Python",
- python_target))
- if setup_target_split < qt_target_split:
- raise DistutilsSetupError(message.format(setup_target, "Qt",
- qt_target))
- # All checks clear, use setup.py provided value.
- return setup_target
-
- # Setup.py value not provided,
- # use same value as provided by Qt.
- if python_target:
- maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)])
- else:
- maximum_target = qt_target
- return maximum_target
-
- @staticmethod
- @memoize
- def macos_plat_name():
- deployment_target = PysideBuild.macos_pyside_min_deployment_target()
- # Example triple "macosx-10.12-x86_64".
- plat = get_platform().split("-")
- plat_name = "{}-{}-{}".format(plat[0], deployment_target, plat[2])
- return plat_name
-
def build_patchelf(self):
if not sys.platform.startswith('linux'):
return
@@ -1004,7 +901,7 @@ class PysideBuild(_build):
# interpreter sysconfig value.
# Doing so could break the detected clang include paths
# for example.
- deployment_target = PysideBuild.macos_pyside_min_deployment_target()
+ deployment_target = macos_pyside_min_deployment_target()
cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format(deployment_target))
os.environ['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
@@ -1268,9 +1165,11 @@ class PysideBuild(_build):
log.info("Patched rpath to '$ORIGIN/' (Linux) or "
"updated rpath (OS/X) in {}.".format(srcpath))
+
class PysideRstDocs(Command):
description = "Build .rst documentation only"
user_options = []
+
def initialize_options(self):
log.info("-- This build process will not include the API documentation."
"API documentation requires a full build of pyside/shiboken.")
@@ -1331,12 +1230,8 @@ class PysideRstDocs(Command):
elif self.name == "shiboken2":
self.sphinx_src = self.out_dir
- sphinx_cmd = ["sphinx-build",
- "-b", "html",
- "-c", self.sphinx_src,
- self.doc_dir,
- self.out_dir
- ]
+ sphinx_cmd = ["sphinx-build", "-b", "html", "-c", self.sphinx_src,
+ self.doc_dir, self.out_dir]
if run_process(sphinx_cmd) != 0:
raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
# Last message
@@ -1346,6 +1241,7 @@ class PysideRstDocs(Command):
def finalize_options(self):
pass
+
cmd_class_dict = {
'build': PysideBuild,
'build_py': PysideBuildPy,
@@ -1357,11 +1253,6 @@ cmd_class_dict = {
'build_rst_docs': PysideRstDocs,
}
if wheel_module_exists:
- params = {}
- params['qt_version'] = get_qt_version()
- params['package_version'] = get_package_version()
- if sys.platform == 'darwin':
- params['macos_plat_name'] = PysideBuild.macos_plat_name()
- pyside_bdist_wheel = get_bdist_wheel_override(params)
+ pyside_bdist_wheel = get_bdist_wheel_override()
if pyside_bdist_wheel:
cmd_class_dict['bdist_wheel'] = pyside_bdist_wheel
diff --git a/build_scripts/qp5_tool.py b/build_scripts/qp5_tool.py
index 1358b21c2..b213948e7 100644
--- a/build_scripts/qp5_tool.py
+++ b/build_scripts/qp5_tool.py
@@ -390,7 +390,7 @@ if __name__ == '__main__':
build_mode = BuildMode.RECONFIGURE
if build_mode == BuildMode.NONE and not (options.clean or options.reset
- or options.pull or options.test):
+ or options.pull or options.test):
argument_parser.print_help()
sys.exit(0)
diff --git a/build_scripts/qtinfo.py b/build_scripts/qtinfo.py
index fa2d771b2..62bfee812 100644
--- a/build_scripts/qtinfo.py
+++ b/build_scripts/qtinfo.py
@@ -125,7 +125,7 @@ class QtInfo(object):
return self.get_property("QT_INSTALL_PREFIX/src")
def get_property(self, prop_name):
- if not self._query_dict:
+ if not self._query_dict:
self._get_query_properties()
self._get_other_properties()
if prop_name not in self._query_dict:
diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py
index 15a0bf380..b54c62796 100644
--- a/build_scripts/setup_runner.py
+++ b/build_scripts/setup_runner.py
@@ -54,6 +54,7 @@ from setuptools import setup
if OPTION["VERBOSE_BUILD"]:
log.set_verbosity(1)
+
class SetupRunner(object):
def __init__(self, orig_argv):
self.invocations_list = []
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index ad17a7ba8..220d32efe 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -1081,18 +1081,20 @@ def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch):
# With windows we are creating building 32-bit target in 64-bit host
if hostArch == "X86_64" and targetArch == "X86":
if python_ver.startswith("3"):
- print("Try to find python from {} env variable".format("PYTHON"+python_ver+"-32_PATH"))
- _path = os.getenv("PYTHON"+python_ver+"-32_PATH", "")
+ var = "PYTHON" + python_ver + "-32_PATH"
+ print("Try to find python from {} env variable".format(var))
+ _path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
_pExe = os.path.join(os.getenv("PYTHON3_32_PATH"), "python.exe")
else:
- _pExe = os.path.join(os.getenv("PYTHON2_32_PATH"), "python.exe")
+ _pExe = os.path.join(os.getenv("PYTHON2_32_PATH"), "python.exe")
else:
- if python_ver.startswith("3"):
- print("Try to find python from {} env variable".format("PYTHON"+python_ver+"-64_PATH"))
- _path = os.getenv("PYTHON"+python_ver+"-64_PATH", "")
+ if python_ver.startswith("3"):
+ var = "PYTHON" + python_ver + "-64_PATH"
+ print("Try to find python from {} env variable".format(var))
+ _path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
@@ -1137,6 +1139,6 @@ def get_ci_qmake_path(ci_install_dir, ci_host_os):
if ci_host_os == "MacOS":
return qmake_path + "/bin/qmake"
elif ci_host_os == "Windows":
- return qmake_path + "\\bin\\qmake.exe"
+ return qmake_path + "\\bin\\qmake.exe"
else:
return qmake_path + "/bin/qmake"
diff --git a/build_scripts/wheel_override.py b/build_scripts/wheel_override.py
index 0a3cb0dbf..e4147a5bc 100644
--- a/build_scripts/wheel_override.py
+++ b/build_scripts/wheel_override.py
@@ -54,6 +54,7 @@ try:
from wheel import __version__ as wheel_version
from .options import OPTION
+ from .wheel_utils import get_package_version, get_qt_version, macos_plat_name
wheel_module_exists = True
except Exception as e:
@@ -62,20 +63,13 @@ except Exception as e:
'Skipping wheel overriding.'.format(e))
-def get_bdist_wheel_override(params):
- if wheel_module_exists:
- class PysideBuildWheelDecorated(PysideBuildWheel):
- def __init__(self, *args, **kwargs):
- self.params = params
- PysideBuildWheel.__init__(self, *args, **kwargs)
- return PysideBuildWheelDecorated
- else:
- return None
+def get_bdist_wheel_override():
+ return PysideBuildWheel if wheel_module_exists else None
class PysideBuildWheel(_bdist_wheel):
def __init__(self, *args, **kwargs):
- self.pyside_params = None
+ self._package_version = None
_bdist_wheel.__init__(self, *args, **kwargs)
def finalize_options(self):
@@ -83,7 +77,7 @@ class PysideBuildWheel(_bdist_wheel):
# Override the platform name to contain the correct
# minimum deployment target.
# This is used in the final wheel name.
- self.plat_name = self.params['macos_plat_name']
+ self.plat_name = macos_plat_name()
# When limited API is requested, notify bdist_wheel to
# create a properly named package.
@@ -92,6 +86,8 @@ class PysideBuildWheel(_bdist_wheel):
if limited_api_enabled:
self.py_limited_api = "cp35.cp36.cp37.cp38.cp39"
+ self._package_version = get_package_version()
+
_bdist_wheel.finalize_options(self)
@property
@@ -102,9 +98,7 @@ class PysideBuildWheel(_bdist_wheel):
# PySide2-5.6-5.6.4-cp27-cp27m-macosx_10_10_intel.whl
# The PySide2 version is "5.6".
# The Qt version built against is "5.6.4".
- qt_version = self.params['qt_version']
- package_version = self.params['package_version']
- wheel_version = "{}-{}".format(package_version, qt_version)
+ wheel_version = "{}-{}".format(self._package_version, get_qt_version())
components = (_safer_name(self.distribution.get_name()), wheel_version)
if self.build_number:
components += (self.build_number,)
diff --git a/build_scripts/wheel_utils.py b/build_scripts/wheel_utils.py
new file mode 100644
index 000000000..71b4e0acf
--- /dev/null
+++ b/build_scripts/wheel_utils.py
@@ -0,0 +1,162 @@
+#############################################################################
+##
+## Copyright (C) 2020 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
+
+import os
+import time
+
+from distutils.errors import DistutilsSetupError
+from distutils.sysconfig import get_config_var
+from distutils.util import get_platform
+from distutils.version import LooseVersion
+
+from .options import OPTION
+from .qtinfo import QtInfo
+from .utils import memoize, get_python_dict
+
+
+@memoize
+def get_package_timestamp():
+ """ In a Coin CI build the returned timestamp will be the
+ Coin integration id timestamp. For regular builds it's
+ just the current timestamp or a user provided one."""
+ option_value = OPTION["PACKAGE_TIMESTAMP"]
+ return option_value if option_value else int(time.time())
+
+
+def get_qt_version():
+ qtinfo = QtInfo()
+ qt_version = qtinfo.version
+
+ if not qt_version:
+ m = "Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command)
+ raise DistutilsSetupError(m)
+
+ if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
+ m = "Incompatible Qt version detected: {}. A Qt version >= 5.7 is required.".format(qt_version)
+ raise DistutilsSetupError(m)
+
+ return qt_version
+
+
+@memoize
+def get_package_version():
+ """ Returns the version string for the PySide2 package. """
+ setup_script_dir = os.getcwd()
+ pyside_version_py = os.path.join(
+ setup_script_dir, "sources", "pyside2", "pyside_version.py")
+ d = get_python_dict(pyside_version_py)
+
+ final_version = "{}.{}.{}".format(
+ d['major_version'], d['minor_version'], d['patch_version'])
+ release_version_type = d['release_version_type']
+ pre_release_version = d['pre_release_version']
+ if pre_release_version and release_version_type:
+ final_version += release_version_type + pre_release_version
+ if release_version_type.startswith("comm"):
+ final_version += "." + release_version_type
+
+ # Add the current timestamp to the version number, to suggest it
+ # is a development snapshot build.
+ if OPTION["SNAPSHOT_BUILD"]:
+ final_version += ".dev{}".format(get_package_timestamp())
+ return final_version
+
+
+def macos_qt_min_deployment_target():
+ target = QtInfo().macos_min_deployment_target
+
+ if not target:
+ raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.")
+ return target
+
+
+@memoize
+def macos_pyside_min_deployment_target():
+ """
+ Compute and validate PySide2 MACOSX_DEPLOYMENT_TARGET value.
+ Candidate sources that are considered:
+ - setup.py provided value
+ - maximum value between minimum deployment target of the
+ Python interpreter and the minimum deployment target of
+ the Qt libraries.
+ If setup.py value is provided, that takes precedence.
+ Otherwise use the maximum of the above mentioned two values.
+ """
+ python_target = get_config_var('MACOSX_DEPLOYMENT_TARGET') or None
+ qt_target = macos_qt_min_deployment_target()
+ setup_target = OPTION["MACOS_DEPLOYMENT_TARGET"]
+
+ qt_target_split = [int(x) for x in qt_target.split('.')]
+ if python_target:
+ python_target_split = [int(x) for x in python_target.split('.')]
+ if setup_target:
+ setup_target_split = [int(x) for x in setup_target.split('.')]
+
+ message = ("Can't set MACOSX_DEPLOYMENT_TARGET value to {} because "
+ "{} was built with minimum deployment target set to {}.")
+ # setup.py provided OPTION["MACOS_DEPLOYMENT_TARGET"] value takes
+ # precedence.
+ if setup_target:
+ if python_target and setup_target_split < python_target_split:
+ raise DistutilsSetupError(message.format(setup_target, "Python",
+ python_target))
+ if setup_target_split < qt_target_split:
+ raise DistutilsSetupError(message.format(setup_target, "Qt",
+ qt_target))
+ # All checks clear, use setup.py provided value.
+ return setup_target
+
+ # Setup.py value not provided,
+ # use same value as provided by Qt.
+ if python_target:
+ maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)])
+ else:
+ maximum_target = qt_target
+ return maximum_target
+
+
+@memoize
+def macos_plat_name():
+ deployment_target = macos_pyside_min_deployment_target()
+ # Example triple "macosx-10.12-x86_64".
+ plat = get_platform().split("-")
+ plat_name = "{}-{}-{}".format(plat[0], deployment_target, plat[2])
+ return plat_name
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index d06a338a3..70cccebcd 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -175,12 +175,12 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
const TypeEntry *entry = it.value();
if (!entry)
continue;
- if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
+ if (!entry->isComplex() || !entry->generateCode())
continue;
auto centry = static_cast<const ComplexTypeEntry *>(entry);
- if (!(centry->codeGeneration() & TypeEntry::GenerateTargetLang))
+ if (!centry->generateCode())
continue;
FunctionModificationList modifications = centry->functionModifications();
@@ -290,7 +290,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
if (arguments.size() == 1) {
unaryOperator = true;
} else if (!baseoperandClass
- || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) {
+ || !baseoperandClass->typeEntry()->generateCode()) {
baseoperandClass = argumentToClass(arguments.at(1), currentClass);
firstArgumentIsSelf = false;
} else {
@@ -551,7 +551,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
&& !types->shouldDropTypeEntry(entry->qualifiedCppName())
&& !entry->isContainer()
&& !entry->isCustom()
- && (entry->generateCode() & TypeEntry::GenerateTargetLang)
+ && entry->generateCode()
&& !AbstractMetaClass::findClass(m_metaClasses, entry)) {
qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry)));
} else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
@@ -570,7 +570,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
qPrintable(msgGlobalFunctionNotDefined(fte, signature)));
}
}
- } else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) {
+ } else if (entry->isEnum() && entry->generateCode()) {
auto enumEntry = static_cast<const EnumTypeEntry *>(entry);
const QString name = enumEntry->targetLangQualifier();
AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
@@ -855,8 +855,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &
return nullptr;
}
- const bool rejectionWarning = !enclosing
- || (enclosing->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang);
+ const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode();
if (!typeEntry) {
if (rejectionWarning)
@@ -1185,7 +1184,7 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel
if (!metaType) {
const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
- if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) {
+ if (cls->typeEntry()->generateCode()) {
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingField(field, cls->name(), type)));
}
@@ -1865,9 +1864,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
// unless the function is virtual (since the override in the
// wrapper can then not correctly be generated).
if (arg->defaultValue() && !functionItem->isVirtual()) {
- if (!currentClass
- || (currentClass->typeEntry()->codeGeneration()
- & TypeEntry::GenerateTargetLang)) {
+ if (!currentClass || currentClass->typeEntry()->generateCode()) {
qCWarning(lcShiboken, "%s",
qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
}
diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp
index 87f5c49df..0d5a8cba7 100644
--- a/sources/shiboken2/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp
@@ -432,7 +432,7 @@ ConstantValueTypeEntry *
const TypeEntry *parent)
{
auto result = new ConstantValueTypeEntry(value, parent);
- result->setCodeGeneration(0);
+ result->setCodeGeneration(TypeEntry::GenerateNothing);
addType(result);
return result;
}
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index 00f56c51e..d3ef2c629 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -598,13 +598,10 @@ public:
Q_ENUM(Type)
enum CodeGeneration {
- GenerateTargetLang = 0x0001,
- GenerateCpp = 0x0002,
- GenerateForSubclass = 0x0004,
-
- GenerateNothing = 0,
- GenerateAll = 0xffff,
- GenerateCode = GenerateTargetLang | GenerateCpp
+ GenerateNothing, // Rejection, private type, ConstantValueTypeEntry or similar
+ GenerationDisabled, // generate='no' in type system
+ GenerateCode, // Generate code
+ GenerateForSubclass, // Inherited from a loaded dependent type system.
};
Q_ENUM(CodeGeneration)
@@ -703,11 +700,11 @@ public:
// Name as specified in XML
QString entryName() const { return m_entryName; }
- uint codeGeneration() const
+ CodeGeneration codeGeneration() const
{
return m_codeGeneration;
}
- void setCodeGeneration(uint cg)
+ void setCodeGeneration(CodeGeneration cg)
{
m_codeGeneration = cg;
}
@@ -719,8 +716,7 @@ public:
// on 'load-typesystem' tag
inline bool generateCode() const
{
- return m_codeGeneration != TypeEntry::GenerateForSubclass
- && m_codeGeneration != TypeEntry::GenerateNothing;
+ return m_codeGeneration == GenerateCode;
}
int revision() const { return m_revision; }
@@ -804,7 +800,7 @@ public:
return m_docModifications;
}
- IncludeList extraIncludes() const
+ const IncludeList &extraIncludes() const
{
return m_extraIncludes;
}
@@ -903,7 +899,7 @@ private:
QVersionNumber m_version;
CustomConversion *m_customConversion = nullptr;
SourceLocation m_sourceLocation; // XML file
- uint m_codeGeneration = GenerateAll;
+ CodeGeneration m_codeGeneration = GenerateCode;
TypeEntry *m_viewOn = nullptr;
int m_revision = 0;
int m_sbkIndex = 0;
diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp
index 7323e01f6..9ad9322b2 100644
--- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp
@@ -505,7 +505,7 @@ QString TypeSystemEntityResolver::resolveUndeclaredEntity(const QString &name)
TypeSystemParser::TypeSystemParser(TypeDatabase *database, bool generate) :
m_database(database),
- m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass)
+ m_generate(generate ? TypeEntry::GenerateCode : TypeEntry::GenerateForSubclass)
{
}
@@ -775,7 +775,7 @@ bool TypeSystemParser::endElement(QStringView localName)
switch (m_current->type) {
case StackElement::Root:
- if (m_generate == TypeEntry::GenerateAll) {
+ if (m_generate == TypeEntry::GenerateCode) {
TypeDatabase::instance()->addGlobalUserFunctions(m_contextStack.top()->addedFunctions);
TypeDatabase::instance()->addGlobalUserFunctionModifications(m_contextStack.top()->functionMods);
for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) {
@@ -790,13 +790,26 @@ bool TypeSystemParser::endElement(QStringView localName)
case StackElement::InterfaceTypeEntry:
case StackElement::NamespaceTypeEntry: {
auto *centry = static_cast<ComplexTypeEntry *>(m_current->entry);
- centry->setAddedFunctions(m_contextStack.top()->addedFunctions);
- centry->setFunctionModifications(m_contextStack.top()->functionMods);
- centry->setFieldModifications(m_contextStack.top()->fieldMods);
- centry->setCodeSnips(m_contextStack.top()->codeSnips);
- centry->setDocModification(m_contextStack.top()->docModifications);
+ auto top = m_contextStack.top();
+ centry->setAddedFunctions(top->addedFunctions);
+ centry->setFunctionModifications(top->functionMods);
+ centry->setFieldModifications(top->fieldMods);
+ centry->setCodeSnips(top->codeSnips);
+ centry->setDocModification(top->docModifications);
}
break;
+
+ case StackElement::TypedefTypeEntry: {
+ auto *centry = static_cast<TypedefEntry *>(m_current->entry)->target();
+ auto top = m_contextStack.top();
+ centry->setAddedFunctions(centry->addedFunctions() + top->addedFunctions);
+ centry->setFunctionModifications(centry->functionModifications() + top->functionMods);
+ centry->setFieldModifications(centry->fieldModifications() + top->fieldMods);
+ centry->setCodeSnips(centry->codeSnips() + top->codeSnips);
+ centry->setDocModification(centry->docModifications() + top->docModifications);
+ }
+ break;
+
case StackElement::AddFunction: {
// Leaving add-function: Assign all modifications to the added function
StackElementContext *top = m_contextStack.top();
@@ -1576,7 +1589,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const QXmlStreamReader &reader
if (generate)
ctype->setCodeGeneration(m_generate);
else
- ctype->setCodeGeneration(TypeEntry::GenerateForSubclass);
+ ctype->setCodeGeneration(TypeEntry::GenerationDisabled);
}
bool TypeSystemParser::parseRenameFunction(const QXmlStreamReader &,
@@ -1760,7 +1773,7 @@ bool TypeSystemParser::loadTypesystem(const QXmlStreamReader &,
}
const bool result =
m_database->parseFile(typeSystemName, m_currentPath, generateChild
- && m_generate == TypeEntry::GenerateAll);
+ && m_generate == TypeEntry::GenerateCode);
if (!result)
m_error = QStringLiteral("Failed to parse: '%1'").arg(typeSystemName);
return result;
@@ -2779,7 +2792,7 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader)
auto *element = new StackElement(m_current);
element->type = elementType;
- if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateAll)
+ if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateCode)
customConversionsForReview.clear();
if (element->type == StackElement::CustomMetaConstructor
diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp
index 487715a3c..445743a74 100644
--- a/sources/shiboken2/generator/generator.cpp
+++ b/sources/shiboken2/generator/generator.cpp
@@ -502,8 +502,7 @@ bool Generator::generate()
bool Generator::shouldGenerateTypeEntry(const TypeEntry *type) const
{
- return (type->codeGeneration() & TypeEntry::GenerateTargetLang)
- && NamespaceTypeEntry::isVisibleScope(type);
+ return type->generateCode() && NamespaceTypeEntry::isVisibleScope(type);
}
bool Generator::shouldGenerate(const AbstractMetaClass *metaClass) const
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 18137a985..a6e9a00b6 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -393,14 +393,18 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo
metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
//Extra includes
- s << "\n// Extra includes\n";
- QVector<Include> includes = metaClass->typeEntry()->extraIncludes();
+ QVector<Include> includes;
+ if (!classContext.useWrapper())
+ includes += metaClass->typeEntry()->extraIncludes();
for (AbstractMetaEnum *cppEnum : qAsConst(classEnums))
includes.append(cppEnum->typeEntry()->extraIncludes());
- std::sort(includes.begin(), includes.end());
- for (const Include &inc : qAsConst(includes))
- s << inc.toString() << Qt::endl;
- s << Qt::endl;
+ if (!includes.isEmpty()) {
+ s << "\n// Extra includes\n";
+ std::sort(includes.begin(), includes.end());
+ for (const Include &inc : qAsConst(includes))
+ s << inc.toString() << Qt::endl;
+ s << '\n';
+ }
s << "\n#include <cctype>\n#include <cstring>\n";
@@ -5234,9 +5238,16 @@ void CppGenerator::writeClassRegister(QTextStream &s,
s << "0,\n";
}
- // 6:baseType
- const auto base = metaClass->isNamespace()
+ // 6:baseType: Find a type that is not disabled.
+ auto base = metaClass->isNamespace()
? metaClass->extendedNamespace() : metaClass->baseClass();
+ if (!metaClass->isNamespace()) {
+ for (; base != nullptr; base = base->baseClass()) {
+ const auto ct = base->typeEntry()->codeGeneration();
+ if (ct == TypeEntry::GenerateCode || ct == TypeEntry::GenerateForSubclass)
+ break;
+ }
+ }
if (base) {
s << INDENT << "reinterpret_cast<SbkObjectType *>("
<< cpythonTypeNameExt(base->typeEntry()) << "),\n";
diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
index 1d3a20447..1ba846d87 100644
--- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
@@ -119,7 +119,13 @@ void HeaderGenerator::generateClass(QTextStream &s, const GeneratorContext &clas
s << "#define protected public\n\n";
//Includes
- s << metaClass->typeEntry()->include() << Qt::endl;
+ auto typeEntry = metaClass->typeEntry();
+ s << typeEntry->include() << '\n';
+ if (classContext.useWrapper() && !typeEntry->extraIncludes().isEmpty()) {
+ s << "\n// Extra includes\n";
+ for (const Include &inc : typeEntry->extraIncludes())
+ s << inc.toString() << '\n';
+ }
if (classContext.useWrapper() && usePySideExtensions() && metaClass->isQObject())
s << "namespace PySide { class DynamicQMetaObject; }\n\n";
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index a6a175999..7b8f2c7e4 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -929,7 +929,7 @@ QString ShibokenGenerator::fixedCppTypeName(const TypeEntry *type, QString typeN
{
if (typeName.isEmpty())
typeName = type->qualifiedCppName();
- if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang)) {
+ if (!type->generateCode()) {
typeName.prepend(QLatin1Char('_'));
typeName.prepend(type->targetLangPackage());
}
@@ -1609,8 +1609,7 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter
// Get only the conversion operators that return a type from another module,
// that are value-types and were not removed in the type system.
const TypeEntry *convType = convOp->type()->typeEntry();
- if ((convType->codeGeneration() & TypeEntry::GenerateTargetLang)
- || !convType->isValue()
+ if (convType->generateCode() || !convType->isValue()
|| convOp->isModifiedRemoved())
continue;
extConvs[convType].append(convOp->ownerClass());
diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp
index fff9d05ec..ca32f5919 100644
--- a/sources/shiboken2/libshiboken/sbkstring.cpp
+++ b/sources/shiboken2/libshiboken/sbkstring.cpp
@@ -42,6 +42,7 @@
#include "autodecref.h"
#include <vector>
+#include <unordered_set>
namespace Shiboken
{
@@ -183,7 +184,7 @@ Py_ssize_t len(PyObject *str)
// PyObject *attr = PyObject_GetAttr(obj, name());
//
-using StaticStrings = std::vector<PyObject *>;
+using StaticStrings = std::unordered_set<PyObject *>;
static void finalizeStaticStrings(); // forward
@@ -195,10 +196,12 @@ static StaticStrings &staticStrings()
static void finalizeStaticStrings()
{
- auto &list = staticStrings();
- for (PyObject *ob : list)
+ auto &set = staticStrings();
+ for (PyObject *ob : set) {
+ Py_REFCNT(ob) = 1;
Py_DECREF(ob);
- list.clear();
+ }
+ set.clear();
}
PyObject *createStaticString(const char *str)
@@ -218,7 +221,16 @@ PyObject *createStaticString(const char *str)
PyErr_Print();
Py_FatalError("unexpected error in createStaticString()");
}
- staticStrings().push_back(result);
+ auto it = staticStrings().find(result);
+ if (it == staticStrings().end())
+ staticStrings().insert(result);
+ /*
+ * Note: We always add one reference even if we have a new string.
+ * This makes the strings immortal, and we are safe if someone
+ * uses AutoDecRef, although the set cannot cope with deletions.
+ * The exit handler cleans that up, anyway.
+ */
+ Py_INCREF(result);
return result;
}
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py
index 64f654d30..ece3d2edb 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/__feature__.py
@@ -104,7 +104,9 @@ Note: This are two imports.
# XXX build an improved C version? I guess not.
def _import(name, *args, **kwargs):
# PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
- importing_module = sys._getframe(1).f_globals.get("__name__", "__main__")
+ # PYSIDE-1398: sys._getframe(1) may not exist when embedding.
+ calling_frame = _cf = sys._getframe().f_back
+ importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__"
existing = pyside_feature_dict.get(importing_module, 0)
if name == "__feature__" and args[2]:
diff --git a/testing/wheel_tester.py b/testing/wheel_tester.py
index 147becdf7..100fd18f7 100644
--- a/testing/wheel_tester.py
+++ b/testing/wheel_tester.py
@@ -65,8 +65,6 @@ this_dir = os.path.dirname(this_file)
setup_script_dir = os.path.abspath(os.path.join(this_dir, '..'))
sys.path.append(setup_script_dir)
-from build_scripts.options import OPTION
-
from build_scripts.utils import find_files_using_glob
from build_scripts.utils import find_glob_in_path
from build_scripts.utils import run_process, run_process_output
@@ -77,14 +75,6 @@ import platform
log.set_verbosity(1)
-def find_executable_qmake():
- return find_executable('qmake', OPTION["QMAKE"])
-
-
-def find_executable_cmake():
- return find_executable('cmake', OPTION["CMAKE"])
-
-
def find_executable(executable, command_line_value):
value = command_line_value
option_str = '--{}'.format(executable)
@@ -108,8 +98,8 @@ def find_executable(executable, command_line_value):
return value
-QMAKE_PATH = find_executable_qmake()
-CMAKE_PATH = find_executable_cmake()
+QMAKE_PATH = None
+CMAKE_PATH = None
def get_wheels_dir():
@@ -351,5 +341,12 @@ if __name__ == "__main__":
parser.add_argument('--no-install-wheels', '-n', action='store_true',
help='Do not install wheels'
' (for developer builds with virtualenv)')
+ parser.add_argument("--qmake", type=str,
+ help="Path to qmake")
+ parser.add_argument("--cmake", type=str,
+ help="Path to cmake")
options = parser.parse_args()
+ QMAKE_PATH = find_executable('qmake', options.qmake)
+ CMAKE_PATH = find_executable('cmake', options.cmake)
+
run_wheel_tests(not options.no_install_wheels)