def __init__(self, os_name, target, version, arch, subarchives=None, modules=None, mirror=None, logging=None, all_extra=False): self.version = version self.target = target self.arch = arch self.mirror = mirror self.os_name = os_name self.all_extra = all_extra self.arch_list = [item.get('arch') for item in Settings().qt_combinations] all_archives = (subarchives is None) if mirror is not None: self.has_mirror = True self.base = mirror + '/online/qtsdkrepository/' else: self.has_mirror = False self.base = self.BASE_URL if logging: self.logger = logging else: self.logger = getLogger('aqt') self.archives = [] self.mod_list = [] qt_ver_num = self.version.replace(".", "") self.qt_ver_base = self.version[0:1] if all_extra: self.all_extra = True else: for m in modules if modules is not None else []: self.mod_list.append("qt.qt{}.{}.{}.{}".format(self.qt_ver_base, qt_ver_num, m, arch)) self.mod_list.append("qt.{}.{}.{}".format(qt_ver_num, m, arch)) self._get_archives(qt_ver_num) if not all_archives: self.archives = list(filter(lambda a: a.name in subarchives, self.archives))
def _check_modules_arg(self, qt_version, modules): if modules is None: return True available = Settings.available_modules(qt_version) if available is None: return False return all([m in available for m in modules])
def test_install_pool_exception(monkeypatch, capsys, make_exception, settings_file, expect_end_msg, expect_return): def mock_installer_func(*args): raise eval(make_exception) host, target, ver, arch = "windows", "desktop", "6.1.0", "win64_mingw81" updates_url = "windows_x86/desktop/qt6_610/Updates.xml" archives = [ plain_qtbase_archive("qt.qt6.610.win64_mingw81", "win64_mingw81") ] cmd = ["install-qt", host, target, ver, arch] mock_get_url, mock_download_archive = make_mock_geturl_download_archive( archives, arch, host, updates_url) monkeypatch.setattr("aqt.archives.getUrl", mock_get_url) monkeypatch.setattr("aqt.installer.getUrl", mock_get_url) monkeypatch.setattr("aqt.installer.installer", mock_installer_func) Settings.load_settings(str(Path(__file__).parent / settings_file)) cli = Cli() assert expect_return == cli.run(cmd) out, err = capsys.readouterr() assert err.rstrip().endswith(expect_end_msg)
def _setup_settings(self, args=None): # setup logging setup_logging() self.logger = getLogger("aqt.main") # setup settings if args is not None and args.config is not None: Settings.load_settings(args.config) else: config = os.getenv("AQT_CONFIG", None) if config is not None and os.path.exists(config): Settings.load_settings(config) self.logger.debug("Load configuration from {}".format(config)) else: Settings.load_settings()
def __init__( self, os_name, target, version, arch, base, subarchives=None, modules=None, logging=None, all_extra=False, timeout=(5, 5), ): self.version = version self.target = target self.arch = arch self.os_name = os_name self.all_extra = all_extra self.arch_list = [item.get("arch") for item in Settings().qt_combinations] all_archives = subarchives is None self.base = base if logging: self.logger = logging else: self.logger = getLogger("aqt") self.archives = [] self.mod_list = [] qt_ver_num = self.version.replace(".", "") self.qt_ver_base = self.version[0:1] if all_extra: self.all_extra = True else: for m in modules if modules is not None else []: self.mod_list.append( "qt.qt{}.{}.{}.{}".format(self.qt_ver_base, qt_ver_num, m, arch) ) self.mod_list.append("qt.{}.{}.{}".format(qt_ver_num, m, arch)) self.timeout = timeout self._get_archives(qt_ver_num) if not all_archives: self.archives = list(filter(lambda a: a.name in subarchives, self.archives))
def setup(): Settings.load_settings( os.path.join(os.path.dirname(__file__), "data", "settings.ini"))
except (ArchiveConnectionError, ArchiveDownloadError) as e: logger.error(format(e)) return 1 def get_tqdm(disable: bool): if disable: return lambda x: x from tqdm import tqdm as base_tqdm return lambda *a: base_tqdm(*a, disable=disable) if __name__ == "__main__": Settings.load_settings() setup_logging() logger = logging.getLogger("aqt.generate_combos") json_filename = Path(__file__).parent.parent / "aqt/combinations.json" parser = argparse.ArgumentParser( description="Generate combinations.json from download.qt.io, " "compare with existing file, and write file to correct differences") parser.add_argument( "--write", help="write to combinations.json if changes detected", action="store_true", ) parser.add_argument( "--no-tqdm",
def __init__(self, env_key='AQT_CONFIG'): config = os.getenv(env_key, None) self.settings = Settings(config=config) self._create_parser()
class Cli: """CLI main class to parse command line argument and launch proper functions.""" __slot__ = ['parser', 'combinations', 'logger'] def __init__(self, env_key='AQT_CONFIG'): config = os.getenv(env_key, None) self.settings = Settings(config=config) self._create_parser() def _check_tools_arg_combination(self, os_name, tool_name, arch): for c in self.settings.tools_combinations: if c['os_name'] == os_name and c['tool_name'] == tool_name and c[ 'arch'] == arch: return True return False def _check_qt_arg_combination(self, qt_version, os_name, target, arch): if qt_version.startswith( '5.15.0') and os_name == 'windows' and target == 'desktop': if arch in [ 'win64_msvc2017_64', 'win32_msvc2017', 'win64_mingw73', 'win32_mingw73' ]: return False for c in self.settings.qt_combinations: if c['os_name'] == os_name and c['target'] == target and c[ 'arch'] == arch: return True return False def _check_qt_arg_versions(self, qt_version): for ver in self.settings.available_versions: if ver == qt_version: return True return False def _set_sevenzip(self, args): sevenzip = args.external if sevenzip is None: return None try: subprocess.run([sevenzip, '--help'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except FileNotFoundError as e: raise Exception( 'Specified 7zip command executable does not exist: {!r}'. format(sevenzip)) from e return sevenzip def _set_arch(self, args, oarch, os_name, target, qt_version): arch = oarch if arch is None: if os_name == "linux" and target == "desktop": arch = "gcc_64" elif os_name == "mac" and target == "desktop": arch = "clang_64" elif os_name == "mac" and target == "ios": arch = "ios" elif target == "android" and parse(qt_version) >= Version( '5.14.0'): arch = "android" if arch == "": print("Please supply a target architecture.") args.print_help() exit(1) return arch def _check_mirror(self, mirror): if mirror is None: pass elif mirror.startswith('http://') or mirror.startswith( 'https://') or mirror.startswith('ftp://'): pass else: return False return True def _check_modules_arg(self, qt_version, modules): if modules is None: return True available = self.settings.available_modules(qt_version) if available is None: return False return all([m in available for m in modules]) def _run_common_part(self, output_dir=None, mirror=None): self.show_aqt_version() if output_dir is not None: output_dir = os.path.normpath(output_dir) if not self._check_mirror(mirror): self.parser.print_help() exit(1) def call_installer(self, qt_archives, target_dir, sevenzip): if target_dir is None: base_dir = os.getcwd() else: base_dir = target_dir tasks = [] for arc in qt_archives.get_archives(): tasks.append((arc, base_dir, sevenzip)) pool = multiprocessing.Pool(self.settings.concurrency) pool.starmap(installer, tasks) def run_install(self, args): start_time = time.perf_counter() arch = args.arch target = args.target os_name = args.host qt_version = args.qt_version output_dir = args.outputdir if output_dir is None: base_dir = os.getcwd() else: base_dir = output_dir arch = self._set_arch(args, arch, os_name, target, qt_version) modules = args.modules sevenzip = self._set_sevenzip(args) mirror = args.base archives = args.archives self._run_common_part(output_dir, mirror) if not self._check_qt_arg_versions(qt_version): self.logger.warning( "Specified Qt version is unknown: {}.".format(qt_version)) if not self._check_qt_arg_combination(qt_version, os_name, target, arch): self.logger.warning( "Specified target combination is not valid or unknown: {} {} {}" .format(os_name, target, arch)) all_extra = True if modules is not None and 'all' in modules else False if not all_extra and not self._check_modules_arg(qt_version, modules): self.logger.warning("Some of specified modules are unknown.") try: qt_archives = QtArchives(os_name, target, qt_version, arch, subarchives=archives, modules=modules, mirror=mirror, logging=self.logger, all_extra=all_extra) except ArchiveDownloadError or ArchiveListError: exit(1) else: target_config = qt_archives.get_target_config() self.call_installer(qt_archives, output_dir, sevenzip) finisher(target_config, base_dir, self.logger) self.logger.info("Finished installation") self.logger.info("Time elasped: {time:.8f} second".format( time=time.perf_counter() - start_time)) def _run_src_doc_examples(self, flavor, args): start_time = time.perf_counter() target = args.target os_name = args.host qt_version = args.qt_version output_dir = args.outputdir mirror = args.base sevenzip = self._set_sevenzip(args) modules = args.modules archives = args.archives self._run_common_part(output_dir, mirror) all_extra = True if modules is not None and 'all' in modules else False if not self._check_qt_arg_versions(qt_version): self.logger.warning( "Specified Qt version is unknown: {}.".format(qt_version)) try: srcdocexamples_archives = SrcDocExamplesArchives( flavor, os_name, target, qt_version, subarchives=archives, modules=modules, mirror=mirror, logging=self.logger, all_extra=all_extra) except ArchiveDownloadError or ArchiveListError: exit(1) else: self.call_installer(srcdocexamples_archives, output_dir, sevenzip) self.logger.info("Finished installation") self.logger.info("Time elasped: {time:.8f} second".format( time=time.perf_counter() - start_time)) def run_src(self, args): self._run_src_doc_examples('src', args) def run_examples(self, args): self._run_src_doc_examples('examples', args) def run_doc(self, args): self._run_src_doc_examples('doc', args) def run_tool(self, args): start_time = time.perf_counter() arch = args.arch tool_name = args.tool_name os_name = args.host output_dir = args.outputdir sevenzip = self._set_sevenzip(args) version = args.version mirror = args.base self._run_common_part(output_dir, mirror) if not self._check_tools_arg_combination(os_name, tool_name, arch): self.logger.warning( "Specified target combination is not valid: {} {} {}".format( os_name, tool_name, arch)) try: tool_archives = ToolArchives(os_name, tool_name, version, arch, mirror=mirror, logging=self.logger) except ArchiveDownloadError or ArchiveListError: exit(1) else: self.call_installer(tool_archives, output_dir, sevenzip) self.logger.info("Finished installation") self.logger.info("Time elasped: {time:.8f} second".format( time=time.perf_counter() - start_time)) def run_list(self, args): self.show_aqt_version() pl = PackagesList(args.qt_version, args.host, args.target) print('List Qt packages in %s for %s' % (args.qt_version, args.host)) table = Texttable() table.set_deco(Texttable.HEADER) table.set_cols_dtype(['t', 't']) table.set_cols_align(["l", "l"]) table.header(["target type", "arch"]) for entry in pl.get_list(): if not entry.virtual: name_list = entry.name.split('.') table.add_row([entry.display_name, name_list[-1]]) print(table.draw()) def show_help(self, args): self.parser.print_help() def show_aqt_version(self): dist = importlib_metadata.distribution('aqtinstall') module_name = dist.entry_points[0].name py_version = platform.python_version() py_impl = platform.python_implementation() py_build = platform.python_compiler() self.logger.info("aqtinstall({}) v{} on Python {} [{} {}]".format( module_name, dist.version, py_version, py_impl, py_build)) def _set_common_options(self, subparser): subparser.add_argument( '-O', '--outputdir', nargs='?', help='Target output directory(default current directory)') subparser.add_argument( '-b', '--base', nargs='?', help= "Specify mirror base url such as http://mirrors.ocf.berkeley.edu/qt/, " "where 'online' folder exist.") subparser.add_argument('-E', '--external', nargs='?', help='Specify external 7zip command path.') subparser.add_argument('--internal', action='store_true', help='Use internal extractor.') def _set_module_options(self, subparser): subparser.add_argument('-m', '--modules', nargs='*', help="Specify extra modules to install") subparser.add_argument( '--archives', nargs='*', help= "Specify subset packages to install (Default: all standard and extra modules)." ) def _set_common_argument(self, subparser): subparser.add_argument("qt_version", help="Qt version in the format of \"5.X.Y\"") subparser.add_argument('host', choices=['linux', 'mac', 'windows'], help="host os name") subparser.add_argument('target', choices=['desktop', 'winrt', 'android', 'ios'], help="target sdk") def _create_parser(self): parser = argparse.ArgumentParser( prog='aqt', description='Installer for Qt SDK.', formatter_class=argparse.RawTextHelpFormatter, add_help=True) parser.add_argument('--logging-conf', type=argparse.FileType('r'), nargs=1, help="Logging configuration ini file.") parser.add_argument('--logger', nargs=1, help="Specify logger name") subparsers = parser.add_subparsers( title='subcommands', description='Valid subcommands', help='subcommand for aqt Qt installer') install_parser = subparsers.add_parser('install') install_parser.set_defaults(func=self.run_install) self._set_common_argument(install_parser) self._set_common_options(install_parser) install_parser.add_argument( 'arch', nargs='?', help="\ntarget linux/desktop: gcc_64, wasm_32" "\ntarget mac/desktop: clang_64, wasm_32" "\ntarget mac/ios: ios" "\nwindows/desktop: win64_msvc2019_64, win32_msvc2019" "\n win64_msvc2017_64, win32_msvc2017" "\n win64_msvc2015_64, win32_msvc2015" "\n win64_mingw73, win32_mingw73" "\n win32_mingw53" "\n wasm_32" "\nwindows/winrt: win64_msvc2019_winrt_x64, win64_msvc2019_winrt_x86" "\n win64_msvc2017_winrt_x64, win64_msvc2017_winrt_x86" "\n win64_msvc2019_winrt_armv7" "\n win64_msvc2017_winrt_armv7" "\nandroid: Qt 5.14: android (optional)" "\n Qt 5.13 or below: android_x86_64, android_arm64_v8a" "\n android_x86, android_armv7" ) self._set_module_options(install_parser) # doc_parser = subparsers.add_parser('doc') doc_parser.set_defaults(func=self.run_doc) self._set_common_argument(doc_parser) self._set_common_options(doc_parser) self._set_module_options(doc_parser) # examples_parser = subparsers.add_parser('examples') examples_parser.set_defaults(func=self.run_examples) self._set_common_argument(examples_parser) self._set_common_options(examples_parser) self._set_module_options(examples_parser) # src_parser = subparsers.add_parser('src') src_parser.set_defaults(func=self.run_src) self._set_common_argument(src_parser) self._set_common_options(src_parser) self._set_module_options(src_parser) # tools_parser = subparsers.add_parser('tool') tools_parser.set_defaults(func=self.run_tool) tools_parser.add_argument('host', choices=['linux', 'mac', 'windows'], help="host os name") tools_parser.add_argument( 'tool_name', help="Name of tool such as tools_ifw, tools_mingw") tools_parser.add_argument( "version", help="Tool version in the format of \"4.1.2\"") tools_parser.add_argument( 'arch', help="Name of full tool name such as qt.tools.ifw.31") self._set_common_options(tools_parser) # list_parser = subparsers.add_parser('list') list_parser.set_defaults(func=self.run_list) self._set_common_argument(list_parser) help_parser = subparsers.add_parser('help') help_parser.set_defaults(func=self.show_help) parser.set_defaults(func=self.show_help) self.parser = parser def _setup_logging(self, args, env_key='LOG_CFG'): envconf = os.getenv(env_key, None) conf = None if args.logging_conf: conf = args.logging_conf elif envconf is not None: conf = envconf if conf is None or not os.path.exists(conf): conf = os.path.join(os.path.dirname(__file__), 'logging.ini') logging.config.fileConfig(conf) if args.logger is not None: self.logger = logging.getLogger(args.logger) else: self.logger = logging.getLogger('aqt') def run(self, arg=None): args = self.parser.parse_args(arg) self._setup_logging(args) return args.func(args)
class Cli: """CLI main class to parse command line argument and launch proper functions.""" __slot__ = ["parser", "combinations", "logger"] def __init__(self, env_key="AQT_CONFIG"): config = os.getenv(env_key, None) self.settings = Settings(config=config) self._create_parser() def _check_tools_arg_combination(self, os_name, tool_name, arch): for c in self.settings.tools_combinations: if ( c["os_name"] == os_name and c["tool_name"] == tool_name and c["arch"] == arch ): return True return False def _check_qt_arg_combination(self, qt_version, os_name, target, arch): if os_name == "windows" and target == "desktop": # check frequent mistakes if qt_version.startswith("5.15.") or qt_version.startswith("6."): if arch in [ "win64_msvc2017_64", "win32_msvc2017", "win64_mingw73", "win32_mingw73", ]: return False elif ( qt_version.startswith("5.9.") or qt_version.startswith("5.10.") or qt_version.startswith("5.11.") ): if arch in [ "win64_mingw73", "win32_mingw73", "win64_mingw81", "win32_mingw81", ]: return False elif arch in [ "win64_msvc2019_64", "win32_msvc2019", "win64_mingw81", "win32_mingw81", ]: return False for c in self.settings.qt_combinations: if c["os_name"] == os_name and c["target"] == target and c["arch"] == arch: return True return False def _check_qt_arg_versions(self, qt_version): for ver in self.settings.available_versions: if ver == qt_version: return True return False def _set_sevenzip(self, external): sevenzip = external if sevenzip is None: return None try: subprocess.run( [sevenzip, "--help"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) except FileNotFoundError as e: raise Exception( "Specified 7zip command executable does not exist: {!r}".format( sevenzip ) ) from e return sevenzip def _set_arch(self, args, oarch, os_name, target, qt_version): arch = oarch if arch is None: if os_name == "linux" and target == "desktop": arch = "gcc_64" elif os_name == "mac" and target == "desktop": arch = "clang_64" elif os_name == "mac" and target == "ios": arch = "ios" elif target == "android" and parse(qt_version) >= Version("5.14.0"): arch = "android" else: print("Please supply a target architecture.") self.show_help(args) exit(1) if arch == "": print("Please supply a target architecture.") self.show_help(args) exit(1) return arch def _check_mirror(self, mirror): if mirror is None: pass elif ( mirror.startswith("http://") or mirror.startswith("https://") or mirror.startswith("ftp://") ): pass else: return False return True def _check_modules_arg(self, qt_version, modules): if modules is None: return True available = self.settings.available_modules(qt_version) if available is None: return False return all([m in available for m in modules]) def _run_common_part(self, output_dir=None, mirror=None): self.show_aqt_version() if output_dir is not None: output_dir = os.path.normpath(output_dir) if not self._check_mirror(mirror): self.parser.print_help() exit(1) def call_installer(self, qt_archives, target_dir, sevenzip, keep): if target_dir is None: base_dir = os.getcwd() else: base_dir = target_dir tasks = [] for arc in qt_archives.get_archives(): tasks.append((arc, base_dir, sevenzip, keep)) pool = multiprocessing.Pool(self.settings.concurrency) pool.starmap(installer, tasks) pool.close() pool.join() def run_install(self, args): """Run install subcommand""" start_time = time.perf_counter() arch = args.arch target = args.target os_name = args.host qt_version = args.qt_version output_dir = args.outputdir keep = args.keep if output_dir is None: base_dir = os.getcwd() else: base_dir = output_dir if args.timeout is not None: timeout = (args.timeout, args.timeout) else: timeout = (5, 5) arch = self._set_arch(args, arch, os_name, target, qt_version) modules = args.modules sevenzip = self._set_sevenzip(args.external) if EXT7Z and sevenzip is None: # override when py7zr is not exist sevenzip = self._set_sevenzip("7z") if args.base is not None: base = args.base + "/online/qtsdkrepository/" else: base = BASE_URL archives = args.archives if args.noarchives: if modules is None: print( "When specified option --no-archives, an option --modules is mandatory." ) exit(1) if archives is not None: print( "Option --archives and --no-archives are conflicted. Aborting..." ) exit(1) else: archives = modules else: if modules is not None and archives is not None: archives.append(modules) nopatch = args.noarchives or ( archives is not None and "qtbase" not in archives ) # type: bool self._run_common_part(output_dir, base) if not self._check_qt_arg_versions(qt_version): self.logger.warning( "Specified Qt version is unknown: {}.".format(qt_version) ) if not self._check_qt_arg_combination(qt_version, os_name, target, arch): self.logger.warning( "Specified target combination is not valid or unknown: {} {} {}".format( os_name, target, arch ) ) all_extra = True if modules is not None and "all" in modules else False if not all_extra and not self._check_modules_arg(qt_version, modules): self.logger.warning("Some of specified modules are unknown.") try: qt_archives = QtArchives( os_name, target, qt_version, arch, base, subarchives=archives, modules=modules, logging=self.logger, all_extra=all_extra, timeout=timeout, ) except ArchiveConnectionError: try: self.logger.warning( "Connection to the download site failed and fallback to mirror site." ) qt_archives = QtArchives( os_name, target, qt_version, arch, random.choice(FALLBACK_URLS), subarchives=archives, modules=modules, logging=self.logger, all_extra=all_extra, timeout=timeout, ) except Exception: self.logger.error("Connection to the download site failed. Aborted...") exit(1) except ArchiveDownloadError or ArchiveListError or NoPackageFound: exit(1) target_config = qt_archives.get_target_config() self.call_installer(qt_archives, output_dir, sevenzip, keep) if not nopatch: Updater.update(target_config, base_dir, self.logger) self.logger.info("Finished installation") self.logger.info( "Time elasped: {time:.8f} second".format( time=time.perf_counter() - start_time ) ) def _run_src_doc_examples(self, flavor, args): start_time = time.perf_counter() target = args.target os_name = args.host qt_version = args.qt_version output_dir = args.outputdir keep = args.keep if args.base is not None: base = args.base + "/online/qtsdkrepository/" else: base = BASE_URL if args.timeout is not None: timeout = (args.timeout, args.timeout) else: timeout = (5, 5) sevenzip = self._set_sevenzip(args) modules = args.modules archives = args.archives self._run_common_part(output_dir, base) all_extra = True if modules is not None and "all" in modules else False if not self._check_qt_arg_versions(qt_version): self.logger.warning( "Specified Qt version is unknown: {}.".format(qt_version) ) try: srcdocexamples_archives = SrcDocExamplesArchives( flavor, os_name, target, qt_version, base, subarchives=archives, modules=modules, logging=self.logger, all_extra=all_extra, timeout=timeout, ) except ArchiveConnectionError: try: self.logger.warning( "Connection to the download site failed and fallback to mirror site." ) srcdocexamples_archives = SrcDocExamplesArchives( flavor, os_name, target, qt_version, random.choice(FALLBACK_URLS), subarchives=archives, modules=modules, logging=self.logger, all_extra=all_extra, timeout=timeout, ) except Exception: self.logger.error("Connection to the download site failed. Aborted...") exit(1) except ArchiveDownloadError or ArchiveListError: exit(1) self.call_installer(srcdocexamples_archives, output_dir, sevenzip, keep) self.logger.info("Finished installation") self.logger.info( "Time elapsed: {time:.8f} second".format( time=time.perf_counter() - start_time ) ) def run_src(self, args): """Run src subcommand""" self._run_src_doc_examples("src", args) def run_examples(self, args): """Run example subcommand""" self._run_src_doc_examples("examples", args) def run_doc(self, args): """Run doc subcommand""" self._run_src_doc_examples("doc", args) def run_tool(self, args): """Run tool subcommand""" start_time = time.perf_counter() arch = args.arch tool_name = args.tool_name os_name = args.host output_dir = args.outputdir sevenzip = self._set_sevenzip(args.external) if EXT7Z and sevenzip is None: # override when py7zr is not exist sevenzip = self._set_sevenzip("7z") version = args.version keep = args.keep if args.base is not None: base = args.base + "/online/qtsdkrepository/" else: base = BASE_URL if args.timeout is not None: timeout = (args.timeout, args.timeout) else: timeout = (5, 5) self._run_common_part(output_dir, base) if not self._check_tools_arg_combination(os_name, tool_name, arch): self.logger.warning( "Specified target combination is not valid: {} {} {}".format( os_name, tool_name, arch ) ) try: tool_archives = ToolArchives( os_name, tool_name, version, arch, base, logging=self.logger, timeout=timeout, ) except ArchiveConnectionError: try: self.logger.warning( "Connection to the download site failed and fallback to mirror site." ) tool_archives = ToolArchives( os_name, tool_name, version, arch, random.choice(FALLBACK_URLS), logging=self.logger, timeout=timeout, ) except Exception: self.logger.error("Connection to the download site failed. Aborted...") exit(1) except ArchiveDownloadError or ArchiveListError: exit(1) self.call_installer(tool_archives, output_dir, sevenzip, keep) self.logger.info("Finished installation") self.logger.info( "Time elapsed: {time:.8f} second".format( time=time.perf_counter() - start_time ) ) def run_list(self, args): """Run list subcommand""" self.show_aqt_version() qt_version = args.qt_version host = args.host target = args.target try: pl = PackagesList(qt_version, host, target, BASE_URL) except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout): pl = PackagesList(qt_version, host, target, random.choice(FALLBACK_URLS)) print("List Qt packages in %s for %s" % (args.qt_version, args.host)) table = Texttable() table.set_deco(Texttable.HEADER) table.set_cols_dtype(["t", "t", "t"]) table.set_cols_align(["l", "l", "l"]) table.header(["target", "arch", "description"]) for entry in pl.get_list(): if qt_version[0:1] == "6" or not entry.virtual: archid = entry.name.split(".")[-1] table.add_row([entry.display_name, archid, entry.desc]) print(table.draw()) def show_help(self, args): """Display help message""" self.parser.print_help() def show_aqt_version(self): """Display version information""" py_version = platform.python_version() py_impl = platform.python_implementation() py_build = platform.python_compiler() self.logger.info( "aqtinstall(aqt) v{} on Python {} [{} {}]".format( aqt.__version__, py_version, py_impl, py_build ) ) def _set_common_options(self, subparser): subparser.add_argument( "-O", "--outputdir", nargs="?", help="Target output directory(default current directory)", ) subparser.add_argument( "-b", "--base", nargs="?", help="Specify mirror base url such as http://mirrors.ocf.berkeley.edu/qt/, " "where 'online' folder exist.", ) subparser.add_argument( "-E", "--external", nargs="?", help="Specify external 7zip command path." ) subparser.add_argument( "--internal", action="store_true", help="Use internal extractor." ) subparser.add_argument( "--timeout", nargs="?", type=float, help="Specify connection timeout for download site.(default: 5 sec)", ) subparser.add_argument( "-k", "--keep", action="store_true", help="Keep downloaded archive when specified, otherwise remove after install", ) def _set_module_options(self, subparser): subparser.add_argument( "-m", "--modules", nargs="*", help="Specify extra modules to install" ) subparser.add_argument( "--archives", nargs="*", help="Specify subset packages to install (Default: all standard and extra modules).", ) def _set_common_argument(self, subparser): subparser.add_argument("qt_version", help='Qt version in the format of "5.X.Y"') subparser.add_argument( "host", choices=["linux", "mac", "windows"], help="host os name" ) subparser.add_argument( "target", choices=["desktop", "winrt", "android", "ios"], help="target sdk" ) def _create_parser(self): parser = argparse.ArgumentParser( prog="aqt", description="Installer for Qt SDK.", formatter_class=argparse.RawTextHelpFormatter, add_help=True, ) parser.add_argument( "--logging-conf", type=argparse.FileType("r"), nargs=1, help="Logging configuration ini file.", ) parser.add_argument("--logger", nargs=1, help="Specify logger name") subparsers = parser.add_subparsers( title="subcommands", description="Valid subcommands", help="subcommand for aqt Qt installer", ) install_parser = subparsers.add_parser("install") install_parser.set_defaults(func=self.run_install) self._set_common_argument(install_parser) self._set_common_options(install_parser) install_parser.add_argument( "arch", nargs="?", help="\ntarget linux/desktop: gcc_64, wasm_32" "\ntarget mac/desktop: clang_64, wasm_32" "\ntarget mac/ios: ios" "\nwindows/desktop: win64_msvc2019_64, win32_msvc2019" "\n win64_msvc2017_64, win32_msvc2017" "\n win64_msvc2015_64, win32_msvc2015" "\n win64_mingw81, win32_mingw81" "\n win64_mingw73, win32_mingw73" "\n win32_mingw53" "\n wasm_32" "\nwindows/winrt: win64_msvc2019_winrt_x64, win64_msvc2019_winrt_x86" "\n win64_msvc2017_winrt_x64, win64_msvc2017_winrt_x86" "\n win64_msvc2019_winrt_armv7" "\n win64_msvc2017_winrt_armv7" "\nandroid: Qt 5.14: android (optional)" "\n Qt 5.13 or below: android_x86_64, android_arm64_v8a" "\n android_x86, android_armv7", ) self._set_module_options(install_parser) install_parser.add_argument( "--noarchives", action="store_true", help="No base packages; allow mod amendment with --modules option.", ) # doc_parser = subparsers.add_parser("doc") doc_parser.set_defaults(func=self.run_doc) self._set_common_argument(doc_parser) self._set_common_options(doc_parser) self._set_module_options(doc_parser) # examples_parser = subparsers.add_parser("examples") examples_parser.set_defaults(func=self.run_examples) self._set_common_argument(examples_parser) self._set_common_options(examples_parser) self._set_module_options(examples_parser) # src_parser = subparsers.add_parser("src") src_parser.set_defaults(func=self.run_src) self._set_common_argument(src_parser) self._set_common_options(src_parser) self._set_module_options(src_parser) # tools_parser = subparsers.add_parser("tool") tools_parser.set_defaults(func=self.run_tool) tools_parser.add_argument( "host", choices=["linux", "mac", "windows"], help="host os name" ) tools_parser.add_argument( "tool_name", help="Name of tool such as tools_ifw, tools_mingw" ) tools_parser.add_argument( "version", help='Tool version in the format of "4.1.2"' ) tools_parser.add_argument( "arch", help="Name of full tool name such as qt.tools.ifw.31" ) self._set_common_options(tools_parser) # list_parser = subparsers.add_parser("list") list_parser.set_defaults(func=self.run_list) self._set_common_argument(list_parser) help_parser = subparsers.add_parser("help") help_parser.set_defaults(func=self.show_help) parser.set_defaults(func=self.show_help) self.parser = parser def _setup_logging(self, args, env_key="LOG_CFG"): envconf = os.getenv(env_key, None) conf = None if args.logging_conf: conf = args.logging_conf elif envconf is not None: conf = envconf if conf is None or not os.path.exists(conf): conf = os.path.join(os.path.dirname(__file__), "logging.ini") logging.config.fileConfig(conf) if args.logger is not None: self.logger = logging.getLogger(args.logger) else: self.logger = logging.getLogger("aqt") def run(self, arg=None): args = self.parser.parse_args(arg) self._setup_logging(args) return args.func(args)
def setup_settings(): Settings.load_settings()
def installer( qt_archive: QtPackage, base_dir: str, command: Optional[str], queue: multiprocessing.Queue, keep: bool = False, response_timeout: Optional[int] = None, ): """ Installer function to download archive files and extract it. It is called through multiprocessing.Pool() """ name = qt_archive.name url = qt_archive.archive_url hashurl = qt_archive.hashurl archive = qt_archive.archive start_time = time.perf_counter() # set defaults Settings.load_settings() # set logging setup_logging() # XXX: why need to load again? qh = QueueHandler(queue) logger = getLogger() for handler in logger.handlers: handler.close() logger.removeHandler(handler) logger.addHandler(qh) # logger.debug("Download URL: {}".format(url)) if response_timeout is None: timeout = (Settings.connection_timeout, Settings.response_timeout) else: timeout = (Settings.connection_timeout, response_timeout) hash = binascii.unhexlify(getUrl(hashurl, timeout)) retry_on_errors( action=lambda: downloadBinaryFile(url, archive, "sha1", hash, timeout), acceptable_errors=(ArchiveChecksumError, ), num_retries=Settings.max_retries_on_checksum_error, name=f"Downloading {name}", ) if command is None: with py7zr.SevenZipFile(archive, "r") as szf: szf.extractall(path=base_dir) else: if base_dir is not None: command_args = [ command, "x", "-aoa", "-bd", "-y", "-o{}".format(base_dir), archive, ] else: command_args = [command, "x", "-aoa", "-bd", "-y", archive] try: proc = subprocess.run(command_args, stdout=subprocess.PIPE, check=True) logger.debug(proc.stdout) except subprocess.CalledProcessError as cpe: msg = "\n".join( filter(None, [ f"Extraction error: {cpe.returncode}", cpe.stdout, cpe.stderr ])) raise ArchiveExtractionError(msg) from cpe if not keep: os.unlink(archive) logger.info("Finished installation of {} in {:.8f}".format( archive, time.perf_counter() - start_time)) qh.flush() qh.close() logger.removeHandler(qh)