ProjectPyramid/Project.py

changeset 56
c7adc68350dd
parent 48
c313efdb01de
child 57
e654970c913e
--- a/ProjectPyramid/Project.py	Sat Sep 28 13:34:57 2013 +0200
+++ b/ProjectPyramid/Project.py	Sun Oct 27 22:43:17 2013 +0100
@@ -7,12 +7,21 @@
 Module implementing the Pyramid project support.
 """
 
+from __future__ import unicode_literals    # __IGNORE_WARNING__
+
+try:
+    import configparser
+except ImportError:
+    str = unicode    # __IGNORE_WARNING__
+    import ConfigParser as configparser    # __IGNORE_WARNING__
+
 import os
-import configparser
 import re
+import sys
 
-from PyQt4.QtCore import QObject, QFileInfo, QProcess, QTimer, QUrl
+from PyQt4.QtCore import QObject, QFileInfo, QTimer, QUrl
 from PyQt4.QtGui import QMenu, QDialog, QInputDialog, QDesktopServices, QLineEdit
+from PyQt4.QtCore import QProcess as QProcessPyQt
 
 from E5Gui.E5Application import e5App
 from E5Gui import E5MessageBox, E5FileDialog
@@ -20,6 +29,7 @@
 
 from .PyramidDialog import PyramidDialog
 
+import Preferences
 import Utilities
 from Globals import isWindowsPlatform
 import UI.PixmapCache
@@ -32,6 +42,41 @@
     pass
 
 
+class QProcess(QProcessPyQt):
+    """
+    Class transforming the call arguments in case of gnome-terminal.
+    """
+    def start(self, cmd, args=[], mode=QProcessPyQt.ReadWrite):
+        """
+        Starts the given program (cmd) in a new process, if none is already
+        running, passing the command line arguments in argss.
+        
+        @param cmd start the given program cmd (string)
+        @keyparam args list of parameters (list of strings)
+        @keyparam mode access mode (QIODevice.OpenMode)
+        """
+        if cmd.endswith('gnome-terminal') and args[0] == '-e':
+            args = ['-e', ' '.join(args[1:])]
+        
+        super(QProcess, self).start(cmd, args, mode)
+    
+    @staticmethod
+    def startDetached(cmd, args=[], path=''):
+        """
+        Starts the given program (cmd) in a new process, if none is already
+        running, passing the command line arguments in argss.
+        
+        @param cmd start the given program cmd (string)
+        @keyparam args list of parameters (list of strings)
+        @keyparam path new working directory (string)
+        @return tuple of successful start and process id (boolean, integer)
+        """
+        if cmd.endswith('gnome-terminal') and args[0] == '-e':
+            args = ['-e', ' '.join(args[1:])]
+        
+        return QProcessPyQt.startDetached(cmd, args, path)
+
+
 class Project(QObject):
     """
     Class implementing the Pyramid project support.
@@ -43,7 +88,7 @@
         @param plugin reference to the plugin object
         @param parent parent (QObject)
         """
-        super().__init__(parent)
+        super(Project, self).__init__(parent)
         
         self.__plugin = plugin
         self.__ui = parent
@@ -519,24 +564,30 @@
                 if fullCmd != cmd:
                     variants.append(variant)
             else:
-                try:
-                    fullCmds = Utilities.getExecutablePaths(cmd)
-                except AttributeError:
-                    fullCmds = self.__getExecutablePaths(cmd)
-                for fullCmd in fullCmds:
+                if isWindowsPlatform():
+                    debugEnv = self.__getDebugEnvironment(variant)
+                    fullCmd = os.path.join(debugEnv, "Scripts", cmd)
+                    if variant.lower() in fullCmd.lower():
+                        variants.append(variant)
+                else:
                     try:
-                        f = open(fullCmd, 'r', encoding='utf-8')
-                        l0 = f.readline()
-                        f.close()
-                    except (IOError, OSError):
-                        l0 = ""
-                    if variant.lower() in l0.lower() or \
-                       "{0}.".format(variant[-1]) in l0 or \
-                       (variant == "Python2" and \
-                        "python3" not in l0.lower() and \
-                        "python" in l0.lower()):
-                        variants.append(variant)
-                        break
+                        fullCmds = Utilities.getExecutablePaths(cmd)
+                    except AttributeError:
+                        fullCmds = self.__getExecutablePaths(cmd)
+                    for fullCmd in fullCmds:
+                        try:
+                            f = open(fullCmd, 'r', encoding='utf-8')
+                            l0 = f.readline()
+                            f.close()
+                        except (IOError, OSError):
+                            l0 = ""
+                        if variant.lower() in l0.lower() or \
+                            "{0}.".format(variant[-1]) in l0 or \
+                            (variant == "Python2" and \
+                            "python3" not in l0.lower() and \
+                            "python" in l0.lower()):
+                                variants.append(variant)
+                                break
         
         return variants
     
@@ -559,7 +610,28 @@
         if virtEnv and not os.path.exists(virtEnv):
             virtEnv = ""
         return virtEnv
-    
+
+    def __getDebugEnvironment(self, language=""):
+        """
+        Private method to get the path of the debugger environment.
+        
+        @param language Python variant to get the debugger environment
+            for (string, one of '', 'Python2' or 'Python3')
+        @return path of the debugger environment (string)
+        """
+        if not language:
+            language = self.__e5project.getProjectLanguage()
+        if language == "Python3":
+            debugEnv = Preferences.getDebugger("Python3Interpreter")
+        elif language == "Python2":
+            debugEnv = Preferences.getDebugger("PythonInterpreter")
+        else:
+            debugEnv = sys.executable
+        debugEnv = os.path.dirname(debugEnv)
+        if debugEnv and not os.path.exists(debugEnv):
+            debugEnv = sys.exec_prefix
+        return debugEnv
+
     def getPyramidCommand(self, cmd, language=""):
         """
         Public method to build a Pyramid command.
@@ -570,17 +642,20 @@
         @return full pyramid command (string)
         """
         virtualEnv = self.__getVirtualEnvironment(language)
-        if virtualEnv:
-            if isWindowsPlatform():
-                cmd = os.path.join(virtualEnv, "Scripts", cmd)
-            else:
-                fullCmd = os.path.join(virtualEnv, "bin", cmd)
-                if not os.path.exists(fullCmd):
-                    fullCmd = os.path.join(virtualEnv, "local", "bin", cmd)
-                    if not os.path.exists(fullCmd):
-                        # fall back to just cmd
-                        fullCmd = cmd
-                cmd = fullCmd
+        if isWindowsPlatform() and not virtualEnv:
+            virtualEnv = self.__getDebugEnvironment(language)
+        if isWindowsPlatform():
+            cmd = os.path.join(virtualEnv, "Scripts", cmd + '.exe')
+        else:
+            fullCmds = [
+                os.path.join(virtualEnv, "bin", cmd),
+                os.path.join(virtualEnv, "local", "bin", cmd),
+                Utilities.getExecutablePath(cmd),
+                cmd     # fall back to just cmd
+            ]
+            for cmd in fullCmds:
+                if os.path.exists(cmd):
+                    break
         return cmd
     
     def getPythonCommand(self):
@@ -589,25 +664,29 @@
         
         @return python command (string)
         """
-        python = "python"
+        language = self.__e5project.getProjectLanguage()
+        pythonExe = "python"
         if isWindowsPlatform():
-            python += ".exe"
+            pythonExe += ".exe"
         else:
-            language = self.__e5project.getProjectLanguage()
             if language == "Python3":
-                python = "python3"
+                pythonExe = "python3"
             elif language == "Python2":
-                python = "python2"
+                pythonExe = "python2"
         virtualEnv = self.__getVirtualEnvironment()
+        if isWindowsPlatform() and not virtualEnv:
+            virtualEnv = self.__getDebugEnvironment(language)
         if virtualEnv:
             if isWindowsPlatform():
-                python = os.path.join(virtualEnv, "Scripts", python)
+                python = os.path.join(virtualEnv, "Scripts", pythonExe)
                 if not os.path.exists(python):
-                    python = os.path.join(virtualEnv, python)
+                    python = os.path.join(virtualEnv, pythonExe)
             else:
-                python = os.path.join(virtualEnv, "bin", python)
+                python = os.path.join(virtualEnv, "bin", pythonExe)
                 if not os.path.exists(python):
                     python = python[:-1]    # omit the version character
+        else:
+            python = pythonExe
         
         return python
     
@@ -643,6 +722,8 @@
         """
         if not self.__pyramidVersion:
             cmd = self.getPyramidCommand("pcreate")
+            if isWindowsPlatform():
+                cmd = os.path.join(os.path.dirname(cmd), "pcreate-script.py")
             try:
                 f = open(cmd, 'r', encoding="utf-8")
                 lines = f.read().splitlines()
@@ -800,10 +881,17 @@
         if self.__currentProject is None:
             self.__e5project.pdata["TRANSLATIONPATTERN"] = []
         else:
+            lowerProject = self.__project().lower()
             config = configparser.ConfigParser()
             config.read(os.path.join(self.__projectPath(), "setup.cfg"))
-            outputDir = config.get("init_catalog", "output_dir")
-            domain = config.get("init_catalog", "domain")
+            try:
+                outputDir = config.get("init_catalog", "output_dir")
+            except (configparser.NoOptionError, configparser.NoSectionError):
+                outputDir = '{0}/locale'.format(lowerProject)
+            try:
+                domain = config.get("init_catalog", "domain")
+            except (configparser.NoOptionError, configparser.NoSectionError):
+                domain = lowerProject
             self.__e5project.pdata["TRANSLATIONPATTERN"] = [
                 os.path.join(project, outputDir, "%language%",
                     "LC_MESSAGES", "{0}.po".format(domain))
@@ -909,7 +997,10 @@
         
         config = configparser.ConfigParser()
         config.read(os.path.join(projectPath, "development.ini"))
-        port = config.get("server:main", "port", fallback="6543")
+        try:
+            port = config.get("server:main", "port")
+        except (configparser.NoOptionError, configparser.NoSectionError):
+            port = "8080"
         url = QUrl("http://localhost:{0}".format(port))
         res = QDesktopServices.openUrl(url)
         if not res:
@@ -979,6 +1070,8 @@
         res = dia.startProcess(cmd, args, wd)
         if res:
             dia.exec_()
+            initCmd = self.__getInitDbCommand()
+            self.initializeDbAct.setEnabled(os.path.exists(initCmd))
     
     ##################################################################
     ## slots below implement distribution functions
@@ -1164,8 +1257,13 @@
         @return extracted locale (string) or None
         """
         if self.__e5project.pdata["TRANSLATIONPATTERN"]:
-            pattern = self.__e5project.pdata["TRANSLATIONPATTERN"][0]\
-                .replace("%language%", "(.*?)")
+            # On Windows, path typically contains backslashes. This leads
+            # to an invalid seach pattern '...\(' because the opening bracked
+            # will be escaped.
+            pattern = self.__e5project.pdata["TRANSLATIONPATTERN"][0]
+            pattern = os.path.normpath(pattern)
+            pattern = pattern.replace("%language%", "(.*?)")
+            pattern = pattern.replace('\\', '\\\\')
             match = re.search(pattern, filename)
             if match is not None:
                 loc = match.group(1)
@@ -1221,6 +1319,28 @@
                 self.trUtf8('No current Pyramid project selected or no Pyramid project'
                             ' created yet. Aborting...'))
             return
+
+        config = configparser.ConfigParser()
+        config.read(os.path.join(projectPath, "setup.cfg"))
+        try:
+            potFile = config.get("extract_messages", "output_file")
+        except configparser.NoSectionError:
+            E5MessageBox.warning(self.__ui,
+                title,
+                self.trUtf8('No setup.cfg found or no "extract_messages"'
+                            ' section found in setup.cfg.'))
+            return
+        except configparser.NoOptionError:
+            E5MessageBox.warning(self.__ui,
+                title,
+                self.trUtf8('No "output_file" option found in setup.cfg.'))
+            return
+        
+        try:
+            path = os.path.join(projectPath, os.path.dirname(potFile))
+            os.makedirs(path)
+        except OSError:
+            pass
         
         cmd = self.getPythonCommand()
         args = []
@@ -1232,25 +1352,8 @@
         res = dia.startProcess(cmd, args, projectPath)
         if res:
             dia.exec_()
+            self.__e5project.appendFile(os.path.join(projectPath, potFile))
             
-            config = configparser.ConfigParser()
-            config.read(os.path.join(projectPath, "setup.cfg"))
-            potFile = config.get("extract_messages", "output_file")
-            if potFile:
-                self.__e5project.appendFile(os.path.join(projectPath, potFile))
-            else:
-                try:
-                    lowerProject = self.__project().lower()
-                except PyramidNoProjectSelectedException:
-                    E5MessageBox.warning(self.__ui,
-                        title,
-                        self.trUtf8('No current Pyramid project selected or no Pyramid'
-                                    ' project created yet. Aborting...'))
-                    return
-                
-                self.__e5project.appendFile(os.path.join(
-                    projectPath, lowerProject, "locale", "%s.pot" % lowerProject))
-    
     def __projectLanguageAdded(self, code):
         """
         Private slot handling the addition of a new language.
@@ -1280,7 +1383,7 @@
         if res:
             dia.exec_()
             
-            langFile = self.__e4project.pdata["TRANSLATIONPATTERN"][0]\
+            langFile = self.__e5project.pdata["TRANSLATIONPATTERN"][0]\
                 .replace("%language%", code)
             self.__e5project.appendFile(langFile)
     

eric ide

mercurial