src/eric7/PipInterface/Pip.py

branch
eric7-maintenance
changeset 10659
43ead32943ca
parent 10534
783d835d7fe4
parent 10641
42536596df9e
child 10694
f46c1e224e8a
--- a/src/eric7/PipInterface/Pip.py	Sun Mar 03 10:39:56 2024 +0100
+++ b/src/eric7/PipInterface/Pip.py	Tue Apr 02 10:00:22 2024 +0200
@@ -11,8 +11,11 @@
 import functools
 import json
 import os
+import re
 import sys
 
+import tomlkit
+
 from PyQt6.QtCore import QCoreApplication, QObject, QProcess, QThread, QUrl, pyqtSlot
 from PyQt6.QtNetwork import (
     QNetworkAccessManager,
@@ -545,6 +548,61 @@
             if res:
                 dia.exec()
 
+    def installPyprojectDependencies(self, venvName):
+        """
+        Public method to install the dependencies listed in a pyproject.toml file.
+
+        @param venvName name of the virtual environment to be used
+        @type str
+        """
+        from .PipFileSelectionDialog import PipFileSelectionDialog
+
+        dlg = PipFileSelectionDialog(self, "pyproject")
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            pyproject, user = dlg.getData()
+            if pyproject and os.path.exists(pyproject):
+                try:
+                    with open(pyproject, "r", encoding="utf-8") as f:
+                        data = tomlkit.load(f)
+                    dependencies = data.get("project", {}).get("dependencies", [])
+                    if not dependencies:
+                        EricMessageBox.warning(
+                            None,
+                            self.tr("Install 'pyproject' Dependencies"),
+                            self.tr(
+                                "The selected 'pyproject.toml' file does not contain"
+                                " a 'project.dependencies' section. Aborting..."
+                            ),
+                        )
+                        return
+                except (OSError, tomlkit.exceptions.ParseError) as err:
+                    EricMessageBox.warning(
+                        None,
+                        self.tr("Install 'pyproject' Dependencies"),
+                        self.tr(
+                            "<p>The selected 'pyproject.toml' file could not be read."
+                            "</p><p>Reason: {0}</p>"
+                        ).format(str(err)),
+                    )
+                    return
+
+                interpreter = self.getVirtualenvInterpreter(venvName)
+                if not interpreter:
+                    return
+
+                if Preferences.getPip("PipSearchIndex"):
+                    indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
+                    args = ["-m", "pip", "install", "--index-url", indexUrl]
+                else:
+                    args = ["-m", "pip", "install"]
+                if user:
+                    args.append("--user")
+                args += dependencies
+                dia = PipDialog(self.tr("Install Packages from 'pyproject.toml'"))
+                res = dia.startProcess(interpreter, args)
+                if res:
+                    dia.exec()
+
     def uninstallPackages(self, packages, venvName):
         """
         Public method to uninstall the given list of packages.
@@ -606,12 +664,85 @@
                         if not interpreter:
                             return
 
-                        args = ["-m", "pip", "uninstall", "--requirement", requirements]
+                        args = [
+                            "-m",
+                            "pip",
+                            "uninstall",
+                            "--yes",
+                            "--requirement",
+                            requirements,
+                        ]
                         dia = PipDialog(self.tr("Uninstall Packages from Requirements"))
                         res = dia.startProcess(interpreter, args)
                         if res:
                             dia.exec()
 
+    def uninstallPyprojectDependencies(self, venvName):
+        """
+        Public method to uninstall the dependencies listed in a pyproject.toml file.
+
+        @param venvName name of the virtual environment to be used
+        @type str
+        """
+        from .PipFileSelectionDialog import PipFileSelectionDialog
+
+        if venvName:
+            dlg = PipFileSelectionDialog(self, "pyproject", install=False)
+            if dlg.exec() == QDialog.DialogCode.Accepted:
+                pyproject, _user = dlg.getData()
+                if pyproject and os.path.exists(pyproject):
+                    try:
+                        with open(pyproject, "r", encoding="utf-8") as f:
+                            data = tomlkit.load(f)
+                        dependencies = data.get("project", {}).get("dependencies", [])
+                        if not dependencies:
+                            EricMessageBox.warning(
+                                None,
+                                self.tr("Uninstall 'pyproject' Dependencies"),
+                                self.tr(
+                                    "The selected 'pyproject.toml' file does not"
+                                    " contain a 'project.dependencies' section."
+                                    " Aborting..."
+                                ),
+                            )
+                            return
+                    except (OSError, tomlkit.exceptions.ParseError) as err:
+                        EricMessageBox.warning(
+                            None,
+                            self.tr("Uninstall 'pyproject' Dependencies"),
+                            self.tr(
+                                "<p>The selected 'pyproject.toml' file could not be"
+                                " read. </p><p>Reason: {0}</p>"
+                            ).format(str(err)),
+                        )
+                        return
+
+                    # Do not uninstall pip.
+                    pipre = re.compile(r"^pip\s*(~=|==|!=|<=|>=|<|>|===)")
+                    for dependency in dependencies:
+                        if pipre.search(dependency):
+                            dependencies.remove(dependency)  # noqa: M569
+                            break
+
+                    dlg = DeleteFilesConfirmationDialog(
+                        self.parent(),
+                        self.tr("Uninstall Packages"),
+                        self.tr("Do you really want to uninstall these packages?"),
+                        dependencies,
+                    )
+                    if dlg.exec() == QDialog.DialogCode.Accepted:
+                        interpreter = self.getVirtualenvInterpreter(venvName)
+                        if not interpreter:
+                            return
+
+                        args = ["-m", "pip", "uninstall", "--yes"] + dependencies
+                        dia = PipDialog(
+                            self.tr("Uninstall Packages from 'pyproject.toml'")
+                        )
+                        res = dia.startProcess(interpreter, args)
+                        if res:
+                            dia.exec()
+
     def getIndexUrl(self):
         """
         Public method to get the index URL for PyPI.

eric ide

mercurial