diff --git a/aqt/helper.py b/aqt/helper.py index b3c40b6..bd524c6 100644 --- a/aqt/helper.py +++ b/aqt/helper.py @@ -34,6 +34,7 @@ from typing import Callable, Dict, Generator, List, Optional, Tuple from urllib.parse import urlparse from xml.etree.ElementTree import Element +import humanize import requests import requests.adapters from defusedxml import ElementTree @@ -290,7 +291,13 @@ def xml_to_modules( name = packageupdate.find("Name").text packages[name] = {} for child in packageupdate: - packages[name][child.tag] = child.text + if child.tag == "UpdateFile": + for attr in "CompressedSize", "UncompressedSize": + if attr not in child.attrib: + continue + packages[name][attr] = humanize.naturalsize(child.attrib[attr], gnu=True) + else: + packages[name][child.tag] = child.text return packages diff --git a/aqt/installer.py b/aqt/installer.py index 3690582..3af3ab5 100644 --- a/aqt/installer.py +++ b/aqt/installer.py @@ -493,9 +493,11 @@ class Cli: 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) + modules_ver, modules_query, is_long = args.modules[0], tuple(args.modules), False + elif args.long_modules: + modules_ver, modules_query, is_long = args.long_modules[0], tuple(args.long_modules), True else: - modules_ver, modules_query = None, None + modules_ver, modules_query, is_long = None, None, False 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) @@ -517,6 +519,7 @@ class Cli: spec=spec, is_latest_version=args.latest_version, modules_query=modules_query, + is_long_listing=is_long, extensions_ver=args.extensions, architectures_ver=args.arch, archives_query=args.archives, @@ -736,6 +739,16 @@ class Cli: 'Second arg: an architecture, which may be printed with the "--arch" flag. ' "When set, this prints all the modules available for either Qt 5.X.Y or the latest version of Qt.", ) + output_modifier_exclusive_group.add_argument( + "--long-modules", + type=str, + nargs=2, + metavar=("(VERSION | latest)", "ARCHITECTURE"), + help='First arg: Qt version in the format of "5.X.Y", or the keyword "latest". ' + 'Second arg: an architecture, which may be printed with the "--arch" flag. ' + "When set, this prints a table that describes all the modules available " + "for either Qt 5.X.Y or the latest version of Qt.", + ) output_modifier_exclusive_group.add_argument( "--extensions", type=str, diff --git a/aqt/metadata.py b/aqt/metadata.py index a314641..9aa3000 100644 --- a/aqt/metadata.py +++ b/aqt/metadata.py @@ -448,9 +448,14 @@ class MetadataFactory: self.request_type = "latest version" self._action = lambda: Versions(self.fetch_latest_version()) elif modules_query: - self.request_type = "modules" - version, arch = modules_query - self._action = lambda: self.fetch_modules(self._to_version(version), arch) + if is_long_listing: + self.request_type = "long modules" + version, arch = modules_query + self._action = lambda: self.fetch_long_modules(self._to_version(version), arch) + else: + self.request_type = "modules" + version, arch = modules_query + self._action = lambda: self.fetch_modules(self._to_version(version), arch) elif extensions_ver: self.request_type = "extensions" self._action = lambda: self.fetch_extensions(self._to_version(extensions_ver)) @@ -731,6 +736,30 @@ class MetadataFactory: modules.add(module) return sorted(modules) + def fetch_long_modules(self, version: Version, arch: str) -> ModuleData: + """Returns long listing of modules""" + self.validate_extension(version) + qt_ver_str = self._get_qt_version_str(version) + # Example: re.compile(r"^(preview\.)?qt\.(qt5\.)?590(\.addons)?\.(?P[^.]+)\.gcc_64$") + pattern = re.compile( + r"^(preview\.)?qt\.(qt" + + str(version.major) + + r"\.)?" + + qt_ver_str + + r"(\.addons)?\.(?P[^.]+)\." + + arch + + r"$" + ) + + def matches_arch(element: Element) -> bool: + name_node = element.find("Name") + return bool(name_node is not None) and bool(pattern.match(str(name_node.text))) + + modules_meta = self._fetch_module_metadata(self.archive_id.to_folder(qt_ver_str), matches_arch) + m = {pattern.match(key).group("module"): value for key, value in modules_meta.items()} + + return ModuleData(m) + def fetch_modules_sde(self, cmd_type: str, version: Version) -> List[str]: """Returns list of modules for src/doc/examples""" assert ( diff --git a/pyproject.toml b/pyproject.toml index 90cf12b..763d040 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,14 +23,15 @@ classifiers = [ ] requires-python = ">=3.6" dependencies = [ - "requests", - "semantic_version", - "patch>=1.16", - "py7zr>=0.18.3", - "texttable", "bs4", "dataclasses;python_version<'3.7'", "defusedxml", + "humanize", + "patch>=1.16", + "py7zr>=0.18.3", + "requests", + "semantic_version", + "texttable", ] dynamic = ["version", "entry-points"]