diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-11-29 11:17:46 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-11-29 11:17:48 +0100 |
| commit | f72b75d9a75a32d93a66147ffaa240ea061bf0cd (patch) | |
| tree | 38b686f7063e0f08864f5cfb2192ec02bc059a02 | |
| parent | 5a74c902555ed6bce4b45889adfdaa1123b64ace (diff) | |
| parent | 26404dd4b6c61083bf5de1c1c2208bf2350aba0e (diff) | |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: Ie902334068eda21ed71934da56de168a9627e41d
36 files changed, 1289 insertions, 860 deletions
diff --git a/build_scripts/config.py b/build_scripts/config.py index 022d7459f..3a590ffb0 100644 --- a/build_scripts/config.py +++ b/build_scripts/config.py @@ -37,7 +37,7 @@ ## ############################################################################# -import sys, os +import os import distutils.log as log @@ -88,8 +88,6 @@ class Config(object): 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', @@ -136,6 +134,8 @@ class Config(object): setup_kwargs['zip_safe'] = False setup_kwargs['cmdclass'] = cmd_class_dict setup_kwargs['version'] = package_version + setup_kwargs['python_requires'] = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.8" + if quiet: # Tells distutils / setuptools to be quiet, and only print warnings or errors. diff --git a/build_scripts/main.py b/build_scripts/main.py index 5f536792a..7877191fe 100644 --- a/build_scripts/main.py +++ b/build_scripts/main.py @@ -52,9 +52,11 @@ setup_py_path = os.path.join(setup_script_dir, "setup.py") start_time = int(time.time()) + def elapsed(): return int(time.time()) - start_time + @memoize def get_package_timestamp(): """ In a Coin CI build the returned timestamp will be the @@ -62,6 +64,7 @@ def get_package_timestamp(): 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. """ @@ -82,6 +85,7 @@ def get_package_version(): 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 @@ -95,8 +99,7 @@ def get_setuptools_extension_modules(): return extension_modules -# Git submodules: ["submodule_name", -# "location_relative_to_sources_folder"] +# Git submodules: ["submodule_name", "location_relative_to_sources_folder"] submodules = [["pyside2-tools"]] try: @@ -151,7 +154,7 @@ def check_allowed_python_version(): if found: major = int(found.group(1)) minor = int(found.group(2)) - supported.append( (major, minor) ) + supported.append((major, minor)) this_py = sys.version_info[:2] if this_py not in supported: print("Unsupported python version detected. Only these python versions are supported: {}" @@ -207,9 +210,9 @@ available_mkspecs = ["msvc", "mingw", "ninja"] if sys.platform == "win32" else [ if OPTION_MAKESPEC is None: OPTION_MAKESPEC = available_mkspecs[0] -if not OPTION_MAKESPEC in available_mkspecs: - print('Invalid option --make-spec "{}". Available values are {}'.format( - OPTION_MAKESPEC, available_mkspecs)) +if OPTION_MAKESPEC not in available_mkspecs: + print('Invalid option --make-spec "{}". Available values are {}'.format(OPTION_MAKESPEC, + available_mkspecs)) sys.exit(1) if OPTION_JOBS: @@ -222,9 +225,11 @@ if OPTION_JOBS: else: OPTION_JOBS = '' + def is_debug_python(): return getattr(sys, "gettotalrefcount", None) is not None + # Return a prefix suitable for the _install/_build directory def prefix(): virtual_env_name = os.environ.get('VIRTUAL_ENV', None) @@ -241,6 +246,7 @@ def prefix(): name += "a" return name + # Initialize, pull and checkout submodules def prepare_sub_modules(): print("Initializing submodules for PySide2 version: {}".format( @@ -263,13 +269,11 @@ def prepare_sub_modules(): if need_init_sub_modules: git_update_cmd = ["git", "submodule", "update", "--init"] if run_process(git_update_cmd) != 0: - m = ("Failed to initialize the git submodules: " - "update --init failed") + m = "Failed to initialize the git submodules: update --init failed" raise DistutilsSetupError(m) git_pull_cmd = ["git", "submodule", "foreach", "git", "fetch", "--all"] if run_process(git_pull_cmd) != 0: - m = ("Failed to initialize the git submodules: " - "git fetch --all failed") + m = "Failed to initialize the git submodules: git fetch --all failed" raise DistutilsSetupError(m) else: print("All submodules present.") @@ -279,10 +283,12 @@ def prepare_sub_modules(): m = "Failed to checkout the correct git submodules SHA1s." raise DistutilsSetupError(m) + # Single global instance of QtInfo to be used later in multiple code # paths. qtinfo = QtInfo(QMAKE_COMMAND) + def get_qt_version(): qt_version = qtinfo.version @@ -291,16 +297,16 @@ def get_qt_version(): 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)) + 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(): - if (os.path.isdir(".git") and not OPTION_IGNOREGIT and - not OPTION_ONLYPACKAGE and not OPTION_REUSE_BUILD): + if (os.path.isdir(".git") and not OPTION_IGNOREGIT and not OPTION_ONLYPACKAGE + and not OPTION_REUSE_BUILD): prepare_sub_modules() # Clean up temp build folder. for n in ["build"]: @@ -321,15 +327,15 @@ def prepare_build(): # In-source, developer build if install_prefix.endswith("qtbase"): qt_src_dir = install_prefix - else: # SDK: Use 'Src' directory - qt_src_dir = os.path.join(os.path.dirname(install_prefix), - 'Src', 'qtbase') + else: # SDK: Use 'Src' directory + qt_src_dir = os.path.join(os.path.dirname(install_prefix), 'Src', 'qtbase') + class PysideInstall(_install): def __init__(self, *args, **kwargs): _install.__init__(self, *args, **kwargs) - def initialize_options (self): + def initialize_options(self): _install.initialize_options(self) if sys.platform == 'darwin': @@ -350,6 +356,7 @@ class PysideInstall(_install): _install.run(self) print('*** Install completed ({}s)'.format(elapsed())) + class PysideDevelop(_develop): def __init__(self, *args, **kwargs): @@ -359,6 +366,7 @@ class PysideDevelop(_develop): self.run_command("build") _develop.run(self) + class PysideBdistEgg(_bdist_egg): def __init__(self, *args, **kwargs): @@ -368,6 +376,7 @@ class PysideBdistEgg(_bdist_egg): self.run_command("build") _bdist_egg.run(self) + class PysideBuildExt(_build_ext): def __init__(self, *args, **kwargs): @@ -399,14 +408,13 @@ class PysideInstallLib(_install_lib): if os.path.isdir(self.build_dir): # Using our own copydir makes sure to preserve symlinks. - outfiles = copydir(os.path.abspath(self.build_dir), - os.path.abspath(self.install_dir)) + outfiles = copydir(os.path.abspath(self.build_dir), os.path.abspath(self.install_dir)) else: - self.warn("'{}' does not exist -- " - "no Python modules to install".format(self.build_dir)) + self.warn("'{}' does not exist -- no Python modules to install".format(self.build_dir)) return return outfiles + class PysideBuild(_build): def __init__(self, *args, **kwargs): @@ -468,12 +476,10 @@ class PysideBuild(_build): 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...") + 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)) + 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)) @@ -493,23 +499,20 @@ class PysideBuild(_build): make_name = "ninja" make_generator = "Ninja" else: - raise DistutilsSetupError( - "Invalid option --make-spec.") + 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)) + 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.") + 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.") + raise DistutilsSetupError("Failed to find qmake. " + "Please specify the path to qmake with --qmake parameter.") # Prepare parameters py_executable = sys.executable @@ -534,8 +537,7 @@ class PysideBuild(_build): 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)) + py_include_dir = os.path.join(py_prefix, "include/python{}".format(py_version)) dbg_postfix = "" if build_type == "Debug": dbg_postfix = "_d" @@ -554,7 +556,7 @@ class PysideBuild(_build): lib_exts.append('.dylib') if sys.version_info[0] > 2: lib_suff = getattr(sys, 'abiflags', None) - else: # Python 2 + else: # Python 2 lib_suff = '' lib_exts.append('.so.1') # Suffix for OpenSuSE 13.01 @@ -573,8 +575,7 @@ class PysideBuild(_build): python_library_found = False libs_tried = [] for lib_ext in lib_exts: - lib_name = "libpython{}{}{}".format(py_version, lib_suff, - lib_ext) + 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 @@ -592,15 +593,12 @@ class PysideBuild(_build): # /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)): + 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: @@ -614,8 +612,7 @@ class PysideBuild(_build): 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) + 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 @@ -625,13 +622,11 @@ class PysideBuild(_build): if not python_library_found: raise DistutilsSetupError( - "Failed to locate the Python library with {}".format( - ", ".join(libs_tried))) + "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)) + log.error("Failed to locate a dynamic Python library, using {}".format(py_library)) self.qtinfo = qtinfo qt_dir = os.path.dirname(OPTION_QMAKE) @@ -642,14 +637,14 @@ class PysideBuild(_build): # Add Clang to path for Windows. # Revisit once Clang is bundled with Qt. - if (sys.platform == "win32" and - LooseVersion(self.qtinfo.version) >= LooseVersion("5.7.0")): + if (sys.platform == "win32" + and LooseVersion(self.qtinfo.version) >= LooseVersion("5.7.0")): clang_dir = detect_clang() if clang_dir[0]: clangBinDir = os.path.join(clang_dir[0], 'bin') - if not clangBinDir in os.environ.get('PATH'): - log.info("Adding {} as detected by {} to PATH".format( - clangBinDir, clang_dir[1])) + if clangBinDir not in os.environ.get('PATH'): + log.info("Adding {} as detected by {} to PATH".format(clangBinDir, + clang_dir[1])) additional_paths.append(clangBinDir) else: raise DistutilsSetupError("Failed to detect Clang when checking " @@ -659,7 +654,8 @@ class PysideBuild(_build): # Used for test blacklists and registry test. self.build_classifiers = "py{}-qt{}-{}-{}".format(py_version, qt_version, - platform.architecture()[0], build_type.lower()) + platform.architecture()[0], + build_type.lower()) if OPTION_SHORTER_PATHS: build_name = "p{}".format(py_version) else: @@ -667,10 +663,8 @@ class PysideBuild(_build): script_dir = setup_script_dir sources_dir = os.path.join(script_dir, "sources") - build_dir = os.path.join(script_dir, prefix() + "_build", - "{}".format(build_name)) - install_dir = os.path.join(script_dir, prefix() + "_install", - "{}".format(build_name)) + build_dir = os.path.join(script_dir, prefix() + "_build", "{}".format(build_name)) + install_dir = os.path.join(script_dir, prefix() + "_install", "{}".format(build_name)) self.make_path = make_path self.make_generator = make_generator @@ -803,8 +797,7 @@ class PysideBuild(_build): target = qtinfo.macos_min_deployment_target if not target: - raise DistutilsSetupError("Failed to query for Qt's " - "QMAKE_MACOSX_DEPLOYMENT_TARGET.") + raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.") return target @staticmethod @@ -831,24 +824,23 @@ class PysideBuild(_build): 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 {}.") + "{} 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)) + 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)) + 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)]) + maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)]) else: maximum_target = qt_target return maximum_target @@ -868,18 +860,12 @@ class PysideBuild(_build): self._patchelf_path = find_executable('patchelf') if self._patchelf_path: if not os.path.isabs(self._patchelf_path): - self._patchelf_path = os.path.join(os.getcwd(), - self._patchelf_path) + self._patchelf_path = os.path.join(os.getcwd(), self._patchelf_path) log.info("Using {} ...".format(self._patchelf_path)) return log.info("Building patchelf...") module_src_dir = os.path.join(self.sources_dir, "patchelf") - build_cmd = [ - "g++", - "{}/patchelf.cc".format(module_src_dir), - "-o", - "patchelf", - ] + build_cmd = ["g++", "{}/patchelf.cc".format(module_src_dir), "-o", "patchelf"] if run_process(build_cmd) != 0: raise DistutilsSetupError("Error building patchelf") self._patchelf_path = os.path.join(self.script_dir, "patchelf") @@ -891,30 +877,25 @@ class PysideBuild(_build): # Prepare folders os.chdir(self.build_dir) - module_build_dir = os.path.join(self.build_dir, extension) - skipflag_file = module_build_dir + '-skip' + module_build_dir = os.path.join(self.build_dir, extension) + skipflag_file = "{} -skip".format(module_build_dir) if os.path.exists(skipflag_file): - log.info("Skipping {} because {} exists".format(extension, - skipflag_file)) + log.info("Skipping {} because {} exists".format(extension, skipflag_file)) return module_build_exists = os.path.exists(module_build_dir) if module_build_exists: if not OPTION_REUSE_BUILD: - log.info("Deleting module build folder {}...".format( - module_build_dir)) + log.info("Deleting module build folder {}...".format(module_build_dir)) try: rmtree(module_build_dir) except Exception as e: - print('***** problem removing "{}"'.format( - module_build_dir)) + print('***** problem removing "{}"'.format(module_build_dir)) print('ignored error: {}'.format(e)) else: - log.info("Reusing module build folder {}...".format( - module_build_dir)) + log.info("Reusing module build folder {}...".format(module_build_dir)) if not os.path.exists(module_build_dir): - log.info("Creating module build folder {}...".format( - module_build_dir)) + log.info("Creating module build folder {}...".format(module_build_dir)) os.makedirs(module_build_dir) os.chdir(module_build_dir) @@ -995,12 +976,11 @@ class PysideBuild(_build): if OPTION_SANITIZE_ADDRESS: # Some simple sanity checking. Only use at your own risk. - if (sys.platform.startswith('linux') or - sys.platform.startswith('darwin')): + if (sys.platform.startswith('linux') + or sys.platform.startswith('darwin')): cmake_cmd.append("-DSANITIZE_ADDRESS=ON") else: - raise DistutilsSetupError("Address sanitizer can only be used " - "on Linux and macOS.") + raise DistutilsSetupError("Address sanitizer can only be used on Linux and macOS.") if extension.lower() == "pyside2": pyside_qt_conf_prefix = '' @@ -1017,8 +997,7 @@ class PysideBuild(_build): # Pass package version to CMake, so this string can be # embedded into _config.py file. package_version = get_package_version() - cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_VERSION={}".format( - package_version)) + cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_VERSION={}".format(package_version)) # In case if this is a snapshot build, also pass the # timestamp as a separate value, because it is the only @@ -1026,8 +1005,7 @@ class PysideBuild(_build): timestamp = '' if OPTION_SNAPSHOT_BUILD: timestamp = get_package_timestamp() - cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_TIMESTAMP={}".format( - timestamp)) + cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_TIMESTAMP={}".format(timestamp)) if extension.lower() in ["shiboken2", "pyside2-tools"]: cmake_cmd.append("-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=yes") @@ -1037,8 +1015,7 @@ class PysideBuild(_build): if sys.platform == 'darwin': if OPTION_MACOS_ARCH: # also tell cmake which architecture to use - cmake_cmd.append("-DCMAKE_OSX_ARCHITECTURES:STRING={}".format( - OPTION_MACOS_ARCH)) + cmake_cmd.append("-DCMAKE_OSX_ARCHITECTURES:STRING={}".format(OPTION_MACOS_ARCH)) if OPTION_MACOS_USE_LIBCPP: # Explicitly link the libc++ standard library (useful @@ -1053,10 +1030,10 @@ class PysideBuild(_build): if OPTION_MACOS_SYSROOT: cmake_cmd.append("-DCMAKE_OSX_SYSROOT={}".format( - OPTION_MACOS_SYSROOT)) + OPTION_MACOS_SYSROOT)) else: - latest_sdk_path = run_process_output(['xcrun', - '--sdk', 'macosx', '--show-sdk-path']) + latest_sdk_path = run_process_output(['xcrun', '--sdk', 'macosx', + '--show-sdk-path']) if latest_sdk_path: latest_sdk_path = latest_sdk_path[0] cmake_cmd.append("-DCMAKE_OSX_SYSROOT={}".format( @@ -1070,18 +1047,14 @@ 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() - cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format( - deployment_target)) + deployment_target = PysideBuild.macos_pyside_min_deployment_target() + cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format(deployment_target)) os.environ['MACOSX_DEPLOYMENT_TARGET'] = deployment_target if not OPTION_SKIP_CMAKE: - log.info("Configuring module {} ({})...".format(extension, - module_src_dir)) + log.info("Configuring module {} ({})...".format(extension, module_src_dir)) if run_process(cmake_cmd) != 0: - raise DistutilsSetupError("Error configuring {}".format( - extension)) + raise DistutilsSetupError("Error configuring {}".format(extension)) else: log.info("Reusing old configuration for module {} ({})...".format( extension, module_src_dir)) @@ -1101,15 +1074,13 @@ class PysideBuild(_build): log.info("Generating Shiboken documentation") if run_process([self.make_path, "doc"]) != 0: - raise DistutilsSetupError( - "Error generating documentation for {}".format( - extension)) + raise DistutilsSetupError("Error generating documentation " + "for {}".format(extension)) except ImportError: log.info("Sphinx not found, skipping documentation build") else: log.info("Skipped documentation generation") - if not OPTION_SKIP_MAKE_INSTALL: log.info("Installing module {}...".format(extension)) # Need to wait a second, so installed file timestamps are @@ -1117,8 +1088,7 @@ class PysideBuild(_build): # See https://gitlab.kitware.com/cmake/cmake/issues/16155 # for issue details. if sys.platform == 'darwin': - log.info("Waiting 1 second, to ensure installation is " - "successful...") + log.info("Waiting 1 second, to ensure installation is successful...") time.sleep(1) # ninja: error: unknown target 'install/fast' target = 'install/fast' if self.make_generator != 'Ninja' else 'install' @@ -1195,8 +1165,9 @@ class PysideBuild(_build): return temp_config def is_webengine_built(self, built_modules): - return ('WebEngineWidgets' in built_modules or 'WebEngineCore' in built_modules - or 'WebEngine' in built_modules) + return ('WebEngineWidgets' in built_modules + or 'WebEngineCore' in built_modules + or 'WebEngine' in built_modules) def prepare_standalone_clang(self, is_win=False): """ @@ -1274,8 +1245,7 @@ class PysideBuild(_build): make_writable_by_owner=True) else: raise RuntimeError("Error copying libclang library " - "from {} to {}. ".format( - clang_lib_path, destination_dir)) + "from {} to {}. ".format(clang_lib_path, destination_dir)) def update_rpath(self, package_path, executables): if sys.platform.startswith('linux'): @@ -1316,8 +1286,7 @@ class PysideBuild(_build): macos_fix_rpaths_for_library(srcpath, final_rpath) else: - raise RuntimeError('Not configured for platform ' + - sys.platform) + raise RuntimeError('Not configured for platform {}'.format(sys.platform)) pyside_libs.extend(executables) diff --git a/build_scripts/options.py b/build_scripts/options.py index c17f6a100..0e38566d5 100644 --- a/build_scripts/options.py +++ b/build_scripts/options.py @@ -44,8 +44,8 @@ import warnings def _warn_multiple_option(option): - w = 'Option "{}" occurs multiple times on the command line.'.format(option) - warnings.warn(w) + warnings.warn('Option "{}" occurs multiple times on the command line.'.format(option)) + def _warn_deprecated_option(option, replacement=None): w = 'Option "{}" is deprecated and may be removed in a future release.'.format(option) @@ -53,6 +53,7 @@ def _warn_deprecated_option(option, replacement=None): w = '{}\nUse "{}" instead.'.format(w, replacement) warnings.warn(w) + class Options(object): def __init__(self): @@ -62,13 +63,13 @@ class Options(object): def has_option(self, name, remove=True): """ Returns True if argument '--name' was passed on the command line. """ - option = '--' + name + option = '--{}'.format(name) count = sys.argv.count(option) remove_count = count if not remove and count > 0: remove_count -= 1 for i in range(remove_count): - sys.argv.remove(option) + sys.argv.remove(option) if count > 1: _warn_multiple_option(option) return count > 0 @@ -127,8 +128,8 @@ def has_option(*args, **kwargs): return options.has_option(*args, **kwargs) -def option_value(*args,**kwargs): - return options.option_value(*args,**kwargs) +def option_value(*args, **kwargs): + return options.option_value(*args, **kwargs) # Declare options diff --git a/build_scripts/platforms/linux.py b/build_scripts/platforms/linux.py index 067179cdc..e1c2dd5a1 100644 --- a/build_scripts/platforms/linux.py +++ b/build_scripts/platforms/linux.py @@ -75,8 +75,7 @@ def prepare_standalone_package_linux(self, vars): # Check if ICU libraries were copied over to the destination # Qt libdir. resolved_destination_lib_dir = destination_lib_dir.format(**vars) - maybe_icu_libs = find_files_using_glob(resolved_destination_lib_dir, - "libicu*") + maybe_icu_libs = find_files_using_glob(resolved_destination_lib_dir, "libicu*") # If no ICU libraries are present in the Qt libdir (like when # Qt is built against system ICU, or in the Coin CI where ICU @@ -90,43 +89,43 @@ def prepare_standalone_package_linux(self, vars): if self.is_webengine_built(built_modules): copydir("{qt_lib_execs_dir}", - "{st_build_dir}/{st_package_name}/Qt/libexec", - filter=None, - recursive=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/libexec", + filter=None, + recursive=False, + vars=vars) copydir("{qt_prefix_dir}/resources", - "{st_build_dir}/{st_package_name}/Qt/resources", - filter=None, - recursive=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/resources", + filter=None, + recursive=False, + vars=vars) if copy_plugins: # <qt>/plugins/* -> <setup>/{st_package_name}/Qt/plugins copydir("{qt_plugins_dir}", - "{st_build_dir}/{st_package_name}/Qt/plugins", - filter=["*.so"], - recursive=True, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/plugins", + filter=["*.so"], + recursive=True, + vars=vars) if copy_qml: # <qt>/qml/* -> <setup>/{st_package_name}/Qt/qml copydir("{qt_qml_dir}", - "{st_build_dir}/{st_package_name}/Qt/qml", - filter=None, - force=False, - recursive=True, - ignore=["*.so.debug"], - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/qml", + filter=None, + force=False, + recursive=True, + ignore=["*.so.debug"], + vars=vars) if copy_translations: # <qt>/translations/* -> # <setup>/{st_package_name}/Qt/translations copydir("{qt_translations_dir}", - "{st_build_dir}/{st_package_name}/Qt/translations", - filter=["*.qm", "*.pak"], - force=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/translations", + filter=["*.qm", "*.pak"], + force=False, + vars=vars) if copy_qt_conf: # Copy the qt.conf file to libexec. diff --git a/build_scripts/platforms/macos.py b/build_scripts/platforms/macos.py index 49f02754d..159364d9a 100644 --- a/build_scripts/platforms/macos.py +++ b/build_scripts/platforms/macos.py @@ -81,8 +81,8 @@ def prepare_standalone_package_macos(self, vars): if self.qt_is_framework_build(): def framework_dir_filter(dir_name, parent_full_path, dir_full_path): if '.framework' in dir_name: - if (dir_name.startswith('QtWebEngine') and - not self.is_webengine_built(built_modules)): + if (dir_name.startswith('QtWebEngine') + and not self.is_webengine_built(built_modules)): return False if constrain_modules and dir_name not in constrain_frameworks: return False @@ -95,8 +95,7 @@ def prepare_standalone_package_macos(self, vars): return False if dir_full_path.endswith('Versions/5/Helpers'): return False - return general_dir_filter(dir_name, parent_full_path, - dir_full_path) + return general_dir_filter(dir_name, parent_full_path, dir_full_path) # Filter out debug frameworks in the # debug_and_release config. @@ -112,18 +111,17 @@ def prepare_standalone_package_macos(self, vars): return True copydir("{qt_lib_dir}", "{st_build_dir}/{st_package_name}/Qt/lib", - recursive=True, vars=vars, - ignore=["*.la", "*.a", "*.cmake", "*.pc", "*.prl"], - dir_filter_function=framework_dir_filter, - file_filter_function=framework_variant_filter) + recursive=True, vars=vars, + ignore=["*.la", "*.a", "*.cmake", "*.pc", "*.prl"], + dir_filter_function=framework_dir_filter, + file_filter_function=framework_variant_filter) # Fix rpath for WebEngine process executable. The already # present rpath does not work because it assumes a symlink # from Versions/5/Helpers, thus adding two more levels of # directory hierarchy. if self.is_webengine_built(built_modules): - qt_lib_path = "{st_build_dir}/{st_package_name}/Qt/lib".format( - **vars) + qt_lib_path = "{st_build_dir}/{st_package_name}/Qt/lib".format(**vars) bundle = "QtWebEngineCore.framework/Helpers/" bundle += "QtWebEngineProcess.app" binary = "Contents/MacOS/QtWebEngineProcess" @@ -142,24 +140,24 @@ def prepare_standalone_package_macos(self, vars): accepted_modules = ["libQt5" + module + "*.5.dylib" for module in constrain_modules] copydir("{qt_lib_dir}", - "{st_build_dir}/{st_package_name}/Qt/lib", - filter=accepted_modules, - ignore=ignored_modules, - file_filter_function=file_variant_filter, - recursive=True, vars=vars, force_copy_symlinks=True) + "{st_build_dir}/{st_package_name}/Qt/lib", + filter=accepted_modules, + ignore=ignored_modules, + file_filter_function=file_variant_filter, + recursive=True, vars=vars, force_copy_symlinks=True) if self.is_webengine_built(built_modules): copydir("{qt_lib_execs_dir}", - "{st_build_dir}/{st_package_name}/Qt/libexec", - filter=None, - recursive=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/libexec", + filter=None, + recursive=False, + vars=vars) copydir("{qt_prefix_dir}/resources", - "{st_build_dir}/{st_package_name}/Qt/resources", - filter=None, - recursive=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/resources", + filter=None, + recursive=False, + vars=vars) # Fix rpath for WebEngine process executable. qt_libexec_path = "{st_build_dir}/{st_package_name}/Qt/libexec".format(**vars) @@ -178,30 +176,29 @@ def prepare_standalone_package_macos(self, vars): if copy_plugins: # <qt>/plugins/* -> <setup>/{st_package_name}/Qt/plugins copydir("{qt_plugins_dir}", - "{st_build_dir}/{st_package_name}/Qt/plugins", - filter=["*.dylib"], - recursive=True, - dir_filter_function=general_dir_filter, - file_filter_function=file_variant_filter, - vars=vars) - + "{st_build_dir}/{st_package_name}/Qt/plugins", + filter=["*.dylib"], + recursive=True, + dir_filter_function=general_dir_filter, + file_filter_function=file_variant_filter, + vars=vars) if copy_qml: # <qt>/qml/* -> <setup>/{st_package_name}/Qt/qml copydir("{qt_qml_dir}", - "{st_build_dir}/{st_package_name}/Qt/qml", - filter=None, - recursive=True, - force=False, - dir_filter_function=general_dir_filter, - file_filter_function=file_variant_filter, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/qml", + filter=None, + recursive=True, + force=False, + dir_filter_function=general_dir_filter, + file_filter_function=file_variant_filter, + vars=vars) if copy_translations: # <qt>/translations/* -> # <setup>/{st_package_name}/Qt/translations copydir("{qt_translations_dir}", - "{st_build_dir}/{st_package_name}/Qt/translations", - filter=["*.qm", "*.pak"], - force=False, - vars=vars) + "{st_build_dir}/{st_package_name}/Qt/translations", + filter=["*.qm", "*.pak"], + force=False, + vars=vars) diff --git a/build_scripts/platforms/unix.py b/build_scripts/platforms/unix.py index 9327e8bd7..7f9a6ba94 100644 --- a/build_scripts/platforms/unix.py +++ b/build_scripts/platforms/unix.py @@ -45,7 +45,7 @@ from .macos import prepare_standalone_package_macos from ..config import config from ..options import * -from ..utils import copydir, copyfile, rmtree, makefile +from ..utils import copydir, copyfile, makefile from ..utils import regenerate_qt_resources @@ -203,13 +203,10 @@ def prepare_packages_posix(self, vars): # Re-generate examples Qt resource files for Python 3 # compatibility if sys.version_info[0] == 3: - examples_path = "{st_build_dir}/{st_package_name}/examples".format( - **vars) - pyside_rcc_path = "{install_dir}/bin/rcc".format( - **vars) + examples_path = "{st_build_dir}/{st_package_name}/examples".format(**vars) + pyside_rcc_path = "{install_dir}/bin/rcc".format(**vars) pyside_rcc_options = ['-g', 'python'] - regenerate_qt_resources(examples_path, pyside_rcc_path, - pyside_rcc_options) + regenerate_qt_resources(examples_path, pyside_rcc_path, pyside_rcc_options) # Copy Qt libs to package if OPTION_STANDALONE: diff --git a/build_scripts/platforms/windows_desktop.py b/build_scripts/platforms/windows_desktop.py index a5a5b8fd2..0e7dd766f 100644 --- a/build_scripts/platforms/windows_desktop.py +++ b/build_scripts/platforms/windows_desktop.py @@ -44,7 +44,7 @@ import fnmatch from ..config import config from ..options import * -from ..utils import copydir, copyfile, rmtree, makefile +from ..utils import copydir, copyfile, makefile from ..utils import regenerate_qt_resources, filter_match from ..utils import download_and_extract_7z @@ -223,16 +223,15 @@ def prepare_packages_win32(self, vars): pyside_rcc_path = "{install_dir}/bin/rcc.exe".format( **vars) pyside_rcc_options = ['-g', 'python'] - regenerate_qt_resources(examples_path, pyside_rcc_path, - pyside_rcc_options) + regenerate_qt_resources(examples_path, pyside_rcc_path, pyside_rcc_options) if vars['ssl_libs_dir']: # <ssl_libs>/* -> <setup>/{st_package_name}/openssl copydir("{ssl_libs_dir}", "{st_build_dir}/{st_package_name}/openssl", - filter=[ - "libeay32.dll", - "ssleay32.dll"], - force=False, vars=vars) + filter=[ + "libeay32.dll", + "ssleay32.dll"], + force=False, vars=vars) if config.is_internal_shiboken_module_build(): # The C++ std library dlls need to be packaged with the @@ -382,19 +381,21 @@ def copy_qt_artifacts(self, copy_pdbs, vars): # e.g. "/home/work/qt/qtbase/bin" file_path_dir_name = os.path.dirname(file_full_path) # e.g. "Qt5Coredd" - maybe_debug_name = file_base_name + 'd' + maybe_debug_name = "{}d".format(file_base_name) if self.debug: filter = debug - def predicate(path): return not os.path.exists(path) + + def predicate(path): + return not os.path.exists(path) else: filter = release - def predicate(path): return os.path.exists(path) + + def predicate(path): + return os.path.exists(path) # e.g. "/home/work/qt/qtbase/bin/Qt5Coredd.dll" - other_config_path = os.path.join(file_path_dir_name, - maybe_debug_name + file_ext) + other_config_path = os.path.join(file_path_dir_name, maybe_debug_name + file_ext) - if (filter_match(file_name, filter) and - predicate(other_config_path)): + if (filter_match(file_name, filter) and predicate(other_config_path)): return True return False @@ -411,19 +412,18 @@ def copy_qt_artifacts(self, copy_pdbs, vars): pdb_pattern = "*{}.pdb" if copy_pdbs: plugin_dll_patterns += [pdb_pattern] - plugin_dll_filter = functools.partial(qt_build_config_filter, - plugin_dll_patterns) + plugin_dll_filter = functools.partial(qt_build_config_filter, plugin_dll_patterns) copydir("{qt_plugins_dir}", "{st_build_dir}/{st_package_name}/plugins", - file_filter_function=plugin_dll_filter, - vars=vars) + file_filter_function=plugin_dll_filter, + vars=vars) if copy_translations: # <qt>/translations/* -> <setup>/{st_package_name}/translations copydir("{qt_translations_dir}", - "{st_build_dir}/{st_package_name}/translations", - filter=["*.qm", "*.pak"], - force=False, - vars=vars) + "{st_build_dir}/{st_package_name}/translations", + filter=["*.qm", "*.pak"], + force=False, + vars=vars) if copy_qml: # <qt>/qml/* -> <setup>/{st_package_name}/qml @@ -433,43 +433,41 @@ def copy_qt_artifacts(self, copy_pdbs, vars): # Copy all files that are not dlls and pdbs (.qml, qmldir). copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml", - ignore=qml_ignore, - force=False, - recursive=True, - vars=vars) + ignore=qml_ignore, + force=False, + recursive=True, + vars=vars) if copy_pdbs: qml_dll_patterns += [pdb_pattern] - qml_dll_filter = functools.partial(qt_build_config_filter, - qml_dll_patterns) + qml_dll_filter = functools.partial(qt_build_config_filter, qml_dll_patterns) # Copy all dlls (and possibly pdbs). copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml", - file_filter_function=qml_dll_filter, - force=False, - recursive=True, - vars=vars) + file_filter_function=qml_dll_filter, + force=False, + recursive=True, + vars=vars) if self.is_webengine_built(built_modules): copydir("{qt_prefix_dir}/resources", - "{st_build_dir}/{st_package_name}/resources", - filter=None, - recursive=False, - vars=vars) + "{st_build_dir}/{st_package_name}/resources", + filter=None, + recursive=False, + vars=vars) filter = 'QtWebEngineProcess{}.exe'.format( 'd' if self.debug else '') copydir("{qt_bin_dir}", - "{st_build_dir}/{st_package_name}", - filter=[filter], - recursive=False, vars=vars) + "{st_build_dir}/{st_package_name}", + filter=[filter], + recursive=False, vars=vars) if copy_qt_conf: # Copy the qt.conf file to prefix dir. - copyfile( - "{build_dir}/pyside2/{st_package_name}/qt.conf", - "{st_build_dir}/{st_package_name}", - vars=vars) + copyfile("{build_dir}/pyside2/{st_package_name}/qt.conf", + "{st_build_dir}/{st_package_name}", + vars=vars) if copy_clang: self.prepare_standalone_clang(is_win=True) diff --git a/build_scripts/qp5_tool.py b/build_scripts/qp5_tool.py index aca8cf7f6..108e38d87 100644 --- a/build_scripts/qp5_tool.py +++ b/build_scripts/qp5_tool.py @@ -72,6 +72,7 @@ Modules=$(MinimalModules),Multimedia Modules-pyside-setup-minimal=$(MinimalModules) """ + def which(needle): """Perform a path search""" needles = [needle] @@ -86,6 +87,7 @@ def which(needle): return binary return None + def execute(args): """Execute a command and print to log""" log_string = '[{}] {}'.format(os.path.basename(os.getcwd()), ' '.join(args)) @@ -94,31 +96,34 @@ def execute(args): if exit_code != 0: raise RuntimeError('FAIL({}): {}'.format(exit_code, log_string)) + def run_git(args): """Run git in the current directory and its submodules""" - args.insert(0, git) # run in repo + args.insert(0, git) # run in repo execute(args) # run for submodules module_args = [git, "submodule", "foreach"] module_args.extend(args) execute(module_args) + def expand_reference(dict, value): """Expand references to other keys in config files $(name) by value.""" pattern = re.compile(r"\$\([^)]+\)") while True: - match = pattern.match(value) - if not match: - break - key = match.group(0)[2:-1] - value = value[:match.start(0)] + dict[key] + value[match.end(0):] + match = pattern.match(value) + if not match: + break + key = match.group(0)[2:-1] + value = value[:match.start(0)] + dict[key] + value[match.end(0):] return value + """ Config file handling, cache and read function """ - config_dict = {} + def read_config_file(fileName): global config_dict keyPattern = re.compile(r'^\s*([A-Za-z0-9\_\-]+)\s*=\s*(.*)$') @@ -136,6 +141,7 @@ def read_config_file(fileName): value += f.readline().rstrip() config_dict[key] = expand_reference(config_dict, value) + def read_tool_config(key): """ Read a value from the '$HOME/.qp5_tool' configuration file. When given @@ -147,11 +153,13 @@ def read_tool_config(key): repo_value = config_dict.get(key + '-' + base_dir) return repo_value if repo_value else config_dict.get(key) + def read_config_build_arguments(): value = read_tool_config('BuildArguments') if value: return re.split(r'\s+', value) - return default_build_args; + return default_build_args + def read_config_modules_argument(): value = read_tool_config('Modules') @@ -159,10 +167,12 @@ def read_config_modules_argument(): return '--module-subset=' + value return None + def read_config_python_binary(): binary = read_tool_config('Python') return binary if binary else 'python' + def get_config_file(): home = os.getenv('HOME') if is_windows: @@ -182,6 +192,7 @@ def get_config_file(): config_file = os.path.join(home, '.' + config_file_name) return config_file + def get_options(desc): parser = ArgumentParser(description=desc, formatter_class=RawTextHelpFormatter) parser.add_argument('--reset', '-r', action='store_true', @@ -199,6 +210,7 @@ def get_options(desc): return parser.parse_args() + if __name__ == '__main__': git = None diff --git a/build_scripts/qtinfo.py b/build_scripts/qtinfo.py index fbe8e68ad..7680dad02 100644 --- a/build_scripts/qtinfo.py +++ b/build_scripts/qtinfo.py @@ -37,9 +37,13 @@ ## ############################################################################# -import os, sys, re, subprocess +import os +import sys +import re +import subprocess from distutils.spawn import find_executable + class QtInfo(object): def __init__(self, qmake_command=None): self.initialized = False @@ -47,7 +51,7 @@ class QtInfo(object): if qmake_command: self._qmake_command = qmake_command else: - self._qmake_command = [find_executable("qmake"),] + self._qmake_command = [find_executable("qmake"), ] # Dict to cache qmake values. self._query_dict = {} @@ -120,9 +124,9 @@ class QtInfo(object): def get_mkspecs_variables(self): return self._mkspecs_dict - def _get_qmake_output(self, args_list = []): + def _get_qmake_output(self, args_list=[]): cmd = self._qmake_command + args_list - proc = subprocess.Popen(cmd, stdout = subprocess.PIPE, shell=False) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=False) output = proc.communicate()[0] proc.wait() if proc.returncode != 0: diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py index 0e45a13f4..522d053a2 100644 --- a/build_scripts/setup_runner.py +++ b/build_scripts/setup_runner.py @@ -37,7 +37,9 @@ ## ############################################################################# -import sys, os, textwrap +import sys +import os +import textwrap from build_scripts.config import config from build_scripts.main import get_package_version, get_setuptools_extension_modules diff --git a/build_scripts/utils.py b/build_scripts/utils.py index 56ec8e350..ca67cc9cf 100644 --- a/build_scripts/utils.py +++ b/build_scripts/utils.py @@ -55,7 +55,6 @@ except ImportError: import urllib import distutils.log as log -from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsSetupError try: @@ -79,7 +78,7 @@ def update_env_path(newpaths): if not path.lower() in paths: log.info("Inserting path '{}' to environment".format(path)) paths.insert(0, path) - os.environ['PATH'] = path + os.pathsep + os.environ['PATH'] + os.environ['PATH'] = "{}{}{}".format(path, os.pathsep, os.environ['PATH']) def winsdk_setenv(platform_arch, build_type): @@ -96,30 +95,27 @@ def winsdk_setenv(platform_arch, build_type): "v7.1": 10.0 } - log.info("Searching Windows SDK with MSVC compiler version {}".format( - MSVC_VERSION)) + log.info("Searching Windows SDK with MSVC compiler version {}".format(MSVC_VERSION)) setenv_paths = [] for base in HKEYS: sdk_versions = Reg.read_keys(base, WINSDK_BASE) if sdk_versions: for sdk_version in sdk_versions: - installationfolder = Reg.get_value(WINSDK_BASE + "\\" + - sdk_version, "installationfolder") - productversion = Reg.get_value(WINSDK_BASE + "\\" + - sdk_version, "productversion") - setenv_path = os.path.join(installationfolder, os.path.join( - 'bin', 'SetEnv.cmd')) + installationfolder = Reg.get_value("{}\\{}".format(WINSDK_BASE, sdk_version), + "installationfolder") + # productversion = Reg.get_value("{}\\{}".format(WINSDK_BASE, sdk_version), + # "productversion") + setenv_path = os.path.join(installationfolder, os.path.join('bin', 'SetEnv.cmd')) if not os.path.exists(setenv_path): continue - if not sdk_version in sdk_version_map: + if sdk_version not in sdk_version_map: continue if sdk_version_map[sdk_version] != MSVC_VERSION: continue setenv_paths.append(setenv_path) if len(setenv_paths) == 0: - raise DistutilsSetupError( - "Failed to find the Windows SDK with MSVC compiler " - "version {}".format(MSVC_VERSION)) + raise DistutilsSetupError("Failed to find the Windows SDK with MSVC compiler " + "version {}".format(MSVC_VERSION)) for setenv_path in setenv_paths: log.info("Found {}".format(setenv_path)) @@ -165,14 +161,13 @@ def find_vcdir(version): else: vsbase = VSEXPRESS_BASE % version try: - productdir = Reg.get_value(r"{}\Setup\VC".format(vsbase), - "productdir") + productdir = Reg.get_value(r"{}\Setup\VC".format(vsbase), "productdir") except KeyError: productdir = None log.debug("Unable to find productdir in registry") if not productdir or not os.path.isdir(productdir): - toolskey = "VS%0.f0COMNTOOLS" % version + toolskey = "VS{:0.0f}0COMNTOOLS".format(version) toolsdir = os.environ.get(toolskey, None) if toolsdir and os.path.isdir(toolsdir): @@ -195,29 +190,25 @@ def init_msvc_env(platform_arch, build_type): log.info("Searching MSVC compiler version {}".format(MSVC_VERSION)) vcdir_path = find_vcdir(MSVC_VERSION) if not vcdir_path: - raise DistutilsSetupError( - "Failed to find the MSVC compiler version {} on your " - "system.".format(MSVC_VERSION)) + raise DistutilsSetupError("Failed to find the MSVC compiler version {} on your " + "system.".format(MSVC_VERSION)) else: log.info("Found {}".format(vcdir_path)) - log.info("Searching MSVC compiler {} environment init script".format( - MSVC_VERSION)) + log.info("Searching MSVC compiler {} environment init script".format(MSVC_VERSION)) if platform_arch.startswith("32"): vcvars_path = os.path.join(vcdir_path, "bin", "vcvars32.bat") else: vcvars_path = os.path.join(vcdir_path, "bin", "vcvars64.bat") if not os.path.exists(vcvars_path): - vcvars_path = os.path.join(vcdir_path, "bin", "amd64", - "vcvars64.bat") + vcvars_path = os.path.join(vcdir_path, "bin", "amd64", "vcvars64.bat") if not os.path.exists(vcvars_path): - vcvars_path = os.path.join(vcdir_path, "bin", "amd64", - "vcvarsamd64.bat") + vcvars_path = os.path.join(vcdir_path, "bin", "amd64", "vcvarsamd64.bat") if not os.path.exists(vcvars_path): # MSVC init script not found, try to find and init Windows SDK env log.error("Failed to find the MSVC compiler environment init script " - "(vcvars.bat) on your system.") + "(vcvars.bat) on your system.") winsdk_setenv(platform_arch, build_type) return else: @@ -249,8 +240,7 @@ def copyfile(src, dst, force=True, vars=None, force_copy_symlink=False, dst = dst.format(**vars) if not os.path.exists(src) and not force: - log.info("**Skiping copy file {} to {}. " - "Source does not exists.".format(src, dst)) + log.info("**Skiping copy file {} to {}. Source does not exists.".format(src, dst)) return if not os.path.islink(src) or force_copy_symlink: @@ -270,17 +260,15 @@ def copyfile(src, dst, force=True, vars=None, force_copy_symlink=False, os.chdir(target_dir) if os.path.exists(link_name): os.remove(link_name) - log.info("Symlinking {} -> {} in {}.".format(link_name, - link_target, target_dir)) + log.info("Symlinking {} -> {} in {}.".format(link_name, link_target, target_dir)) os.symlink(link_target, link_name) except OSError: - log.error("{} -> {}: Error creating symlink".format(link_name, - link_target)) + log.error("{} -> {}: Error creating symlink".format(link_name, link_target)) finally: os.chdir(current_directory) else: log.error("{} -> {}: Can only create symlinks within the same " - "directory".format(src, link_target_path)) + "directory".format(src, link_target_path)) return dst @@ -297,15 +285,13 @@ def makefile(dst, content=None, vars=None): if not os.path.exists(dstdir): os.makedirs(dstdir) - f = open(dst, "wt") - if content is not None: - f.write(content) - f.close() + with open(dst, "wt") as f: + if content is not None: + f.write(content) -def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, - vars=None, dir_filter_function=None, file_filter_function=None, - force_copy_symlinks=False): +def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, vars=None, + dir_filter_function=None, file_filter_function=None, force_copy_symlinks=False): if vars is not None: src = src.format(**vars) @@ -319,11 +305,10 @@ def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, if not os.path.exists(src) and not force: log.info("**Skiping copy tree {} to {}. Source does not exists. " - "filter={}. ignore={}.".format(src, dst, filter, ignore)) + "filter={}. ignore={}.".format(src, dst, filter, ignore)) return [] - log.info("Copying tree {} to {}. filter={}. ignore={}.".format(src, - dst, filter, ignore)) + log.info("Copying tree {} to {}. filter={}. ignore={}.".format(src, dst, filter, ignore)) names = os.listdir(src) @@ -334,25 +319,20 @@ def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): - if (dir_filter_function and - not dir_filter_function(name, src, srcname)): + if (dir_filter_function and not dir_filter_function(name, src, srcname)): continue if recursive: - results.extend( - copydir(srcname, dstname, filter, ignore, force, - recursive, vars, dir_filter_function, - file_filter_function, force_copy_symlinks)) + results.extend(copydir(srcname, dstname, filter, ignore, force, recursive, + vars, dir_filter_function, file_filter_function, + force_copy_symlinks)) else: - if ((file_filter_function is not None and - not file_filter_function(name, srcname)) or - (filter is not None and - not filter_match(name, filter)) or - (ignore is not None and filter_match(name, ignore))): + if ((file_filter_function is not None and not file_filter_function(name, srcname)) + or (filter is not None and not filter_match(name, filter)) + or (ignore is not None and filter_match(name, ignore))): continue if not os.path.exists(dst): os.makedirs(dst) - results.append(copyfile(srcname, dstname, True, vars, - force_copy_symlinks)) + results.append(copyfile(srcname, dstname, True, vars, force_copy_symlinks)) # catch the Error from the recursive copytree so that we can # continue with other files except shutil.Error as err: @@ -372,26 +352,27 @@ def copydir(src, dst, filter=None, ignore=None, force=True, recursive=True, raise EnvironmentError(errors) return results + def make_file_writable_by_owner(path): current_permissions = stat.S_IMODE(os.lstat(path).st_mode) os.chmod(path, current_permissions | stat.S_IWUSR) + def rmtree(dirname, ignore=False): def handle_remove_readonly(func, path, exc): excvalue = exc[1] if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777 + os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777 func(path) else: raise IOError shutil.rmtree(dirname, ignore_errors=ignore, onerror=handle_remove_readonly) + def run_process_output(args, initial_env=None): if initial_env is None: initial_env = os.environ - std_out = subprocess.Popen(args, - env = initial_env, - universal_newlines = 1, + std_out = subprocess.Popen(args, env=initial_env, universal_newlines=1, stdout=subprocess.PIPE).stdout result = [] for raw_line in std_out.readlines(): @@ -399,15 +380,14 @@ def run_process_output(args, initial_env=None): result.append(line.rstrip()) return result + def run_process(args, initial_env=None): """ Run process until completion and return the process exit code. No output is captured. """ - log.info("Running process in directory {0}: command {1}".format( - os.getcwd(), - " ".join([(" " in x and '"{0}"'.format(x) or x) for x in args])) - ) + command = " ".join([(" " in x and '"{}"'.format(x) or x) for x in args]) + log.info("Running process in directory {}: command {}".format(os.getcwd(), command)) if initial_env is None: initial_env = os.environ @@ -441,7 +421,8 @@ def get_environment_from_batch_command(env_cmd, initial=None): def consume(iter): try: - while True: next(iter) + while True: + next(iter) except StopIteration: pass @@ -452,22 +433,19 @@ def get_environment_from_batch_command(env_cmd, initial=None): # create a tag so we can tell in the output when the proc is done tag = 'Done running command' # construct a cmd.exe command to do accomplish this - cmd = 'cmd.exe /E:ON /V:ON /s /c "{} && echo "{}" && set"'.format(env_cmd, - tag) + cmd = 'cmd.exe /E:ON /V:ON /s /c "{} && echo "{}" && set"'.format(env_cmd, tag) # launch the process proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial) # parse the output sent to stdout lines = proc.stdout if sys.version_info[0] > 2: # make sure the lines are strings - make_str = lambda s: s.decode() - lines = map(make_str, lines) + lines = map(lambda s: s.decode(), lines) # consume whatever output occurs until the tag is reached consume(itertools.takewhile(lambda l: tag not in l, lines)) # define a way to handle each KEY=VALUE line - handle_line = lambda l: l.rstrip().split('=',1) # parse key/values into pairs - pairs = map(handle_line, lines) + pairs = map(lambda l: l.rstrip().split('=', 1), lines) # make sure the pairs are valid valid_pairs = filter(validate_pair, pairs) # construct a dictionary of the pairs @@ -482,19 +460,14 @@ def regenerate_qt_resources(src, pyside_rcc_path, pyside_rcc_options): for name in names: srcname = os.path.join(src, name) if os.path.isdir(srcname): - regenerate_qt_resources(srcname, - pyside_rcc_path, - pyside_rcc_options) + regenerate_qt_resources(srcname, pyside_rcc_path, pyside_rcc_options) elif srcname.endswith('.qrc'): # Replace last occurence of '.qrc' in srcname srcname_split = srcname.rsplit('.qrc', 1) dstname = '_rc.py'.join(srcname_split) if os.path.exists(dstname): - log.info('Regenerating {} from {}'.format(dstname, - os.path.basename(srcname))) - run_process([pyside_rcc_path] + - pyside_rcc_options - + [srcname, '-o', dstname]) + log.info('Regenerating {} from {}'.format(dstname, os.path.basename(srcname))) + run_process([pyside_rcc_path] + pyside_rcc_options + [srcname, '-o', dstname]) def back_tick(cmd, ret_err=False): @@ -526,8 +499,7 @@ def back_tick(cmd, ret_err=False): Raises RuntimeError if command returns non-zero exit code when ret_err isn't set. """ - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, shell=True) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) out, err = proc.communicate() if not isinstance(out, str): # python 3 @@ -536,7 +508,7 @@ def back_tick(cmd, ret_err=False): retcode = proc.returncode if retcode is None and not ret_err: proc.terminate() - raise RuntimeError(cmd + ' process did not terminate') + raise RuntimeError("{} process did not terminate".format(cmd)) if retcode != 0 and not ret_err: raise RuntimeError("{} process returned code {}\n*** {}".format( (cmd, retcode, err))) @@ -548,6 +520,7 @@ def back_tick(cmd, ret_err=False): MACOS_OUTNAME_RE = re.compile(r'\(compatibility version [\d.]+, current version [\d.]+\)') + def macos_get_install_names(libpath): """ Get macOS library install names from library `libpath` using ``otool`` @@ -562,13 +535,14 @@ def macos_get_install_names(libpath): install_names : list of str install names in library `libpath` """ - out = back_tick('otool -L ' + libpath) + out = back_tick("otool -L {}".format(libpath)) libs = [line for line in out.split('\n')][1:] return [MACOS_OUTNAME_RE.sub('', lib).strip() for lib in libs] MACOS_RPATH_RE = re.compile(r"path (.+) \(offset \d+\)") + def macos_get_rpaths(libpath): """ Get rpath load commands from library `libpath` using ``otool`` @@ -586,7 +560,7 @@ def macos_get_rpaths(libpath): ----- See ``man dyld`` for more information on rpaths in libraries """ - lines = back_tick('otool -l ' + libpath).split('\n') + lines = back_tick('otool -l {}'.format(libpath)).split('\n') ctr = 0 rpaths = [] while ctr < len(lines): @@ -598,14 +572,15 @@ def macos_get_rpaths(libpath): rpath_line = lines[ctr + 2].strip() match = MACOS_RPATH_RE.match(rpath_line) if match is None: - raise RuntimeError('Unexpected path line: ' + rpath_line) + raise RuntimeError("Unexpected path line: {}".format(rpath_line)) rpaths.append(match.groups()[0]) ctr += 3 return rpaths + def macos_add_rpath(rpath, library_path): - back_tick('install_name_tool -add_rpath {rpath} {library_path}'.format( - rpath=rpath, library_path=library_path)) + back_tick("install_name_tool -add_rpath {} {}".format(rpath, library_path)) + def macos_fix_rpaths_for_library(library_path, qt_lib_dir): """ Adds required rpath load commands to given library. @@ -648,11 +623,11 @@ def macos_fix_rpaths_for_library(library_path, qt_lib_dir): # If the library depends on a Qt library, add an rpath load comment # pointing to the Qt lib directory. - macos_add_qt_rpath(library_path, qt_lib_dir, existing_rpath_commands, - install_names) + macos_add_qt_rpath(library_path, qt_lib_dir, existing_rpath_commands, install_names) + -def macos_add_qt_rpath(library_path, qt_lib_dir, - existing_rpath_commands = [], library_dependencies = []): +def macos_add_qt_rpath(library_path, qt_lib_dir, existing_rpath_commands=[], + library_dependencies=[]): """ Adds an rpath load command to the Qt lib directory if necessary @@ -680,6 +655,7 @@ def macos_add_qt_rpath(library_path, qt_lib_dir, if needs_qt_rpath: macos_add_rpath(qt_lib_dir, library_path) + # Find an executable specified by a glob pattern ('foo*') in the OS path def find_glob_in_path(pattern): result = [] @@ -691,6 +667,7 @@ def find_glob_in_path(pattern): result.append(match) return result + # Locate the most recent version of llvm_config in the path. def find_llvm_config(): version_re = re.compile(r'(\d+)\.(\d+)\.(\d+)') @@ -702,8 +679,9 @@ def find_llvm_config(): if output: match = version_re.match(output[0]) if match: - version_string = '%02d%02d%02d' % (int(match.group(1)), - int(match.group(2)), int(match.group(3))) + version_string = "{:02d}{:02d}{:02d}".format(int(match.group(1)), + int(match.group(2)), + int(match.group(3))) if (version_string > last_version_string): result = llvm_config last_version_string = version_string @@ -711,6 +689,7 @@ def find_llvm_config(): pass return result + # Add Clang to path for Windows for the shiboken ApiExtractor tests. # Revisit once Clang is bundled with Qt. def detect_clang(): @@ -729,12 +708,14 @@ def detect_clang(): except OSError: pass if clang_dir: - arch = '64' if sys.maxsize > 2**31-1 else '32' + arch = '64' if sys.maxsize > 2 ** 31 - 1 else '32' clang_dir = clang_dir.replace('_ARCH_', arch) return (clang_dir, source) + _7z_binary = None + def download_and_extract_7z(fileurl, target): """ Downloads 7z file from fileurl and extract to target """ info = "" @@ -752,12 +733,12 @@ def download_and_extract_7z(fileurl, target): try: global _7z_binary - outputDir = "-o" + target + outputDir = "-o{}".format(target) if not _7z_binary: if sys.platform == 'win32': candidate = 'c:\\Program Files\\7-Zip\\7z.exe' if os.path.exists(candidate): - _7z_binary = candidate + _7z_binary = candidate if not _7z_binary: _7z_binary = '7z' print("calling {} x {} {}".format(_7z_binary, localfile, outputDir)) @@ -765,10 +746,12 @@ def download_and_extract_7z(fileurl, target): except: raise RuntimeError(' Error extracting {}'.format(localfile)) -def split_and_strip(input): - lines = [s.strip() for s in input.splitlines()] + +def split_and_strip(sinput): + lines = [s.strip() for s in sinput.splitlines()] return lines + def ldd_get_dependencies(executable_path): """ Returns a dictionary of dependencies that `executable_path` @@ -787,8 +770,8 @@ def ldd_get_dependencies(executable_path): dependencies[match.group(1)] = match.group(2) return dependencies -def ldd_get_paths_for_dependencies(dependencies_regex, executable_path = None, - dependencies = None): + +def ldd_get_paths_for_dependencies(dependencies_regex, executable_path=None, dependencies=None): """ Returns file paths to shared library dependencies that match given `dependencies_regex` against given `executable_path`. @@ -818,6 +801,7 @@ def ldd_get_paths_for_dependencies(dependencies_regex, executable_path = None, return paths + def ldd(executable_path): """ Returns ld.so output of shared library dependencies for given @@ -848,8 +832,7 @@ def ldd(executable_path): chosen_rtld = None # List of ld's considered by ldd on Ubuntu (here's hoping it's the # same on all distros). - rtld_list = ["/lib/ld-linux.so.2", "/lib64/ld-linux-x86-64.so.2", - "/libx32/ld-linux-x32.so.2"] + rtld_list = ["/lib/ld-linux.so.2", "/lib64/ld-linux-x86-64.so.2", "/libx32/ld-linux-x32.so.2"] # Choose appropriate runtime dynamic linker. for rtld in rtld_list: @@ -858,8 +841,7 @@ def ldd(executable_path): # Code 127 is returned by ld.so when called without any # arguments (some kind of sanity check I guess). if code == 127: - (_, _, code) = back_tick("{} --verify {}".format(rtld, - executable_path), True) + (_, _, code) = back_tick("{} --verify {}".format(rtld, executable_path), True) # Codes 0 and 2 mean given executable_path can be # understood by ld.so. if code in [0, 2]: @@ -867,8 +849,7 @@ def ldd(executable_path): break if not chosen_rtld: - raise RuntimeError("Could not find appropriate ld.so to query " - "for dependencies.") + raise RuntimeError("Could not find appropriate ld.so to query for dependencies.") # Query for shared library dependencies. rtld_env = "LD_TRACE_LOADED_OBJECTS=1" @@ -878,7 +859,8 @@ def ldd(executable_path): return out else: raise RuntimeError("ld.so failed to query for dependent shared " - "libraries of {} ".format(executable_path)) + "libraries of {} ".format(executable_path)) + def find_files_using_glob(path, pattern): """ Returns list of files that matched glob `pattern` in `path`. """ @@ -886,6 +868,7 @@ def find_files_using_glob(path, pattern): maybe_files = glob.glob(final_pattern) return maybe_files + def find_qt_core_library_glob(lib_dir): """ Returns path to the QtCore library found in `lib_dir`. """ maybe_file = find_files_using_glob(lib_dir, "libQt5Core.so.?") @@ -893,6 +876,7 @@ def find_qt_core_library_glob(lib_dir): return maybe_file[0] return None + # @TODO: Possibly fix ICU library copying on macOS and Windows. # This would require to implement the equivalent of the custom written # ldd for the specified platforms. @@ -907,7 +891,7 @@ def copy_icu_libs(patchelf, destination_lib_dir): if not qt_core_library_path or not os.path.exists(qt_core_library_path): raise RuntimeError('QtCore library does not exist at path: {}. ' - 'Failed to copy ICU libraries.'.format(qt_core_library_path)) + 'Failed to copy ICU libraries.'.format(qt_core_library_path)) dependencies = ldd_get_dependencies(qt_core_library_path) @@ -921,11 +905,9 @@ def copy_icu_libs(patchelf, destination_lib_dir): break if icu_required: - paths = ldd_get_paths_for_dependencies(icu_regex, - dependencies=dependencies) + paths = ldd_get_paths_for_dependencies(icu_regex, dependencies=dependencies) if not paths: - raise RuntimeError("Failed to find the necessary ICU libraries " - "required by QtCore.") + raise RuntimeError("Failed to find the necessary ICU libraries required by QtCore.") log.info('Copying the detected ICU libraries required by QtCore.') if not os.path.exists(destination_lib_dir): @@ -941,8 +923,7 @@ def copy_icu_libs(patchelf, destination_lib_dir): # Patch the QtCore library to find the copied over ICU libraries # (if necessary). - log.info("Checking if QtCore library needs a new rpath to make it " - "work with ICU libs.") + log.info("Checking if QtCore library needs a new rpath to make it work with ICU libs.") rpaths = linux_get_rpaths(qt_core_library_path) if not rpaths or not rpaths_has_origin(rpaths): log.info('Patching QtCore library to contain $ORIGIN rpath.') @@ -967,8 +948,7 @@ def linux_set_rpaths(patchelf, executable_path, rpath_string): cmd = [patchelf, '--set-rpath', rpath_string, executable_path] if run_process(cmd) != 0: - raise RuntimeError("Error patching rpath in {}".format( - executable_path)) + raise RuntimeError("Error patching rpath in {}".format(executable_path)) def linux_get_dependent_libraries(executable_path): @@ -1061,6 +1041,7 @@ def linux_fix_rpaths_for_library(patchelf, executable_path, qt_rpath, override=F rpaths_string = ':'.join(rpaths) linux_set_rpaths(patchelf, executable_path, rpaths_string) + def memoize(function): """ Decorator to wrap a function with a memoizing callable. @@ -1068,6 +1049,7 @@ def memoize(function): the same arguments. """ memo = {} + def wrapper(*args): if args in memo: return memo[args] @@ -1077,6 +1059,7 @@ def memoize(function): return rv return wrapper + def get_python_dict(python_script_path): try: with open(python_script_path) as f: @@ -1086,9 +1069,10 @@ def get_python_dict(python_script_path): return python_dict except IOError as e: print("get_python_dict: Couldn't get dict from python " - "file: {}.".format(python_script_path)) + "file: {}.".format(python_script_path)) raise + def install_pip_package_from_url_specifier(env_pip, url, upgrade=True): args = [env_pip, "install", url] if upgrade: @@ -1096,22 +1080,24 @@ def install_pip_package_from_url_specifier(env_pip, url, upgrade=True): args.append(url) run_instruction(args, "Failed to install {}".format(url)) + def install_pip_dependencies(env_pip, packages, upgrade=True): for p in packages: args = [env_pip, "install"] if upgrade: args.append("--upgrade") args.append(p) - run_instruction(args, "Failed to install " + p) + run_instruction(args, "Failed to install {}".format(p)) + def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch): _pExe = "python" - _env = "env" + str(python_ver) + _env = "env{}".format(str(python_ver)) env_python = _env + "/bin/python" env_pip = _env + "/bin/pip" if host == "Windows": - print("New virtualenv to build " + targetArch + " in " + hostArch + " host.") + print("New virtualenv to build {} in {} host".format(targetArch, hostArch)) _pExe = "python.exe" # With windows we are creating building 32-bit target in 64-bit host if hostArch == "X86_64" and targetArch == "X86": @@ -1129,26 +1115,30 @@ def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch): _pExe = "python3" return(_pExe, _env, env_pip, env_python) + def run_instruction(instruction, error, initial_env=None): if initial_env is None: initial_env = os.environ - print("Running Coin instruction: " + ' '.join(str(e) for e in instruction)) + print("Running Coin instruction: {}".format(' '.join(str(e) for e in instruction))) result = subprocess.call(instruction, env=initial_env) if result != 0: - print("ERROR : " + error) + print("ERROR : {}".format(error)) exit(result) + def acceptCITestConfiguration(hostOS, hostOSVer, targetArch, compiler): # Disable unsupported CI configs for now # NOTE: String must match with QT CI's storagestruct thrift - if hostOSVer in ["WinRT_10", "WebAssembly", "Ubuntu_18_04", "Android_ANY"] \ - or hostOSVer.startswith("SLES_"): - print("Disabled " + hostOSVer + " from Coin configuration") + if (hostOSVer in ["WinRT_10", "WebAssembly", "Ubuntu_18_04", "Android_ANY"] + or hostOSVer.startswith("SLES_")): + print("Disabled {} from Coin configuration".format(hostOSVer)) return False - # With 5.11 CI will create two sets of release binaries, one with msvc 2015 and one with msvc 2017 - # we shouldn't release the 2015 version. BUT, 32 bit build is done only on msvc 2015... + # With 5.11 CI will create two sets of release binaries, + # one with msvc 2015 and one with msvc 2017 + # we shouldn't release the 2015 version. + # BUT, 32 bit build is done only on msvc 2015... if compiler in ["MSVC2015"] and targetArch in ["X86_64"]: - print("Disabled " + compiler + " to " + targetArch + " from Coin configuration") + print("Disabled {} to {} from Coin configuration".format(compiler, targetArch)) return False return True @@ -1158,6 +1148,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 b06628b3b..c6eb87d39 100644 --- a/build_scripts/wheel_override.py +++ b/build_scripts/wheel_override.py @@ -41,7 +41,8 @@ wheel_module_exists = False try: - import os, sys + import os + import sys from distutils import log as logger from wheel import pep425tags @@ -60,6 +61,7 @@ except Exception as e: print('***** Exception while trying to prepare bdist_wheel override class: {}. ' 'Skipping wheel overriding.'.format(e)) + def get_bdist_wheel_override(params): if wheel_module_exists: class PysideBuildWheelDecorated(PysideBuildWheel): @@ -70,6 +72,7 @@ def get_bdist_wheel_override(params): else: return None + class PysideBuildWheel(_bdist_wheel): def __init__(self, *args, **kwargs): self.pyside_params = None @@ -101,8 +104,7 @@ class PysideBuildWheel(_bdist_wheel): qt_version = self.params['qt_version'] package_version = self.params['package_version'] wheel_version = "{}-{}".format(package_version, qt_version) - components = (_safer_name(self.distribution.get_name()), - wheel_version) + components = (_safer_name(self.distribution.get_name()), wheel_version) if self.build_number: components += (self.build_number,) return '-'.join(components) @@ -135,8 +137,9 @@ class PysideBuildWheel(_bdist_wheel): # pypi). # TODO: Add actual distro detection, instead of # relying on limited_api option. - if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize > 2147483647 \ - and (self.py_limited_api or sys.version_info[0] == 2): + if (plat_name in ('linux-x86_64', 'linux_x86_64') + and sys.maxsize > 2147483647 + and (self.py_limited_api or sys.version_info[0] == 2)): plat_name = 'manylinux1_x86_64' plat_name = plat_name.replace('-', '_').replace('.', '_') @@ -163,8 +166,7 @@ class PysideBuildWheel(_bdist_wheel): if (self.py_limited_api) or (plat_name in ('manylinux1_x86_64') and sys.version_info[0] == 2): return tag assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) - assert tag in supported_tags, ( - "would build wheel with unsupported tag {}".format(tag)) + assert tag in supported_tags, ("would build wheel with unsupported tag {}".format(tag)) return tag # Copy of get_tag from bdist_wheel.py, to write a triplet Tag @@ -201,4 +203,3 @@ class PysideBuildWheel(_bdist_wheel): if not wheel_module_exists: del PysideBuildWheel - diff --git a/coin/module_config.yaml b/coin/module_config.yaml new file mode 100644 index 000000000..71d4613b0 --- /dev/null +++ b/coin/module_config.yaml @@ -0,0 +1,546 @@ +version: 2 +accept_configuration: + condition: or + conditions: + - condition: and + conditions: + - condition: property # No cross compilation + property: host.os + equals_property: target.os + - condition: property # qtnamespace is not supported + property: configureArgs + not_contains_value: -qtnamespace + - condition: property # no-widgets is notsupported + property: configureArgs + not_contains_value: -no-widgets + - condition: property # no-gui is not supported + property: configureArgs + not_contains_value: -no-gui + - condition: property # Following configs are not supported + property: target.osVersion + not_in_values: [OPENSUSE_13_01, QEMU, WebAssembly, Ubuntu_18_04, SLES_12, SLES_15] + - condition: property # MibnGW and msvc2015 are not supported + property: target.compiler + not_in_values: [Mingw73, MSVC2015] + - condition: and + conditions: + - condition: property + property: target.osVersion + equals_value: Ubuntu_18_04 + - condition: property + property: features + contains_value: LicenseCheck + +set_environment: &set_environment + type: Group + instructions: + - type: EnvironmentVariable + variableName: TARGET_ARCHITECTURE + variableValue: amd64 + enable_if: + condition: and + conditions: + - condition: property + property: target.arch + equals_value: X86_64 + - condition: property + property: host.os + equals_value: Windows + - type: EnvironmentVariable + variableName: TARGET_ARCHITECTURE + variableValue: amd64_x86 + enable_if: + condition: and + conditions: + - condition: property + property: target.arch + equals_value: X86 + - condition: property + property: host.os + equals_value: Windows + - type: EnvironmentVariable + variableName: MAKEFLAGS + variableValue: "" + enable_if: + condition: property + property: host.os + equals_value: Windows + - type: AppendToEnvironmentVariable + variableName: PATH + variableValue: ;%CI_JOM_PATH% + enable_if: + condition: property + property: host.os + equals_value: Windows + - type: PrependToEnvironmentVariable + variableName: PATH + variableValue: "\\Users\\qt\\work\\install\\bin;" + enable_if: + condition: property + property: host.os + equals_value: Windows + - type: EnvironmentVariable + variableName: ICC64_18_LDLP + variableValue: /opt/intel/lib/intel64 + enable_if: + condition: property + property: target.compiler + equals_value: ICC_18 + - type: EnvironmentVariable + variableName: ICC64_18_PATH # Seems a bit hard to maintain + variableValue: /opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:/opt/intel/bin + enable_if: + condition: property + property: target.compiler + equals_value: ICC_18 + - type: AppendToEnvironmentVariable + variableName: LD_LIBRARY_PATH + variableValue: :/opt/intel/lib/intel64 + enable_if: + condition: property + property: target.compiler + equals_value: ICC_18 + - type: AppendToEnvironmentVariable + variableName: PATH + variableValue: ":{{.Env.ICC64_18_PATH}}" + enable_if: + condition: property + property: target.compiler + equals_value: ICC_18 + - type: EnvironmentVariable + variableName: QT_MODULE_TO_TEST + variableValue: "pyside/pyside-setup" + enable_if: + condition: property + property: features + contains_value: LicenseCheck + +find_path_to_msvc_compiler: &find_path_to_msvc_compiler + type: Group + enable_if: + condition: property + property: host.os + equals_value: Windows + instructions: + - type: EnvironmentVariable + variableName: VC_SCRIPT + variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2017\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat" + enable_if: + condition: property + property: host.compiler + equals_value: MSVC2017 + - type: EnvironmentVariable + variableName: VC_SCRIPT + variableValue: "%ProgramFiles(x86)%\\Microsoft Visual Studio\\2019\\Professional\\VC\\Auxiliary\\Build\\vcvarsall.bat" + enable_if: + condition: property + property: host.compiler + equals_value: MSVC2019 + - type: WriteFile + fileContents: "call \"{{.Env.VC_SCRIPT}}\" {{.Env.TARGET_ARCHITECTURE}} \r\ncmd /c %*" + filename: "c:\\users\\qt\\MSVC.bat" + fileMode: 420 + enable_if: + condition: property + property: host.os + equals_value: Windows + +run_instructions: &run_instructions + type: Group + instructions: + - type: ExecuteCommand + command: python -u coin_build_instructions.py --os=MacOS --packaging --instdir=/Users/qt/work/install --targetOs=MacOS --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: MacOS + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute build instructions on osx + - type: ExecuteCommand + command: python -u coin_build_instructions.py --os=MacOS --instdir=/Users/qt/work/install --targetOs=MacOS --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: MacOS + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute build instructions on osx + - type: ExecuteCommand + command: python -u coin_build_instructions.py --os=Linux --packaging --instdir=/home/qt/work/install --targetOs=Linux --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Linux + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute build instructions on Linux + - type: ExecuteCommand + command: python -u coin_build_instructions.py --os=Linux --instdir=/home/qt/work/install --targetOs=Linux --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Linux + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute build instructions on Linux + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os=Windows --packaging --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: features + contains_value: Packaging + - condition: property + property: target.arch + equals_property: host.arch + userMessageOnFailure: > + Failed to execute build instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: features + not_contains_value: Packaging + - condition: property + property: target.arch + equals_property: host.arch + userMessageOnFailure: > + Failed to execute build instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os=Windows --packaging --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: features + contains_value: Packaging + - condition: property + property: target.arch + equals_value: X86 + userMessageOnFailure: > + Failed to execute 32 bit build instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_build_instructions.py --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 300 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: features + not_contains_value: Packaging + - condition: property + property: target.arch + equals_value: X86 + userMessageOnFailure: > + Failed to execute 32 bit build instructions on 64 bit Windows +run_test_instructions: &run_test_instructions + type: Group + enable_if: + condition: property + property: features + not_contains_value: LicenseCheck + instructions: + - type: ExecuteCommand + command: python -u coin_test_instructions.py --os=MacOS --instdir=/Users/qt/work/install --targetOs=MacOS --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: MacOS + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on osx + - type: ExecuteCommand + command: python -u coin_test_instructions.py --packaging --os=MacOS --instdir=/Users/qt/work/install --targetOs=MacOS --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: MacOS + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on osx + - type: ExecuteCommand + command: python -u coin_test_instructions.py --os=Linux --instdir=/home/qt/work/install --targetOs=Linux --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Linux + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on Linux + - type: ExecuteCommand + command: python -u coin_test_instructions.py --packaging --os=Linux --instdir=/home/qt/work/install --targetOs=Linux --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 14400 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Linux + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on Linux + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: target.arch + equals_property: host.arch + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: target.arch + equals_value: X86 + - condition: property + property: features + not_contains_value: Packaging + userMessageOnFailure: > + Failed to execute test instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --packaging --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86_64 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: target.arch + equals_property: host.arch + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute 32 bit test instructions on 64 bit Windows + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat python -u coin_test_instructions.py --packaging --os=Windows --instdir=\Users\qt\work\install --targetOs=Windows --hostArch=X86_64 --targetArch=X86 + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: and + conditions: + - condition: property + property: host.os + equals_value: Windows + - condition: property + property: target.arch + equals_value: X86 + - condition: property + property: features + contains_value: Packaging + userMessageOnFailure: > + Failed to execute 32 bit test instructions on 64 bit Windows + +relocate_pyside: &relocate_pyside + type: Group + enable_if: + condition: property + property: features + not_contains_value: LicenseCheck + instructions: + - type: ChangeDirectory + directory: "{{.AgentWorkingDir}}/pyside" + maxTimeInSeconds: 300 + maxTimeBetweenOutput: 120 + userMessageOnFailure: > + Failed to change to pyside dir + - type: ExecuteCommand + command: c:\\users\\qt\\MSVC.bat rd /s /q pyside-setup + maxTimeInSeconds: 300 + maxTimeBetweenOutput: 120 + enable_if: + condition: property + property: host.os + equals_value: Windows + userMessageOnFailure: > + Failed to remove pyside-setup dir + - type: ExecuteCommand + command: /bin/rm -rf pyside-setup + maxTimeInSeconds: 300 + maxTimeBetweenOutput: 120 + enable_if: + condition: property + property: host.os + not_equals_value: Windows + userMessageOnFailure: > + Failed to remove pyside-setup dir + - type: InstallBinaryArchive + relativeStoragePath: "{{.Env.MODULE_ARTIFACTS_RELATIVE_STORAGE_PATH}}/artifacts.tar.gz" + directory: "pyside" + maxTimeInSeconds: 1200 + maxTimeBetweenOutput: 1200 + - type: ChangeDirectory + directory: "{{.AgentWorkingDir}}\\pyside\\pyside-setup" + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: property + property: host.os + equals_value: Windows + userMessageOnFailure: > + Failed to install binary artifacts + - type: ChangeDirectory + directory: "{{.AgentWorkingDir}}/pyside/pyside-setup" + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + enable_if: + condition: property + property: host.os + not_equals_value: Windows + userMessageOnFailure: > + Failed to change to pyside-setup dir + +upload_pyside: &upload_pyside + type: Group + instructions: + - type: UploadArtifact + archiveDirectory: "{{.AgentWorkingDir}}\\pyside" + transferType: UploadModuleBuildArtifact + maxTimeInSeconds: 1200 + maxTimeBetweenOutput: 1200 + enable_if: + condition: property + property: host.os + equals_value: Windows + - type: UploadArtifact + archiveDirectory: "{{.AgentWorkingDir}}/pyside" + transferType: UploadModuleBuildArtifact + maxTimeInSeconds: 1200 + maxTimeBetweenOutput: 1200 + enable_if: + condition: property + property: host.os + not_equals_value: Windows + +instructions: + LicenseCheck: + - type: ChangeDirectory + directory: "{{.AgentWorkingDir}}" + - type: InstallSourceArchive + maxTimeInSeconds: 600 + maxTimeBetweenOutput: 600 + project: qt/qtbase + ref: 5.14 + directory: qt/qtbase + userMessageOnFailure: > + Could not install source archive. Please investigate why. + - type: InstallSourceArchive + maxTimeInSeconds: 600 + maxTimeBetweenOutput: 600 + project: qt/qtqa + ref: master + directory: qt/qtqa-latest + userMessageOnFailure: > + Could not install source archive. Please investigate why. + - type: EnvironmentVariable + variableName: QT_MODULE_TO_TEST + variableValue: pyside/pyside-setup + userMessageOnFailure: > + Failed to set environment variable. This should not happen. + - type: ExecuteCommand + command: perl qt/qtqa-latest/tests/prebuild/license/tst_licenses.pl + maxTimeInSeconds: 7200 + maxTimeBetweenOutput: 120 + userMessageOnFailure: > + Failed to run license check script. + + Build: + - *set_environment + - *find_path_to_msvc_compiler + - *run_instructions + - *upload_pyside + Test: + - *set_environment + - *find_path_to_msvc_compiler + - *relocate_pyside + - *run_test_instructions + diff --git a/coin_build_instructions.py b/coin_build_instructions.py index dbdbdbd0d..8df12ee4c 100644 --- a/coin_build_instructions.py +++ b/coin_build_instructions.py @@ -43,9 +43,10 @@ from build_scripts.utils import get_qtci_virtualEnv from build_scripts.utils import run_instruction from build_scripts.utils import rmtree from build_scripts.utils import get_python_dict -from build_scripts.utils import acceptCITestConfiguration from build_scripts.utils import get_ci_qmake_path import os +import datetime +import calendar # Values must match COIN thrift CI_HOST_OS = option_value("os") @@ -56,7 +57,7 @@ CI_HOST_OS_VER = option_value("osVer") CI_ENV_INSTALL_DIR = option_value("instdir") CI_ENV_AGENT_DIR = option_value("agentdir") CI_COMPILER = option_value("compiler") -CI_INTEGRATION_ID = option_value("coinIntegrationId") +CI_INTEGRATION_ID = option_value("coinIntegrationId") or str(calendar.timegm(datetime.datetime.now().timetuple())) CI_FEATURES = [] _ci_features = option_value("features") if _ci_features is not None: @@ -101,6 +102,9 @@ def is_snapshot_build(): return False def call_setup(python_ver, phase): + print("call_setup") + print("python_ver", python_ver) + print("phase", phase) _pExe, _env, env_pip, env_python = get_qtci_virtualEnv(python_ver, CI_HOST_OS, CI_HOST_ARCH, CI_TARGET_ARCH) if phase in ["BUILD"]: @@ -137,7 +141,6 @@ def call_setup(python_ver, phase): env = os.environ run_instruction(cmd, "Failed to run setup.py for build", initial_env=env) - def run_build_instructions(phase): # Uses default python, hopefully we have python2 installed on all hosts @@ -145,12 +148,11 @@ def run_build_instructions(phase): if CI_HOST_OS != "Windows": call_setup("", phase) # In case of packaging build, we have to build also python3 wheel + if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]: call_setup("3", phase) if __name__ == "__main__": - if not acceptCITestConfiguration(CI_HOST_OS, CI_HOST_OS_VER, CI_TARGET_ARCH, CI_COMPILER): - exit() # Remove some environment variables that impact cmake for env_var in ['CC', 'CXX']: diff --git a/coin_test_instructions.py b/coin_test_instructions.py index 8ba82c26f..5c20e9848 100644 --- a/coin_test_instructions.py +++ b/coin_test_instructions.py @@ -42,7 +42,6 @@ from build_scripts.utils import install_pip_dependencies from build_scripts.utils import get_qtci_virtualEnv from build_scripts.utils import run_instruction from build_scripts.utils import rmtree -from build_scripts.utils import acceptCITestConfiguration from build_scripts.utils import get_ci_qmake_path import os @@ -82,9 +81,6 @@ def call_testrunner(python_ver, buildnro): run_instruction(cmd, "Error while running wheel_tester.py") def run_test_instructions(): - if not acceptCITestConfiguration(CI_HOST_OS, CI_HOST_OS_VER, CI_TARGET_ARCH, CI_COMPILER): - exit() - # Remove some environment variables that impact cmake for env_var in ['CC', 'CXX']: if os.environ.get(env_var): @@ -97,7 +93,7 @@ def run_test_instructions(): call_testrunner("", str(testRun)) testRun =+ 1 # We know that second build was with python3 - if CI_RELEASE_CONF and CI_HOST_OS_VER not in ["RHEL_6_6"]: + if CI_RELEASE_CONF: call_testrunner("3", str(testRun)) if __name__ == "__main__": diff --git a/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml b/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml index b8550ef2c..a14177586 100644 --- a/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml +++ b/sources/pyside2/PySide2/QtCharts/typesystem_charts.xml @@ -41,6 +41,9 @@ --> <typesystem package="PySide2.QtCharts"> <load-typesystem name="QtWidgets/typesystem_widgets.xml" generate="no"/> + <!-- PYSIDE-1101 Removing inherited method to avoid argument conflict + on the QChart::scroll overload --> + <rejection class="QGraphicsItem" function-name="scroll"/> <namespace-type name="QtCharts"> <object-type name="QAbstractAxis" since="5.7"> <enum-type name="AxisType"/> diff --git a/sources/pyside2/PySide2/QtQuick/typesystem_quick.xml b/sources/pyside2/PySide2/QtQuick/typesystem_quick.xml index 7a18dac54..223eff773 100644 --- a/sources/pyside2/PySide2/QtQuick/typesystem_quick.xml +++ b/sources/pyside2/PySide2/QtQuick/typesystem_quick.xml @@ -55,8 +55,9 @@ <object-type name="QQuickAsyncImageProvider" since="5.6"/> - <object-type name="QQuickFramebufferObject"/> - <object-type name="QQuickFramebufferObject::Renderer"/> + <object-type name="QQuickFramebufferObject"> + <object-type name="Renderer"/> + </object-type> <object-type name="QQuickTextureFactory"/> <object-type name="QQuickImageProvider"/> @@ -122,12 +123,12 @@ <enum-type name="AttributeType" since="5.8"/> <enum-type name="DrawingMode" since="5.8"/> <enum-type name="Type" since="5.8"/> + <value-type name="Attribute"/> + <value-type name="AttributeSet"/> + <value-type name="ColoredPoint2D"/> + <value-type name="Point2D"/> + <value-type name="TexturedPoint2D"/> </object-type> - <value-type name="QSGGeometry::Attribute"/> - <value-type name="QSGGeometry::AttributeSet"/> - <value-type name="QSGGeometry::ColoredPoint2D"/> - <value-type name="QSGGeometry::Point2D"/> - <value-type name="QSGGeometry::TexturedPoint2D"/> <object-type name="QSGGeometryNode"/> <!-- QSGMaterialShader doesn't compile because of const char * char * types not being recognized diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp index 47b3dd6db..8bcc315b2 100644 --- a/sources/pyside2/PySide2/glue/qtcore.cpp +++ b/sources/pyside2/PySide2/glue/qtcore.cpp @@ -81,7 +81,6 @@ if (typeObj) { for (int i = 0; i < valuesSize; i++) { PyObject *item = PyUnicode_FromString(valuesList[i].data()); PyList_SET_ITEM(list, i, item); - Py_DECREF(item); } %PYARG_0 = list; @@ -110,15 +109,23 @@ if (typeObj) { float asFloat = out.toFloat(); %PYARG_0 = PyFloat_FromDouble(asFloat); } else if (typeObj == &PyBool_Type) { - %PYARG_0 = out.toBool() ? Py_True : Py_False; + if (out.toBool()) { + Py_INCREF(Py_True); + %PYARG_0 = Py_True; + } else { + Py_INCREF(Py_False); + %PYARG_0 = Py_False; + } } // TODO: PyDict_Type and PyTuple_Type } else { - if (!out.isValid()) + if (!out.isValid()) { + Py_INCREF(Py_None); %PYARG_0 = Py_None; - else + } else { %PYARG_0 = %CONVERTTOPYTHON[QVariant](out); + } } // @snippet qsettings-value diff --git a/sources/pyside2/doc/deployment-pyinstaller.rst b/sources/pyside2/doc/deployment-pyinstaller.rst index c9c7b09fd..e7ed643f6 100644 --- a/sources/pyside2/doc/deployment-pyinstaller.rst +++ b/sources/pyside2/doc/deployment-pyinstaller.rst @@ -1,55 +1,49 @@ |project| & PyInstaller ####################### -`PyInstaller <https://www.pyinstaller.org/>`_ lets you freeze your python -application into a stand-alone executable. -The supported platforms are Linux, macOS, Windows, FreeBSD, and others. +`PyInstaller <https://www.pyinstaller.org/>`_ lets you freeze your python application into a +stand-alone executable. This installer supports Linux, macOS, Windows, and more; and is also +compatible with 3rd-party Python modules, such as |pymodname|. -One of the main goals of `PyInstaller` is to be compatible with 3rd-party -Python modules, for example: |pymodname|. - -You can read the `official documentation <https://www.pyinstaller.org/documentation.html>`_ -to clarify any further question, and remember to contribute to -`the project <https://github.com/pyinstaller/pyinstaller>`_ -by filing issues if you find any, or contributing to their development. +For more details, see the `official documentation <https://www.pyinstaller.org/documentation.html>`_. Preparation =========== -Installing `PyInstaller` can be done using **pip**:: +Install the `PyInstaller` via **pip** with the following command:: pip install pyinstaller -If you are using a virtual environment, remember to activate it before -installing `PyInstaller` into it. +If you're using a virtual environment, remember to activate it before installing `PyInstaller`. -After the installation, the `pyinstaller` binary will be located in the `bin/` -directory of your virtual environment, or where your Python executable is located. -If that directory is not in your `PATH`, include the whole path when executing `pyinstaller`. +After installation, the `pyinstaller` binary is located in your virtual environment's `bin/` +directory, or where your Python executable is located. If that directory isn't in your `PATH`, +include the whole path when you run `pyinstaller`. .. warning:: If you already have a PySide2 or Shiboken2 version installed in your - system path, PyInstaller will pick them instead of your virtual environment - version. + system path, PyInstaller uses them instead of your virtual environment version. -Freezing an application +Freeze an application ======================= -`PyInstaller` has many options that you can use. -To learn more about them you can just run `pyinstaller -h`. +`PyInstaller` has many options that you can use. To list them all, run `pyinstaller -h`. -Two main features are the option to package the whole project -(including the shared libraries) into one executable file (`--onefile`), -and to place it in a directory containing the libraries. +There are two main features: -Additionally, for Windows you can enable opening a console during the -execution with the option, `-c` (or equivalent `--console` or `--nowindowed`). -Further, you can specify to not open such console window -on macOS and Windows with the option, `-w` (or equivalent `--windowed` or `--noconsole`). + * the option to package the whole project (including shared libraries) into one executable file + (`--onefile`) + * the option to place it in a directory containing the libraries -Creating an example -------------------- +Additionally, on Windows when the command is running, you can open a console with the `-c` option +(or `--console` or `--nowindowed` equivalent). + +Otherwise, you can specify to not open such a console window on macOS and Windows with the `-w` +option (or `--windowed` or `--noconsole` equivalent). -Now, consider the following simple script, named `hello.py`:: +Create an example +----------------- + +Now, consider the following script, named `hello.py`:: import sys import random @@ -90,68 +84,58 @@ Now, consider the following simple script, named `hello.py`:: sys.exit(app.exec_()) -As it has a UI, you will use the `--windowed` option. +Since it has a UI, you use the `--windowed` option. The command line to proceed looks like this:: pyinstaller --name="MyApplication" --windowed hello.py -This process creates a `dist/` and `build/` directory. -The application executable and the required shared libraries are -placed in `dist/MyApplication`. +This process creates two directories: `dist/` and `build/`. The application executable and the +required shared libraries are placed in `dist/MyApplication`. -To run the application you can go to `dist/MyApplication` and -execute the program:: +To run the application, go to `dist/MyApplication` and run the program:: cd dist/MyApplication/ ./MyApplication -.. note:: The directory inside `dist/` and the executable will have - the same name. +.. note:: The directory inside `dist/` and the executable have the same name. -If you prefer to have everything bundled into one executable, -without the shared libraries next to it, you can use the option -`--onefile`:: +Use the `--onefile` option if you prefer to have everything bundled into one executable, without +the shared libraries next to it:: pyinstaller --name="MyApplication" --windowed --onefile hello.py -This process takes a bit longer, but in the end you will have one -executable in the `dist/` directory:: +This process takes a bit longer, but in the end you have one executable in the `dist/` directory:: cd dist/ ./MyApplication -Current Caveats To Be Aware Of -============================== +Some Caveats +============ -PyInstaller Problem -------------------- +PyInstaller Issue +----------------- -As already mentioned, `PyInstaller` will pick a system installation -of PySide2 or Shiboken2 instead of your virtualenv version without -notice, if it exists. This may not be a problem if those two -versions are the same. +As mentioned before, if available, `PyInstaller` picks a system installation of PySide2 or +Shiboken2 instead of your `virtualenv` version without notice. This is negligible if those +two versions are the same. -If you are working with different versions, this can result in -frustrating debugging sessions. You could think you are testing the -latest version, but `PyInstaller` could be working with an older +If you're working with different versions, this can result in frustrating debugging sessions +when you think you are testing the latest version, but `PyInstaller` is working with an older version. -Problem with numpy in Python 2.7.16 ------------------------------------ +Issue with numpy in Python 2.7.16 +--------------------------------- -A recent problem of PyInstaller is the Python 2 release, that is -v2.7.16. This Python version creates a problem that is known from -Python 3 as a `Tcl/Tk` problem. It rarely shows up in Python 3 as -`Tcl/Tk` is seldom used with `PyInstaller. +A recent issue with PyInstaller is the appearance of Python 2.7.16. This Python version creates +an issue that is known from Python 3 as a `Tcl/Tk` problem. This rarely shows up in Python 3 +because `Tcl/Tk` is seldom used with `PyInstaller`. -On Python 2.7.16, this problem is very much visible, as many are -using numpy. For some reason, installing `numpy` creates a -dependency to `Tcl/Tk`, which can be circumvented only by explicitly -excluding `Tcl/Tk` related things by adding this line to the analysis -section of the spec-file:: +On Python 2.7.16, this problem is common, as many developers use numpy. For some reason, +installing `numpy` creates a dependency to `Tcl/Tk`, which can be circumvented only by explicitly +excluding `Tcl/Tk` by adding this line to spec-file's analysis section:: excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'], diff --git a/sources/pyside2/doc/overview.rst b/sources/pyside2/doc/overview.rst index 86c3a54fe..88f03c4eb 100644 --- a/sources/pyside2/doc/overview.rst +++ b/sources/pyside2/doc/overview.rst @@ -1,12 +1,11 @@ Overview ========= -The |project| project aims to provide a complete port of the PySide module to Qt 5. -The development started on GitHub in May 2015. The project managed to port Pyside to -Qt 5.3, 5. 4 & 5.5. +The |project| project provides a complete port of the PySide module to Qt 5. Development started on +GitHub in May 2015. Since then, the project has ported PySide to Qt 5.3, 5.4, and 5.5. -The `PySide2` module was released mid June 2018 as a Technical Preview (supporting Qt 5.11), -and it has been fully supported since Qt 5.12. +In June 2018, the `PySide2` module was released as a Technical Preview (supporting Qt 5.11); it's +been fully supported since Qt 5.12. |project| is available under LGPLv3/GPLv2 and commercial license for the following platforms: @@ -23,34 +22,3 @@ and it has been fully supported since Qt 5.12. * (*): `No Qt release <https://wiki.qt.io/Qt_5.12_Tools_and_Versions#Software_configurations_for_Qt_5.12.0>`_ * (**): `MSVC issue with Python 2.7 and Qt <https://wiki.qt.io/Qt_for_Python/Considerations#Missing_Windows_.2F_Python_2.7_release>`_ - -What does PySide2 look like? ----------------------------- - -A simple Hello World example in PySide2 looks like this: - -:: - - import sys - from PySide2.QtWidgets import QApplication, QLabel - - - if __name__ == "__main__": - app = QApplication(sys.argv) - label = QLabel("Hello World") - label.show() - sys.exit(app.exec_()) - - -Additional overviews --------------------- - -These additional topics provide detailed information about -several Qt-specific features: - -.. toctree:: - :titlesonly: - :glob: - - overviews/* - diff --git a/sources/pyside2/tests/registry/exists_darwin_5_14_0_ci.py b/sources/pyside2/tests/registry/exists_darwin_5_14_0_ci.py index a1385298a..98ec8fcbc 100644 --- a/sources/pyside2/tests/registry/exists_darwin_5_14_0_ci.py +++ b/sources/pyside2/tests/registry/exists_darwin_5_14_0_ci.py @@ -34972,7 +34972,7 @@ sig_dict.update({ "PySide2.QtCharts.QtCharts.QChart.removeAllSeries": (), "PySide2.QtCharts.QtCharts.QChart.removeAxis": ('PySide2.QtCharts.QtCharts.QAbstractAxis',), "PySide2.QtCharts.QtCharts.QChart.removeSeries": ('PySide2.QtCharts.QtCharts.QAbstractSeries',), - "PySide2.QtCharts.QtCharts.QChart.scroll": [('float', 'float'), ('float', 'float', 'PySide2.QtCore.QRectF')], + "PySide2.QtCharts.QtCharts.QChart.scroll": ('float', 'float'), "PySide2.QtCharts.QtCharts.QChart.series": (), "PySide2.QtCharts.QtCharts.QChart.setAnimationDuration": ('int',), "PySide2.QtCharts.QtCharts.QChart.setAnimationEasingCurve": ('PySide2.QtCore.QEasingCurve',), diff --git a/sources/pyside2/tests/registry/exists_red_hat_enterprise_linux_workstation7_6_5_14_0_ci.py b/sources/pyside2/tests/registry/exists_red_hat_enterprise_linux_workstation7_6_5_14_0_ci.py index 2cdf9d6f7..e19f8a27c 100644 --- a/sources/pyside2/tests/registry/exists_red_hat_enterprise_linux_workstation7_6_5_14_0_ci.py +++ b/sources/pyside2/tests/registry/exists_red_hat_enterprise_linux_workstation7_6_5_14_0_ci.py @@ -34994,7 +34994,7 @@ sig_dict.update({ "PySide2.QtCharts.QtCharts.QChart.removeAllSeries": (), "PySide2.QtCharts.QtCharts.QChart.removeAxis": ('PySide2.QtCharts.QtCharts.QAbstractAxis',), "PySide2.QtCharts.QtCharts.QChart.removeSeries": ('PySide2.QtCharts.QtCharts.QAbstractSeries',), - "PySide2.QtCharts.QtCharts.QChart.scroll": [('float', 'float'), ('float', 'float', 'PySide2.QtCore.QRectF')], + "PySide2.QtCharts.QtCharts.QChart.scroll": ('float', 'float'), "PySide2.QtCharts.QtCharts.QChart.series": (), "PySide2.QtCharts.QtCharts.QChart.setAnimationDuration": ('int',), "PySide2.QtCharts.QtCharts.QChart.setAnimationEasingCurve": ('PySide2.QtCore.QEasingCurve',), diff --git a/sources/pyside2/tests/registry/exists_win32_5_14_0_ci.py b/sources/pyside2/tests/registry/exists_win32_5_14_0_ci.py index b89ecc7dd..575236710 100644 --- a/sources/pyside2/tests/registry/exists_win32_5_14_0_ci.py +++ b/sources/pyside2/tests/registry/exists_win32_5_14_0_ci.py @@ -35148,7 +35148,7 @@ sig_dict.update({ "PySide2.QtCharts.QtCharts.QChart.removeAllSeries": (), "PySide2.QtCharts.QtCharts.QChart.removeAxis": ('PySide2.QtCharts.QtCharts.QAbstractAxis',), "PySide2.QtCharts.QtCharts.QChart.removeSeries": ('PySide2.QtCharts.QtCharts.QAbstractSeries',), - "PySide2.QtCharts.QtCharts.QChart.scroll": [('float', 'float'), ('float', 'float', 'PySide2.QtCore.QRectF')], + "PySide2.QtCharts.QtCharts.QChart.scroll": ('float', 'float'), "PySide2.QtCharts.QtCharts.QChart.series": (), "PySide2.QtCharts.QtCharts.QChart.setAnimationDuration": ('int',), "PySide2.QtCharts.QtCharts.QChart.setAnimationEasingCurve": ('PySide2.QtCore.QEasingCurve',), diff --git a/sources/pyside2/tests/registry/exists_x86_64_suse_linux_5_14_0_ci.py b/sources/pyside2/tests/registry/exists_x86_64_suse_linux_5_14_0_ci.py index 0e293986a..2bacf6ae7 100644 --- a/sources/pyside2/tests/registry/exists_x86_64_suse_linux_5_14_0_ci.py +++ b/sources/pyside2/tests/registry/exists_x86_64_suse_linux_5_14_0_ci.py @@ -34987,7 +34987,7 @@ sig_dict.update({ "PySide2.QtCharts.QtCharts.QChart.removeAllSeries": (), "PySide2.QtCharts.QtCharts.QChart.removeAxis": ('PySide2.QtCharts.QtCharts.QAbstractAxis',), "PySide2.QtCharts.QtCharts.QChart.removeSeries": ('PySide2.QtCharts.QtCharts.QAbstractSeries',), - "PySide2.QtCharts.QtCharts.QChart.scroll": [('float', 'float'), ('float', 'float', 'PySide2.QtCore.QRectF')], + "PySide2.QtCharts.QtCharts.QChart.scroll": ('float', 'float'), "PySide2.QtCharts.QtCharts.QChart.series": (), "PySide2.QtCharts.QtCharts.QChart.setAnimationDuration": ('int',), "PySide2.QtCharts.QtCharts.QChart.setAnimationEasingCurve": ('PySide2.QtCore.QEasingCurve',), diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 12dafb47d..4566ed3bc 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -539,9 +539,6 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls)); } } - - if (cls->isAbstract() && !cls->isInterface()) - cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper")); } const auto &allEntries = types->entries(); @@ -584,7 +581,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); const bool enumFound = cls - ? cls->findEnum(entry->targetLangName()) != nullptr + ? cls->findEnum(entry->targetLangEntryName()) != nullptr : m_enums.contains(entry); if (!enumFound) { @@ -838,13 +835,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & TypeEntry *typeEntry = nullptr; const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr; if (enumItem->accessPolicy() == CodeModel::Private) { - QStringList names = enumItem->qualifiedName(); - const QString &enumName = names.constLast(); - QString nspace; - if (names.size() > 1) - nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); - typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0), - enclosingTypeEntry); + typeEntry = new EnumTypeEntry(enumItem->qualifiedName().constLast(), + QVersionNumber(0, 0), enclosingTypeEntry); TypeDatabase::instance()->addType(typeEntry); } else if (enumItem->enumKind() != AnonymousEnum) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); @@ -947,26 +939,13 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & metaEnum->setOriginalAttributes(metaEnum->attributes()); // Register all enum values on Type database - QString prefix; - if (enclosing) { - prefix += enclosing->typeEntry()->qualifiedCppName(); - prefix += colonColon(); - } - if (enumItem->enumKind() == EnumClass) { - prefix += enumItem->name(); - prefix += colonColon(); - } + const bool isScopedEnum = enumItem->enumKind() == EnumClass; const EnumeratorList &enumerators = enumItem->enumerators(); for (const EnumeratorModelItem &e : enumerators) { - QString name; - if (enclosing) { - name += enclosing->name(); - name += colonColon(); - } - EnumValueTypeEntry *enumValue = - new EnumValueTypeEntry(prefix + e->name(), e->stringValue(), - enumTypeEntry, enumTypeEntry->version(), - enumTypeEntry->parent()); + auto enumValue = + new EnumValueTypeEntry(e->name(), e->stringValue(), + enumTypeEntry, isScopedEnum, + enumTypeEntry->version()); TypeDatabase::instance()->addType(enumValue); if (e->value().isNullValue()) enumTypeEntry->setNullValue(enumValue); @@ -1305,27 +1284,37 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF metaFunction->replaceType(metaType); } -static bool _compareAbstractMetaTypes(const AbstractMetaType *type, const AbstractMetaType *other) +static bool _compareAbstractMetaTypes(const AbstractMetaType *type, + const AbstractMetaType *other, + AbstractMetaType::ComparisonFlags flags = {}) { return (type != nullptr) == (other != nullptr) - && (type == nullptr || *type == *other); + && (type == nullptr || type->compare(*other, flags)); } -static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, const AbstractMetaFunction *other) +static bool _compareAbstractMetaFunctions(const AbstractMetaFunction *func, + const AbstractMetaFunction *other, + AbstractMetaType::ComparisonFlags argumentFlags = {}) { if (!func && !other) return true; if (!func || !other) return false; - if (func->arguments().count() != other->arguments().count() + if (func->name() != other->name()) + return false; + const int argumentsCount = func->arguments().count(); + if (argumentsCount != other->arguments().count() || func->isConstant() != other->isConstant() || func->isStatic() != other->isStatic() || !_compareAbstractMetaTypes(func->type(), other->type())) { return false; } - for (int i = 0; i < func->arguments().count(); ++i) { - if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type())) + for (int i = 0; i < argumentsCount; ++i) { + if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), + other->arguments().at(i)->type(), + argumentFlags)) { return false; + } } return true; } @@ -1351,29 +1340,6 @@ AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const Sco return result; } -// For template classes, entries with more specific types may exist from out-of- -// line definitions. If there is a declaration which matches it after fixing -// the parameters, remove it as duplicate. For example: -// template class<T> Vector { public: -// Vector(const Vector &rhs); -// }; -// template class<T> -// Vector<T>::Vector(const Vector<T>&) {} // More specific, remove declaration. - -class DuplicatingFunctionPredicate : public std::unary_function<bool, const AbstractMetaFunction *> { -public: - explicit DuplicatingFunctionPredicate(const AbstractMetaFunction *f) : m_function(f) {} - - bool operator()(const AbstractMetaFunction *rhs) const - { - return rhs != m_function && rhs->name() == m_function->name() - && _compareAbstractMetaFunctions(m_function, rhs); - } - -private: - const AbstractMetaFunction *m_function; -}; - void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, AbstractMetaClass *metaClass) { @@ -2681,9 +2647,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, if (isNumber) { t = typeDb->findType(typeName); if (!t) { - t = new EnumValueTypeEntry(typeName, typeName, nullptr, - QVersionNumber(0, 0), - subclass->typeEntry()->parent()); + t = new ConstantValueTypeEntry(typeName, subclass->typeEntry()->typeSystemTypeEntry()); t->setCodeGeneration(0); typeDb->addType(t); } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index a040f3caa..5ae671d87 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -166,19 +166,9 @@ QString AbstractMetaType::package() const return m_typeEntry->targetLangPackage(); } -static QString lastNameSegment(QString name) -{ - const int index = name.lastIndexOf(QStringLiteral("::")); - if (index >= 0) - name.remove(0, index + 2); - return name; -} - QString AbstractMetaType::name() const { - if (m_name.isEmpty()) - m_name = lastNameSegment(m_typeEntry->targetLangName()); - return m_name; + return m_typeEntry->targetLangEntryName(); } QString AbstractMetaType::fullName() const @@ -256,11 +246,16 @@ AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const return result; } -bool AbstractMetaType::isConstRef() const +bool AbstractMetaType::passByConstRef() const { return isConstant() && m_referenceType == LValueReference && indirections() == 0; } +bool AbstractMetaType::passByValue() const +{ + return m_referenceType == NoReference && indirections() == 0; +} + QString AbstractMetaType::cppSignature() const { if (m_cachedCppSignature.isEmpty()) @@ -282,7 +277,7 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isTemplateArgument() || m_referenceType == RValueReference) return InvalidPattern; - if (m_typeEntry->isPrimitive() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isPrimitive() && (actualIndirections() == 0 || passByConstRef())) return PrimitivePattern; if (m_typeEntry->isVoid()) @@ -291,7 +286,7 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isVarargs()) return VarargsPattern; - if (m_typeEntry->isEnum() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isEnum() && (actualIndirections() == 0 || passByConstRef())) return EnumPattern; if (m_typeEntry->isObject()) { @@ -306,7 +301,7 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isSmartPointer() && indirections() == 0) return SmartPointerPattern; - if (m_typeEntry->isFlags() && (actualIndirections() == 0 || isConstRef())) + if (m_typeEntry->isFlags() && (actualIndirections() == 0 || passByConstRef())) return FlagsPattern; if (m_typeEntry->isArray()) @@ -352,21 +347,29 @@ bool AbstractMetaType::hasTemplateChildren() const return false; } -bool AbstractMetaType::equals(const AbstractMetaType &rhs) const +bool AbstractMetaType::compare(const AbstractMetaType &rhs, ComparisonFlags flags) const { - if (m_typeEntry != rhs.m_typeEntry || m_constant != rhs.m_constant - || m_referenceType != rhs.m_referenceType + if (m_typeEntry != rhs.m_typeEntry || m_indirections != rhs.m_indirections || m_instantiations.size() != rhs.m_instantiations.size() || m_arrayElementCount != rhs.m_arrayElementCount) { return false; } + + if (m_constant != rhs.m_constant || m_referenceType != rhs.m_referenceType) { + if (!flags.testFlag(ConstRefMatchesValue) + || !(passByValue() || passByConstRef()) + || !(rhs.passByValue() || rhs.passByConstRef())) { + return false; + } + } + if ((m_arrayElementType != nullptr) != (rhs.m_arrayElementType != nullptr) - || (m_arrayElementType != nullptr && !m_arrayElementType->equals(*rhs.m_arrayElementType))) { + || (m_arrayElementType != nullptr && !m_arrayElementType->compare(*rhs.m_arrayElementType, flags))) { return false; } for (int i = 0, size = m_instantiations.size(); i < size; ++i) { - if (!m_instantiations.at(i)->equals(*rhs.m_instantiations.at(i))) + if (!m_instantiations.at(i)->compare(*rhs.m_instantiations.at(i), flags)) return false; } return true; @@ -1598,7 +1601,7 @@ bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const QString AbstractMetaClass::name() const { - return lastNameSegment(m_typeEntry->targetLangName()); + return m_typeEntry->targetLangEntryName(); } void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) @@ -2549,7 +2552,7 @@ QString AbstractMetaType::formatPythonSignature(bool minimal) const else result.append(formatArraySize(m_arrayElementCount)); } else { - result += typeEntry()->qualifiedCppName(); + result += typeEntry()->targetLangName(); } if (!m_instantiations.isEmpty()) { result += QLatin1Char('['); @@ -2778,7 +2781,7 @@ AbstractMetaEnumValue *AbstractMetaEnum::findEnumValue(const QString &value) con QString AbstractMetaEnum::name() const { - return m_typeEntry->targetLangName(); + return m_typeEntry->targetLangEntryName(); } QString AbstractMetaEnum::qualifier() const diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index e9ce4d71b..2ae1b6d21 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -302,6 +302,11 @@ public: }; Q_ENUM(TypeUsagePattern) + enum ComparisonFlag { + ConstRefMatchesValue = 0x1 + }; + Q_DECLARE_FLAGS(ComparisonFlags, ComparisonFlag); + AbstractMetaType(); ~AbstractMetaType(); @@ -428,7 +433,8 @@ public: bool isVolatile() const { return m_volatile; } void setVolatile(bool v) { m_volatile = v; } - bool isConstRef() const; + bool passByConstRef() const; + bool passByValue() const; ReferenceType referenceType() const { return m_referenceType; } void setReferenceType(ReferenceType ref) { m_referenceType = ref; } @@ -527,7 +533,7 @@ public: bool hasTemplateChildren() const; - bool equals(const AbstractMetaType &rhs) const; + bool compare(const AbstractMetaType &rhs, ComparisonFlags = {}) const; private: TypeUsagePattern determineUsagePattern() const; @@ -537,7 +543,6 @@ private: const TypeEntry *m_typeEntry = nullptr; AbstractMetaTypeList m_instantiations; QString m_package; - mutable QString m_name; mutable QString m_cachedCppSignature; mutable QString m_cachedPythonSignature; QString m_originalTypeDescription; @@ -559,10 +564,12 @@ private: Q_DISABLE_COPY(AbstractMetaType) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaType::ComparisonFlags); + inline bool operator==(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return t1.equals(t2); } +{ return t1.compare(t2); } inline bool operator!=(const AbstractMetaType &t1, const AbstractMetaType &t2) -{ return !t1.equals(t2); } +{ return !t1.compare(t2); } #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaType *at); diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index b60e1f73b..546e9c4ed 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -480,6 +480,12 @@ QString msgNoRootTypeSystemEntry() return QLatin1String("Type system entry appears out of order, there does not seem to be a root type system element."); } +QString msgIncorrectlyNestedName(const QString &name) +{ + return QLatin1String("Nesting types by specifying '::' is no longer supported (") + + name + QLatin1String(")."); +} + // qtdocgenerator.cpp QString msgTagWarning(const QXmlStreamReader &reader, const QString &context, diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 5bbd7ba58..2b7b75ba0 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -133,6 +133,8 @@ QString msgInvalidRegularExpression(const QString &pattern, const QString &why); QString msgNoRootTypeSystemEntry(); +QString msgIncorrectlyNestedName(const QString &name); + QString msgCyclicDependency(const QString &funcName, const QString &graphName, const QVector<const AbstractMetaFunction *> &involvedConversions); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 4f8887bd2..014f4dadc 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -793,7 +793,8 @@ void TypeEntry::formatDebug(QDebug &d) const if (m_name != cppName) d << "\", cppName=\"" << cppName << '"'; d << ", type=" << m_type << ", codeGeneration=0x" - << hex << m_codeGeneration << dec; + << hex << m_codeGeneration << dec + << ", target=\"" << targetLangName() << '"'; FORMAT_NONEMPTY_STRING("package", m_targetLangPackage) FORMAT_BOOL("stream", m_stream) FORMAT_LIST_SIZE("codeSnips", m_codeSnips) @@ -812,7 +813,6 @@ void TypeEntry::formatDebug(QDebug &d) const void ComplexTypeEntry::formatDebug(QDebug &d) const { TypeEntry::formatDebug(d); - FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName) FORMAT_BOOL("polymorphicBase", m_polymorphicBase) FORMAT_BOOL("genericClass", m_genericClass) FORMAT_BOOL("deleteInMainThread", m_deleteInMainThread) @@ -822,7 +822,6 @@ void ComplexTypeEntry::formatDebug(QDebug &d) const << ", except=" << int(m_exceptionHandling); FORMAT_NONEMPTY_STRING("defaultSuperclass", m_defaultSuperclass) FORMAT_NONEMPTY_STRING("polymorphicIdValue", m_polymorphicIdValue) - FORMAT_NONEMPTY_STRING("lookupName", m_lookupName) FORMAT_NONEMPTY_STRING("targetType", m_targetType) FORMAT_NONEMPTY_STRING("hash", m_hashFunction) FORMAT_LIST_SIZE("addedFunctions", m_addedFunctions) @@ -840,9 +839,6 @@ void TypedefEntry::formatDebug(QDebug &d) const void EnumTypeEntry::formatDebug(QDebug &d) const { TypeEntry::formatDebug(d); - FORMAT_NONEMPTY_STRING("package", m_packageName) - FORMAT_NONEMPTY_STRING("qualifier", m_qualifier) - FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName) if (m_flags) d << ", flags=(" << m_flags << ')'; } diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index a5572354f..abd2bfb07 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -43,18 +43,13 @@ static QString strings_jobject = QLatin1String("jobject"); static inline QString callOperator() { return QStringLiteral("operator()"); } -PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr, +PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, PrimitiveType, vr, parent), + TypeEntry(entryName, PrimitiveType, vr, parent), m_preferredTargetLangType(true) { } -QString PrimitiveTypeEntry::targetLangName() const -{ - return m_targetLangName; -} - QString PrimitiveTypeEntry::targetLangApiName() const { return m_targetLangApiName; @@ -119,12 +114,6 @@ FieldModification ComplexTypeEntry::fieldModification(const QString &name) const return mod; } -QString ComplexTypeEntry::targetLangName() const -{ - return m_targetLangName.isEmpty() ? - TypeEntry::targetLangName() : m_targetLangName; -} - void ComplexTypeEntry::setDefaultConstructor(const QString& defaultConstructor) { m_defaultConstructor = defaultConstructor; @@ -148,36 +137,11 @@ void ComplexTypeEntry::useAsTypedef(const ComplexTypeEntry *source) { TypeEntry::useAsTypedef(source); m_qualifiedCppName = source->m_qualifiedCppName; - m_targetLangName = source->m_targetLangName; - m_lookupName = source->m_lookupName; m_targetType = source->m_targetType; } ComplexTypeEntry::ComplexTypeEntry(const ComplexTypeEntry &) = default; -QString ContainerTypeEntry::targetLangName() const -{ - - switch (m_type) { - case StringListContainer: return QLatin1String("QStringList"); - case ListContainer: return QLatin1String("QList"); - case LinkedListContainer: return QLatin1String("QLinkedList"); - case VectorContainer: return QLatin1String("QVector"); - case StackContainer: return QLatin1String("QStack"); - case QueueContainer: return QLatin1String("QQueue"); - case SetContainer: return QLatin1String("QSet"); - case MapContainer: return QLatin1String("QMap"); - case MultiMapContainer: return QLatin1String("QMultiMap"); - case HashContainer: return QLatin1String("QHash"); - case MultiHashContainer: return QLatin1String("QMultiHash"); - case PairContainer: return QLatin1String("QPair"); - default: - qWarning("bad type... %d", m_type); - break; - } - return QString(); -} - QString ContainerTypeEntry::qualifiedCppName() const { if (m_type == StringListContainer) @@ -194,23 +158,19 @@ ContainerTypeEntry::ContainerTypeEntry(const ContainerTypeEntry &) = default; QString EnumTypeEntry::targetLangQualifier() const { - TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier); - return te ? te->targetLangName() : m_qualifier; + const QString q = qualifier(); + if (!q.isEmpty()) { + if (auto te = TypeDatabase::instance()->findType(q)) + return te->targetLangName(); + } + return q; } -QString EnumTypeEntry::qualifiedTargetLangName() const +QString EnumTypeEntry::qualifier() const { - QString qualifiedName; - QString pkg = targetLangPackage(); - QString qualifier = targetLangQualifier(); - - if (!pkg.isEmpty()) - qualifiedName += pkg + QLatin1Char('.'); - if (!qualifier.isEmpty()) - qualifiedName += qualifier + QLatin1Char('.'); - qualifiedName += targetLangName(); - - return qualifiedName; + auto parentEntry = parent(); + return parentEntry && parentEntry->type() != TypeEntry::TypeSystemType ? + parentEntry->name() : QString(); } QString EnumTypeEntry::targetLangApiName() const @@ -237,17 +197,6 @@ TypeEntry *FlagsTypeEntry::clone() const FlagsTypeEntry::FlagsTypeEntry(const FlagsTypeEntry &) = default; -QString FlagsTypeEntry::qualifiedTargetLangName() const -{ - return targetLangPackage() + QLatin1Char('.') + m_enum->targetLangQualifier() - + QLatin1Char('.') + targetLangName(); -} - -QString FlagsTypeEntry::targetLangName() const -{ - return m_targetLangName; -} - QString TemplateInstance::expandCode() const { TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name); @@ -617,11 +566,17 @@ AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& si return parseType(signature); } -ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, +static QString buildName(const QString &entryName, const TypeEntry *parent) +{ + return parent == nullptr || parent->type() == TypeEntry::TypeSystemType + ? entryName : parent->name() + QLatin1String("::") + entryName; +} + +ComplexTypeEntry::ComplexTypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, t, vr, parent), - m_qualifiedCppName(name), + TypeEntry(entryName, t, vr, parent), + m_qualifiedCppName(buildName(entryName, parent)), m_polymorphicBase(false), m_genericClass(false), m_deleteInMainThread(false) @@ -633,11 +588,6 @@ bool ComplexTypeEntry::isComplex() const return true; } -QString ComplexTypeEntry::lookupName() const -{ - return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; -} - QString ComplexTypeEntry::targetLangApiName() const { return strings_jobject; @@ -719,10 +669,11 @@ bool TypeEntry::isCppPrimitive() const return typeName.contains(QLatin1Char(' ')) || primitiveCppTypes().contains(typeName); } -TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr, +TypeEntry::TypeEntry(const QString &entryName, TypeEntry::Type t, const QVersionNumber &vr, const TypeEntry *parent) : m_parent(parent), - m_name(name), + m_name(buildName(entryName, parent)), + m_entryName(entryName), m_version(vr), m_type(t) { @@ -742,6 +693,42 @@ const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const return nullptr; } +QString TypeEntry::targetLangName() const +{ + if (m_cachedTargetLangName.isEmpty()) + m_cachedTargetLangName = buildTargetLangName(); + return m_cachedTargetLangName; +} + +QString TypeEntry::buildTargetLangName() const +{ + QString result = m_entryName; + for (auto p = parent(); p && p->type() != TypeEntry::TypeSystemType; p = p->parent()) { + if (!result.isEmpty()) + result.prepend(QLatin1Char('.')); + QString n = p->m_entryName; + n.replace(QLatin1String("::"), QLatin1String(".")); // Primitive types may have "std::" + result.prepend(n); + } + return result; +} + +QString TypeEntry::targetLangEntryName() const +{ + if (m_cachedTargetLangEntryName.isEmpty()) { + m_cachedTargetLangEntryName = targetLangName(); + const int lastDot = m_cachedTargetLangEntryName.lastIndexOf(QLatin1Char('.')); + if (lastDot != -1) + m_cachedTargetLangEntryName.remove(0, lastDot + 1); + } + return m_cachedTargetLangEntryName; +} + +QString TypeEntry::qualifiedTargetLangName() const +{ + return targetLangPackage() + QLatin1Char('.') + targetLangName(); +} + bool TypeEntry::hasCustomConversion() const { return m_customConversion != nullptr; @@ -765,6 +752,7 @@ TypeEntry *TypeEntry::clone() const // Take over parameters relevant for typedefs void TypeEntry::useAsTypedef(const TypeEntry *source) { + m_entryName = source->m_entryName; m_name = source->m_name; m_targetLangPackage = source->m_targetLangPackage; m_codeGeneration = source->m_codeGeneration; @@ -773,9 +761,9 @@ void TypeEntry::useAsTypedef(const TypeEntry *source) TypeEntry::TypeEntry(const TypeEntry &) = default; -TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr, +TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, TypeSystemType, vr, parent) + TypeEntry(entryName, TypeSystemType, vr, parent) { } @@ -810,9 +798,9 @@ TypeEntry *VarargsTypeEntry::clone() const VarargsTypeEntry::VarargsTypeEntry(const VarargsTypeEntry &) = default; -TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, const QVersionNumber &vr, +TemplateArgumentEntry::TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, TemplateArgumentType, vr, parent) + TypeEntry(entryName, TemplateArgumentType, vr, parent) { } @@ -831,7 +819,7 @@ ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumbe Q_ASSERT(m_nestedType); } -QString ArrayTypeEntry::targetLangName() const +QString ArrayTypeEntry::buildTargetLangName() const { return m_nestedType->targetLangName() + QLatin1String("[]"); } @@ -850,25 +838,19 @@ TypeEntry *ArrayTypeEntry::clone() const ArrayTypeEntry::ArrayTypeEntry(const ArrayTypeEntry &) = default; -EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName, +EnumTypeEntry::EnumTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, - EnumType, vr, parent), - m_qualifier(nspace), - m_targetLangName(enumName) + TypeEntry(entryName, EnumType, vr, parent) { } -QString EnumTypeEntry::targetLangName() const -{ - return m_targetLangName; -} - EnumValueTypeEntry::EnumValueTypeEntry(const QString &name, const QString &value, const EnumTypeEntry *enclosingEnum, - const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, TypeEntry::EnumValue, vr, parent), + bool isScopedEnum, + const QVersionNumber &vr) : + TypeEntry(name, TypeEntry::EnumValue, vr, + isScopedEnum ? enclosingEnum : enclosingEnum->parent()), m_value(value), m_enclosingEnum(enclosingEnum) { @@ -881,17 +863,37 @@ TypeEntry *EnumValueTypeEntry::clone() const EnumValueTypeEntry::EnumValueTypeEntry(const EnumValueTypeEntry &) = default; -FlagsTypeEntry::FlagsTypeEntry(const QString &name, const QVersionNumber &vr, +FlagsTypeEntry::FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, FlagsType, vr, parent) + TypeEntry(entryName, FlagsType, vr, parent) { } +QString FlagsTypeEntry::buildTargetLangName() const +{ + QString on = m_originalName; + on.replace(QLatin1String("::"), QLatin1String(".")); + return on; +} + +ConstantValueTypeEntry::ConstantValueTypeEntry(const QString& name, + const TypeEntry *parent) : + TypeEntry(name, ConstantValueType, QVersionNumber(0, 0), parent) +{ +} + +TypeEntry *ConstantValueTypeEntry::clone() const +{ + return new ConstantValueTypeEntry(*this); +} + +ConstantValueTypeEntry::ConstantValueTypeEntry(const ConstantValueTypeEntry &) = default; + /* A typedef entry allows for specifying template specializations in the * typesystem XML file. */ -TypedefEntry::TypedefEntry(const QString &name, const QString &sourceType, +TypedefEntry::TypedefEntry(const QString &entryName, const QString &sourceType, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, TypedefType, vr, parent), + ComplexTypeEntry(entryName, TypedefType, vr, parent), m_sourceType(sourceType) { } @@ -903,21 +905,21 @@ TypeEntry *TypedefEntry::clone() const TypedefEntry::TypedefEntry(const TypedefEntry &) = default; -ContainerTypeEntry::ContainerTypeEntry(const QString &name, Type type, +ContainerTypeEntry::ContainerTypeEntry(const QString &entryName, Type type, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, ContainerType, vr, parent), + ComplexTypeEntry(entryName, ContainerType, vr, parent), m_type(type) { setCodeGeneration(GenerateForSubclass); } -SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &name, +SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &entryName, const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, SmartPointerType, vr, parent), + ComplexTypeEntry(entryName, SmartPointerType, vr, parent), m_getterName(getterName), m_smartPointerType(smartPointerType), m_refCountMethodName(refCountMethodName) @@ -931,9 +933,9 @@ TypeEntry *SmartPointerTypeEntry::clone() const SmartPointerTypeEntry::SmartPointerTypeEntry(const SmartPointerTypeEntry &) = default; -NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, const QVersionNumber &vr, +NamespaceTypeEntry::NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, NamespaceType, vr, parent) + ComplexTypeEntry(entryName, NamespaceType, vr, parent) { } @@ -957,9 +959,9 @@ bool NamespaceTypeEntry::matchesFile(const QString &needle) const return m_filePattern.match(needle).hasMatch(); } -ValueTypeEntry::ValueTypeEntry(const QString &name, const QVersionNumber &vr, +ValueTypeEntry::ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, BasicValueType, vr, parent) + ComplexTypeEntry(entryName, BasicValueType, vr, parent) { } @@ -980,9 +982,9 @@ TypeEntry *ValueTypeEntry::clone() const ValueTypeEntry::ValueTypeEntry(const ValueTypeEntry &) = default; -ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr, +ValueTypeEntry::ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, t, vr, parent) + ComplexTypeEntry(entryName, t, vr, parent) { } @@ -1120,9 +1122,9 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, const QVersionNumber &vr, +InterfaceTypeEntry::InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) : - ComplexTypeEntry(name, InterfaceType, vr, parent) + ComplexTypeEntry(entryName, InterfaceType, vr, parent) { } @@ -1144,10 +1146,10 @@ TypeEntry *InterfaceTypeEntry::clone() const InterfaceTypeEntry::InterfaceTypeEntry(const InterfaceTypeEntry &) = default; -FunctionTypeEntry::FunctionTypeEntry(const QString &name, const QString &signature, +FunctionTypeEntry::FunctionTypeEntry(const QString &entryName, const QString &signature, const QVersionNumber &vr, const TypeEntry *parent) : - TypeEntry(name, FunctionType, vr, parent) + TypeEntry(entryName, FunctionType, vr, parent) { addSignature(signature); } @@ -1159,9 +1161,9 @@ TypeEntry *FunctionTypeEntry::clone() const FunctionTypeEntry::FunctionTypeEntry(const FunctionTypeEntry &) = default; -ObjectTypeEntry::ObjectTypeEntry(const QString &name, const QVersionNumber &vr, +ObjectTypeEntry::ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent) - : ComplexTypeEntry(name, ObjectType, vr, parent) + : ComplexTypeEntry(entryName, ObjectType, vr, parent) { } diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 6d7a9d450..4d0a23ca1 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -560,6 +560,7 @@ public: FlagsType, EnumType, EnumValue, + ConstantValueType, TemplateArgumentType, ThreadType, BasicValueType, @@ -592,7 +593,7 @@ public: }; Q_ENUM(CodeGeneration) - explicit TypeEntry(const QString &name, Type t, const QVersionNumber &vr, + explicit TypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, const TypeEntry *parent); virtual ~TypeEntry(); @@ -706,10 +707,9 @@ public: } // The type's name in C++, fully qualified - QString name() const - { - return m_name; - } + QString name() const { return m_name; } + // Name as specified in XML + QString entryName() const { return m_entryName; } uint codeGeneration() const { @@ -756,28 +756,15 @@ public: } // The type's name in TargetLang - virtual QString targetLangName() const - { - return m_name; - } - - // The type to lookup when converting to TargetLang - virtual QString lookupName() const - { - return targetLangName(); - } + QString targetLangName() const; // "Foo.Bar" + void setTargetLangName(const QString &n) { m_cachedTargetLangName = n; } + QString targetLangEntryName() const; // "Bar" // The package QString targetLangPackage() const { return m_targetLangPackage; } void setTargetLangPackage(const QString &p) { m_targetLangPackage = p; } - virtual QString qualifiedTargetLangName() const - { - QString pkg = targetLangPackage(); - if (pkg.isEmpty()) - return targetLangName(); - return pkg + QLatin1Char('.') + targetLangName(); - } + QString qualifiedTargetLangName() const; virtual InterfaceTypeEntry *designatedInterface() const { @@ -905,10 +892,15 @@ public: protected: TypeEntry(const TypeEntry &); + virtual QString buildTargetLangName() const; + private: const TypeEntry *m_parent; - QString m_name; + QString m_name; // fully qualified + QString m_entryName; QString m_targetLangPackage; + mutable QString m_cachedTargetLangName; // "Foo.Bar" + mutable QString m_cachedTargetLangEntryName; // "Bar" CustomFunction m_customConstructor; CustomFunction m_customDestructor; CodeSnipList m_codeSnips; @@ -928,7 +920,7 @@ private: class TypeSystemTypeEntry : public TypeEntry { public: - explicit TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr, + explicit TypeSystemTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); TypeEntry *clone() const override; @@ -962,7 +954,7 @@ protected: class TemplateArgumentEntry : public TypeEntry { public: - explicit TemplateArgumentEntry(const QString &name, const QVersionNumber &vr, + explicit TemplateArgumentEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); int ordinal() const @@ -998,7 +990,6 @@ public: return m_nestedType; } - QString targetLangName() const override; QString targetLangApiName() const override; TypeEntry *clone() const override; @@ -1006,6 +997,8 @@ public: protected: ArrayTypeEntry(const ArrayTypeEntry &); + QString buildTargetLangName() const override; + private: const TypeEntry *m_nestedType; }; @@ -1014,15 +1007,9 @@ private: class PrimitiveTypeEntry : public TypeEntry { public: - explicit PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr, + explicit PrimitiveTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - QString targetLangName() const override; - void setTargetLangName(const QString &targetLangName) - { - m_targetLangName = targetLangName; - } - QString targetLangApiName() const override; void setTargetLangApiName(const QString &targetLangApiName) { @@ -1082,7 +1069,6 @@ protected: PrimitiveTypeEntry(const PrimitiveTypeEntry &); private: - QString m_targetLangName; QString m_targetLangApiName; QString m_defaultConstructor; uint m_preferredTargetLangType : 1; @@ -1094,24 +1080,15 @@ class EnumValueTypeEntry; class EnumTypeEntry : public TypeEntry { public: - explicit EnumTypeEntry(const QString &nspace, const QString &enumName, + explicit EnumTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - QString targetLangName() const override; QString targetLangQualifier() const; - QString qualifiedTargetLangName() const override; QString targetLangApiName() const override; - QString qualifier() const - { - return m_qualifier; - } - void setQualifier(const QString &q) - { - m_qualifier = q; - } + QString qualifier() const; const EnumValueTypeEntry *nullValue() const { return m_nullValue; } void setNullValue(const EnumValueTypeEntry *n) { m_nullValue = n; } @@ -1146,9 +1123,6 @@ protected: EnumTypeEntry(const EnumTypeEntry &); private: - QString m_packageName; - QString m_qualifier; - QString m_targetLangName; const EnumValueTypeEntry *m_nullValue = nullptr; QStringList m_rejectedEnums; @@ -1164,8 +1138,7 @@ class EnumValueTypeEntry : public TypeEntry public: explicit EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, - const QVersionNumber &vr, - const TypeEntry *parent); + bool isScopedEnum, const QVersionNumber &vr); QString value() const { return m_value; } const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } @@ -1183,11 +1156,9 @@ private: class FlagsTypeEntry : public TypeEntry { public: - explicit FlagsTypeEntry(const QString &name, const QVersionNumber &vr, + explicit FlagsTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); - QString qualifiedTargetLangName() const override; - QString targetLangName() const override; QString targetLangApiName() const override; QString originalName() const @@ -1201,11 +1172,11 @@ public: QString flagsName() const { - return m_targetLangName; + return m_flagsName; } void setFlagsName(const QString &name) { - m_targetLangName = name; + m_flagsName = name; } EnumTypeEntry *originator() const @@ -1222,12 +1193,27 @@ public: protected: FlagsTypeEntry(const FlagsTypeEntry &); + QString buildTargetLangName() const override; + private: QString m_originalName; - QString m_targetLangName; + QString m_flagsName; EnumTypeEntry *m_enum = nullptr; }; +// For primitive values, typically to provide a dummy type for +// example the '2' in non-type template 'Array<2>'. +class ConstantValueTypeEntry : public TypeEntry +{ +public: + explicit ConstantValueTypeEntry(const QString& name, + const TypeEntry *parent); + + TypeEntry *clone() const override; + +protected: + ConstantValueTypeEntry(const ConstantValueTypeEntry &); +}; class ComplexTypeEntry : public TypeEntry { @@ -1243,18 +1229,11 @@ public: Unknown }; - explicit ComplexTypeEntry(const QString &name, Type t, const QVersionNumber &vr, + explicit ComplexTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, const TypeEntry *parent); bool isComplex() const override; - void setLookupName(const QString &name) - { - m_lookupName = name; - } - - QString lookupName() const override; - QString targetLangApiName() const override; void setTypeFlags(TypeFlags flags) @@ -1346,12 +1325,6 @@ public: m_targetType = code; } - QString targetLangName() const override; - void setTargetLangName(const QString &name) - { - m_targetLangName = name; - } - bool isGenericClass() const { return m_genericClass; @@ -1419,14 +1392,12 @@ private: QString m_defaultConstructor; QString m_defaultSuperclass; QString m_qualifiedCppName; - QString m_targetLangName; uint m_polymorphicBase : 1; uint m_genericClass : 1; uint m_deleteInMainThread : 1; QString m_polymorphicIdValue; - QString m_lookupName; QString m_targetType; TypeFlags m_typeFlags; CopyableFlag m_copyableFlag = Unknown; @@ -1443,7 +1414,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(ComplexTypeEntry::TypeFlags) class TypedefEntry : public ComplexTypeEntry { public: - explicit TypedefEntry(const QString &name, + explicit TypedefEntry(const QString &entryName, const QString &sourceType, const QVersionNumber &vr, const TypeEntry *parent); @@ -1492,7 +1463,7 @@ public: }; Q_ENUM(Type) - explicit ContainerTypeEntry(const QString &name, Type type, const QVersionNumber &vr, + explicit ContainerTypeEntry(const QString &entryName, Type type, const QVersionNumber &vr, const TypeEntry *parent); Type type() const @@ -1501,7 +1472,6 @@ public: } QString typeName() const; - QString targetLangName() const override; QString qualifiedCppName() const override; TypeEntry *clone() const override; @@ -1519,7 +1489,7 @@ private: class SmartPointerTypeEntry : public ComplexTypeEntry { public: - explicit SmartPointerTypeEntry(const QString &name, + explicit SmartPointerTypeEntry(const QString &entryName, const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, @@ -1550,7 +1520,7 @@ private: class NamespaceTypeEntry : public ComplexTypeEntry { public: - explicit NamespaceTypeEntry(const QString &name, const QVersionNumber &vr, + explicit NamespaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); TypeEntry *clone() const override; @@ -1581,7 +1551,7 @@ private: class ValueTypeEntry : public ComplexTypeEntry { public: - explicit ValueTypeEntry(const QString &name, const QVersionNumber &vr, + explicit ValueTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); bool isValue() const override; @@ -1591,7 +1561,7 @@ public: TypeEntry *clone() const override; protected: - explicit ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr, + explicit ValueTypeEntry(const QString &entryName, Type t, const QVersionNumber &vr, const TypeEntry *parent); ValueTypeEntry(const ValueTypeEntry &); }; @@ -1599,7 +1569,7 @@ protected: class InterfaceTypeEntry : public ComplexTypeEntry { public: - explicit InterfaceTypeEntry(const QString &name, const QVersionNumber &vr, + explicit InterfaceTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); static QString interfaceName(const QString &name) @@ -1662,7 +1632,7 @@ private: class ObjectTypeEntry : public ComplexTypeEntry { public: - explicit ObjectTypeEntry(const QString &name, const QVersionNumber &vr, + explicit ObjectTypeEntry(const QString &entryName, const QVersionNumber &vr, const TypeEntry *parent); InterfaceTypeEntry *designatedInterface() const override; diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 6ecdf1dc9..7388b07fc 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -81,6 +81,7 @@ static inline QString preferredTargetLangTypeAttribute() { return QStringLiteral static inline QString removeAttribute() { return QStringLiteral("remove"); } static inline QString renameAttribute() { return QStringLiteral("rename"); } static inline QString readAttribute() { return QStringLiteral("read"); } +static inline QString targetLangNameAttribute() { return QStringLiteral("target-lang-name"); } static inline QString writeAttribute() { return QStringLiteral("write"); } static inline QString replaceAttribute() { return QStringLiteral("replace"); } static inline QString toAttribute() { return QStringLiteral("to"); } @@ -1064,34 +1065,35 @@ void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttribut FlagsTypeEntry * TypeSystemParser::parseFlagsEntry(const QXmlStreamReader &, - EnumTypeEntry *enumEntry, - const QString &name, QString flagName, + EnumTypeEntry *enumEntry, QString flagName, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - auto ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), + auto ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + enumEntry->name() + QLatin1Char('>'), since, currentParentTypeEntry()->typeSystemTypeEntry()); ftype->setOriginator(enumEntry); ftype->setTargetLangPackage(enumEntry->targetLangPackage()); - // Try to get the guess the qualified flag name - const int lastSepPos = name.lastIndexOf(colonColon()); - if (lastSepPos >= 0 && !flagName.contains(colonColon())) - flagName.prepend(name.left(lastSepPos + 2)); + // Try toenumEntry get the guess the qualified flag name + if (!flagName.contains(colonColon())) { + auto eq = enumEntry->qualifier(); + if (!eq.isEmpty()) + flagName.prepend(eq + colonColon()); + } ftype->setOriginalName(flagName); applyCommonAttributes(ftype, attributes); - QString n = ftype->originalName(); - QStringList lst = n.split(colonColon()); + QStringList lst = flagName.split(colonColon()); + const QString targetLangFlagName = QStringList(lst.mid(0, lst.size() - 1)).join(QLatin1Char('.')); const QString &targetLangQualifier = enumEntry->targetLangQualifier(); - if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != targetLangQualifier) { + if (targetLangFlagName != targetLangQualifier) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum %1 and flags %2 differ in qualifiers") - .arg(targetLangQualifier, lst.constFirst()); + << QStringLiteral("enum %1 and flags %2 (%3) differ in qualifiers") + .arg(targetLangQualifier, lst.constFirst(), targetLangFlagName); } ftype->setFlagsName(lst.constLast()); @@ -1174,8 +1176,8 @@ PrimitiveTypeEntry * applyCommonAttributes(type, attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); - if (name == QLatin1String("target-lang-name")) { - type->setTargetLangName(attributes->takeAt(i).value().toString()); + if (name == targetLangNameAttribute()) { + type->setTargetLangName(attributes->takeAt(i).value().toString()); } else if (name == QLatin1String("target-lang-api-name")) { type->setTargetLangApiName(attributes->takeAt(i).value().toString()); } else if (name == preferredConversionAttribute()) { @@ -1190,8 +1192,6 @@ PrimitiveTypeEntry * } } - if (type->targetLangName().isEmpty()) - type->setTargetLangName(type->name()); if (type->targetLangApiName().isEmpty()) type->setTargetLangApiName(type->name()); type->setTargetLangPackage(m_defaultPackage); @@ -1223,19 +1223,12 @@ ContainerTypeEntry * EnumTypeEntry * TypeSystemParser::parseEnumTypeEntry(const QXmlStreamReader &reader, - const QString &fullName, const QVersionNumber &since, + const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { if (!checkRootElement()) return nullptr; - QString scope; - QString name = fullName; - const int sep = fullName.lastIndexOf(colonColon()); - if (sep != -1) { - scope = fullName.left(sep); - name = fullName.right(fullName.size() - sep - 2); - } - auto *entry = new EnumTypeEntry(scope, name, since, currentParentTypeEntry()); + auto *entry = new EnumTypeEntry(name, since, currentParentTypeEntry()); applyCommonAttributes(entry, attributes); entry->setTargetLangPackage(m_defaultPackage); @@ -1263,7 +1256,7 @@ EnumTypeEntry * if (!flagNames.isEmpty()) { const QStringList &flagNameList = flagNames.split(QLatin1Char(',')); for (const QString &flagName : flagNameList) - parseFlagsEntry(reader, entry, fullName, flagName.trimmed(), since, attributes); + parseFlagsEntry(reader, entry, flagName.trimmed(), since, attributes); } return entry; } @@ -1281,7 +1274,7 @@ ObjectTypeEntry * bool generate = true; for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); - if (name == QLatin1String("target-lang-name")) { + if (name == targetLangNameAttribute()) { targetLangName = attributes->takeAt(i).value().toString(); } else if (name == generateAttribute()) { generate = convertBoolean(attributes->takeAt(i).value(), @@ -1291,6 +1284,7 @@ ObjectTypeEntry * auto itype = new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since, currentParentTypeEntry()); + itype->setTargetLangName(targetLangName); if (generate) itype->setCodeGeneration(m_generate); @@ -1443,7 +1437,7 @@ void TypeSystemParser::applyComplexTypeAttributes(const QXmlStreamReader &reader qPrintable(msgUnimplementedAttributeWarning(reader, name))); const bool v = convertBoolean(attributes->takeAt(i).value(), genericClassAttribute(), false); ctype->setGenericClass(v); - } else if (name == QLatin1String("target-lang-name")) { + } else if (name == targetLangNameAttribute()) { ctype->setTargetLangName(attributes->takeAt(i).value().toString()); } else if (name == QLatin1String("polymorphic-base")) { ctype->setPolymorphicIdValue(attributes->takeAt(i).value().toString()); @@ -2668,6 +2662,12 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) return false; } } + // Allow for primitive and/or std:: types only, else require proper nesting. + if (element->type != StackElement::PrimitiveTypeEntry && name.contains(QLatin1Char(':')) + && !name.contains(QLatin1String("std::"))) { + m_error = msgIncorrectlyNestedName(name); + return false; + } if (m_database->hasDroppedTypeEntries()) { QString identifier = getNamePrefix(element) + QLatin1Char('.'); @@ -2715,13 +2715,6 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) } } - // Fix type entry name using nesting information. - if (element->type & StackElement::TypeEntryMask - && element->parent && element->parent->type != StackElement::Root) { - name = element->parent->entry->name() + colonColon() + name; - } - - if (name.isEmpty()) { m_error = QLatin1String("no 'name' attribute specified"); return false; diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index afe68a689..d3ea54fc6 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -176,8 +176,8 @@ private: const QVersionNumber &since, QXmlStreamAttributes *); FlagsTypeEntry * parseFlagsEntry(const QXmlStreamReader &, EnumTypeEntry *enumEntry, - const QString &name, QString flagName, - const QVersionNumber &since, QXmlStreamAttributes *); + QString flagName, const QVersionNumber &since, + QXmlStreamAttributes *); NamespaceTypeEntry * parseNamespaceTypeEntry(const QXmlStreamReader &, diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index de023f079..ca9f9b3ae 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -2209,7 +2209,7 @@ void QtDocGenerator::writeModuleDocumentation() QStringList::iterator it2 = fileList.begin(); for (; it2 != fileList.end(); ++it2) { QString origFileName(*it2); - it2->remove(0, it.key().count() + 1); + it2->remove(0, moduleName.indexOf(QLatin1Char('.'))); QString newFilePath = outputDir + QLatin1Char('/') + *it2; if (QFile::exists(newFilePath)) QFile::remove(newFilePath); diff --git a/tools/missing_bindings.py b/tools/missing_bindings.py index 8f3c0b808..850716a2f 100644 --- a/tools/missing_bindings.py +++ b/tools/missing_bindings.py @@ -77,6 +77,7 @@ modules_to_test['QtMultimediaWidgets'] = 'qtmultimediawidgets-module.html' modules_to_test['QtNetwork'] = 'qtnetwork-module.html' modules_to_test['QtQml'] = 'qtqml-module.html' modules_to_test['QtQuick'] = 'qtquick-module.html' +modules_to_test['QtQuickWidgets'] = 'qtquickwidgets-module.html' modules_to_test['QtSql'] = 'qtsql-module.html' modules_to_test['QtTest'] = 'qttest-module.html' modules_to_test['QtWidgets'] = 'qtwidgets-module.html' @@ -89,16 +90,17 @@ modules_to_test['Qt3DRender'] = 'qt3drender-module.html' modules_to_test['Qt3DAnimation'] = 'qt3danimation-module.html' modules_to_test['Qt3DExtras'] = 'qt3dextras-module.html' modules_to_test['QtConcurrent'] = 'qtconcurrent-module.html' -modules_to_test['QtNetworkAuth'] = 'qtnetworkauth-module.html' +#modules_to_test['QtNetworkAuth'] = 'qtnetworkauth-module.html' modules_to_test['QtHelp'] = 'qthelp-module.html' modules_to_test['QtLocation'] = 'qtlocation-module.html' modules_to_test['QtPrintSupport'] = 'qtprintsupport-module.html' -modules_to_test['QtSCXML'] = 'qtscxml-module.html' -modules_to_test['QtSpeech'] = 'qtspeech-module.html' +modules_to_test['QtScxml'] = 'qtscxml-module.html' +#modules_to_test['QtSpeech'] = 'qtspeech-module.html' modules_to_test['QtSvg'] = 'qtsvg-module.html' modules_to_test['QtUiTools'] = 'qtuitools-module.html' modules_to_test['QtWebChannel'] = 'qtwebchannel-module.html' modules_to_test['QtWebEngine'] = 'qtwebengine-module.html' +modules_to_test['QtWebEngineCore'] = 'qtwebenginecore-module.html' modules_to_test['QtWebEngineWidgets'] = 'qtwebenginewidgets-module.html' modules_to_test['QtWebSockets'] = 'qtwebsockets-module.html' modules_to_test['QtMacExtras'] = 'qtmacextras-module.html' @@ -108,7 +110,12 @@ modules_to_test['QtXml'] = 'qtxml-module.html' modules_to_test['QtXmlPatterns'] = 'qtxmlpatterns-module.html' modules_to_test['QtCharts'] = 'qtcharts-module.html' modules_to_test['QtDataVisualization'] = 'qtdatavisualization-module.html' - +modules_to_test['QtOpenGL'] = 'qtopengl-module.html' +modules_to_test['QtPositioning'] = 'qtpositioning-module.html' +modules_to_test['QtRemoteObjects'] = 'qtremoteobjects-module.html' +modules_to_test['QtScript'] = 'qtscript-module.html' +modules_to_test['QtScriptTools'] = 'qtscripttools-module.html' +modules_to_test['QtSensors'] = 'qtsensors-module.html' types_to_ignore = set() # QtCore types_to_ignore.add('QFlag') @@ -219,6 +226,8 @@ qt_documentation_website_prefixes['5.10'] = 'http://doc.qt.io/qt-5.10/' qt_documentation_website_prefixes['5.11'] = 'http://doc.qt.io/qt-5.11/' qt_documentation_website_prefixes['5.11'] = 'http://doc.qt.io/qt-5.11/' qt_documentation_website_prefixes['5.12'] = 'http://doc.qt.io/qt-5.12/' +qt_documentation_website_prefixes['5.13'] = 'http://doc.qt.io/qt-5.13/' +qt_documentation_website_prefixes['5.14'] = 'http://doc.qt.io/qt-5/' qt_documentation_website_prefixes['dev'] = 'http://doc-snapshots.qt.io/qt5-dev/' @@ -242,7 +251,7 @@ parser.add_argument("module", parser.add_argument("--qt-version", "-v", default='5.12', - choices=['5.6', '5.9', '5.11', '5.12', 'dev'], + choices=['5.6', '5.9', '5.11', '5.12', '5.13', '5.14', 'dev'], type=str, dest='version', help="the Qt version to use to check for types") |
