5 |
5 |
6 """ |
6 """ |
7 Module implementing the Pyramid project support. |
7 Module implementing the Pyramid project support. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
|
11 |
|
12 try: |
|
13 import configparser |
|
14 except ImportError: |
|
15 str = unicode # __IGNORE_WARNING__ |
|
16 import ConfigParser as configparser # __IGNORE_WARNING__ |
|
17 |
|
18 import os |
10 import os |
19 import re |
11 import re |
20 import sys |
12 import configparser |
21 |
13 |
22 from PyQt5.QtCore import QObject, QFileInfo, QTimer, QUrl |
14 from PyQt5.QtCore import QObject, QFileInfo, QTimer, QUrl |
23 from PyQt5.QtGui import QDesktopServices |
15 from PyQt5.QtGui import QDesktopServices |
24 from PyQt5.QtWidgets import QMenu, QDialog, QInputDialog, QLineEdit |
16 from PyQt5.QtWidgets import QMenu, QDialog, QInputDialog, QLineEdit |
25 from PyQt5.QtCore import QProcess as QProcessPyQt |
17 from PyQt5.QtCore import QProcess as QProcessPyQt |
451 def projectOpenedHooks(self): |
443 def projectOpenedHooks(self): |
452 """ |
444 """ |
453 Public method to add our hook methods. |
445 Public method to add our hook methods. |
454 """ |
446 """ |
455 if self.__e5project.getProjectType() == "Pyramid": |
447 if self.__e5project.getProjectType() == "Pyramid": |
456 self.__formsBrowser = \ |
448 self.__formsBrowser = ( |
457 e5App().getObject("ProjectBrowser").getProjectBrowser("forms") |
449 e5App().getObject("ProjectBrowser") |
|
450 .getProjectBrowser("forms")) |
458 self.__formsBrowser.addHookMethodAndMenuEntry( |
451 self.__formsBrowser.addHookMethodAndMenuEntry( |
459 "newForm", self.newForm, self.tr("New template...")) |
452 "newForm", self.newForm, self.tr("New template...")) |
460 |
453 |
461 self.__e5project.projectLanguageAddedByCode.connect( |
454 self.__e5project.projectLanguageAddedByCode.connect( |
462 self.__projectLanguageAdded) |
455 self.__projectLanguageAdded) |
463 self.__translationsBrowser = \ |
456 self.__translationsBrowser = ( |
464 e5App().getObject("ProjectBrowser")\ |
457 e5App().getObject("ProjectBrowser") |
465 .getProjectBrowser("translations") |
458 .getProjectBrowser("translations")) |
466 self.__translationsBrowser.addHookMethodAndMenuEntry( |
459 self.__translationsBrowser.addHookMethodAndMenuEntry( |
467 "extractMessages", self.extractMessages, |
460 "extractMessages", self.extractMessages, |
468 self.tr("Extract Messages")) |
461 self.tr("Extract Messages")) |
469 self.__translationsBrowser.addHookMethodAndMenuEntry( |
462 self.__translationsBrowser.addHookMethodAndMenuEntry( |
470 "releaseAll", self.compileCatalogs, |
463 "releaseAll", self.compileCatalogs, |
654 """ |
647 """ |
655 Private method to test, if a detected command file is suitable for the |
648 Private method to test, if a detected command file is suitable for the |
656 given Python variant. |
649 given Python variant. |
657 |
650 |
658 @param variant Python variant to test for |
651 @param variant Python variant to test for |
659 @type str (one of Python2 or Python3) |
652 @type str |
660 @param line0 first line of the executable |
653 @param line0 first line of the executable |
661 @type str |
654 @type str |
662 @return flag indicating a suitable command |
655 @return flag indicating a suitable command |
663 @rtype bool |
656 @rtype bool |
664 """ |
657 """ |
665 assert variant in ("Python2", "Python3") |
|
666 |
|
667 l0 = line0.lower() |
658 l0 = line0.lower() |
668 ok = (variant.lower() in l0 or |
659 ok = (variant.lower() in l0 or |
669 "{0}.".format(variant[-1]) in l0) |
660 "{0}.".format(variant[-1]) in l0) |
670 if variant == "Python2": |
661 ok |= "pypy3" in l0 |
671 ok |= "python3" not in l0 and "python" in l0 |
|
672 ok |= "pypy2" in l0 |
|
673 ok |= "pypy3" not in l0 and "pypy" in l0 |
|
674 else: |
|
675 ok |= "pypy3" in l0 |
|
676 |
662 |
677 return ok |
663 return ok |
678 |
664 |
679 def __getVirtualEnvironment(self, language=""): |
665 def __getVirtualEnvironment(self, language=""): |
680 """ |
666 """ |
681 Private method to get the path of the virtual environment. |
667 Private method to get the path of the virtual environment. |
682 |
668 |
683 @param language Python variant to get the virtual environment |
669 @param language Python variant to get the virtual environment |
684 for (string, one of '', 'Python2' or 'Python3') |
670 for (string, one of '' or 'Python3') |
685 @return path of the virtual environment (string) |
671 @return path of the virtual environment (string) |
686 """ |
672 """ |
687 if not language: |
673 if not language: |
688 language = self.__e5project.getProjectLanguage() |
674 language = self.__e5project.getProjectLanguage() |
689 if self.__virtualEnvManager: |
675 if self.__virtualEnvManager: |
690 if language == "Python3": |
676 if language == "Python3": |
691 venvName = self.__plugin.getPreferences( |
677 venvName = self.__plugin.getPreferences( |
692 "VirtualEnvironmentNamePy3") |
678 "VirtualEnvironmentNamePy3") |
693 elif language == "Python2": |
|
694 venvName = self.__plugin.getPreferences( |
|
695 "VirtualEnvironmentNamePy2") |
|
696 else: |
679 else: |
697 venvName = "" |
680 venvName = "" |
698 if venvName: |
681 if venvName: |
699 virtEnv = self.__virtualEnvManager.getVirtualenvDirectory( |
682 virtEnv = self.__virtualEnvManager.getVirtualenvDirectory( |
700 venvName) |
683 venvName) |
704 venvName)) |
687 venvName)) |
705 if virtEnv.endswith(("Scripts", "bin")): |
688 if virtEnv.endswith(("Scripts", "bin")): |
706 virtEnv = os.path.dirname(virtEnv) |
689 virtEnv = os.path.dirname(virtEnv) |
707 else: |
690 else: |
708 virtEnv = "" |
691 virtEnv = "" |
709 else: |
692 |
710 # backward compatibility |
|
711 if language == "Python3": |
|
712 virtEnv = self.__plugin.getPreferences("VirtualEnvironmentPy3") |
|
713 elif language == "Python2": |
|
714 virtEnv = self.__plugin.getPreferences("VirtualEnvironmentPy2") |
|
715 else: |
|
716 virtEnv = "" |
|
717 if virtEnv and not os.path.exists(virtEnv): |
693 if virtEnv and not os.path.exists(virtEnv): |
718 virtEnv = "" |
694 virtEnv = "" |
719 return virtEnv |
695 return virtEnv # __IGNORE_WARNING_M834__ |
720 |
696 |
721 def __getDebugEnvironment(self, language=""): |
697 def __getDebugEnvironment(self, language=""): |
722 """ |
698 """ |
723 Private method to get the path of the debugger environment. |
699 Private method to get the path of the debugger environment. |
724 |
700 |
725 @param language Python variant to get the debugger environment |
701 @param language Python variant to get the debugger environment |
726 for (string, one of '', 'Python2' or 'Python3') |
702 for (string, one of '' or 'Python3') |
727 @return path of the debugger environment (string) |
703 @return path of the debugger environment (string) |
728 """ |
704 """ |
729 if not language: |
705 if not language: |
730 language = self.__e5project.getProjectLanguage() |
706 language = self.__e5project.getProjectLanguage() |
731 if self.__virtualEnvManager: |
707 if self.__virtualEnvManager: |
732 debugEnv = self.__getVirtualEnvironment(language) |
708 debugEnv = self.__getVirtualEnvironment(language) |
733 if not debugEnv: |
709 if not debugEnv: |
734 if language == "Python3": |
710 if language == "Python3": |
735 venvName = Preferences.getDebugger("Python3VirtualEnv") |
711 venvName = Preferences.getDebugger("Python3VirtualEnv") |
736 elif language == "Python2": |
|
737 venvName = Preferences.getDebugger("Python2VirtualEnv") |
|
738 else: |
712 else: |
739 venvName = "" |
713 venvName = "" |
740 |
714 |
741 if venvName: |
715 if venvName: |
742 debugEnv = self.__virtualEnvManager.getVirtualenvDirectory( |
716 return self.__virtualEnvManager.getVirtualenvDirectory( |
743 venvName) |
717 venvName) |
744 else: |
718 |
745 debugEnv = "" |
719 return "" |
746 else: |
|
747 # backward compatibility |
|
748 if language == "Python3": |
|
749 debugEnv = Preferences.getDebugger("Python3Interpreter") |
|
750 if not debugEnv and sys.version_info[0] == 3: |
|
751 debugEnv = sys.executable |
|
752 elif language == "Python2": |
|
753 debugEnv = Preferences.getDebugger("PythonInterpreter") |
|
754 if not debugEnv and sys.version_info[0] == 2: |
|
755 debugEnv = sys.executable |
|
756 else: |
|
757 debugEnv = sys.executable |
|
758 debugEnv = os.path.dirname(debugEnv) |
|
759 if debugEnv and not os.path.exists(debugEnv): |
|
760 if (language == "Python3" and sys.version_info[0] == 3) or \ |
|
761 (language == "Python2" and sys.version_info[0] == 2): |
|
762 debugEnv = sys.exec_prefix |
|
763 else: |
|
764 debugEnv = "" |
|
765 return debugEnv |
|
766 |
720 |
767 def getPyramidCommand(self, cmd, language=""): |
721 def getPyramidCommand(self, cmd, language=""): |
768 """ |
722 """ |
769 Public method to build a Pyramid command. |
723 Public method to build a Pyramid command. |
770 |
724 |
771 @param cmd command (string) |
725 @param cmd command (string) |
772 @param language Python variant to get the virtual environment |
726 @param language Python variant to get the virtual environment |
773 for (string, one of '', 'Python2' or 'Python3') |
727 for (string, one of '' or 'Python3') |
774 @return full pyramid command (string) |
728 @return full pyramid command (string) |
775 """ |
729 """ |
776 if not language: |
730 if not language: |
777 language = self.__e5project.getProjectLanguage() |
731 language = self.__e5project.getProjectLanguage() |
778 |
732 |
812 venvName = self.__plugin.getPreferences( |
766 venvName = self.__plugin.getPreferences( |
813 "VirtualEnvironmentNamePy3") |
767 "VirtualEnvironmentNamePy3") |
814 if not venvName: |
768 if not venvName: |
815 # if none configured, use the global one |
769 # if none configured, use the global one |
816 venvName = Preferences.getDebugger("Python3VirtualEnv") |
770 venvName = Preferences.getDebugger("Python3VirtualEnv") |
817 elif language == "Python2": |
|
818 venvName = self.__plugin.getPreferences( |
|
819 "VirtualEnvironmentNamePy2") |
|
820 if not venvName: |
|
821 # if none configured, use the global one |
|
822 venvName = Preferences.getDebugger("Python2VirtualEnv") |
|
823 else: |
771 else: |
824 venvName = "" |
772 venvName = "" |
825 if venvName: |
773 if venvName: |
826 python = self.__virtualEnvManager.getVirtualenvInterpreter( |
774 return self.__virtualEnvManager.getVirtualenvInterpreter( |
827 venvName) |
775 venvName) |
828 else: |
776 |
829 python = "" |
777 return "" |
830 else: |
|
831 # backward compatibility |
|
832 virtualEnv = self.__getVirtualEnvironment() |
|
833 if isWindowsPlatform(): |
|
834 pythonExeList = ["python.exe", "pypy.exe"] |
|
835 if not virtualEnv: |
|
836 virtualEnv = self.__getDebugEnvironment(language) |
|
837 for pythonExe in pythonExeList: |
|
838 for python in [ |
|
839 os.path.join(virtualEnv, "Scripts", pythonExe), |
|
840 os.path.join(virtualEnv, "bin", pythonExe), |
|
841 os.path.join(virtualEnv, pythonExe) |
|
842 ]: |
|
843 if os.path.exists(python): |
|
844 break |
|
845 else: |
|
846 python = "" |
|
847 |
|
848 if python: |
|
849 break |
|
850 else: |
|
851 python = "" |
|
852 else: |
|
853 if language == "Python3": |
|
854 pythonExeList = ["python3", "pypy3"] |
|
855 elif language == "Python2": |
|
856 pythonExeList = ["python2", "pypy2"] |
|
857 if not virtualEnv: |
|
858 virtualEnv = self.__getDebugEnvironment(language) |
|
859 |
|
860 for pythonExe in pythonExeList: |
|
861 for python in [ |
|
862 os.path.join(virtualEnv, "bin", pythonExe), |
|
863 # omit the version character |
|
864 os.path.join(virtualEnv, "bin", pythonExe)[:-1], |
|
865 os.path.join(virtualEnv, pythonExe), |
|
866 # omit the version character |
|
867 os.path.join(virtualEnv, pythonExe)[:-1], |
|
868 ]: |
|
869 if os.path.exists(python): |
|
870 break |
|
871 else: |
|
872 python = "" |
|
873 |
|
874 if python: |
|
875 break |
|
876 else: |
|
877 python = "" |
|
878 |
|
879 return python |
|
880 |
778 |
881 def __pyramidInfo(self): |
779 def __pyramidInfo(self): |
882 """ |
780 """ |
883 Private slot to show some info about Pyramid. |
781 Private slot to show some info about Pyramid. |
884 """ |
782 """ |
921 f = open(cmd, 'r', encoding="utf-8") |
819 f = open(cmd, 'r', encoding="utf-8") |
922 lines = f.read().splitlines() |
820 lines = f.read().splitlines() |
923 f.close() |
821 f.close() |
924 for line in lines: |
822 for line in lines: |
925 if line.startswith("__requires__"): |
823 if line.startswith("__requires__"): |
926 # sample: __requires__ = 'pyramid==1.4' |
824 ## sample: __requires__ = 'pyramid==1.4' |
927 vers = line.strip().split()[-1][1:-1].split("==")[1] |
825 vers = line.strip().split()[-1][1:-1].split("==")[1] |
928 self.__pyramidVersion = vers |
826 self.__pyramidVersion = vers |
929 except (IOError, OSError): |
827 except (IOError, OSError): |
930 self.__pyramidVersion = "" |
828 self.__pyramidVersion = "" |
931 |
829 |
1191 args.append("--log-file=server.log") |
1091 args.append("--log-file=server.log") |
1192 args.append("--reload") |
1092 args.append("--reload") |
1193 args.append(os.path.join(projectPath, "development.ini")) |
1093 args.append(os.path.join(projectPath, "development.ini")) |
1194 |
1094 |
1195 if isWindowsPlatform(): |
1095 if isWindowsPlatform(): |
1196 serverProcStarted, pid = \ |
1096 serverProcStarted, pid = QProcess.startDetached( |
1197 QProcess.startDetached(args[0], args[1:], projectPath) |
1097 args[0], args[1:], projectPath) |
1198 else: |
1098 else: |
1199 if self.__serverProc is not None: |
1099 if self.__serverProc is not None: |
1200 self.__serverProcFinished() |
1100 self.__serverProcFinished() |
1201 |
1101 |
1202 self.__serverProc = QProcess() |
1102 self.__serverProc = QProcess() |
1218 |
1118 |
1219 def __serverProcFinished(self): |
1119 def __serverProcFinished(self): |
1220 """ |
1120 """ |
1221 Private slot connected to the finished signal. |
1121 Private slot connected to the finished signal. |
1222 """ |
1122 """ |
1223 if self.__serverProc is not None and \ |
1123 if ( |
1224 self.__serverProc.state() != QProcess.NotRunning: |
1124 self.__serverProc is not None and |
|
1125 self.__serverProc.state() != QProcess.NotRunning |
|
1126 ): |
1225 self.__serverProc.terminate() |
1127 self.__serverProc.terminate() |
1226 QTimer.singleShot(2000, self.__serverProc.kill) |
1128 QTimer.singleShot(2000, self.__serverProc.kill) |
1227 self.__serverProc.waitForFinished(3000) |
1129 self.__serverProc.waitForFinished(3000) |
1228 self.__serverProc = None |
1130 self.__serverProc = None |
1229 |
1131 |
1277 return |
1179 return |
1278 |
1180 |
1279 args = Utilities.parseOptionString(consoleCmd) |
1181 args = Utilities.parseOptionString(consoleCmd) |
1280 args[0] = Utilities.getExecutablePath(args[0]) |
1182 args[0] = Utilities.getExecutablePath(args[0]) |
1281 args.append(self.getPyramidCommand("pshell")) |
1183 args.append(self.getPyramidCommand("pshell")) |
1282 language = self.__e5project.getProjectLanguage() |
1184 consoleType = self.__plugin.getPreferences("Python3ConsoleType") |
1283 if language == "Python2": |
|
1284 consoleType = self.__plugin.getPreferences( |
|
1285 "Python2ConsoleType") |
|
1286 else: |
|
1287 consoleType = self.__plugin.getPreferences( |
|
1288 "Python3ConsoleType") |
|
1289 args.append("--python-shell={0}".format(consoleType)) |
1185 args.append("--python-shell={0}".format(consoleType)) |
1290 args.append(os.path.join(projectPath, "development.ini")) |
1186 args.append(os.path.join(projectPath, "development.ini")) |
1291 |
1187 |
1292 self.__adjustWorkingDirectory(args, projectPath) |
1188 self.__adjustWorkingDirectory(args, projectPath) |
1293 started, pid = QProcess.startDetached( |
1189 started, pid = QProcess.startDetached( |
1352 title, |
1248 title, |
1353 self.tr('No current Pyramid project selected or no Pyramid' |
1249 self.tr('No current Pyramid project selected or no Pyramid' |
1354 ' project created yet. Aborting...')) |
1250 ' project created yet. Aborting...')) |
1355 return |
1251 return |
1356 |
1252 |
1357 from .DistributionTypeSelectionDialog import \ |
1253 from .DistributionTypeSelectionDialog import ( |
1358 DistributionTypeSelectionDialog |
1254 DistributionTypeSelectionDialog |
|
1255 ) |
1359 |
1256 |
1360 dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui) |
1257 dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui) |
1361 if dlg.exec_() == QDialog.Accepted: |
1258 if dlg.exec_() == QDialog.Accepted: |
1362 formats = dlg.getFormats() |
1259 formats = dlg.getFormats() |
1363 cmd = self.getPythonCommand() |
1260 cmd = self.getPythonCommand() |
1536 pattern = os.path.normpath(pattern) |
1433 pattern = os.path.normpath(pattern) |
1537 pattern = pattern.replace("%language%", "(.*?)") |
1434 pattern = pattern.replace("%language%", "(.*?)") |
1538 pattern = pattern.replace('\\', '\\\\') |
1435 pattern = pattern.replace('\\', '\\\\') |
1539 match = re.search(pattern, filename) |
1436 match = re.search(pattern, filename) |
1540 if match is not None: |
1437 if match is not None: |
1541 loc = match.group(1) |
1438 return match.group(1) |
1542 return loc |
1439 |
1543 else: |
1440 return None |
1544 loc = None |
|
1545 else: |
|
1546 loc = None |
|
1547 |
|
1548 return loc |
|
1549 |
1441 |
1550 def __normalizeList(self, filenames): |
1442 def __normalizeList(self, filenames): |
1551 """ |
1443 """ |
1552 Private method to normalize a list of file names. |
1444 Private method to normalize a list of file names. |
1553 |
1445 |