src/eric7/PipInterface/Pip.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9218
71cf3979a6c9
child 9260
eb19dcb8d852
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
+        )

eric ide

mercurial