--- a/scripts/install.py Sun Jun 02 09:51:47 2024 +0200 +++ b/scripts/install.py Wed Jul 03 09:20:41 2024 +0200 @@ -30,8 +30,6 @@ import sysconfig import time -from functools import partial - # Define the globals. currDir = os.getcwd() modDir = None @@ -47,6 +45,7 @@ yes2All = False withPyqt6Tools = False verbose = False +proxy = None cfg = {} progLanguages = ["MicroPython", "Python3", "QSS"] sourceDir = "eric" @@ -707,7 +706,7 @@ @return result code @rtype int """ - global distDir, doCleanup, cfg, progLanguages, sourceDir, configName + global distDir, cfg, progLanguages, sourceDir, configName global installApis # Create the platform specific wrappers. @@ -1460,7 +1459,7 @@ @return flag indicating a successful installation @rtype bool """ - global yes2All + global yes2All, proxy ok = False if yes2All or force: @@ -1474,17 +1473,18 @@ ) answer = input() # secok if answer in ("", "Y", "y"): - exitCode = subprocess.run( # secok - [ - sys.executable, - "-m", - "pip", - "install", - "--prefer-binary", - "--upgrade", - packageName, - ] - ).returncode + args = [ + sys.executable, + "-m", + "pip", + "install", + "--prefer-binary", + "--upgrade", + ] + if proxy: + args.append(f"--proxy={proxy}") + args.append(packageName) + exitCode = subprocess.run(args).returncode # secok ok = exitCode == 0 return ok @@ -1497,10 +1497,22 @@ @return flag indicating an outdated pip @rtype bool """ + global proxy + try: + args = [ + sys.executable, + "-m", + "pip", + "list", + "--outdated", + "--format=json", + ] + if proxy: + args.append(f"--proxy={proxy}") pipOut = ( subprocess.run( # secok - [sys.executable, "-m", "pip", "list", "--outdated", "--format=json"], + args, check=True, capture_output=True, text=True, @@ -1531,7 +1543,7 @@ """ Update the installed pip package. """ - global yes2All + global yes2All, proxy if yes2All: answer = "y" @@ -1539,9 +1551,17 @@ print("Shall 'pip' be updated (recommended)? (Y/n)", end=" ") answer = input() # secok if answer in ("", "Y", "y"): - subprocess.run( # secok - [sys.executable, "-m", "pip", "install", "--upgrade", "pip"] - ) + args = [ + sys.executable, + "-m", + "pip", + "install", + "--upgrade", + ] + if proxy: + args.append(f"--proxy={proxy}") + args.append("pip") + subprocess.run(args) # secok def versionToStr(version): @@ -1804,8 +1824,8 @@ qtMajor = int(qVersion().split(".")[0]) qtMinor = int(qVersion().split(".")[1]) print("Qt6: {0}".format(qVersion().strip())) - if qtMajor == 6 and qtMinor < 1: - print("Sorry, you must have Qt version 6.1.0 or better.") + if qtMajor == 6 and qtMinor < 2: + print("Sorry, you must have Qt version 6.2.0 or better.") exit(2) # check version of sip @@ -1907,97 +1927,6 @@ print() -def __pyName(py_dir, py_file): - """ - Local function to create the Python source file name for the compiled - .ui file. - - @param py_dir suggested name of the directory - @type str - @param py_file suggested name for the compile source file - @type str - @return tuple of directory name and source file name - @rtype tuple of (str, str) - """ - return py_dir, "Ui_{0}".format(py_file) - - -def __compileOneUi(ui_path, mapFunc=None): - """ - Function to compile a single form file to Python code. - - @param ui_path path of the Qt form file - @type str - @param mapFunc function to change directory and/or name of the resulting Python file - (defaults to None) - @type func (optional) - """ - from PyQt6.uic import compileUi # noqa: I102 - - py_dir, py_file = os.path.split(ui_path[:-3] + ".py") - - # Allow the caller to change the name of the .py file or generate - # it in a different directory. - if mapFunc is not None: - py_dir, py_file = mapFunc(py_dir, py_file) - - # Make sure the destination directory exists. - os.makedirs(py_dir, exist_ok=True) - - py_path = os.path.join(py_dir, py_file) - - with open(py_path, "w", encoding="utf-8") as py_file: - compileUi(ui_path, py_file, execute=False, indent=4) - - -def compileUiDir(root, recurse=False, mapFunc=None, workers=1): - """ - Function to compile all Qt form files of a directory or directory tree - to Python code. - - @param root directory to scan for Qt form files (i.e. files ending with '.ui' - @type str - @param recurse flag indicating to recurse into sub-directories (defaults to False) - @type bool (optional) - @param mapFunc function to change directory and/or name of the resulting Python file - (defaults to None) - @type func (optional) - @param workers number of worker processes to be used to compile (defaults to 1) - @type int (optional) - """ - if recurse: - ui_files = [] - for rootDir, _, files in os.walk(root): - ui_files.extend( - os.path.join(rootDir, ui) for ui in files if ui.endswith(".ui") - ) - else: - ui_files = [ - os.path.join(root, ui) - for ui in os.listdir(root) - if os.path.isfile(os.path.join(root, ui) and ui.endswith(".ui")) - ] - - ProcessPoolExecutor = None - if workers != 1: - try: - from concurrent.futures import ProcessPoolExecutor # noqa: I101, I103 - except NotImplementedError: - workers = 1 - - if workers != 1 and ProcessPoolExecutor is not None: - # If workers == 0, let ProcessPoolExecutor determine worker count. - workers = workers or None - with ProcessPoolExecutor(max_workers=workers) as executor: - executor.map( - partial(__compileOneUi, mapFunc=mapFunc), - ui_files, - ) - else: - for ui_file in ui_files: - __compileOneUi(ui_file, mapFunc=mapFunc) - - def prepareInfoFile(fileName): """ Function to prepare an Info.py file when installing from source. @@ -2167,11 +2096,11 @@ parser = argparse.ArgumentParser( description="Install eric7 from the source code tree.", epilog="The file given to the -f option must be valid Python code defining a" - "dictionary called 'cfg' with the keys 'ericDir', 'ericPixDir', ericIconDir'," + " dictionary called 'cfg' with the keys 'ericDir', 'ericPixDir', ericIconDir'," " 'ericDTDDir', 'ericCSSDir', 'ericStylesDir', 'ericThemesDir', ericDocDir'," " ericExamplesDir', ericTranslationsDir', 'ericTemplatesDir'," " 'ericCodeTemplatesDir', ericOthersDir','bindir', 'mdir' and 'apidir." - "These define the directories for the installation of the various parts of" + " These define the directories for the installation of the various parts of" " eric.", ) @@ -2277,6 +2206,12 @@ action="store_true", help="install the 'qt6-applications' package", ) + parser.add_argument( + "--proxy", + default=None, + metavar="url", + help="HTTP proxy url will be used with pip (default: no proxy used)", + ) return parser @@ -2291,7 +2226,7 @@ global modDir, doCleanup, doCompile, distDir, cfg, apisDir global sourceDir, eric7SourceDir, configName, platBinDir global macAppBundlePath, macAppBundleName, macPythonExe - global installApis, doCleanDesktopLinks, yes2All + global installApis, doCleanDesktopLinks, yes2All, proxy global createInstallInfoFile, installCwd global withPyqt6Tools global verbose @@ -2318,6 +2253,7 @@ doCompile = args.z installApis = not args.no_apis yes2All = args.yes + proxy = args.proxy withPyqt6Tools = args.with_tools createInstallInfoFile = not args.no_info verbose = args.verbose @@ -2413,16 +2349,6 @@ createInstallInfo() print(" Done") - # Compile .ui files - print("Compiling user interface files ...", end="", flush=True) - # step 1: remove old Ui_*.py files - for root, _, files in os.walk(sourceDir): - for file in [f for f in files if fnmatch.fnmatch(f, "Ui_*.py")]: - os.remove(os.path.join(root, file)) - # step 2: compile the forms - compileUiDir(eric7SourceDir, recurse=True, mapFunc=__pyName, workers=0) - print(" Done") - if doCompile: print("Compiling source files ...", end="", flush=True) skipRe = re.compile(r"DebugClients[\\/]Python[\\/]")