diff options
Diffstat (limited to 'testing/wheel_tester.py')
-rw-r--r-- | testing/wheel_tester.py | 237 |
1 files changed, 120 insertions, 117 deletions
diff --git a/testing/wheel_tester.py b/testing/wheel_tester.py index 567d2380e..b36ee55a4 100644 --- a/testing/wheel_tester.py +++ b/testing/wheel_tester.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2019 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only """ This script is used by Coin (coin_test_instructions.py specifically) to @@ -52,11 +16,15 @@ Make sure that some generated wheels already exist in the dist/ directory (e.g. setup.py bdist_wheel was already executed). """ -from argparse import ArgumentParser, RawTextHelpFormatter -from pathlib import Path import os +import platform +import shutil import sys import tempfile +import logging +from argparse import ArgumentParser, RawTextHelpFormatter +from pathlib import Path +from configparser import ConfigParser try: this_file = __file__ @@ -67,14 +35,13 @@ this_dir = os.path.dirname(this_file) setup_script_dir = os.path.abspath(os.path.join(this_dir, "..")) sys.path.append(setup_script_dir) -from build_scripts.utils import find_files_using_glob -from build_scripts.utils import find_glob_in_path -from build_scripts.utils import run_process, run_process_output -from build_scripts.utils import rmtree -import distutils.log as log -import platform +from build_scripts.utils import (find_files_using_glob, find_glob_in_path, # noqa: E402 + remove_tree, run_process, run_process_output) +from build_scripts.log import log # noqa: E402 + +log.setLevel(logging.DEBUG) -log.set_verbosity(1) +NEW_WHEELS = False def find_executable(executable, command_line_value): @@ -104,8 +71,8 @@ QMAKE_PATH = None CMAKE_PATH = None -def get_wheels_dir(): - return os.path.join(setup_script_dir, "dist") +def get_wheels_dir(dir_name): + return os.path.join(setup_script_dir, dir_name) def get_examples_dir(): @@ -115,7 +82,11 @@ def get_examples_dir(): def package_prefix_names(): # Note: shiboken6_generator is not needed for compile_using_nuitka, # but building modules with cmake needs it. - return ["shiboken6", "shiboken6_generator", "PySide6"] + if NEW_WHEELS: + return ["shiboken6", "shiboken6_generator", "PySide6_Essentials", "PySide6_Addons", + "PySide6"] + else: + return ["shiboken6", "shiboken6_generator", "PySide6"] def clean_egg_info(): @@ -128,7 +99,7 @@ def clean_egg_info(): paths = find_files_using_glob(setup_script_dir, "*.egg-info") for p in paths: log.info(f"Removing {p}") - rmtree(p) + remove_tree(p) def install_wheel(wheel_path): @@ -167,40 +138,19 @@ def try_install_wheels(wheels_dir, py_version): ) -def is_unix(): - if sys.platform.startswith("linux") or sys.platform == "darwin": - return True - return False - - def generate_build_cmake(): - args = [CMAKE_PATH] - if is_unix(): - args.extend(["-G", "Unix Makefiles"]) - else: - args.extend(["-G", "NMake Makefiles"]) - args.append("-DCMAKE_BUILD_TYPE=Release") - args.append(f"-Dpython_interpreter={sys.executable}") - - # Specify prefix path so find_package(Qt5) works. - qmake_dir = os.path.abspath(os.path.join(os.path.dirname(QMAKE_PATH), "..")) - args.append(f"-DCMAKE_PREFIX_PATH={qmake_dir}") - - args.append("..") - + # Specify prefix path so find_package(Qt6) works. + qmake_dir = Path(QMAKE_PATH).resolve().parent.parent + args = [CMAKE_PATH, "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release", + f"-Dpython_interpreter={sys.executable}", + f"-DCMAKE_PREFIX_PATH={qmake_dir}", + ".."] exit_code = run_process(args) if exit_code: raise RuntimeError("Failure while running cmake.") log.info("") -def generate_build_qmake(): - exit_code = run_process([QMAKE_PATH, "..", f"python_interpreter={sys.executable}"]) - if exit_code: - raise RuntimeError("Failure while running qmake.") - log.info("") - - def raise_error_pyinstaller(msg): print() print(f"PYINST: {msg}") @@ -255,32 +205,73 @@ def run_nuitka_test(example): raise RuntimeError(f"Failure running {example} with Nuitka.") -def run_make(): - args = [] - if is_unix(): - executable = "make" +def _run_deploy_test(example, tmpdirname): + """Helper for running deployment and example.""" + main_file = None + for py_file in example.glob("*.py"): + shutil.copy(py_file, tmpdirname) + if not main_file or py_file.name == "main.py": + main_file = py_file + deploy_tool = Path(sys.executable).parent / "pyside6-deploy" + cmd = [os.fspath(deploy_tool), "-f", main_file.name, "--init"] + if run_process(cmd) != 0: + raise RuntimeError("Error creating pysidedeploy.spec") + + config_file = Path(tmpdirname) / "pysidedeploy.spec" + parser = ConfigParser(comment_prefixes="/", allow_no_value=True) + parser.read(config_file) + parser.set("nuitka", "extra_args", "--verbose --assume-yes-for-downloads") + with open(config_file, "w+") as config_file_writer: + parser.write(config_file_writer, space_around_delimiters=True) + + cmd = [os.fspath(deploy_tool), "-f", "-c", os.fspath(config_file)] + if run_process(cmd) != 0: + raise RuntimeError("Error deploying") + + suffix = "exe" if sys.platform == "win32" else "bin" + + if sys.platform != "darwin": + binary = f"{tmpdirname}/{main_file.stem}.{suffix}" else: - executable = "nmake" - args.append(executable) + binary = f"{tmpdirname}/pyside_app_demo.app/Contents/MacOS/{main_file.stem}" + + if run_process([binary]) != 0: + raise RuntimeError("Error running the deployed example") + return True + +def run_deploy_test(example): + """Test pyside6-deploy.""" + log.info(f"Running deploy test of {example}") + current_dir = Path.cwd() + result = False + with tempfile.TemporaryDirectory() as tmpdirname: + try: + os.chdir(tmpdirname) + result = _run_deploy_test(example, tmpdirname) + except RuntimeError as e: + log.error(str(e)) + raise e + finally: + os.chdir(os.fspath(current_dir)) + state = "succeeded" if result else "failed" + log.info(f"Deploy test {state}") + return result + + +def run_ninja(): + args = ["ninja"] exit_code = run_process(args) if exit_code: - raise RuntimeError(f"Failure while running {executable}.") + raise RuntimeError(f"Failure while running {' '.join(args)}.") log.info("") -def run_make_install(): - args = [] - if is_unix(): - executable = "make" - else: - executable = "nmake" - args.append(executable) - args.append("install") - +def run_ninja_install(): + args = ["ninja", "install"] exit_code = run_process(args) if exit_code: - raise RuntimeError(f"Failed while running {executable} install.") + raise RuntimeError(f"Failed while running {' '.join(args)} install.") log.info("") @@ -307,7 +298,7 @@ def prepare_build_folder(src_path, build_folder_name): # preparing a build folder should clean any previous existing build. if os.path.exists(build_path): log.info(f"Removing {build_path}") - rmtree(build_path) + remove_tree(build_path) log.info(f"Creating {build_path}") os.makedirs(build_path) @@ -330,30 +321,31 @@ def try_build_examples(): log.info("Attempting to build hello.py using Nuitka.") src_path = Path(examples_dir) / "installer_test" - # Nuitka is loaded by coin_build_instructions.py, but not when - # testing directly this script. - run_nuitka_test(os.fspath(src_path / "hello.py")) + + # disable for windows as it Nuitka --onefile deployment in Windows + # requires DependencyWalker. Download and installing will slow down + # Coin + if sys.platform != "win32": + run_deploy_test(src_path) + + if False: # pre 6.4.1, kept for reference + # Nuitka is loaded by coin_build_instructions.py, but not when + # testing directly this script. + run_nuitka_test(os.fspath(src_path / "hello.py")) log.info("Attempting to build and run samplebinding using cmake.") src_path = os.path.join(examples_dir, "samplebinding") prepare_build_folder(src_path, "cmake") generate_build_cmake() - run_make() - run_make_install() + run_ninja() + run_ninja_install() execute_script(os.path.join(src_path, "main.py")) - log.info("*** Defunct: build scriptableapplication using cmake.") - # log.info("Attempting to build scriptableapplication using cmake.") - # src_path = os.path.join(examples_dir, "scriptableapplication") - # prepare_build_folder(src_path, "cmake") - # generate_build_cmake() - # run_make() - - log.info("Attempting to build scriptableapplication using qmake.") + log.info("Attempting to build scriptableapplication using cmake.") src_path = os.path.join(examples_dir, "scriptableapplication") - prepare_build_folder(src_path, "qmake") - generate_build_qmake() - run_make() + prepare_build_folder(src_path, "cmake") + generate_build_cmake() + run_ninja() if sys.version_info[:2] >= (3, 7): log.info("Checking Python Interface Files in Python 3 with all features selected") @@ -372,11 +364,13 @@ def try_build_examples(): from PySide6 import __all__ as modules for modname in modules: - execute_script(src_path / f"{modname}.pyi") + # PYSIDE-1735: pyi files are no longer compatible with Python. + # XXX Maybe add a test with Mypy here? + pass # execute_script(src_path / f"{modname}.pyi") -def run_wheel_tests(install_wheels): - wheels_dir = get_wheels_dir() +def run_wheel_tests(install_wheels, wheels_dir_name): + wheels_dir = get_wheels_dir(wheels_dir_name) py_version = f"{sys.version_info.major}.{sys.version_info.minor}" if install_wheels: @@ -384,8 +378,13 @@ def run_wheel_tests(install_wheels): try_install_wheels(wheels_dir, py_version) log.info("Attempting to build examples.\n") - try_build_examples() + bin_dir = os.fspath(Path(sys.executable).parent) + path = os.environ["PATH"] + if bin_dir not in path: + log.info(f"Adding {bin_dir} to PATH...") + os.environ["PATH"] = f"{bin_dir}{os.pathsep}{path}" + try_build_examples() log.info("All tests passed!") @@ -399,8 +398,12 @@ if __name__ == "__main__": ) parser.add_argument("--qmake", type=str, help="Path to qmake") parser.add_argument("--cmake", type=str, help="Path to cmake") + parser.add_argument("--wheels-dir", type=str, help="Path to where the wheels are", + default="dist") + parser.add_argument("--new", action="store_true", help="Option to test new wheels") options = parser.parse_args() QMAKE_PATH = find_executable("qmake", options.qmake) CMAKE_PATH = find_executable("cmake", options.cmake) + NEW_WHEELS = options.new - run_wheel_tests(not options.no_install_wheels) + run_wheel_tests(not options.no_install_wheels, options.wheels_dir) |