mirror of
https://github.com/miurahr/aqtinstall.git
synced 2025-12-16 20:27:05 +03:00
Merge pull request #909 from Kidev/fix_linux_version
Some checks failed
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.7.3) (push) Has been cancelled
Check tox tests / Check packaging 📦 (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Publish Python 🐍 distributions 📦 to PyPI / Build package (push) Has been cancelled
Test on GH actions environment / test (binary, windows-latest, 3.13, 6.6.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.5.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.6.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.8.0) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.8.1) (push) Has been cancelled
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.5.3) (push) Has been cancelled
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.6.3) (push) Has been cancelled
Publish Python 🐍 distributions 📦 to PyPI / publish Python 🐍 distributions 📦 to PyPI (push) Has been cancelled
Some checks failed
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.7.3) (push) Has been cancelled
Check tox tests / Check packaging 📦 (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Publish Python 🐍 distributions 📦 to PyPI / Build package (push) Has been cancelled
Test on GH actions environment / test (binary, windows-latest, 3.13, 6.6.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.5.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.6.3) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.8.0) (push) Has been cancelled
Test on GH actions environment / test (standard, ubuntu-latest, 3.13, 6.8.1) (push) Has been cancelled
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.5.3) (push) Has been cancelled
Test on GH actions environment / test (standard, windows-latest, 3.13, 6.6.3) (push) Has been cancelled
Publish Python 🐍 distributions 📦 to PyPI / publish Python 🐍 distributions 📦 to PyPI (push) Has been cancelled
Fix arch guessing error when version not fully qualified, fix list-qt android, add --UNSAFE-ignore-hash, add --use-official-installer to list-qt
This commit is contained in:
@@ -467,12 +467,14 @@ class SettingsClass:
|
||||
"config": None,
|
||||
"configfile": None,
|
||||
"loggingconf": None,
|
||||
"_ignore_hash_override": None,
|
||||
"_lock": Lock(),
|
||||
}
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.config: Optional[ConfigParser]
|
||||
self._lock: Lock
|
||||
self._ignore_hash_override: Optional[bool] = None
|
||||
self._initialize()
|
||||
|
||||
def __new__(cls, *p, **k):
|
||||
@@ -506,6 +508,10 @@ class SettingsClass:
|
||||
assert self.config is not None
|
||||
return self.config
|
||||
|
||||
def set_ignore_hash_for_session(self, value: bool) -> None:
|
||||
"""Override the INSECURE_NOT_FOR_PRODUCTION_ignore_hash setting for the current session without modifying config."""
|
||||
self._ignore_hash_override = value
|
||||
|
||||
def load_settings(self, file: Optional[Union[str, TextIO]] = None) -> None:
|
||||
if self.config is None:
|
||||
return
|
||||
@@ -604,6 +610,8 @@ class SettingsClass:
|
||||
|
||||
@property
|
||||
def ignore_hash(self):
|
||||
if self._ignore_hash_override is not None:
|
||||
return self._ignore_hash_override
|
||||
return self.config.getboolean("requests", "INSECURE_NOT_FOR_PRODUCTION_ignore_hash", fallback=False)
|
||||
|
||||
@property
|
||||
|
||||
103
aqt/installer.py
103
aqt/installer.py
@@ -105,6 +105,9 @@ class ListArgumentParser(BaseArgumentParser):
|
||||
qt_version_spec: str
|
||||
spec: str
|
||||
target: str
|
||||
email: Optional[str]
|
||||
pw: Optional[str]
|
||||
search_terms: Optional[str]
|
||||
|
||||
|
||||
class ListToolArgumentParser(ListArgumentParser):
|
||||
@@ -369,6 +372,9 @@ class Cli:
|
||||
qt_version = args.qt_version
|
||||
Cli._validate_version_str(qt_version)
|
||||
|
||||
if qt_version != qt_version_or_spec:
|
||||
arch = self._set_arch(args.arch, os_name, target, qt_version)
|
||||
|
||||
if hasattr(args, "use_official_installer") and args.use_official_installer is not None:
|
||||
|
||||
if len(args.use_official_installer) not in [0, 2]:
|
||||
@@ -659,6 +665,62 @@ class Cli:
|
||||
def run_list_qt(self, args: ListArgumentParser):
|
||||
"""Print versions of Qt, extensions, modules, architectures"""
|
||||
|
||||
if hasattr(args, "use_official_installer") and args.use_official_installer is not None:
|
||||
|
||||
if len(args.use_official_installer) not in [0, 2]:
|
||||
raise CliInputError(
|
||||
"When providing arguments to --use-official-installer, exactly 2 arguments are required: "
|
||||
"--use-official-installer email password"
|
||||
)
|
||||
|
||||
self.logger.info("Using official Qt installer for search")
|
||||
|
||||
commercial_search_args = ListArgumentParser()
|
||||
|
||||
email = None
|
||||
password = None
|
||||
if len(args.use_official_installer) == 2:
|
||||
email, password = args.use_official_installer
|
||||
self.logger.info("Using credentials provided with --use-official-installer")
|
||||
|
||||
commercial_search_args.email = email or getattr(args, "email", None)
|
||||
commercial_search_args.pw = password or getattr(args, "pw", None)
|
||||
|
||||
target_str = ""
|
||||
version_str = ""
|
||||
if hasattr(args, "target") and args.target is not None:
|
||||
target_str = args.target
|
||||
if hasattr(args, "arch") and args.arch is not None:
|
||||
try:
|
||||
version = Version(args.arch)
|
||||
version_str = f"{version.major}{version.minor}{version.patch}"
|
||||
except Exception as e:
|
||||
self.logger.warning(f"{e}. Ignoring 'arch' value")
|
||||
|
||||
commercial_search_args.search_terms = [rf"^.*{re.escape(version_str)}\.{re.escape(target_str)}.*$"]
|
||||
|
||||
ignored_options = []
|
||||
if getattr(args, "extensions", False):
|
||||
ignored_options.append("--extensions")
|
||||
if getattr(args, "extension", False):
|
||||
ignored_options.append("--extension")
|
||||
if getattr(args, "modules", None):
|
||||
ignored_options.append("--modules")
|
||||
if getattr(args, "long_modules", False):
|
||||
ignored_options.append("--long_modules")
|
||||
if getattr(args, "spec", False):
|
||||
ignored_options.append("--spec")
|
||||
if getattr(args, "archives", False):
|
||||
ignored_options.append("--archives")
|
||||
if getattr(args, "latest-version", False):
|
||||
ignored_options.append("--latest-version")
|
||||
|
||||
if ignored_options:
|
||||
self.logger.warning("Options ignored because you requested the official installer:")
|
||||
self.logger.warning(", ".join(ignored_options))
|
||||
|
||||
return self.run_list_qt_commercial(commercial_search_args, print_version=False)
|
||||
|
||||
if args.extensions:
|
||||
self._warn_on_deprecated_parameter("extensions", args.extensions)
|
||||
self.logger.warning(
|
||||
@@ -818,10 +880,11 @@ class Cli:
|
||||
install_qt_parser.add_argument(
|
||||
"arch",
|
||||
nargs="?",
|
||||
help="\ntarget linux/desktop: gcc_64, wasm_32"
|
||||
help="\ntarget linux/desktop: linux_gcc_64, gcc_64, wasm_32"
|
||||
"\ntarget mac/desktop: clang_64, wasm_32"
|
||||
"\ntarget mac/ios: ios"
|
||||
"\nwindows/desktop: win64_msvc2019_64, win32_msvc2019"
|
||||
"\nwindows/desktop: win64_msvc2022_64"
|
||||
"\n win64_msvc2019_64, win32_msvc2019"
|
||||
"\n win64_msvc2017_64, win32_msvc2017"
|
||||
"\n win64_msvc2015_64, win32_msvc2015"
|
||||
"\n win64_mingw81, win32_mingw81"
|
||||
@@ -953,9 +1016,10 @@ class Cli:
|
||||
help="Search terms (all non-option arguments are treated as search terms)",
|
||||
)
|
||||
|
||||
def run_list_qt_commercial(self, args) -> None:
|
||||
def run_list_qt_commercial(self, args: ListArgumentParser, print_version: Optional[bool] = True) -> None:
|
||||
"""Execute Qt commercial package listing."""
|
||||
self.show_aqt_version()
|
||||
if print_version:
|
||||
self.show_aqt_version()
|
||||
|
||||
# Create temporary directory for installer
|
||||
temp_dir = Settings.qt_installer_temp_path
|
||||
@@ -1126,6 +1190,16 @@ class Cli:
|
||||
help="Filter output so that only versions that match the specification are printed. "
|
||||
'IE: `aqt list-qt windows desktop --spec "5.12"` prints all versions beginning with 5.12',
|
||||
)
|
||||
list_parser.add_argument(
|
||||
"--use-official-installer",
|
||||
nargs="*",
|
||||
default=None,
|
||||
metavar=("EMAIL", "PASSWORD"),
|
||||
help="Use the official Qt installer for research instead of the aqt researcher. "
|
||||
"Can be used without arguments or with email and password: --use-official-installer email password. "
|
||||
"This redirects to list-qt-official. "
|
||||
"Arguments not compatible with the official installer will be ignored.",
|
||||
)
|
||||
output_modifier_exclusive_group = list_parser.add_mutually_exclusive_group()
|
||||
output_modifier_exclusive_group.add_argument(
|
||||
"--modules",
|
||||
@@ -1265,6 +1339,11 @@ class Cli:
|
||||
action="store_true",
|
||||
help="Print what would be downloaded and installed without actually doing it",
|
||||
)
|
||||
subparser.add_argument(
|
||||
"--UNSAFE-ignore-hash",
|
||||
action="store_true",
|
||||
help="UNSAFE: Skip hash verification of downloaded files. Use at your own risk.",
|
||||
)
|
||||
|
||||
def _set_module_options(self, subparser):
|
||||
subparser.add_argument("-m", "--modules", nargs="*", help="Specify extra modules to install")
|
||||
@@ -1321,6 +1400,22 @@ class Cli:
|
||||
else:
|
||||
Settings.load_settings()
|
||||
|
||||
# Set ignore_hash to True if --UNSAFE-ignore-hash flag was passed
|
||||
if args is not None and hasattr(args, "UNSAFE_ignore_hash") and args.UNSAFE_ignore_hash:
|
||||
self.logger.warning(
|
||||
"************************************************************************************************"
|
||||
)
|
||||
self.logger.warning(
|
||||
"Hash verification is disabled. This is UNSAFE and may allow malicious files to be downloaded."
|
||||
)
|
||||
self.logger.warning(
|
||||
"If your install mirror hosts malicious files, you won't be able to know. Use at your own risk."
|
||||
)
|
||||
self.logger.warning(
|
||||
"************************************************************************************************"
|
||||
)
|
||||
Settings.set_ignore_hash_for_session(True)
|
||||
|
||||
@staticmethod
|
||||
def _validate_version_str(
|
||||
version_str: Optional[str],
|
||||
|
||||
@@ -250,7 +250,7 @@ class ArchiveId:
|
||||
"mac": ["android", "desktop", "ios"],
|
||||
"linux": ["android", "desktop"],
|
||||
"linux_arm64": ["desktop"],
|
||||
"all_os": ["wasm", "qt"],
|
||||
"all_os": ["wasm", "qt", "android"],
|
||||
}
|
||||
EXTENSIONS_REQUIRED_ANDROID_QT6 = {"x86_64", "x86", "armv7", "arm64_v8a"}
|
||||
ALL_EXTENSIONS = {
|
||||
@@ -779,14 +779,22 @@ class MetadataFactory:
|
||||
return arches
|
||||
|
||||
def fetch_versions(self, extension: str = "") -> Versions:
|
||||
def match_any_ext(ver: Version) -> bool:
|
||||
return (
|
||||
self.archive_id.host == "all_os"
|
||||
and self.archive_id.target in ArchiveId.TARGETS_FOR_HOST["all_os"]
|
||||
and ver in SimpleSpec("6.7.*")
|
||||
)
|
||||
|
||||
def filter_by(ver: Version, ext: str) -> bool:
|
||||
return (self.spec is None or ver in self.spec) and ext == extension
|
||||
return (self.spec is None or ver in self.spec) and (ext == extension or match_any_ext(ver))
|
||||
|
||||
versions_extensions = self.get_versions_extensions(
|
||||
self.fetch_http(self.archive_id.to_url(), False), self.archive_id.category
|
||||
)
|
||||
versions = sorted([ver for ver, ext in versions_extensions if ver is not None and filter_by(ver, ext)])
|
||||
versions = sorted({ver for ver, ext in versions_extensions if ver is not None and filter_by(ver, ext)})
|
||||
grouped = cast(Iterable[Tuple[int, Iterable[Version]]], itertools.groupby(versions, lambda version: version.minor))
|
||||
|
||||
return Versions(grouped)
|
||||
|
||||
def fetch_latest_version(self, ext: str) -> Optional[Version]:
|
||||
@@ -912,9 +920,32 @@ class MetadataFactory:
|
||||
|
||||
def get_versions_extensions(self, html_doc: str, category: str) -> Iterator[Tuple[Optional[Version], str]]:
|
||||
def folder_to_version_extension(folder: str) -> Tuple[Optional[Version], str]:
|
||||
components = folder.split("_", maxsplit=2)
|
||||
ext = "" if len(components) < 3 else components[2]
|
||||
ver = "" if len(components) < 2 else components[1]
|
||||
|
||||
ext = ""
|
||||
ver = ""
|
||||
|
||||
# Special case for Qt6.7 unique format
|
||||
if folder.startswith("qt6_7_"):
|
||||
# Split the input into version and extension parts
|
||||
# For qt6_7_3_arm64_v8a, we want to extract "6_7_3" and "arm64_v8a"
|
||||
# Should not be more than qt6_7_3_backup (extension should not have _, but you know...)
|
||||
|
||||
# Remove the "qt" prefix first
|
||||
remainder = folder[2:]
|
||||
|
||||
# Split the first 3 parts for the version (6_7_3)
|
||||
version_parts = remainder.split("_", 3)[:3]
|
||||
ver = "_".join(version_parts)
|
||||
|
||||
# Everything after version is the extension
|
||||
if len(remainder.split("_", 3)) > 3:
|
||||
ext = remainder.split("_", 3)[3]
|
||||
else:
|
||||
ext = ""
|
||||
else:
|
||||
components = folder.split("_", maxsplit=2)
|
||||
ext = "" if len(components) < 3 else components[2]
|
||||
ver = "" if len(components) < 2 else components[1]
|
||||
return (
|
||||
get_semantic_version(qt_ver=ver, is_preview="preview" in ext),
|
||||
ext,
|
||||
|
||||
Reference in New Issue
Block a user