--- a/PipxInterface/Pipx.py Mon Jul 29 11:58:31 2024 +0200 +++ b/PipxInterface/Pipx.py Tue Jul 30 17:45:46 2024 +0200 @@ -435,40 +435,6 @@ if res: dia.exec() - def checkPackageOutdated(self, package): - """ - Public method to check, if a given package is outdated. - - @param package name of the package - @type str - @return tuple containing the latest version in case the package is outdated - or None otherwise and a flag indicating any outdated dependencies - @rtype tuple of (str or None, bool) - """ - args = ["runpip", package, "list", "--outdated", "--format", "json"] - if Preferences.getPip("PipSearchIndex"): - indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" - args += ["--index-url", indexUrl] - ok, output = self.runPipxProcess(args) - if not ok: - EricMessageBox.information( - None, - self.tr("Check Outdated Package"), - self.tr( - "<p>The status of package <b>{0}</b> could not be determined.</p>" - "<p>Reason: {1}</p>" - ).format(package, output), - ) - return None, False - - outdatedList = json.loads(output) - # check if the main package is in the list - for outdatedPackage in outdatedList: - if outdatedPackage["name"] == package: - return outdatedPackage["latest_version"], len(outdatedList) > 1 - - return None, bool(outdatedList) - def upgradePackage(self, package): """ Public method to upgrade the given package. @@ -543,3 +509,143 @@ res = dia.startProcess(self.__getPipxExecutable(), args) if res: dia.exec() + + ############################################################################ + ## Special methods based on 'runpip' + ############################################################################ + + def checkPackageOutdated(self, package): + """ + Public method to check, if a given package is outdated. + + @param package name of the package + @type str + @return tuple containing the latest version in case the package is outdated + or None otherwise and a flag indicating any outdated dependencies + @rtype tuple of (str or None, bool) + """ + args = ["runpip", package, "list", "--outdated", "--format", "json"] + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" + args += ["--index-url", indexUrl] + ok, output = self.runPipxProcess(args) + if not ok: + EricMessageBox.information( + None, + self.tr("Check Outdated Package"), + self.tr( + "<p>The status of package <b>{0}</b> could not be determined.</p>" + "<p>Reason: {1}</p>" + ).format(package, output), + ) + return None, False + + outdatedList = json.loads(output) + # check if the main package is in the list + for outdatedPackage in outdatedList: + if outdatedPackage["name"] == package: + return outdatedPackage["latest_version"], len(outdatedList) > 1 + + return None, bool(outdatedList) + + def __getPackageDependencies(self, package, uptodate=False, outdated=False): + """ + Private method to get a list of dependencies of a given package. + + @param package name of the package + @type str + @param uptodate DESCRIPTION (defaults to False) + @type TYPE (optional) + @param outdated DESCRIPTION (defaults to False) + @type TYPE (optional) + @return list of dictionaries as returned by 'pip' + @rtype list[dict[str: str]] + """ + if outdated: + args = ["runpip", package, "list", "--format", "json", "--outdated"] + elif uptodate: + args = ["runpip", package, "list", "--format", "json", "--uptodate"] + else: + args = ["runpip", package, "list", "--format", "json"] + if Preferences.getPip("PipSearchIndex"): + indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" + args += ["--index-url", indexUrl] + ok, output = self.runPipxProcess(args) + if not ok: + EricMessageBox.information( + None, + self.tr("Get Package Dependencies"), + self.tr( + "<p>The status of dependencies of package <b>{0}</b> could not" + " be determined.</p><p>Reason: {1}</p>" + ).format(package, output), + ) + return [] + + return json.loads(output) + + def getOutdatedPackageDependencies(self, package): + """ + Public method to get the list of outdated package dependencies. + + @param package name of the package + @type str + @return list of tuples containing the dependency name, version and latest + version + @rtype list of tuple of (str, str, str) + """ + outdatedList = self.__getPackageDependencies(package=package, outdated=True) + return [ + (d["name"], d["version"], d["latest_version"]) + for d in outdatedList + if d["name"] != package + ] + + def getUptodatePackageDependencies(self, package): + """ + Public method to get the list of up-to-date package dependencies. + + @param package name of the package + @type str + @return list of tuples containing the dependency name and version + @rtype list of tuple of (str, str) + """ + uptodateList = self.__getPackageDependencies(package=package, uptodate=True) + return [(d["name"], d["version"]) for d in uptodateList if d["name"] != package] + + def getAllPackageDependencies(self, package): + """ + Public method to get the list of package dependencies. + + @param package name of the package + @type str + @return list of tuples containing the dependency name and version + @rtype list of tuple of (str, str) + """ + dependenciesList = self.__getPackageDependencies(package=package) + return [ + (d["name"], d["version"]) for d in dependenciesList if d["name"] != package + ] + + def upgradePackageDependencies(self, package): + """ + Public method to upgrade the dependencies of the given package. + + @param package name of the package + @type str + """ + outdatedDependencies = [ + d[0] for d in self.getOutdatedPackageDependencies(package=package) + ] + args = [ + "runpip", + package, + "install", + "--upgrade", + "--prefer-binary", + ] + outdatedDependencies + + dia = PipxExecDialog(self.tr("Upgrade Dependencies")) + res = dia.startProcess(self.__getPipxExecutable(), args) + if res: + dia.exec()