= What is wxPRE? = [[wxPRE]] is the [[wxPython]] Runtime Environment. [[wxPRE]] is being planned at the moment, and there has been some progress but there is plenty more to do. === Aim === The aim is to create a Runtime Environment containing [[wxPython]] and Python. Inspired by the [[http:/java.sun.com|JRE]] These wiki pages are used for the planning and will hopefully become the basis for the [[wxPRE]]. === Related Pages === * VersionSelection may be an important part of [[wxPRE]] * [[http://starship.python.net/crew/theller/py2exe/|py2exe]] and other related systems will be helpful = wxPRE requirements = wxPRE itself should contain everything needed to run wxPython apps, either as a standalone python source file, or as an application bundle of some sort. It should be possible to create the following kinds of installers: * A standalone wxPRE installer. * An application installer that includes a bundled wxPRE * A "light" application installer that relies on an already-installed wxPRE = Implementation questions = * How should applications be bundled? Possible in a zip file. In which directory? * How will wxPRE installations be found? On Windows, could be through the registry. * How will wxPRE handle multiple versions being installed? * py2exe is Windows-only at the moment. How can wxPRE be made for other platforms? Is it neccessary? = Progress so far = So far a simple wxPRE script has been created that works successfully with [[http://starship.python.net/crew/theller/py2exe/|py2exe]]. A setup script has also been created that produces the py2exe-d wxPRE executable. It also uses [[http://www.jrsoftware.org/isinfo.php|InnoSetup]] to create a wxPRE installer. However there isn't yet a mechanism to produce application installers (with bundled wxPRE or lightweight). = Source code = === wxPRE.py === {{{ #!/usr/bin/env python """wxPython Runtime Environment""" import sys import os __version__ = "0.2.1" def getversion(): """returns wxPRE version, including the wx version if available""" try: import wx return "%s-wx%s-mingw" % (__version__, wx.VERSION_STRING) except ImportError: return __version__ def addpathsfromdir(dirname): """looks in the directory for .pth files and adds them to sys.path""" for direntry in os.listdir(dirname): if os.path.splitext(direntry)[1] == '.pth': pthfile = open(os.path.join(dirname, direntry), 'r') pthdirs = [pthdir.strip() for pthdir in pthfile] pthfile.close() for pthdir in pthdirs: if os.path.isdir(pthdir): sys.path.append(pthdir) if __name__ == "__main__": import sys if len(sys.argv) > 1: arg = sys.argv[1] if arg == "--version": print sys.argv[0], getversion() elif arg == "--test": print repr(sys.path) print repr(sys.prefix) print repr(sys.executable) print repr(getattr(sys, "frozen", None)) print repr(getattr(locals, "__file__", None)) print repr(sys.argv) else: filename = os.path.abspath(arg) addpathsfromdir(os.path.dirname(filename)) addpathsfromdir(os.getcwd()) sys.argv = sys.argv[1:] #make sure the current path is the required one #and that imports can be made path = os.path.dirname(filename) if path is not os.getcwd(): os.chdir(path) if path not in sys.path: sys.path.append(path) try: execfile(filename) except ImportError,detail: print >>sys.stderr, "wxPRE ImportError: ",detail print >>sys.stderr, "Try adding a .pth file here or in the scripts dir." raise else: print >>sys.stderr, "Need to supply script filename for %s (version %s)" % (sys.argv[0], getversion()) }}} === setup.py === {{{ #!/usr/bin/env python from distutils.core import setup, gen_usage, Command, grok_environment_error from distutils.dist import Distribution from distutils.errors import * import os import sys try: import py2exe build_exe = py2exe.build_exe.py2exe Distribution = py2exe.Distribution except ImportError: py2exe = None build_exe = Command import wxPRE class InnoScript: """class that builds an InnoSetup script""" def __init__(self, name, lib_dir, dist_dir, windows_exe_files = [], lib_files = [], version = "1.0"): self.lib_dir = lib_dir self.dist_dir = dist_dir if not self.dist_dir.endswith(os.sep): self.dist_dir += os.sep self.name = name self.version = version self.windows_exe_files = [self.chop(p) for p in windows_exe_files] self.lib_files = [self.chop(p) for p in lib_files] def chop(self, pathname): """returns the path relative to self.dist_dir""" assert pathname.startswith(self.dist_dir) return pathname[len(self.dist_dir):] def create(self, pathname=None): """creates the InnoSetup script""" if pathname is None: self.pathname = os.path.join(self.dist_dir, self.name + os.extsep + "iss") else: self.pathname = pathname ofi = self.file = open(self.pathname, "w") print >> ofi, "; WARNING: This script has been created by py2exe. Changes to this script" print >> ofi, "; will be overwritten the next time py2exe is run!" print >> ofi, r"[Setup]" print >> ofi, r"AppName=%s" % self.name print >> ofi, r"AppVerName=%s %s" % (self.name, self.version) print >> ofi, r"DefaultDirName={pf}\%s" % self.name print >> ofi, r"DefaultGroupName=%s" % self.name print >> ofi, r"OutputBaseFilename=%s-%s-setup" % (self.name, self.version) print >> ofi print >> ofi, r"[Files]" for path in self.windows_exe_files + self.lib_files: print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path)) print >> ofi print >> ofi, r"[Icons]" for path in self.windows_exe_files: print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \ (self.name, path) print >> ofi, 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name def compile(self, compilercmd="compile"): """compiles the script using InnoSetup""" try: import ctypes except ImportError: try: import win32api except ImportError: os.startfile(self.pathname) else: print "Ok, using win32api." win32api.ShellExecute(0, compilercmd, self.pathname, None, None, 0) else: print "Cool, you have ctypes installed." res = ctypes.windll.shell32.ShellExecuteA(0, compilercmd, self.pathname, None, None, 0) if res < 32: raise RuntimeError, "ShellExecute failed, error %d" % res ############################################################### class build_installer(build_exe): """distutils class that first builds the exe file(s), then creates a Windows installer using InnoSetup""" def run(self): # First, let py2exe do it's work. build_exe.run(self) lib_dir = self.lib_dir dist_dir = self.dist_dir # create the Installer, using the files py2exe has created. script = InnoScript(self.distribution.metadata.name, lib_dir, dist_dir, self.windows_exe_files, self.lib_files, version=wxPRE.getversion()) print "*** creating the inno setup script***" script.create() print "*** compiling the inno setup script***" script.compile("compil32") # Note: By default the final setup.exe will be in an Output subdirectory. class wxPREDistribution(Distribution): """A distribution class for wxPRE""" def __init__(self, attrs): baseattrs = {} baseattrs['script_name'] = os.path.basename(sys.argv[0]) baseattrs['script_args'] = sys.argv[1:] # package information baseattrs['name'] = "wxPRE" baseattrs['version'] = wxPRE.__version__ baseattrs['url'] = "http://wiki.wxpython.org/index.cgi/wxPRE" baseattrs['author'] = "David Fraser and Stephen Emslie" baseattrs['author_email'] = 'info@sjsoft.com' baseattrs['description'] = 'wxPython Runtime Environment' baseattrs['long_description'] = wxPRE.__doc__ baseattrs['license'] = "wxWidgets license" py2exeoptions = {} py2exeoptions["packages"] = ["wx"] py2exeoptions["compressed"] = True py2exeoptions["dist_dir"] = "wxPRE-%s" % wxPRE.getversion() baseattrs['options'] = {"py2exe": py2exeoptions} if py2exe: baseattrs['console'] = ["wxPRE.py"] baseattrs['zipfile'] = "wxPRElibs.zip" baseattrs['cmdclass'] = {"py2exe": build_installer} baseattrs.update(attrs) Distribution.__init__(self, baseattrs) if __name__ == "__main__": dist = wxPREDistribution({}) try: ok = dist.parse_command_line() except DistutilsArgError, msg: raise SystemExit, gen_usage(dist.script_name) + "\nerror: %s" % msg if ok: try: dist.run_commands() except KeyboardInterrupt: raise SystemExit, "interrupted" except (IOError, os.error), exc: error = grok_environment_error(exc) raise SystemExit, error except (DistutilsError, CCompilerError), msg: raise SystemExit, "error: " + str(msg) }}}