PluginCxFreeze.py

changeset 47
986f27beaad4
parent 44
8b51b5efd1ae
child 50
ed85ec1358f0
--- a/PluginCxFreeze.py	Sun Apr 28 18:09:10 2013 +0200
+++ b/PluginCxFreeze.py	Sun Jul 07 20:40:48 2013 +0200
@@ -7,8 +7,10 @@
 Module implementing the CxFreeze plugin.
 """
 
+from __future__ import unicode_literals    # __IGNORE_WARNING__
+
 import os
-import sys
+import platform
 
 from PyQt4.QtCore import QObject, QTranslator, QCoreApplication
 from PyQt4.QtGui import QDialog
@@ -24,7 +26,7 @@
 author = "Detlev Offenbach <detlev@die-offenbachs.de>"
 autoactivate = True
 deactivateable = True
-version = "5.1.2"
+version = "5.2.0"
 className = "CxFreezePlugin"
 packageName = "CxFreeze"
 shortDescription = "Show the CxFreeze dialogs."
@@ -35,88 +37,116 @@
 # End-of-Header
 
 error = ""
+exePy2 = []
+exePy3 = []
 
-def exeDisplayData():
+def exeDisplayDataList():
     """
     Public method to support the display of some executable info.
     
     @return dictionary containing the data to query the presence of
         the executable
     """
+    dataList = []
     data = {
-        "programEntry"      : True, 
+        "programEntry"      : True,
         "header"            : QCoreApplication.translate("CxFreezePlugin",
-                                "Packagers - cx_freeze"), 
-        "exe"               : 'dummyfreeze', 
-        "versionCommand"    : '--version', 
-        "versionStartsWith" : 'dummyfreeze', 
-        "versionPosition"   : -1, 
-        "version"           : "", 
-        "versionCleanup"    : None, 
+                                "Packagers - cx_freeze"),
+        "exe"               : 'dummyfreeze',
+        "versionCommand"    : '--version',
+        "versionStartsWith" : 'dummyfreeze',
+        "versionPosition"   : -1,
+        "version"           : "",
+        "versionCleanup"    : None,
     }
     
-    exe = _findExecutable()
-    if exe:
-        data["exe"] = exe
-        data["versionStartsWith"] = "cxfreeze"
-    
-    return data
+    if _checkProgram():
+        for exePath in (exePy2+exePy3):
+            data["exe"] = exePath
+            data["versionStartsWith"] = "cxfreeze"
+            dataList.append(data.copy())
+    else:
+        dataList.append(data)
+    return dataList
 
-def _findExecutable():
+def _findExecutable(majorVersion):
+    """
+    Restricted function to determine the names of the executable.
+    
+    @param majorVersion major python version of the executables (int)
+    @return names of the executable (list)
     """
-    Restricted function to determine the name of the executable.
+    # Determine Python Version
+    if majorVersion == 3:
+        minorVersions = range(5)
+    elif majorVersion == 2:
+        minorVersions = range(5, 9)
+    else:
+        return []
     
-    @return name of the executable (string)
-    """
+    executables = set()
     if Utilities.isWindowsPlatform():
         #
         # Windows
         #
-        exe = 'cxfreeze.bat'
-        if Utilities.isinpath(exe):
-            return exe
         try:
-            #only since python 3.2
-            import sysconfig
-            scripts = sysconfig.get_path('scripts','nt')
-            return os.path.join(scripts, exe)
+            import winreg
         except ImportError:
+            import _winreg as winreg    # __IGNORE_WARNING__
+        
+        def getExePath(branch, access, versionStr):
             try:
-                import winreg
-            except ImportError:
-                # give up ...
+                software = winreg.OpenKey(branch, 'Software', 0, access)
+                python = winreg.OpenKey(software, 'Python', 0, access)
+                pcore = winreg.OpenKey(python, 'PythonCore', 0, access)
+                version = winreg.OpenKey(pcore, versionStr, 0, access)
+                installpath = winreg.QueryValue(version, 'InstallPath')
+                exe = os.path.join(installpath, 'Scripts', 'cxfreeze.bat')
+                if os.access(exe, os.X_OK):
+                    return exe
+            except WindowsError:        # __IGNORE_WARNING__
                 return None
+            return None
+        
+        for minorVersion in minorVersions:
+            versionStr = '{0}.{1}'.format(majorVersion, minorVersion)
+            exePath = getExePath(winreg.HKEY_CURRENT_USER,
+                winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
+                
+            if exePath is not None:
+                executables.add(exePath)
+            exePath = getExePath(winreg.HKEY_LOCAL_MACHINE,
+                winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
             
-            def getExePath(branch):
-                version = str(sys.version_info.major) + '.' + \
-                          str(sys.version_info.minor)
-                try:
-                    software = winreg.OpenKey(branch, 'Software')
-                    python = winreg.OpenKey(software, 'Python')
-                    pcore = winreg.OpenKey(python, 'PythonCore')
-                    version = winreg.OpenKey(pcore, version)
-                    installpath = winreg.QueryValue(version, 'InstallPath')
-                    return os.path.join(installpath, 'Scripts', exe)
-                except WindowsError:        # __IGNORE_WARNING__
-                    return None
-            
-            exePath = getExePath(winreg.HKEY_CURRENT_USER)
-            if not exePath:
-                exePath = getExePath(winreg.HKEY_LOCAL_MACHINE)
-            return exePath
+            # Even on Intel 64-bit machines it's 'AMD64'
+            if platform.machine() == 'AMD64':
+                if exePath is not None:
+                    executables.add(exePath)
+                exePath = getExePath(winreg.HKEY_CURRENT_USER,
+                    winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
+                
+                if exePath is not None:
+                    executables.add(exePath)
+                exePath = getExePath(winreg.HKEY_LOCAL_MACHINE,
+                    winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
+                
+                if exePath is not None:
+                    executables.add(exePath)
     else:
         #
         # Linux, Unix ...
         cxfreezeScript = 'cxfreeze'
         scriptSuffixes = ["",
-                          "-python{0}".format(sys.version[:1]),
-                          "-python{0}".format(sys.version[:3])]
+                    "-python{0}".format(majorVersion)]
+        for minorVersion in minorVersions:
+            scriptSuffixes.append(
+                    "-python{0}.{1}".format(majorVersion, minorVersion))
         # There could be multiple cxfreeze executables in the path
         # e.g. for different python variants
         path = Utilities.getEnvironmentEntry('PATH')
         # environment variable not defined
         if path is None:
-            return None
+            return  []
         
         # step 1: determine possible candidates
         exes = []
@@ -127,27 +157,34 @@
                 if os.access(exe, os.X_OK):
                     exes.append(exe)
         
-        # step 2: determine the Python 3 variant
-        found = False
+        # step 2: determine the Python variant
         if Utilities.isMacPlatform():
             checkStrings = ["Python.framework/Versions/3".lower(),
                             "python3"]
         else:
             checkStrings = ["python3"]
+        
+        _exePy2 = set()
+        _exePy3 = set()
         for exe in exes:
             try:
                 f = open(exe, "r")
                 line0 = f.readline()
                 for checkStr in checkStrings:
                     if checkStr in line0.lower():
-                        found = True
+                        _exePy3.add(exe)
                         break
+                else:
+                        _exePy2.add(exe)
             finally:
                 f.close()
-            if found:
-                return exe
+        
+        executables = _exePy3 if majorVersion == 3 else _exePy2
     
-    return None
+    # sort items, the probably newest topmost
+    executables = list(executables)
+    executables.sort(reverse=True)
+    return executables
 
 def _checkProgram():
     """
@@ -155,15 +192,17 @@
     
     @return flag indicating availability (boolean)
     """
-    global error
+    global error, exePy2, exePy3
     
-    if _findExecutable() is None:
+    exePy2 = _findExecutable(2)
+    exePy3 = _findExecutable(3)
+    if (exePy2+exePy3) == []:
         error = QCoreApplication.translate("CxFreezePlugin",
             "The cxfreeze executable could not be found.")
         return False
     else:
         return True
-_checkProgram()
+
 
 class CxFreezePlugin(QObject):
     """
@@ -201,7 +240,8 @@
         if not _checkProgram():
             return None, False
         
-        menu = e5App().getObject("Project").getMenu("Packagers")
+        project = e5App().getObject("Project")
+        menu = project.getMenu("Packagers")
         if menu:
             self.__projectAct = E5Action(self.trUtf8('Use cx_freeze'),
                     self.trUtf8('Use cx_&freeze'), 0, 0,
@@ -216,8 +256,9 @@
             """ relative to the project directory.</p>"""
             ))
             self.__projectAct.triggered[()].connect(self.__cxfreeze)
-            e5App().getObject("Project").addE5Actions([self.__projectAct])
+            project.addE5Actions([self.__projectAct])
             menu.addAction(self.__projectAct)
+            project.showMenu.connect(self.__projectShowMenu)
         
         error = ""
         return None, True
@@ -233,6 +274,20 @@
                 e5App().getObject("Project").removeE5Actions([self.__projectAct])
         self.__initialize()
     
+    def __projectShowMenu(self, menuName, menu):
+        """
+        Private slot called, when the the project menu or a submenu is
+        about to be shown.
+        
+        @param menuName name of the menu to be shown (string)
+        @param menu reference to the menu (QMenu)
+        """
+        if menuName == "Packagers":
+            if self.__projectAct is not None:
+                self.__projectAct.setEnabled(
+                    e5App().getObject("Project").getProjectLanguage() in \
+                        ["Python", "Python2", "Python3"])
+    
     def __loadTranslator(self):
         """
         Private method to load the translation file.
@@ -267,15 +322,16 @@
                 E5MessageBox.StandardButtons(E5MessageBox.Abort))
             return
         
-        parms = project.getData('PACKAGERSPARMS', "CXFREEZE")
-        exe = _findExecutable()
-        if exe is None:
+        majorVersionStr = project.getProjectLanguage()
+        exe = {"Python": exePy2, "Python2": exePy2, "Python3": exePy3}.get(majorVersionStr)
+        if exe == []:
             E5MessageBox.critical(None,
                 self.trUtf8("cxfreeze"),
                 self.trUtf8("""The cxfreeze executable could not be found."""))
             return
 
         from CxFreeze.CxfreezeConfigDialog import CxfreezeConfigDialog
+        parms = project.getData('PACKAGERSPARMS', "CXFREEZE")
         dlg = CxfreezeConfigDialog(project, exe, parms)
         if dlg.exec_() == QDialog.Accepted:
             args, parms = dlg.generateParameters()
@@ -285,8 +341,7 @@
             from CxFreeze.CxfreezeExecDialog import CxfreezeExecDialog
             dia = CxfreezeExecDialog("cxfreeze")
             dia.show()
-            res = dia.start(args, 
+            res = dia.start(args,
                 os.path.join(project.ppath, project.pdata["MAINSCRIPT"][0]))
             if res:
                 dia.exec_()
-

eric ide

mercurial