diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/PipInterface/Pip.py --- a/src/eric7/PipInterface/Pip.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/PipInterface/Pip.py Wed Jul 13 14:55:47 2022 +0200 @@ -12,20 +12,18 @@ import json import contextlib -from PyQt6.QtCore import ( - pyqtSlot, QObject, QProcess, QUrl, QCoreApplication, QThread -) +from PyQt6.QtCore import pyqtSlot, QObject, QProcess, QUrl, QCoreApplication, QThread from PyQt6.QtWidgets import QDialog, QInputDialog, QLineEdit -from PyQt6.QtNetwork import ( - QNetworkAccessManager, QNetworkRequest, QNetworkReply -) +from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply from EricWidgets import EricMessageBox from EricWidgets.EricApplication import ericApp from EricNetwork.EricNetworkProxyFactory import proxyAuthenticationRequired + try: from EricNetwork.EricSslErrorHandler import EricSslErrorHandler + SSL_AVAILABLE = True except ImportError: SSL_AVAILABLE = False @@ -41,63 +39,66 @@ """ Class implementing the pip GUI logic. """ + DefaultPyPiUrl = "https://pypi.org" DefaultIndexUrlPypi = DefaultPyPiUrl + "/pypi" DefaultIndexUrlSimple = DefaultPyPiUrl + "/simple" DefaultIndexUrlSearch = DefaultPyPiUrl + "/search/" - + def __init__(self, parent=None): """ Constructor - + @param parent reference to the user interface object @type QObject """ super().__init__(parent) - + self.__ui = parent - + # attributes for the network objects self.__networkManager = QNetworkAccessManager(self) self.__networkManager.proxyAuthenticationRequired.connect( - proxyAuthenticationRequired) + proxyAuthenticationRequired + ) if SSL_AVAILABLE: self.__sslErrorHandler = EricSslErrorHandler(self) self.__networkManager.sslErrors.connect( - self.__sslErrorHandler.sslErrorsReply) + self.__sslErrorHandler.sslErrorsReply + ) self.__replies = [] - + self.__vulnerabilityChecker = PipVulnerabilityChecker(self, self) - + def getNetworkAccessManager(self): """ Public method to get a reference to the network access manager object. - + @return reference to the network access manager object @rtype QNetworkAccessManager """ return self.__networkManager - + def getVulnerabilityChecker(self): """ Public method to get a reference to the vulnerability checker object. - + @return reference to the vulnerability checker object @rtype PipVulnerabilityChecker """ return self.__vulnerabilityChecker - + ########################################################################## ## Methods below implement some utility functions ########################################################################## - + def runProcess(self, args, interpreter): """ Public method to execute the current pip with the given arguments. - + The selected pip executable is called with the given arguments and waited for its end. - + @param args list of command line arguments @type list of str @param interpreter path of the Python interpreter to be used @@ -107,7 +108,7 @@ @rtype tuple of (bool, str) """ ioEncoding = Preferences.getSystem("IOEncoding") - + process = QProcess() process.start(interpreter, args) procStarted = process.waitForStarted() @@ -115,27 +116,28 @@ finished = process.waitForFinished(30000) if finished: if process.exitCode() == 0: - output = str(process.readAllStandardOutput(), ioEncoding, - 'replace') + output = str(process.readAllStandardOutput(), ioEncoding, "replace") return True, output else: - return (False, - self.tr("python exited with an error ({0}).") - .format(process.exitCode())) + return ( + False, + self.tr("python exited with an error ({0}).").format( + process.exitCode() + ), + ) else: process.terminate() process.waitForFinished(2000) process.kill() process.waitForFinished(3000) - return False, self.tr("python did not finish within" - " 30 seconds.") - + return False, self.tr("python did not finish within" " 30 seconds.") + return False, self.tr("python could not be started.") - + def getUserConfig(self): """ Public method to get the name of the user configuration file. - + @return path of the user configuration file @rtype str """ @@ -143,24 +145,23 @@ # OS X: ~/Library/Application Support/pip/pip.conf # Windows: %APPDATA%\pip\pip.ini # Environment: $PIP_CONFIG_FILE - + with contextlib.suppress(KeyError): return os.environ["PIP_CONFIG_FILE"] - + if Globals.isWindowsPlatform(): config = os.path.join(os.environ["APPDATA"], "pip", "pip.ini") elif Globals.isMacPlatform(): - config = os.path.expanduser( - "~/Library/Application Support/pip/pip.conf") + config = os.path.expanduser("~/Library/Application Support/pip/pip.conf") else: config = os.path.expanduser("~/.config/pip/pip.conf") - + return config - + def getVirtualenvConfig(self, venvName): """ Public method to get the name of the virtualenv configuration file. - + @param venvName name of the environment to get config file path for @type str @return path of the virtualenv configuration file @@ -168,24 +169,24 @@ """ # Unix, OS X: $VIRTUAL_ENV/pip.conf # Windows: %VIRTUAL_ENV%\pip.ini - + pip = "pip.ini" if Globals.isWindowsPlatform() else "pip.conf" - + venvManager = ericApp().getObject("VirtualEnvManager") venvDirectory = ( os.path.dirname(self.getUserConfig()) - if venvManager.isGlobalEnvironment(venvName) else - venvManager.getVirtualenvDirectory(venvName) + if venvManager.isGlobalEnvironment(venvName) + else venvManager.getVirtualenvDirectory(venvName) ) - + config = os.path.join(venvDirectory, pip) if venvDirectory else "" - + return config - + def getProjectEnvironmentString(self): """ Public method to get the string for the project environment. - + @return string for the project environment @rtype str """ @@ -193,11 +194,11 @@ return self.tr("<project>") else: return "" - + def getVirtualenvInterpreter(self, venvName): """ Public method to get the interpreter for a virtual environment. - + @param venvName logical name for the virtual environment @type str @return interpreter path @@ -205,23 +206,27 @@ """ interpreter = ( ericApp().getObject("Project").getProjectInterpreter() - if venvName == self.getProjectEnvironmentString() else - ericApp().getObject("VirtualEnvManager") + if venvName == self.getProjectEnvironmentString() + else ericApp() + .getObject("VirtualEnvManager") .getVirtualenvInterpreter(venvName) ) if not interpreter: EricMessageBox.critical( None, self.tr("Interpreter for Virtual Environment"), - self.tr("""No interpreter configured for the selected""" - """ virtual environment.""")) - + self.tr( + """No interpreter configured for the selected""" + """ virtual environment.""" + ), + ) + return interpreter - + def getVirtualenvNames(self, noRemote=False, noConda=False): """ Public method to get a sorted list of virtual environment names. - + @param noRemote flag indicating to exclude environments for remote debugging @type bool @@ -231,13 +236,15 @@ @rtype list of str """ return sorted( - ericApp().getObject("VirtualEnvManager").getVirtualenvNames( - noRemote=noRemote, noConda=noConda)) - + ericApp() + .getObject("VirtualEnvManager") + .getVirtualenvNames(noRemote=noRemote, noConda=noConda) + ) + def installPip(self, venvName, userSite=False): """ Public method to install pip. - + @param venvName name of the environment to install pip into @type str @param userSite flag indicating an install to the user install @@ -247,91 +254,102 @@ interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return - - dia = PipDialog(self.tr('Install PIP')) + + dia = PipDialog(self.tr("Install PIP")) commands = ( [(interpreter, ["-m", "ensurepip", "--user"])] - if userSite else - [(interpreter, ["-m", "ensurepip"])] + if userSite + else [(interpreter, ["-m", "ensurepip"])] ) if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--upgrade"] + args = ["-m", "pip", "install", "--index-url", indexUrl, "--upgrade"] else: args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args.append("pip") commands.append((interpreter, args[:])) - + res = dia.startProcesses(commands) if res: dia.exec() - + @pyqtSlot() def repairPip(self, venvName): """ Public method to repair the pip installation. - + @param venvName name of the environment to install pip into @type str """ interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return - + # python -m pip install --ignore-installed pip if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--ignore-installed"] + args = [ + "-m", + "pip", + "install", + "--index-url", + indexUrl, + "--ignore-installed", + ] else: args = ["-m", "pip", "install", "--ignore-installed"] args.append("pip") - - dia = PipDialog(self.tr('Repair PIP')) + + dia = PipDialog(self.tr("Repair PIP")) res = dia.startProcess(interpreter, args) if res: dia.exec() - + def __checkUpgradePyQt(self, packages): """ Private method to check, if an upgrade of PyQt packages is attempted. - + @param packages list of packages to upgrade @type list of str @return flag indicating a PyQt upgrade @rtype bool """ pyqtPackages = [ - p for p in packages if p.lower() in [ - "pyqt6", "pyqt6-sip", "pyqt6-webengine", "pyqt6-charts", - "pyqt6-qscintilla", "pyqt6-qt6", "pyqt6-webengine-qt6", - "pyqt6-charts-qt6" + p + for p in packages + if p.lower() + in [ + "pyqt6", + "pyqt6-sip", + "pyqt6-webengine", + "pyqt6-charts", + "pyqt6-qscintilla", + "pyqt6-qt6", + "pyqt6-webengine-qt6", + "pyqt6-charts-qt6", ] ] return bool(pyqtPackages) - + def __checkUpgradeEric(self, packages): """ Private method to check, if an upgrade of the eric-ide package is attempted. - + @param packages list of packages to upgrade @type list of str @return flag indicating an eric-ide upgrade @rtype bool """ - ericPackages = [ - p for p in packages if p.lower() == "eric-ide" - ] + ericPackages = [p for p in packages if p.lower() == "eric-ide"] return bool(ericPackages) - + def upgradePackages(self, packages, venvName, userSite=False): """ Public method to upgrade the given list of packages. - + @param packages list of packages to upgrade @type list of str @param venvName name of the virtual environment to be used @@ -344,9 +362,10 @@ """ if not venvName: return False - + if self.getVirtualenvInterpreter(venvName) in ( - sys.executable, Globals.getPythonExecutable() + sys.executable, + Globals.getPythonExecutable(), ): upgradePyQt = self.__checkUpgradePyQt(packages) upgradeEric = self.__checkUpgradeEric(packages) @@ -358,34 +377,39 @@ self.__ui.upgradeEric() elif upgradePyQt: self.__ui.upgradePyQt() - return None # should not be reached; play it safe + return None # should not be reached; play it safe except AttributeError: return False - + interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return False - + if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" - args = ["-m", "pip", "install", "--index-url", indexUrl, - "--upgrade"] + args = ["-m", "pip", "install", "--index-url", indexUrl, "--upgrade"] else: args = ["-m", "pip", "install", "--upgrade"] if userSite: args.append("--user") args += packages - dia = PipDialog(self.tr('Upgrade Packages')) + dia = PipDialog(self.tr("Upgrade Packages")) res = dia.startProcess(interpreter, args) if res: dia.exec() return res - - def installPackages(self, packages, venvName="", userSite=False, - interpreter="", forceReinstall=False): + + def installPackages( + self, + packages, + venvName="", + userSite=False, + interpreter="", + forceReinstall=False, + ): """ Public method to install the given list of packages. - + @param packages list of packages to install @type list of str @param venvName name of the virtual environment to be used @@ -403,7 +427,7 @@ interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return - + if interpreter: if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" @@ -415,19 +439,20 @@ if forceReinstall: args.append("--force-reinstall") args += packages - dia = PipDialog(self.tr('Install Packages')) + dia = PipDialog(self.tr("Install Packages")) res = dia.startProcess(interpreter, args) if res: dia.exec() - + def installRequirements(self, venvName): """ Public method to install packages as given in a requirements file. - + @param venvName name of the virtual environment to be used @type str """ from .PipFileSelectionDialog import PipFileSelectionDialog + dlg = PipFileSelectionDialog(self, "requirements") if dlg.exec() == QDialog.DialogCode.Accepted: requirements, user = dlg.getData() @@ -435,7 +460,7 @@ interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return - + if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" args = ["-m", "pip", "install", "--index-url", indexUrl] @@ -444,15 +469,15 @@ if user: args.append("--user") args += ["--requirement", requirements] - dia = PipDialog(self.tr('Install Packages from Requirements')) + dia = PipDialog(self.tr("Install Packages from Requirements")) res = dia.startProcess(interpreter, args) if res: dia.exec() - + def uninstallPackages(self, packages, venvName): """ Public method to uninstall the given list of packages. - + @param packages list of packages to uninstall @type list of str @param venvName name of the virtual environment to be used @@ -462,37 +487,36 @@ """ res = False if packages and venvName: - from UI.DeleteFilesConfirmationDialog import ( - DeleteFilesConfirmationDialog - ) + from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog + dlg = DeleteFilesConfirmationDialog( self.parent(), self.tr("Uninstall Packages"), - self.tr( - "Do you really want to uninstall these packages?"), - packages) + self.tr("Do you really want to uninstall these packages?"), + packages, + ) if dlg.exec() == QDialog.DialogCode.Accepted: interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return False args = ["-m", "pip", "uninstall", "--yes"] + packages - dia = PipDialog(self.tr('Uninstall Packages')) + dia = PipDialog(self.tr("Uninstall Packages")) res = dia.startProcess(interpreter, args) if res: dia.exec() return res - + def uninstallRequirements(self, venvName): """ Public method to uninstall packages as given in a requirements file. - + @param venvName name of the virtual environment to be used @type str """ if venvName: from .PipFileSelectionDialog import PipFileSelectionDialog - dlg = PipFileSelectionDialog(self, "requirements", - install=False) + + dlg = PipFileSelectionDialog(self, "requirements", install=False) if dlg.exec() == QDialog.DialogCode.Accepted: requirements, _user = dlg.getData() if requirements and os.path.exists(requirements): @@ -501,79 +525,79 @@ reqs = f.read().splitlines() except OSError: return - + from UI.DeleteFilesConfirmationDialog import ( - DeleteFilesConfirmationDialog + DeleteFilesConfirmationDialog, ) + dlg = DeleteFilesConfirmationDialog( self.parent(), self.tr("Uninstall Packages"), - self.tr( - "Do you really want to uninstall these packages?"), - reqs) + self.tr("Do you really want to uninstall these packages?"), + reqs, + ) if dlg.exec() == QDialog.DialogCode.Accepted: interpreter = self.getVirtualenvInterpreter(venvName) if not interpreter: return - - args = ["-m", "pip", "uninstall", "--requirement", - requirements] - dia = PipDialog( - self.tr('Uninstall Packages from Requirements')) + + args = ["-m", "pip", "uninstall", "--requirement", requirements] + dia = PipDialog(self.tr("Uninstall Packages from Requirements")) res = dia.startProcess(interpreter, args) if res: dia.exec() - + def getIndexUrl(self): """ Public method to get the index URL for PyPI. - + @return index URL for PyPI @rtype str """ indexUrl = ( Preferences.getPip("PipSearchIndex") + "/simple" - if Preferences.getPip("PipSearchIndex") else - Pip.DefaultIndexUrlSimple + if Preferences.getPip("PipSearchIndex") + else Pip.DefaultIndexUrlSimple ) - + return indexUrl - + def getIndexUrlPypi(self): """ Public method to get the index URL for PyPI API calls. - + @return index URL for XML RPC calls @rtype str """ indexUrl = ( Preferences.getPip("PipSearchIndex") + "/pypi" - if Preferences.getPip("PipSearchIndex") else - Pip.DefaultIndexUrlPypi + if Preferences.getPip("PipSearchIndex") + else Pip.DefaultIndexUrlPypi ) - + return indexUrl - + def getIndexUrlSearch(self): """ Public method to get the index URL for PyPI API calls. - + @return index URL for XML RPC calls @rtype str """ indexUrl = ( Preferences.getPip("PipSearchIndex") + "/search/" - if Preferences.getPip("PipSearchIndex") else - Pip.DefaultIndexUrlSearch + if Preferences.getPip("PipSearchIndex") + else Pip.DefaultIndexUrlSearch ) - + return indexUrl - - def getInstalledPackages(self, envName, localPackages=True, - notRequired=False, usersite=False): + + def getInstalledPackages( + self, envName, localPackages=True, notRequired=False, usersite=False + ): """ Public method to get the list of installed packages. - + @param envName name of the environment to get the packages for @type str @param localPackages flag indicating to get local packages only @@ -588,12 +612,13 @@ @rtype list of tuple of (str, str) """ packages = [] - + if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: args = [ - "-m", "pip", + "-m", + "pip", "list", "--format=json", ] @@ -603,36 +628,41 @@ args.append("--not-required") if usersite: args.append("--user") - + if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" args += ["--index-url", indexUrl] - + proc = QProcess() proc.start(interpreter, args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ).strip() try: jsonList = json.loads(output) except Exception: jsonList = [] - + for package in jsonList: if isinstance(package, dict): - packages.append(( - package["name"], - package["version"], - )) - + packages.append( + ( + package["name"], + package["version"], + ) + ) + return packages - - def getOutdatedPackages(self, envName, localPackages=True, - notRequired=False, usersite=False): + + def getOutdatedPackages( + self, envName, localPackages=True, notRequired=False, usersite=False + ): """ Public method to get the list of outdated packages. - + @param envName name of the environment to get the packages for @type str @param localPackages flag indicating to get local packages only @@ -648,12 +678,13 @@ @rtype list of tuple of (str, str, str) """ packages = [] - + if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: args = [ - "-m", "pip", + "-m", + "pip", "list", "--outdated", "--format=json", @@ -664,36 +695,40 @@ args.append("--not-required") if usersite: args.append("--user") - + if Preferences.getPip("PipSearchIndex"): indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" args += ["--index-url", indexUrl] - + proc = QProcess() proc.start(interpreter, args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ).strip() 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.append( + ( + package["name"], + package["version"], + package["latest_version"], + ) + ) + return packages - + def checkPackageOutdated(self, packageStart, envName): """ Public method to check, if a group of packages is outdated. - + @param packageStart start string for package names to be checked (case insensitive) @type str @@ -705,20 +740,20 @@ @rtype tuple of (bool, (str, str, str)) """ filteredPackages = [] - + if bool(envName) and bool(packageStart): packages = self.getOutdatedPackages(envName) filterStr = packageStart.lower() filteredPackages = [ - p for p in packages - if p[0].lower().startswith(filterStr)] - + p for p in packages if p[0].lower().startswith(filterStr) + ] + return bool(filteredPackages), filteredPackages - + def getPackageDetails(self, name, version): """ Public method to get package details using the PyPI JSON interface. - + @param name package name @type str @param version package version @@ -727,38 +762,37 @@ @rtype dict """ result = {} - + if name and version: - url = "{0}/{1}/{2}/json".format( - self.getIndexUrlPypi(), name, version) + url = "{0}/{1}/{2}/json".format(self.getIndexUrlPypi(), name, version) request = QNetworkRequest(QUrl(url)) reply = self.__networkManager.get(request) while not reply.isFinished(): QCoreApplication.processEvents() QThread.msleep(100) - + reply.deleteLater() if reply.error() == QNetworkReply.NetworkError.NoError: - data = str(reply.readAll(), - Preferences.getSystem("IOEncoding"), - 'replace') + data = str( + reply.readAll(), Preferences.getSystem("IOEncoding"), "replace" + ) with contextlib.suppress(Exception): result = json.loads(data) - + return result - + def getPackageVersions(self, name): """ Public method to get a list of versions available for the given package. - + @param name package name @type str @return list of available versions @rtype list of str """ result = [] - + if name: url = "{0}/{1}/json".format(self.getIndexUrlPypi(), name) request = QNetworkRequest(QUrl(url)) @@ -766,23 +800,24 @@ while not reply.isFinished(): QCoreApplication.processEvents() QThread.msleep(100) - + reply.deleteLater() if reply.error() == QNetworkReply.NetworkError.NoError: - dataStr = str(reply.readAll(), - Preferences.getSystem("IOEncoding"), - 'replace') + dataStr = str( + reply.readAll(), Preferences.getSystem("IOEncoding"), "replace" + ) with contextlib.suppress(Exception): data = json.loads(dataStr) result = list(data["releases"].keys()) - + return result - - def getFrozenPackages(self, envName, localPackages=True, usersite=False, - requirement=None): + + def getFrozenPackages( + self, envName, localPackages=True, usersite=False, requirement=None + ): """ Public method to get the list of package specifiers to freeze them. - + @param envName name of the environment to get the package specifiers for @type str @@ -798,12 +833,13 @@ @rtype list of str """ specifiers = [] - + if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: args = [ - "-m", "pip", + "-m", + "pip", "freeze", ] if localPackages: @@ -813,22 +849,23 @@ if requirement and os.path.exists(requirement): args.append("--requirement") args.append(requirement) - + success, output = self.runProcess(args, interpreter) if success and output: - specifiers = [spec.strip() for spec in output.splitlines() - if spec.strip()] - + specifiers = [ + spec.strip() for spec in output.splitlines() if spec.strip() + ] + return specifiers - + ####################################################################### ## Cache handling methods below ####################################################################### - + def showCacheInfo(self, venvName): """ Public method to show some information about the pip cache. - + @param venvName name of the virtual environment to be used @type str """ @@ -840,11 +877,11 @@ res = dia.startProcess(interpreter, args, showArgs=False) if res: dia.exec() - + def cacheList(self, venvName): """ Public method to list files contained in the pip cache. - + @param venvName name of the virtual environment to be used @type str """ @@ -855,22 +892,22 @@ None, self.tr("List Cached Files"), self.tr("Enter a file pattern (empty for all):"), - QLineEdit.EchoMode.Normal) - + QLineEdit.EchoMode.Normal, + ) + if ok: args = ["-m", "pip", "cache", "list"] if pattern.strip(): args.append(pattern.strip()) dia = PipDialog(self.tr("List Cached Files")) - res = dia.startProcess(interpreter, args, - showArgs=False) + res = dia.startProcess(interpreter, args, showArgs=False) if res: dia.exec() - + def cacheRemove(self, venvName): """ Public method to remove files from the pip cache. - + @param venvName name of the virtual environment to be used @type str """ @@ -881,20 +918,20 @@ None, self.tr("Remove Cached Files"), self.tr("Enter a file pattern:"), - QLineEdit.EchoMode.Normal) - + QLineEdit.EchoMode.Normal, + ) + if ok and pattern.strip(): args = ["-m", "pip", "cache", "remove", pattern.strip()] dia = PipDialog(self.tr("Remove Cached Files")) - res = dia.startProcess(interpreter, args, - showArgs=False) + res = dia.startProcess(interpreter, args, showArgs=False) if res: dia.exec() - + def cachePurge(self, venvName): """ Public method to remove all files from the pip cache. - + @param venvName name of the virtual environment to be used @type str """ @@ -904,25 +941,28 @@ ok = EricMessageBox.yesNo( None, self.tr("Purge Cache"), - self.tr("Do you really want to purge the pip cache? All" - " files need to be downloaded again.")) + self.tr( + "Do you really want to purge the pip cache? All" + " files need to be downloaded again." + ), + ) if ok: args = ["-m", "pip", "cache", "purge"] dia = PipDialog(self.tr("Purge Cache")) - res = dia.startProcess(interpreter, args, - showArgs=False) + res = dia.startProcess(interpreter, args, showArgs=False) if res: dia.exec() - + ####################################################################### ## Dependency tree handling methods below ####################################################################### - - def getDependencyTree(self, envName, localPackages=True, usersite=False, - reverse=False): + + def getDependencyTree( + self, envName, localPackages=True, usersite=False, reverse=False + ): """ Public method to get the dependency tree of installed packages. - + @param envName name of the environment to get the packages for @type str @param localPackages flag indicating to get the tree for local @@ -939,11 +979,12 @@ @rtype list of dict """ dependencies = [] - + if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: from . import pipdeptree + with open(pipdeptree.__file__, "r") as f: content = f.read() args = [ @@ -957,27 +998,28 @@ args.append("--user-only") if reverse: args.append("--reverse") - + proc = QProcess() proc.start(interpreter, args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ).strip() with contextlib.suppress(json.JSONDecodeError): dependencies = json.loads(output) - + return dependencies - + ####################################################################### ## License handling methods below ####################################################################### - - def getLicenses(self, envName, localPackages=True, usersite=False, - summary=False): + + def getLicenses(self, envName, localPackages=True, usersite=False, summary=False): """ Public method to get the licenses per package for a given environment. - + @param envName name of the environment to get the licenses for @type str @param localPackages flag indicating to get the licenses for local @@ -994,11 +1036,12 @@ @rtype dict """ licenses = [] - + if envName: interpreter = self.getVirtualenvInterpreter(envName) if interpreter: from . import piplicenses + with open(piplicenses.__file__, "r") as f: content = f.read() args = [ @@ -1017,23 +1060,25 @@ args.append("--user-only") if summary: args.append("--summary") - + proc = QProcess() proc.start(interpreter, args) if proc.waitForStarted(15000) and proc.waitForFinished(30000): - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() + output = str( + proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + "replace", + ).strip() with contextlib.suppress(json.JSONDecodeError): licenses = json.loads(output) - + return licenses - + def getLicensesSummary(self, envName, localPackages=True, usersite=False): """ Public method to get a summary of licenses found in a given environment. - + @param envName name of the environment to get the licenses summary for @type str @param localPackages flag indicating to get the licenses summary for @@ -1046,5 +1091,6 @@ packages @rtype dict """ - return self.getLicenses(envName, localPackages=localPackages, - usersite=usersite, summary=True) + return self.getLicenses( + envName, localPackages=localPackages, usersite=usersite, summary=True + )