# A setup script showing how to extend py2exe. # # In this case, the py2exe command is subclassed to create an installation # script for InnoSetup, which can be compiled with the InnoSetup compiler # to a single file windows installer. # # By default, the installer will be created as dist\Output\setup.exe. from distutils.core import setup import py2exe import sys ################################################################ # A program using wxPython # The manifest will be inserted as resource into test_wx.exe. This # gives the controls the Windows XP appearance (if run on XP ;-) # # Another option would be to store if in a file named # test_wx.exe.manifest, and probably copy it with the data_files # option. # manifest_template = ''' %(prog)s Program ''' RT_MANIFEST = 24 ################################################################ # arguments for the setup() call test_wx = dict( script = "test_wx.py", other_resources = [(RT_MANIFEST, 1, manifest_template % dict(prog="test_wx"))], dest_base = r"prog\test_wx") zipfile = r"lib\shardlib" options = {"py2exe": {"compressed": 1, "optimize": 2}} ################################################################ import os class InnoScript: 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[-1] in "\\/": self.dist_dir += "\\" 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): assert pathname.startswith(self.dist_dir) return pathname[len(self.dist_dir):] def create(self, pathname="dist\\test_wx.iss"): self.pathname = pathname ofi = self.file = open(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 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): try: import ctypes except ImportError: try: import win32api except ImportError: import os os.startfile(self.pathname) else: print "Ok, using win32api." win32api.ShellExecute(0, "compile", self.pathname, None, None, 0) else: print "Cool, you have ctypes installed." res = ctypes.windll.shell32.ShellExecuteA(0, "compile", self.pathname, None, None, 0) if res < 32: raise RuntimeError, "ShellExecute failed, error %d" % res ################################################################ from py2exe.build_exe import py2exe class build_installer(py2exe): # This class first builds the exe file(s), then creates a Windows installer. # You need InnoSetup for it. def run(self): # First, let py2exe do it's work. py2exe.run(self) lib_dir = self.lib_dir dist_dir = self.dist_dir # create the Installer, using the files py2exe has created. script = InnoScript("test_wx", lib_dir, dist_dir, self.windows_exe_files, self.lib_files) print "*** creating the inno setup script***" script.create() print "*** compiling the inno setup script***" script.compile() # Note: By default the final setup.exe will be in an Output subdirectory. ################################################################ setup( options = options, # The lib directory contains everything except the executables and the python dll. zipfile = zipfile, windows = [test_wx], # use out build_installer class as extended py2exe build command cmdclass = {"py2exe": build_installer}, )