9 |
9 |
10 import contextlib |
10 import contextlib |
11 import functools |
11 import functools |
12 import json |
12 import json |
13 import os |
13 import os |
|
14 import re |
14 import sys |
15 import sys |
|
16 |
|
17 import tomlkit |
15 |
18 |
16 from PyQt6.QtCore import QCoreApplication, QObject, QProcess, QThread, QUrl, pyqtSlot |
19 from PyQt6.QtCore import QCoreApplication, QObject, QProcess, QThread, QUrl, pyqtSlot |
17 from PyQt6.QtNetwork import ( |
20 from PyQt6.QtNetwork import ( |
18 QNetworkAccessManager, |
21 QNetworkAccessManager, |
19 QNetworkProxyFactory, |
22 QNetworkProxyFactory, |
543 dia = PipDialog(self.tr("Install Project")) |
546 dia = PipDialog(self.tr("Install Project")) |
544 res = dia.startProcess(interpreter, args) |
547 res = dia.startProcess(interpreter, args) |
545 if res: |
548 if res: |
546 dia.exec() |
549 dia.exec() |
547 |
550 |
|
551 def installPyprojectDependencies(self, venvName): |
|
552 """ |
|
553 Public method to install the dependencies listed in a pyproject.toml file. |
|
554 |
|
555 @param venvName name of the virtual environment to be used |
|
556 @type str |
|
557 """ |
|
558 from .PipFileSelectionDialog import PipFileSelectionDialog |
|
559 |
|
560 dlg = PipFileSelectionDialog(self, "pyproject") |
|
561 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
562 pyproject, user = dlg.getData() |
|
563 if pyproject and os.path.exists(pyproject): |
|
564 try: |
|
565 with open(pyproject, "r", encoding="utf-8") as f: |
|
566 data = tomlkit.load(f) |
|
567 dependencies = data.get("project", {}).get("dependencies", []) |
|
568 if not dependencies: |
|
569 EricMessageBox.warning( |
|
570 None, |
|
571 self.tr("Install 'pyproject' Dependencies"), |
|
572 self.tr( |
|
573 "The selected 'pyproject.toml' file does not contain" |
|
574 " a 'project.dependencies' section. Aborting..." |
|
575 ), |
|
576 ) |
|
577 return |
|
578 except (tomlkit.exceptions.ParseError, OSError) as err: |
|
579 EricMessageBox.warning( |
|
580 None, |
|
581 self.tr("Install 'pyproject' Dependencies"), |
|
582 self.tr( |
|
583 "<p>The selected 'pyproject.toml' file could not be read." |
|
584 "</p><p>Reason: {0}</p>" |
|
585 ).format(str(err)), |
|
586 ) |
|
587 return |
|
588 |
|
589 interpreter = self.getVirtualenvInterpreter(venvName) |
|
590 if not interpreter: |
|
591 return |
|
592 |
|
593 if Preferences.getPip("PipSearchIndex"): |
|
594 indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" |
|
595 args = ["-m", "pip", "install", "--index-url", indexUrl] |
|
596 else: |
|
597 args = ["-m", "pip", "install"] |
|
598 if user: |
|
599 args.append("--user") |
|
600 args += dependencies |
|
601 dia = PipDialog(self.tr("Install Packages from 'pyproject.toml'")) |
|
602 res = dia.startProcess(interpreter, args) |
|
603 if res: |
|
604 dia.exec() |
|
605 |
548 def uninstallPackages(self, packages, venvName): |
606 def uninstallPackages(self, packages, venvName): |
549 """ |
607 """ |
550 Public method to uninstall the given list of packages. |
608 Public method to uninstall the given list of packages. |
551 |
609 |
552 @param packages list of packages to uninstall |
610 @param packages list of packages to uninstall |
604 if dlg.exec() == QDialog.DialogCode.Accepted: |
662 if dlg.exec() == QDialog.DialogCode.Accepted: |
605 interpreter = self.getVirtualenvInterpreter(venvName) |
663 interpreter = self.getVirtualenvInterpreter(venvName) |
606 if not interpreter: |
664 if not interpreter: |
607 return |
665 return |
608 |
666 |
609 args = ["-m", "pip", "uninstall", "--requirement", requirements] |
667 args = [ |
|
668 "-m", |
|
669 "pip", |
|
670 "uninstall", |
|
671 "--yes", |
|
672 "--requirement", |
|
673 requirements, |
|
674 ] |
610 dia = PipDialog(self.tr("Uninstall Packages from Requirements")) |
675 dia = PipDialog(self.tr("Uninstall Packages from Requirements")) |
|
676 res = dia.startProcess(interpreter, args) |
|
677 if res: |
|
678 dia.exec() |
|
679 |
|
680 def uninstallPyprojectDependencies(self, venvName): |
|
681 """ |
|
682 Public method to uninstall the dependencies listed in a pyproject.toml file. |
|
683 |
|
684 @param venvName name of the virtual environment to be used |
|
685 @type str |
|
686 """ |
|
687 from .PipFileSelectionDialog import PipFileSelectionDialog |
|
688 |
|
689 if venvName: |
|
690 dlg = PipFileSelectionDialog(self, "pyproject", install=False) |
|
691 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
692 pyproject, _user = dlg.getData() |
|
693 if pyproject and os.path.exists(pyproject): |
|
694 try: |
|
695 with open(pyproject, "r", encoding="utf-8") as f: |
|
696 data = tomlkit.load(f) |
|
697 dependencies = data.get("project", {}).get("dependencies", []) |
|
698 if not dependencies: |
|
699 EricMessageBox.warning( |
|
700 None, |
|
701 self.tr("Uninstall 'pyproject' Dependencies"), |
|
702 self.tr( |
|
703 "The selected 'pyproject.toml' file does not" |
|
704 " contain a 'project.dependencies' section." |
|
705 " Aborting..." |
|
706 ), |
|
707 ) |
|
708 return |
|
709 except (tomlkit.exceptions.ParseError, OSError) as err: |
|
710 EricMessageBox.warning( |
|
711 None, |
|
712 self.tr("Uninstall 'pyproject' Dependencies"), |
|
713 self.tr( |
|
714 "<p>The selected 'pyproject.toml' file could not be" |
|
715 " read. </p><p>Reason: {0}</p>" |
|
716 ).format(str(err)), |
|
717 ) |
|
718 return |
|
719 |
|
720 # Do not uninstall pip. |
|
721 pipre = re.compile(r"^pip\s*(~=|==|!=|<=|>=|<|>|===)") |
|
722 for dependency in dependencies: |
|
723 if pipre.search(dependency): |
|
724 dependencies.remove(dependency) |
|
725 break |
|
726 |
|
727 dlg = DeleteFilesConfirmationDialog( |
|
728 self.parent(), |
|
729 self.tr("Uninstall Packages"), |
|
730 self.tr("Do you really want to uninstall these packages?"), |
|
731 dependencies, |
|
732 ) |
|
733 if dlg.exec() == QDialog.DialogCode.Accepted: |
|
734 interpreter = self.getVirtualenvInterpreter(venvName) |
|
735 if not interpreter: |
|
736 return |
|
737 |
|
738 args = ["-m", "pip", "uninstall", "--yes"] + dependencies |
|
739 dia = PipDialog( |
|
740 self.tr("Uninstall Packages from 'pyproject.toml'") |
|
741 ) |
611 res = dia.startProcess(interpreter, args) |
742 res = dia.startProcess(interpreter, args) |
612 if res: |
743 if res: |
613 dia.exec() |
744 dia.exec() |
614 |
745 |
615 def getIndexUrl(self): |
746 def getIndexUrl(self): |