--- 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_() -