--- a/src/eric7/PipInterface/Pip.py Fri Sep 01 10:26:51 2023 +0200 +++ b/src/eric7/PipInterface/Pip.py Thu Oct 05 09:59:53 2023 +0200 @@ -8,6 +8,7 @@ """ import contextlib +import functools import json import os import sys @@ -684,6 +685,7 @@ notRequired=False, usersite=False, interpreter=None, + callback=None, ): """ Public method to get the list of outdated packages. @@ -702,6 +704,9 @@ @param interpreter path of an interpreter executable. If this is not None, it will override the given environment name (defaults to None) @type str (optional) + @param callback method accepting a list of tuples containing the + package name, installed version and available version + @type function @return list of tuples containing the package name, installed version and available version @rtype list of tuple of (str, str, str) @@ -731,32 +736,78 @@ args += ["--index-url", indexUrl] proc = QProcess() + if callback: + self.__outdatedProc = proc + proc.finished.connect( + functools.partial(self.__outdatedFinished, callback, proc) + ) + proc.start(interpreter, args) + return None + proc.start(interpreter, args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): - output = str( - proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - "replace", - ).strip() - if output: - output = output.splitlines()[0] - try: - jsonList = json.loads(output) - except Exception: - jsonList = [] - - for package in jsonList: - if isinstance(package, dict): - packages.append( - ( - package["name"], - package["version"], - package["latest_version"], - ) - ) + packages = self.__extractOutdatedPackages(proc) return packages + def __extractOutdatedPackages(self, proc): + """ + Private method to extract the outdated packages list out of the process output. + + @param proc reference to the process + @type QProcess + @return list of tuples containing the package name, installed version + and available version + @rtype list of tuple of (str, str, str) + """ + packages = [] + + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ).strip() + if output: + output = output.splitlines()[0] + try: + jsonList = json.loads(output) + except Exception: + jsonList = [] + + for package in jsonList: + if isinstance(package, dict): + packages.append( + ( + package["name"], + package["version"], + package["latest_version"], + ) + ) + + return packages + + def __outdatedFinished(self, callback, proc, exitCode, exitStatus): + """ + Private method to handle the process finished signal. + + @param callback reference to the function to be called with the list of + outdated packages + @type function + @param proc reference to the process + @type QProcess + @param exitCode exit code of the process + @type int + @param exitStatus exit status of the process + @type QProcess.ExitStatus + """ + packages = ( + self.__extractOutdatedPackages(proc) + if exitStatus == QProcess.ExitStatus.NormalExit and exitCode == 0 + else [] + ) + callback(packages) + self.__outdatedProc = None + def checkPackagesOutdated(self, packageStarts, envName, interpreter=None): """ Public method to check, if groups of packages are outdated. @@ -1019,10 +1070,7 @@ if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: - args = [ - os.path.join(os.path.dirname(__file__), "pipdeptree.py"), - "--json-tree", - ] + args = ["-m", "pipdeptree", "--python", interpreter, "--json-tree"] if localPackages: args.append("--local-only") if usersite: @@ -1031,7 +1079,7 @@ args.append("--reverse") proc = QProcess() - proc.start(interpreter, args) + proc.start(PythonUtilities.getPythonExecutable(), args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): output = str( proc.readAllStandardOutput(),