diff options
Diffstat (limited to 'testing')
-rw-r--r-- | testing/__init__.py | 41 | ||||
-rw-r--r-- | testing/blacklist.py | 50 | ||||
-rw-r--r-- | testing/buildlog.py | 57 | ||||
-rw-r--r-- | testing/command.py | 78 | ||||
-rw-r--r-- | testing/helper.py | 41 | ||||
-rw-r--r-- | testing/parser.py | 42 | ||||
-rw-r--r-- | testing/runner.py | 76 | ||||
-rw-r--r-- | testing/wheel_tester.py | 237 |
8 files changed, 210 insertions, 412 deletions
diff --git a/testing/__init__.py b/testing/__init__.py index ca4e621ce..62614c438 100644 --- a/testing/__init__.py +++ b/testing/__init__.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 """ testing/__init__.py @@ -46,6 +10,7 @@ testing/__init__.py import builtins import sys + from . import command main = command.main diff --git a/testing/blacklist.py b/testing/blacklist.py index 09848dce4..eacb51cbb 100644 --- a/testing/blacklist.py +++ b/testing/blacklist.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 """ testing/blacklist.py @@ -46,8 +10,9 @@ find_matching_line() adds info using classifiers. """ from io import StringIO -from .helper import decorate + from .buildlog import builds +from .helper import decorate class BlackList(object): @@ -63,7 +28,7 @@ class BlackList(object): def filtered_line(line): if "#" in line: - line = line[line.index("#")] + line = line[:line.index("#")] return line.split() # now put every bracketed line in a test @@ -77,7 +42,6 @@ class BlackList(object): # nothing supplied return - self.index = {} for idx, line in enumerate(lines): fline = filtered_line(line) if not fline: @@ -92,8 +56,8 @@ class BlackList(object): if is_test(fline): # a new name name = decorate(fline[0][1:-1]) - self.tests[name] = [] - self.index[name] = idx + # Allow for repeated sections + self.tests.setdefault(name, []) elif fline: # a known name with a new entry self.tests[name].append(fline) diff --git a/testing/buildlog.py b/testing/buildlog.py index d268c1ac3..f82191f91 100644 --- a/testing/buildlog.py +++ b/testing/buildlog.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 """ testing/buildlog.py @@ -46,8 +10,9 @@ BuildLog.classifiers finds the set of classifier strings. """ import os -import sys +import platform import shutil +import sys from collections import namedtuple from textwrap import dedent @@ -112,6 +77,7 @@ class BuildLog(object): # we take the latest build for now. build_history.sort() self.history = build_history + self.python_version = None self._buildno = None if not is_ci: # there seems to be a timing problem in RHel 7.6, so we better don't touch it @@ -160,8 +126,8 @@ class BuildLog(object): if not self.selected: raise ValueError("+++ No build with the configuration found!") # Python2 legacy: Correct 'linux2' to 'linux', recommended way. - platform = "linux" if sys.platform.startswith("linux") else sys.platform - res = [platform, "qt6"] + plat_name = "linux" if sys.platform.startswith("linux") else sys.platform + res = [plat_name, "qt6"] if is_ci: res.append("ci") if self.selected.build_classifiers: @@ -172,6 +138,9 @@ class BuildLog(object): path = self.selected.build_dir base = os.path.basename(path) res.extend(base.split("-")) + # add exact Python version + if self.python_version: + res.append("py" + ".".join(map(str, self.python_version))) # add all the python and qt subkeys for entry in res: parts = entry.split(".") @@ -179,7 +148,13 @@ class BuildLog(object): key = ".".join(parts[:idx]) if key not in res: res.append(key) + # Allow to check the processor. + # This gives "i386" or "arm" on macOS. + res.append(platform.processor()) return res + def set_python_version(self, version_triple): + self.python_version = version_triple + builds = BuildLog() diff --git a/testing/command.py b/testing/command.py index 307a59761..31a48f87c 100644 --- a/testing/command.py +++ b/testing/command.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 """ testrunner @@ -70,23 +34,24 @@ The full mode can be tested locally by setting export COIN_RERUN_FAILED_ONLY=0 """ +import argparse import os import sys -import argparse -from textwrap import dedent from collections import OrderedDict +from textwrap import dedent from timeit import default_timer as timer -from .helper import script_dir, decorate -from .buildlog import builds from .blacklist import BlackList -from .runner import TestRunner +from .buildlog import builds +from .helper import decorate, script_dir from .parser import TestParser +from .runner import TestRunner # Should we repeat only failed tests? COIN_RERUN_FAILED_ONLY = True COIN_THRESHOLD = 3 # report error if >= COIN_TESTING = 5 # number of runs +TIMEOUT = 20 * 60 if os.environ.get("COIN_RERUN_FAILED_ONLY", "1").lower() in "0 f false n no".split(): COIN_RERUN_FAILED_ONLY = False @@ -95,6 +60,14 @@ if os.environ.get("COIN_RERUN_FAILED_ONLY", "1").lower() in "0 f false n no".spl def test_project(project, args, blacklist, runs): ret = [] + if "pypy" in builds.classifiers: + # As long as PyPy has so many bugs, we use 1 test only... + global COIN_TESTING + COIN_TESTING = runs = 1 + # ...and extend the timeout. + global TIMEOUT + TIMEOUT = 100 * 60 + # remove files from a former run for idx in range(runs): index = idx + 1 @@ -106,6 +79,8 @@ def test_project(project, args, blacklist, runs): for idx in range(runs): index = idx + 1 runner = TestRunner(builds.selected, project, index) + # For the full Python version we need to ask the TestRunner. + builds.set_python_version(runner.get_python_version()) print() print(f"********* Start testing of {project} *********") print("Config: Using", " ".join(builds.classifiers)) @@ -120,7 +95,7 @@ def test_project(project, args, blacklist, runs): break else: rerun = None - runner.run(f"RUN {idx + 1}:", rerun, 10 * 60) + runner.run(f"RUN {idx + 1}:", rerun, TIMEOUT) results = TestParser(runner.logfile) r = 5 * [0] rerun_list = [] @@ -154,7 +129,7 @@ def test_project(project, args, blacklist, runs): print("FATAL ERROR:", fatal) print("Repetitions cancelled!") break - return ret, fatal + return ret, fatal, runs def main(): @@ -261,14 +236,15 @@ def main(): key, value = things os.environ[key] = value + version = sys.version.replace("\n", " ") print( dedent( - """\ + f"""\ System: - Platform={sys.__dict__["platform"]} - Executable={sys.__dict__["executable"]} - Version={sys.version.replace("\n", " ")} - API version={sys.__dict__["api_version"]} + Platform={sys.platform} + Executable={sys.executable} + Version={version} + API version={sys.api_version} Environment:""" ) @@ -284,7 +260,7 @@ def main(): # now loop over the projects and accumulate fatal = False for project in args.projects: - res, fatal = test_project(project, args, bl, runs) + res, fatal, runs = test_project(project, args, bl, runs) if fatal: runs = 1 for idx, r in enumerate(res): diff --git a/testing/helper.py b/testing/helper.py index a8d3a65ff..d89f0d849 100644 --- a/testing/helper.py +++ b/testing/helper.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 """ testing/helper.py @@ -45,7 +9,6 @@ Some tools that do not fit elsewhere. import os - script_dir = os.path.dirname(os.path.dirname(__file__)) diff --git a/testing/parser.py b/testing/parser.py index 7e1e6c792..a01c4d029 100644 --- a/testing/parser.py +++ b/testing/parser.py @@ -1,41 +1,5 @@ -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of Qt for Python. -## -## $QT_BEGIN_LICENSE:LGPL$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU Lesser General Public License Usage -## Alternatively, this file may be used under the terms of the GNU Lesser -## General Public License version 3 as published by the Free Software -## Foundation and appearing in the file LICENSE.LGPL3 included in the -## packaging of this file. Please review the following information to -## ensure the GNU Lesser General Public License version 3 requirements -## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 2.0 or (at your option) the GNU General -## Public license version 3 or any later version approved by the KDE Free -## Qt Foundation. The licenses are as published by the Free Software -## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-2.0.html and -## https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# +# 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 import os import re @@ -129,7 +93,7 @@ def _parse_tests(test_log): match = re.match(pat, line, re.VERBOSE) if match and line.split()[-1] != "sec": # don't change the number of lines - lines[idx : idx + 2] = [line.rstrip() + lines[idx + 1], ""] + lines[idx:idx + 2] = [line.rstrip() + lines[idx + 1], ""] pat = _TEST_PAT for line in lines: diff --git a/testing/runner.py b/testing/runner.py index 50c08d21d..b52ac4937 100644 --- a/testing/runner.py +++ b/testing/runner.py @@ -1,50 +1,13 @@ -############################################################################# -## -## Copyright (C) 2018 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the Qt for Python project. -## -## $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 +import inspect import os -import sys import re import subprocess -import inspect - -from textwrap import dedent +import sys from subprocess import TimeoutExpired +from textwrap import dedent # Get the dir path to the utils module try: @@ -53,10 +16,10 @@ except NameError: this_file = sys.argv[0] this_file = os.path.abspath(this_file) this_dir = os.path.dirname(this_file) -build_scripts_dir = os.path.abspath(os.path.join(this_dir, "../build_scripts")) +build_scripts_dir = os.path.abspath(os.path.join(this_dir, "..")) sys.path.append(build_scripts_dir) -from utils import detect_clang +from build_scripts.utils import detect_clang class TestRunner(object): @@ -73,6 +36,31 @@ class TestRunner(object): self._setup_clang() self._setup() + def get_python_version(self): + """ + Finding the exact Python version. + --------------------------------- + + This is done by asking the interpreter, because it cannot reliably + be found from any file name parsing as a triple. + + Note: We need to look into the CMakeCache.txt file to find out + what CMake has found as the Python interpreter to use. + This is *not* necessarily the same Python that runs this script, + otherwise we could use the version info directly. + """ + look_python = os.path.join(self.test_dir, "CMakeCache.txt") + look_for = "PYTHON_EXECUTABLE:FILEPATH=" + with open(look_python) as f: + for line in f: + if line.startswith(look_for): + python_exec = line.split("=")[-1].strip() + res = subprocess.run([python_exec, "-c", + "import sys;print(sys.version_info[:3])"], + capture_output=True) + return eval(res.stdout.decode("utf-8")) + return None + def _setup_clang(self): if sys.platform != "win32": return 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) |