def test_list_versions_tools(monkeypatch, spec_regex, os_name, target, in_file, expect_out_file): _html = (Path(__file__).parent / "data" / in_file).read_text("utf-8") monkeypatch.setattr(MetadataFactory, "fetch_http", lambda *args, **kwargs: _html) expected = json.loads( (Path(__file__).parent / "data" / expect_out_file).read_text("utf-8")) # Test 'aqt list-tool' tools = MetadataFactory(ArchiveId("tools", os_name, target)).getList() assert tools == expected["tools"] for ext, expected_output in expected["qt"].items(): # Test 'aqt list-qt' archive_id = ArchiveId("qt", os_name, target, ext if ext != "qt" else "") all_versions = MetadataFactory(archive_id).getList() if len(expected_output) == 0: assert not all_versions else: assert f"{all_versions}" == "\n".join(expected_output) # Filter for the latest version only latest_ver = MetadataFactory(archive_id, is_latest_version=True).getList() if len(expected_output) == 0: assert not latest_ver else: assert f"{latest_ver}" == expected_output[-1].split(" ")[-1] for row in expected_output: spec_str = spec_regex.search(row).group(1) spec = SimpleSpec(spec_str) if not ext.endswith( "preview") else SimpleSpec(spec_str + ".0-preview") # Find the latest version for a particular spec latest_ver_for_spec = MetadataFactory( archive_id, spec=spec, is_latest_version=True, ).getList() assert f"{latest_ver_for_spec}" == row.split(" ")[-1] # Find all versions for a particular spec all_ver_for_spec = MetadataFactory( archive_id, spec=spec, ).getList() assert f"{all_ver_for_spec}" == row
def test_cli_determine_qt_version(monkeypatch, host, target, arch, version_or_spec: str, expected_version: Version, is_bad_spec: bool): _html = (Path(__file__).parent / "data" / f"{host}-{target}.html").read_text("utf-8") monkeypatch.setattr(MetadataFactory, "fetch_http", lambda *args, **kwargs: _html) cli = Cli() cli._setup_settings() if is_bad_spec: with pytest.raises(CliInputError) as e: Cli._determine_qt_version(version_or_spec, host, target, arch) assert e.type == CliInputError assert format( e.value ) == f"Invalid version or SimpleSpec: '{version_or_spec}'\n" + SimpleSpec.usage( ) elif not expected_version: with pytest.raises(CliInputError) as e: Cli._determine_qt_version(version_or_spec, host, target, arch) assert e.type == CliInputError expect_msg = f"No versions of Qt exist for spec={version_or_spec} with host={host}, target={target}, arch={arch}" actual_msg = format(e.value) assert actual_msg == expect_msg else: ver = Cli._determine_qt_version(version_or_spec, host, target, arch) assert ver == expected_version
def test_list_fetch_tool_by_simple_spec(monkeypatch): update_xml = ( Path(__file__).parent / "data" / "windows-desktop-tools_vcredist-update.xml").read_text("utf-8") monkeypatch.setattr(MetadataFactory, "fetch_http", lambda self, _: update_xml) expect_json = ( Path(__file__).parent / "data" / "windows-desktop-tools_vcredist-expect.json").read_text("utf-8") expected = json.loads(expect_json)["modules_data"] def check(actual, expect): for key in ( "Description", "DisplayName", "DownloadableArchives", "ReleaseDate", "SHA1", "Version", "Virtual", ): assert actual[key] == expect[key] meta = MetadataFactory(ArchiveId("tools", "windows", "desktop")) check( meta.fetch_tool_by_simple_spec(tool_name="tools_vcredist", simple_spec=SimpleSpec("2011")), expected["qt.tools.vcredist"], ) check( meta.fetch_tool_by_simple_spec(tool_name="tools_vcredist", simple_spec=SimpleSpec("2014")), expected["qt.tools.vcredist_msvc2013_x86"], ) nonexistent = meta.fetch_tool_by_simple_spec( tool_name="tools_vcredist", simple_spec=SimpleSpec("1970")) assert nonexistent is None # Simulate a broken Updates.xml file, with invalid versions highest_module_info = MetadataFactory.choose_highest_version_in_spec( all_tools_data={"some_module": { "Version": "not_a_version" }}, simple_spec=SimpleSpec("*"), ) assert highest_module_info is None
def run_list_qt(self, args: argparse.ArgumentParser): """Print versions of Qt, extensions, modules, architectures""" if not args.target: print(" ".join(ArchiveId.TARGETS_FOR_HOST[args.host])) return if args.target not in ArchiveId.TARGETS_FOR_HOST[args.host]: raise CliInputError( "'{0.target}' is not a valid target for host '{0.host}'". format(args)) if args.modules: modules_ver, modules_query = args.modules[0], tuple(args.modules) else: modules_ver, modules_query = None, None for version_str in (modules_ver, args.extensions, args.arch, args.archives[0] if args.archives else None): Cli._validate_version_str(version_str, allow_latest=True, allow_empty=True) spec = None try: if args.spec is not None: spec = SimpleSpec(args.spec) except ValueError as e: raise CliInputError( f"Invalid version specification: '{args.spec}'.\n" + SimpleSpec.usage()) from e meta = MetadataFactory( archive_id=ArchiveId( "qt", args.host, args.target, args.extension if args.extension else "", ), spec=spec, is_latest_version=args.latest_version, modules_query=modules_query, extensions_ver=args.extensions, architectures_ver=args.arch, archives_query=args.archives, ) show_list(meta)
def default_desktop_arch_dir(host: str, version: Union[Version, str]) -> str: version: Version = version if isinstance(version, Version) else Version(version) if host == "linux": return "gcc_64" elif host == "mac": return "macos" if version in SimpleSpec(">=6.1.2") else "clang_64" else: # Windows # This is a temporary solution. This arch directory cannot exist for many versions of Qt. # TODO: determine this dynamically return "mingw81_64"
def _determine_qt_version(qt_version_or_spec: str, host: str, target: str, arch: str) -> Version: def choose_highest(x: Optional[Version], y: Optional[Version]) -> Optional[Version]: if x and y: return max(x, y) return x or y def opt_version_for_spec(ext: str, _spec: SimpleSpec) -> Optional[Version]: try: return MetadataFactory(ArchiveId("qt", host, target, ext), spec=_spec).getList().latest() except AqtException: return None try: return Version(qt_version_or_spec) except ValueError: pass try: spec = SimpleSpec(qt_version_or_spec) except ValueError as e: raise CliInputError( f"Invalid version or SimpleSpec: '{qt_version_or_spec}'\n" + SimpleSpec.usage()) from e else: version: Optional[Version] = None for ext in QtRepoProperty.possible_extensions_for_arch(arch): version = choose_highest(version, opt_version_for_spec(ext, spec)) if not version: raise CliInputError( f"No versions of Qt exist for spec={spec} with host={host}, target={target}, arch={arch}" ) getLogger("aqt.installer").info( f"Resolved spec '{qt_version_or_spec}' to {version}") return version
def test_show_list_bad_connection(monkeypatch, capsys): for exception_class, error_msg in ( (ArchiveConnectionError, "Failure to connect to some url"), (ArchiveDownloadError, "Failure to download some xml file"), ): def mock(self): raise exception_class(error_msg) monkeypatch.setattr(MetadataFactory, "getList", mock) meta = MetadataFactory(mac_wasm, spec=SimpleSpec("<5.9")) with pytest.raises(exception_class) as error: show_list(meta) assert error.type == exception_class assert format(error.value) == ( f"{error_msg}\n" "==============================Suggested follow-up:==============================\n" "* Please use 'aqt list-qt mac desktop --extensions <QT_VERSION>' to list valid extensions.\n" "* Please use 'aqt list-qt mac desktop' to check that versions of qt exist within the spec '<5.9'." )
def update(cls, target: TargetConfig, base_dir: str): """ Make Qt configuration files, qt.conf and qtconfig.pri. And update pkgconfig and patch Qt5Core and qmake """ logger = getLogger("aqt.updater") arch = target.arch version = Version(target.version) os_name = target.os_name version_dir = "5.9" if version == Version("5.9.0") else target.version if arch is None: arch_dir = "" elif arch.startswith("win64_mingw"): arch_dir = arch[6:] + "_64" elif arch.startswith("win32_mingw"): arch_dir = arch[6:] + "_32" elif arch.startswith("win"): m = re.match(r"win\d{2}_(msvc\d{4})_(winrt_x\d{2})", arch) if m: a, b = m.groups() arch_dir = b + "_" + a else: arch_dir = arch[6:] elif version in SimpleSpec( ">=6.1.2") and os_name == "mac" and arch == "clang_64": arch_dir = "macos" else: arch_dir = arch try: prefix = pathlib.Path(base_dir) / version_dir / arch_dir updater = Updater(prefix, logger) updater.set_license(base_dir, version_dir, arch_dir) if target.arch not in [ "ios", "android", "wasm_32", "android_x86_64", "android_arm64_v8a", "android_x86", "android_armv7", ]: # desktop version updater.make_qtconf(base_dir, version_dir, arch_dir) updater.patch_qmake() if target.os_name == "linux": updater.patch_pkgconfig("/home/qt/work/install", target.os_name) updater.patch_libtool("/home/qt/work/install/lib", target.os_name) elif target.os_name == "mac": updater.patch_pkgconfig("/Users/qt/work/install", target.os_name) updater.patch_libtool("/Users/qt/work/install/lib", target.os_name) elif target.os_name == "windows": updater.make_qtenv2(base_dir, version_dir, arch_dir) if version < Version("5.14.0"): updater.patch_qtcore(target) elif version in SimpleSpec(">=5.0,<6.0"): updater.patch_qmake() else: # qt6 non-desktop updater.patch_qmake_script(base_dir, version_dir, target.os_name) updater.patch_target_qt_conf(base_dir, version_dir, arch_dir, target.os_name) except IOError as e: raise UpdaterError(f"Updater caused an IO error: {e}") from e
), ) def test_invalid_spec(capsys, cmd: str, spec: str): expect_prefix = f"ERROR : Invalid version specification: '{spec}'" host, target = "linux", "desktop" cli = Cli() return_code = cli.run([cmd, host, target, "--spec", spec]) out, err = capsys.readouterr() assert return_code == 1 assert err.strip().startswith(expect_prefix) @pytest.mark.parametrize( "simple_spec, expected_name", ( (SimpleSpec("*"), "mytool.999"), (SimpleSpec(">3.5"), "mytool.999"), (SimpleSpec("3.5.5"), "mytool.355"), (SimpleSpec("<3.5"), "mytool.300"), (SimpleSpec("<=3.5"), "mytool.355"), (SimpleSpec("<=3.5.0"), "mytool.350"), (SimpleSpec(">10"), None), ), ) def test_list_choose_tool_by_version(simple_spec, expected_name): tools_data = { "mytool.999": { "Version": "9.9.9", "Name": "mytool.999" }, "mytool.355": {