ProjectPyramid/Project.py

changeset 138
72ebb74aa42d
parent 133
8f183975895d
child 140
a891fb543d28
equal deleted inserted replaced
137:be24be92ed0f 138:72ebb74aa42d
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,
618 @return list of supported Python variants (list of strings) 611 @return list of supported Python variants (list of strings)
619 """ 612 """
620 variants = [] 613 variants = []
621 cmd = "pcreate" 614 cmd = "pcreate"
622 615
623 for variant in 'Python2', 'Python3': 616 for variant in ['Python3']:
624 virtEnv = self.__getVirtualEnvironment(variant) 617 virtEnv = self.__getVirtualEnvironment(variant)
625 if virtEnv: 618 if virtEnv:
626 fullCmd = self.getPyramidCommand(cmd, variant) 619 fullCmd = self.getPyramidCommand(cmd, variant)
627 if fullCmd != cmd: 620 if fullCmd != cmd:
628 variants.append(variant) 621 variants.append(variant)
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
1040 @return list of projects (list of string) 938 @return list of projects (list of string)
1041 """ 939 """
1042 projects = [] 940 projects = []
1043 ppath = self.__e5project.getProjectPath() 941 ppath = self.__e5project.getProjectPath()
1044 for entry in os.listdir(ppath): 942 for entry in os.listdir(ppath):
1045 if entry[0] not in "._" and \ 943 if (
1046 os.path.isdir(os.path.join(ppath, entry)): 944 entry[0] not in "._" and
945 os.path.isdir(os.path.join(ppath, entry))
946 ):
1047 projects.append(entry) 947 projects.append(entry)
1048 return projects 948 return projects
1049 949
1050 def __selectProject(self): 950 def __selectProject(self):
1051 """ 951 """
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
1634 """ 1526 """
1635 Private slot handling the addition of a new language. 1527 Private slot handling the addition of a new language.
1636 1528
1637 @param code language code of the new language (string) 1529 @param code language code of the new language (string)
1638 """ 1530 """
1639 title = self.tr("Initializing message catalog for '{0}'")\ 1531 title = self.tr(
1640 .format(code) 1532 "Initializing message catalog for '{0}'").format(code)
1641 try: 1533 try:
1642 projectPath = self.__projectPath() 1534 projectPath = self.__projectPath()
1643 except PyramidNoProjectSelectedException: 1535 except PyramidNoProjectSelectedException:
1644 E5MessageBox.warning( 1536 E5MessageBox.warning(
1645 self.__ui, 1537 self.__ui,
1661 " successfully.")) 1553 " successfully."))
1662 res = dia.startProcess(cmd, args, projectPath) 1554 res = dia.startProcess(cmd, args, projectPath)
1663 if res: 1555 if res:
1664 dia.exec_() 1556 dia.exec_()
1665 1557
1666 langFile = self.__e5project.getTranslationPattern()\ 1558 langFile = self.__e5project.getTranslationPattern().replace(
1667 .replace("%language%", code) 1559 "%language%", code)
1668 self.__e5project.appendFile(langFile) 1560 self.__e5project.appendFile(langFile)
1669 1561
1670 def compileCatalogs(self, filenames): 1562 def compileCatalogs(self, filenames):
1671 """ 1563 """
1672 Public method to compile the message catalogs. 1564 Public method to compile the message catalogs.

eric ide

mercurial