From b98a53df92fe8f4401f1c97c5aed93e97e40d114 Mon Sep 17 00:00:00 2001 From: giovannibajo Date: Fri, 2 Sep 2005 17:15:02 +0000 Subject: [PATCH] Imported Python Installer 5b5 git-svn-id: http://svn.pyinstaller.org/trunk@2 8dd32b29-ccff-0310-8a9a-9233e24343b1 --- ArchiveViewer.py | 140 +++ Build.py | 784 ++++++++++++++++ Configure.py | 202 +++++ GrabVersion.py | 14 + MakeCOMServer_old.py | 150 ++++ MakeComServer.py | 150 ++++ Makespec.py | 251 ++++++ McGUI.py | 100 +++ README.txt | 22 + __version__.py | 1 + archive.py | 390 ++++++++ bindepend.py | 310 +++++++ buildtests/hooks1/hook-pkg1.py | 11 + buildtests/pkg1/__init__.py | 10 + buildtests/pkg1/a.py | 6 + buildtests/pkg2/__init__.py | 9 + buildtests/pkg2/a.py | 6 + buildtests/pkg2/a/readme.txt | 1 + buildtests/pkg2/extra/b.py | 4 + buildtests/runtests.py | 65 ++ buildtests/test1.py | 18 + buildtests/test1.spec | 13 + buildtests/test2-version.txt | 38 + buildtests/test2.ico | Bin 0 -> 766 bytes buildtests/test2.py | 18 + buildtests/test2.spec | 16 + buildtests/test3.py | 7 + buildtests/test3.spec | 13 + buildtests/test4.py | 14 + buildtests/test4.spec | 13 + buildtests/test5.py | 3 + buildtests/test5.spec | 13 + buildtests/test6.py | 14 + buildtests/test6.spec | 12 + buildtests/test6x.py | 1 + buildtests/test7.py | 16 + buildtests/test7.spec | 12 + buildtests/test7x.py | 5 + carchive.py | 260 ++++++ doc/CArchive.gif | Bin 0 -> 6412 bytes doc/SE_exe.gif | Bin 0 -> 4846 bytes doc/ZlibArchive.gif | Bin 0 -> 6083 bytes doc/archives.html | 36 + doc/begin.html | 149 +++ doc/help.html | 143 +++ doc/iu4.html | 73 ++ doc/license.txt | 18 + doc/me_inc.gif | Bin 0 -> 7546 bytes doc/mf4.html | 103 +++ doc/specfiles.html | 258 ++++++ doc/standalones.html | 60 ++ doc/utilities.html | 51 ++ e2etests/common/hanoi.py | 154 ++++ e2etests/common/maketests.py | 34 + e2etests/win32/NextID.py | 62 ++ e2etests/win32/readme.txt | 23 + e2etests/win32/testEnsureDispatch.py | 9 + e2etests/win32/testMSOffice.py | 181 ++++ e2etests/win32/testNextID.vbs | 9 + e2etests/win32/testcomext.py | 44 + hooks/__init__.py | 1 + hooks/hook-DateTime.mxDateTime.py | 1 + hooks/hook-DateTime.py | 1 + hooks/hook-Image.py | 19 + hooks/hook-PIL.Image.py | 19 + hooks/hook-_sre.py | 1 + hooks/hook-anydbm.py | 2 + hooks/hook-cPickle.py | 1 + hooks/hook-cStringIO.py | 1 + hooks/hook-carchive.py | 9 + hooks/hook-codecs.py | 1 + hooks/hook-encodings.py | 63 ++ hooks/hook-iu.py | 23 + hooks/hook-os.py | 28 + hooks/hook-parser.py | 1 + hooks/hook-pyexpat.py | 2 + hooks/hook-pythoncom.py | 22 + hooks/hook-pywintypes.py | 20 + hooks/hook-regex.py | 1 + hooks/hook-vtkpython.py | 7 + hooks/hook-win32com.client.py | 1 + hooks/hook-win32com.py | 8 + hooks/hook-win32ui.py | 1 + hooks/hook-xml.dom.domreg.py | 2 + hooks/hook-xml.dom.ext.py | 23 + hooks/hook-xml.dom.ext.reader.py | 6 + hooks/hook-xml.dom.html.HTMLDocument.py | 57 ++ hooks/hook-xml.dom.html.py | 18 + hooks/hook-xml.dom.py | 64 ++ hooks/hook-xml.py | 18 + hooks/hook-xml.sax.py | 12 + hooks/hook-xml.sax.saxexts.py | 13 + icon.py | 138 +++ iu.py | 500 +++++++++++ mf.py | 625 +++++++++++++ rthooks.dat | 5 + source/common/launch.c | 1095 +++++++++++++++++++++++ source/common/launch.h | 313 +++++++ source/linux/Make.py | 169 ++++ source/linux/bkfile.py | 54 ++ source/linux/getpath.c | 269 ++++++ source/linux/main.c | 110 +++ source/linux/makemakefile.py | 32 + source/linux/parsesetup.py | 113 +++ source/windows/dllmain.c | 262 ++++++ source/windows/dllmain.def | 6 + source/windows/icon1.ico | Bin 0 -> 767 bytes source/windows/iconw.ico | Bin 0 -> 767 bytes source/windows/inprocsrvr.dsp | 106 +++ source/windows/installer.dsw | 53 ++ source/windows/resource.h | 16 + source/windows/run.dsp | 103 +++ source/windows/run.rc | 72 ++ source/windows/runw.dsp | 109 +++ source/windows/runw.rc | 72 ++ source/windows/winmain.c | 123 +++ support/_mountzlib.py | 6 + support/inprocsrvr.dll | Bin 0 -> 32768 bytes support/inprocsrvr_d.dll | Bin 0 -> 57856 bytes support/removeTK.py | 27 + support/rthooks/versioneddll.py | 19 + support/rthooks/win32comgenpy.py | 14 + support/run.exe | Bin 0 -> 32256 bytes support/run_d.exe | Bin 0 -> 54272 bytes support/runw.exe | Bin 0 -> 34304 bytes support/runw_d.exe | Bin 0 -> 57344 bytes support/unpackTK.py | 16 + support/useUnicode.py | 1 + versionInfo.py | 519 +++++++++++ 129 files changed, 9912 insertions(+) create mode 100644 ArchiveViewer.py create mode 100644 Build.py create mode 100644 Configure.py create mode 100644 GrabVersion.py create mode 100644 MakeCOMServer_old.py create mode 100644 MakeComServer.py create mode 100644 Makespec.py create mode 100644 McGUI.py create mode 100644 README.txt create mode 100644 __version__.py create mode 100644 archive.py create mode 100644 bindepend.py create mode 100644 buildtests/hooks1/hook-pkg1.py create mode 100644 buildtests/pkg1/__init__.py create mode 100644 buildtests/pkg1/a.py create mode 100644 buildtests/pkg2/__init__.py create mode 100644 buildtests/pkg2/a.py create mode 100644 buildtests/pkg2/a/readme.txt create mode 100644 buildtests/pkg2/extra/b.py create mode 100644 buildtests/runtests.py create mode 100644 buildtests/test1.py create mode 100644 buildtests/test1.spec create mode 100644 buildtests/test2-version.txt create mode 100644 buildtests/test2.ico create mode 100644 buildtests/test2.py create mode 100644 buildtests/test2.spec create mode 100644 buildtests/test3.py create mode 100644 buildtests/test3.spec create mode 100644 buildtests/test4.py create mode 100644 buildtests/test4.spec create mode 100644 buildtests/test5.py create mode 100644 buildtests/test5.spec create mode 100644 buildtests/test6.py create mode 100644 buildtests/test6.spec create mode 100644 buildtests/test6x.py create mode 100644 buildtests/test7.py create mode 100644 buildtests/test7.spec create mode 100644 buildtests/test7x.py create mode 100644 carchive.py create mode 100644 doc/CArchive.gif create mode 100644 doc/SE_exe.gif create mode 100644 doc/ZlibArchive.gif create mode 100644 doc/archives.html create mode 100644 doc/begin.html create mode 100644 doc/help.html create mode 100644 doc/iu4.html create mode 100644 doc/license.txt create mode 100644 doc/me_inc.gif create mode 100644 doc/mf4.html create mode 100644 doc/specfiles.html create mode 100644 doc/standalones.html create mode 100644 doc/utilities.html create mode 100644 e2etests/common/hanoi.py create mode 100644 e2etests/common/maketests.py create mode 100644 e2etests/win32/NextID.py create mode 100644 e2etests/win32/readme.txt create mode 100644 e2etests/win32/testEnsureDispatch.py create mode 100644 e2etests/win32/testMSOffice.py create mode 100644 e2etests/win32/testNextID.vbs create mode 100644 e2etests/win32/testcomext.py create mode 100644 hooks/__init__.py create mode 100644 hooks/hook-DateTime.mxDateTime.py create mode 100644 hooks/hook-DateTime.py create mode 100644 hooks/hook-Image.py create mode 100644 hooks/hook-PIL.Image.py create mode 100644 hooks/hook-_sre.py create mode 100644 hooks/hook-anydbm.py create mode 100644 hooks/hook-cPickle.py create mode 100644 hooks/hook-cStringIO.py create mode 100644 hooks/hook-carchive.py create mode 100644 hooks/hook-codecs.py create mode 100644 hooks/hook-encodings.py create mode 100644 hooks/hook-iu.py create mode 100644 hooks/hook-os.py create mode 100644 hooks/hook-parser.py create mode 100644 hooks/hook-pyexpat.py create mode 100644 hooks/hook-pythoncom.py create mode 100644 hooks/hook-pywintypes.py create mode 100644 hooks/hook-regex.py create mode 100644 hooks/hook-vtkpython.py create mode 100644 hooks/hook-win32com.client.py create mode 100644 hooks/hook-win32com.py create mode 100644 hooks/hook-win32ui.py create mode 100644 hooks/hook-xml.dom.domreg.py create mode 100644 hooks/hook-xml.dom.ext.py create mode 100644 hooks/hook-xml.dom.ext.reader.py create mode 100644 hooks/hook-xml.dom.html.HTMLDocument.py create mode 100644 hooks/hook-xml.dom.html.py create mode 100644 hooks/hook-xml.dom.py create mode 100644 hooks/hook-xml.py create mode 100644 hooks/hook-xml.sax.py create mode 100644 hooks/hook-xml.sax.saxexts.py create mode 100644 icon.py create mode 100644 iu.py create mode 100644 mf.py create mode 100644 rthooks.dat create mode 100644 source/common/launch.c create mode 100644 source/common/launch.h create mode 100644 source/linux/Make.py create mode 100644 source/linux/bkfile.py create mode 100644 source/linux/getpath.c create mode 100644 source/linux/main.c create mode 100644 source/linux/makemakefile.py create mode 100644 source/linux/parsesetup.py create mode 100644 source/windows/dllmain.c create mode 100644 source/windows/dllmain.def create mode 100644 source/windows/icon1.ico create mode 100644 source/windows/iconw.ico create mode 100644 source/windows/inprocsrvr.dsp create mode 100644 source/windows/installer.dsw create mode 100644 source/windows/resource.h create mode 100644 source/windows/run.dsp create mode 100644 source/windows/run.rc create mode 100644 source/windows/runw.dsp create mode 100644 source/windows/runw.rc create mode 100644 source/windows/winmain.c create mode 100644 support/_mountzlib.py create mode 100644 support/inprocsrvr.dll create mode 100644 support/inprocsrvr_d.dll create mode 100644 support/removeTK.py create mode 100644 support/rthooks/versioneddll.py create mode 100644 support/rthooks/win32comgenpy.py create mode 100644 support/run.exe create mode 100644 support/run_d.exe create mode 100644 support/runw.exe create mode 100644 support/runw_d.exe create mode 100644 support/unpackTK.py create mode 100644 support/useUnicode.py create mode 100644 versionInfo.py diff --git a/ArchiveViewer.py b/ArchiveViewer.py new file mode 100644 index 0000000..6b77670 --- /dev/null +++ b/ArchiveViewer.py @@ -0,0 +1,140 @@ +#! /usr/bin/env python +import archive +import carchive +import sys, string, tempfile, os +try: + import zlib +except ImportError: + zlib = archive.DummyZlib() +import pprint + +stack = [] +cleanup = [] + +def main(): + global stack + name = sys.argv[1] + arch = getArchive(name) + stack.append((name, arch)) + show(name, arch) + + while 1: + toks = string.split(raw_input('? '), ' ', 1) + if not toks: + usage() + continue + if len(toks) == 1: + cmd = toks[0] + arg = '' + else: + cmd, arg = toks + cmd = string.upper(cmd) + if cmd == 'U': + if len(stack) > 1: + arch = stack[-1][1] + arch.lib.close() + del stack[-1] + nm, arch = stack[-1] + show(nm, arch) + elif cmd == 'O': + if not arg: + arg = raw_input('open name? ') + arg = string.strip(arg) + arch = getArchive(arg) + if arch is None: + print arg, "not found" + continue + stack.append((arg, arch)) + show(arg, arch) + elif cmd == 'X': + if not arg: + arg = raw_input('extract name? ') + arg = string.strip(arg) + data = getData(arg, arch) + if data is None: + print "Not found" + continue + fnm = raw_input('to filename? ') + if not fnm: + print `data` + else: + open(fnm, 'wb').write(data) + elif cmd == 'Q': + break + else: + usage() + for (nm, arch) in stack: + arch.lib.close() + stack = [] + for fnm in cleanup: + try: + os.remove(fnm) + except Exception, e: + print "couldn't delete", fnm, e.args +def usage(): + print "U: go Up one level" + print "O : open embedded archive nm" + print "X : extract nm" + print "Q: quit" +def getArchive(nm): + if not stack: + if string.lower(nm[-4:]) == '.pyz': + return ZlibArchive(nm) + return carchive.CArchive(nm) + parent = stack[-1][1] + try: + return parent.openEmbedded(nm) + except KeyError, e: + return None + except (ValueError, RuntimeError): + ndx = parent.toc.find(nm) + dpos, dlen, ulen, flag, typcd, nm = parent.toc[ndx] + x, data = parent.extract(ndx) + tfnm = tempfile.mktemp() + cleanup.append(tfnm) + open(tfnm, 'wb').write(data) + if typcd == 'z': + return ZlibArchive(tfnm) + else: + return carchive.CArchive(tfnm) + +def getData(nm, arch): + if type(arch.toc) is type({}): + (ispkg, pos, lngth) = arch.toc.get(nm, (0, None, 0)) + if pos is None: + return None + arch.lib.seek(arch.start + pos) + return zlib.decompress(arch.lib.read(lngth)) + ndx = arch.toc.find(nm) + dpos, dlen, ulen, flag, typcd, nm = arch.toc[ndx] + x, data = arch.extract(ndx) + if flag == 1: + return zlib.decompress(data) + return data + +def show(nm, arch): + if type(arch.toc) == type({}): + print " Name: (ispkg, pos, len)" + toc = arch.toc + else: + print " pos, length, uncompressed, iscompressed, type, name" + toc = arch.toc.data + pprint.pprint(toc) + +class ZlibArchive(archive.ZlibArchive): + def checkmagic(self): + """ Overridable. + Check to see if the file object self.lib actually has a file + we understand. + """ + self.lib.seek(self.start) #default - magic is at start of file + if self.lib.read(len(self.MAGIC)) != self.MAGIC: + raise RuntimeError, "%s is not a valid %s archive file" \ + % (self.path, self.__class__.__name__) + if self.lib.read(len(self.pymagic)) != self.pymagic: + print "Warning: pyz is from a different Python version" + self.lib.read(4) + +if __name__ == '__main__': + main() + diff --git a/Build.py b/Build.py new file mode 100644 index 0000000..f7fd756 --- /dev/null +++ b/Build.py @@ -0,0 +1,784 @@ +#! /usr/bin/env python +import sys, os, shutil, mf, archive, iu, carchive, pprint, time, py_compile, bindepend, tempfile + +STRINGTYPE = type('') +TUPLETYPE = type((None,)) + +HOMEPATH = os.path.dirname(sys.argv[0]) +SPECPATH = None +BUILDPATH = None +WARNFILE = None +rthooks = {} +iswin = sys.platform[:3] == 'win' +cygwin = sys.platform == 'cygwin' +try: + config = eval(open(os.path.join(HOMEPATH, 'config.dat'), 'r').read()) +except IOError: + print "You must run Configure.py before building!" + sys.exit(1) + +if config['hasRsrcUpdate']: + import icon, versionInfo + +def build(spec): + global SPECPATH, BUILDPATH, WARNFILE, rthooks + rthooks = eval(open(os.path.join(HOMEPATH, 'rthooks.dat'), 'r').read()) + SPECPATH, specnm = os.path.split(spec) + specnm = os.path.splitext(specnm)[0] + if SPECPATH == '': + SPECPATH = os.getcwd() + WARNFILE = os.path.join(SPECPATH, 'warn%s.txt' % specnm) + BUILDPATH = os.path.join(SPECPATH, 'build%s' % specnm) + if '-o' in sys.argv: + bpath = sys.argv[sys.argv.index('-o')+1] + if os.path.isabs(bpath): + BUILDPATH = bpath + else: + BUILDPATH = os.path.join(SPECPATH, bpath) + if not os.path.exists(BUILDPATH): + os.mkdir(BUILDPATH) + exec open(spec, 'r').read()+'\n' + +def mtime(fnm): + try: + return os.stat(fnm)[8] + except: + return 0 + +class Target: + invcnum = 0 + def __init__(self): + self.invcnum = Target.invcnum + Target.invcnum = Target.invcnum + 1 + self.out = os.path.join(BUILDPATH, 'out%d.toc' % self.invcnum) + self.dependencies = TOC() + def __postinit__(self): + print "checking %s" % (self.__class__.__name__,) + if self.check_guts(mtime(self.out)): + self.assemble() + +class Analysis(Target): + def __init__(self, scripts=None, pathex=None, hookspath=None, excludes=None): + Target.__init__(self) + self.inputs = scripts + for script in scripts: + if not os.path.exists(script): + raise ValueError, "script '%s' not found" % script + self.pathex = [] + if pathex: + for path in pathex: + self.pathex.append(os.path.abspath(os.path.normpath(path))) + self.hookspath = hookspath + self.excludes = excludes + self.scripts = TOC() + self.pure = TOC() + self.binaries = TOC() + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + if last_build == 0: + print "building %s because %s non existent" % (self.__class__.__name__, outnm) + return 1 + for fnm in self.inputs: + if mtime(fnm) > last_build: + print "building because %s changed" % fnm + return 1 + try: + inputs, pathex, hookspath, excludes, scripts, pure, binaries = eval(open(self.out, 'r').read()) + except: + print "building because %s disappeared" % outnm + return 1 + if inputs != self.inputs: + print "building %s because inputs changed" % outnm + return 1 + if pathex != self.pathex: + print "building %s because pathex changed" % outnm + return 1 + if hookspath != self.hookspath: + print "building %s because hookspath changed" % outnm + return 1 + if excludes != self.excludes: + print "building %s because excludes changed" % outnm + return 1 + for (nm, fnm, typ) in scripts: + if mtime(fnm) > last_build: + print "building because %s changed" % fnm + return 1 + for (nm, fnm, typ) in pure: + if mtime(fnm) > last_build: + print "building because %s changed" % fnm + return 1 + elif mtime(fnm[:-1]) > last_build: + print "building because %s changed" % fnm[:-1] + return 1 + for (nm, fnm, typ) in binaries: + if mtime(fnm) > last_build: + print "building because %s changed" % fnm + return 1 + self.scripts = TOC(scripts) + self.pure = TOC(pure) + self.binaries = TOC(binaries) + return 0 + def assemble(self): + print "running Analysis", os.path.basename(self.out) + paths = self.pathex + for i in range(len(paths)): + paths[i] = os.path.abspath(os.path.normpath(paths[i])) + dirs = {} + pynms = [] + for script in self.inputs: + if not os.path.exists(script): + print "Analysis: script %s not found!" % script + sys.exit(1) + d, base = os.path.split(script) + if not d: + d = os.getcwd() + d = os.path.abspath(os.path.normpath(d)) + pynm, ext = os.path.splitext(base) + dirs[d] = 1 + pynms.append(pynm) + analyzer = mf.ImportTracker(dirs.keys()+paths, self.hookspath, self.excludes) + #print analyzer.path + scripts = [] + for i in range(len(self.inputs)): + script = self.inputs[i] + print "Analyzing:", script + analyzer.analyze_script(script) + scripts.append((pynms[i], script, 'PYSOURCE')) + pure = [] + binaries = [] + rthooks = [] + for modnm, mod in analyzer.modules.items(): + if mod is not None: + hooks = findRTHook(modnm) #XXX + if hooks: + rthooks.extend(hooks) + if isinstance(mod, mf.BuiltinModule): + pass + else: + fnm = mod.__file__ + if isinstance(mod, mf.ExtensionModule): + binaries.append((mod.__name__, fnm, 'EXTENSION')) + elif modnm == '__main__': + pass + else: + pure.append((modnm, fnm, 'PYMODULE')) + binaries.extend(bindepend.Dependencies(binaries)) + scripts[1:1] = rthooks + self.scripts = TOC(scripts) + self.pure = TOC(pure) + self.binaries = TOC(binaries) + try: + oldstuff = eval(open(self.out, 'r').read()) + except: + oldstuff = None + if oldstuff != (self.inputs, self.pathex, self.hookspath, self.excludes, scripts, pure, binaries): + outf = open(self.out, 'w') + pprint.pprint( + (self.inputs, self.pathex, self.hookspath, self.excludes, self.scripts, self.pure, self.binaries), + outf) + outf.close() + wf = open(WARNFILE, 'w') + for ln in analyzer.getwarnings(): + wf.write(ln+'\n') + wf.close() + print "Warnings written to %s" % WARNFILE + return 1 + print self.out, "no change!" + return 0 + +def findRTHook(modnm): + hooklist = rthooks.get(modnm) + if hooklist: + rslt = [] + for script in hooklist: + nm = os.path.basename(script) + nm = os.path.splitext(nm)[0] + if os.path.isabs(script): + path = script + else: + path = os.path.join(HOMEPATH, script) + rslt.append((nm, path, 'PYSOURCE')) + return rslt + return None + +class PYZ(Target): + typ = 'PYZ' + def __init__(self, toc, name=None, level=9): + Target.__init__(self) + self.toc = toc + self.name = name + if name is None: + self.name = self.out[:-3] + 'pyz' + if config['useZLIB']: + self.level = level + else: + self.level = 0 + self.dependencies = config['PYZ_dependencies'] + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + if not os.path.exists(self.name): + print "rebuilding %s because %s is missing" % (outnm, os.path.basename(self.name)) + return 1 + try: + name, level, toc = eval(open(self.out, 'r').read()) + except: + print "rebuilding %s because missing" % outnm + return 1 + if name != self.name: + print "rebuilding %s because name changed" % outnm + return 1 + if level != self.level: + print "rebuilding %s because level changed" % outnm + return 1 + if toc != self.toc: + print "rebuilding %s because toc changed" % outnm + return 1 + for (nm, fnm, typ) in toc: + if mtime(fnm) > last_build: + print "rebuilding %s because %s changed" % (outnm, fnm) + return 1 + if fnm[-1] in ('c', 'o'): + if mtime(fnm[:-1]) > last_build: + print "rebuilding %s because %s changed" % (outnm, fnm[:-1]) + return 1 + return 0 + def assemble(self): + print "building PYZ", os.path.basename(self.out) + pyz = archive.ZlibArchive(level=self.level) + toc = self.toc - config['PYZ_dependencies'] + for (nm, fnm, typ) in toc: + if mtime(fnm[:-1]) > mtime(fnm): + py_compile.compile(fnm[:-1]) + pyz.build(self.name, toc) + outf = open(self.out, 'w') + pprint.pprint((self.name, self.level, self.toc), outf) + outf.close() + return 1 + +def checkCache(fnm, strip, upx): + if not strip and not upx: + return fnm + cachedir = os.path.join(HOMEPATH, 'bincache%d%d' % (strip, upx)) + if not os.path.exists(cachedir): + os.makedirs(cachedir) + basenm = os.path.basename(fnm) + cachedfile = os.path.join(cachedir, basenm ) + if os.path.exists(cachedfile): + if mtime(fnm) > mtime(cachedfile): + os.remove(cachedfile) + else: + return cachedfile + if upx: + if strip: + fnm = checkCache(fnm, 1, 0) + cmd = "upx --best -q %s" % cachedfile + else: + cmd = "strip %s" % cachedfile + shutil.copy2(fnm, cachedfile) + os.chmod(cachedfile, 0755) + os.system(cmd) + return cachedfile + +UNCOMPRESSED, COMPRESSED, SOURCEFORM = range(3) +class PKG(Target): + typ = 'PKG' + xformdict = {'PYMODULE' : 'm', + 'PYSOURCE' : 's', + 'EXTENSION' : 'b', + 'PYZ' : 'z', + 'PKG' : 'a', + 'DATA': 'x', + 'BINARY': 'b', + 'EXECUTABLE': 'b'} + def __init__(self, toc, name=None, cdict=None, exclude_binaries=0, + strip_binaries=0, upx_binaries=0): + Target.__init__(self) + self.toc = toc + self.cdict = cdict + self.name = name + self.exclude_binaries = exclude_binaries + self.strip_binaries = strip_binaries + self.upx_binaries = upx_binaries + if name is None: + self.name = self.out[:-3] + 'pkg' + if self.cdict is None: + if config['useZLIB']: + self.cdict = {'EXTENSION':COMPRESSED, + 'DATA':COMPRESSED, + 'BINARY':COMPRESSED, + 'EXECUTABLE':COMPRESSED, + 'PYSOURCE':SOURCEFORM } + else: + self.cdict = { 'PYSOURCE':SOURCEFORM } + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + if not os.path.exists(self.name): + print "rebuilding %s because %s is missing" % (outnm, os.path.basename(self.name)) + return 1 + try: + name, cdict, toc, exclude_binaries, strip_binaries, upx_binaries = eval(open(self.out, 'r').read()) + except: + print "rebuilding %s because %s is missing" % (outnm, outnm) + return 1 + if name != self.name: + print "rebuilding %s because name changed" % outnm + return 1 + if cdict != self.cdict: + print "rebuilding %s because cdict changed" % outnm + return 1 + if toc != self.toc: + print "rebuilding %s because toc changed" % outnm + return 1 + if exclude_binaries != self.exclude_binaries: + print "rebuilding %s because exclude_binaries changed" % outnm + return 1 + if strip_binaries != self.strip_binaries: + print "rebuilding %s because strip_binaries changed" % outnm + return 1 + if upx_binaries != self.upx_binaries: + print "rebuilding %s because upx_binaries changed" % outnm + return 1 + for (nm, fnm, typ) in toc: + if mtime(fnm) > last_build: + print "rebuilding %s because %s changed" % (outnm, fnm) + return 1 + return 0 + def assemble(self): + print "building PKG", os.path.basename(self.name) + trash = [] + mytoc = [] + toc = TOC() + for item in self.toc: + inm, fnm, typ = item + if typ == 'EXTENSION': + binext = os.path.splitext(fnm)[1] + if not os.path.splitext(inm)[1] == binext: + inm = inm + binext + toc.append((inm, fnm, typ)) + for inm, fnm, typ in toc: + if typ in ('BINARY', 'EXTENSION'): + if self.exclude_binaries: + self.dependencies.append((inm, fnm, typ)) + else: + fnm = checkCache(fnm, self.strip_binaries, + self.upx_binaries and ( iswin or cygwin ) + and config['hasUPX']) + mytoc.append((inm, fnm, self.cdict.get(typ,0), + self.xformdict.get(typ,'b'))) + elif typ == 'OPTION': + mytoc.append((inm, '', 0, 'o')) + else: + mytoc.append((inm, fnm, self.cdict.get(typ,0), self.xformdict.get(typ,'b'))) + archive = carchive.CArchive() + archive.build(self.name, mytoc) + outf = open(self.out, 'w') + pprint.pprint((self.name, self.cdict, self.toc, self.exclude_binaries, self.strip_binaries, self.upx_binaries), outf) + outf.close() + for item in trash: + os.remove(item) + return 1 + +class ELFEXE(Target): + typ = 'EXECUTABLE' + exclude_binaries = 0 + def __init__(self, *args, **kws): + Target.__init__(self) + self.console = kws.get('console',1) + self.debug = kws.get('debug',0) + self.name = kws.get('name',None) + self.icon = kws.get('icon',None) + self.versrsrc = kws.get('version',None) + self.strip = kws.get('strip',None) + self.upx = kws.get('upx',None) + self.exclude_binaries = kws.get('exclude_binaries',0) + if self.name is None: + self.name = self.out[:-3] + 'exe' + if not os.path.isabs(self.name): + self.name = os.path.join(SPECPATH, self.name) + self.toc = TOC() + for arg in args: + if isinstance(arg, TOC): + self.toc.extend(arg) + elif isinstance(arg, Target): + self.toc.append((os.path.basename(arg.name), arg.name, arg.typ)) + self.toc.extend(arg.dependencies) + else: + self.toc.extend(arg) + self.toc.extend(config['EXE_dependencies']) + self.pkg = PKG(self.toc, cdict=kws.get('cdict',None), exclude_binaries=self.exclude_binaries, + strip_binaries=self.strip, upx_binaries=self.upx) + self.dependencies = self.pkg.dependencies + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + if not os.path.exists(self.name): + print "rebuilding %s because %s missing" % (outnm, os.path.basename(self.name)) + return 1 + try: + name, console, debug, icon, versrsrc, strip, upx, mtm = eval(open(self.out, 'r').read()) + except: + print "rebuilding %s because %s missing or bad" % (outnm, outnm) + return 1 + if name != self.name: + print "rebuilding %s because name changed" % outnm + return 1 + if console != self.console: + print "rebuilding %s because console option changed" % outnm + return 1 + if debug != self.debug: + print "rebuilding %s because debug option changed" % outnm + return 1 + if config['hasRsrcUpdate']: + if icon != self.icon: + print "rebuilding %s because icon option changed" % outnm + return 1 + if versrsrc != self.versrsrc: + print "rebuilding %s because versrsrc option changed" % outnm + return 1 + else: + if icon or versrsrc: + print "ignoring icon and version resources = platform not capable" + if strip != self.strip: + print "rebuilding %s because strip option changed" % outnm + return 1 + if upx != self.upx: + print "rebuilding %s because upx option changed" % outnm + return 1 + if mtm != mtime(self.name): + print "rebuilding %s because mtimes don't match" % outnm + return 1 + if mtm < mtime(self.pkg.out): + print "rebuilding %s because pkg is more recent" % outnm + return 1 + return 0 + def assemble(self): + print "building ELFEXE", os.path.basename(self.out) + trash = [] + outf = open(self.name, 'wb') + exe = 'support/run' + if not self.console: + exe = exe + 'w' + if self.debug: + exe = exe + '_d' + exe = os.path.join(HOMEPATH, exe) + if iswin or cygwin: + exe = exe + '.exe' + if config['hasRsrcUpdate']: + if self.icon: + tmpnm = tempfile.mktemp() + shutil.copy2(exe, tmpnm) + os.chmod(tmpnm, 0755) + icon.CopyIcons(tmpnm, self.icon) + trash.append(tmpnm) + exe = tmpnm + if self.versrsrc: + tmpnm = tempfile.mktemp() + shutil.copy2(exe, tmpnm) + os.chmod(tmpnm, 0755) + versionInfo.SetVersion(tmpnm, self.versrsrc) + trash.append(tmpnm) + exe = tmpnm + exe = checkCache(exe, self.strip, self.upx and config['hasUPX']) + self.copy(exe, outf) + self.copy(self.pkg.name, outf) + outf.close() + os.chmod(self.name, 0755) + f = open(self.out, 'w') + pprint.pprint((self.name, self.console, self.debug, self.icon, self.versrsrc, + self.strip, self.upx, mtime(self.name)), f) + f.close() + for item in trash: + os.remove(item) + return 1 + def copy(self, fnm, outf): + inf = open(fnm, 'rb') + while 1: + data = inf.read(64*1024) + if not data: + break + outf.write(data) + +class DLL(ELFEXE): + def assemble(self): + print "building DLL", os.path.basename(self.out) + outf = open(self.name, 'wb') + dll = 'support/inprocsrvr' + if self.debug: + dll = dll + '_d' + dll = os.path.join(HOMEPATH, dll) + '.dll' + self.copy(dll, outf) + self.copy(self.pkg.name, outf) + outf.close() + os.chmod(self.name, 0755) + f = open(self.out, 'w') + pprint.pprint((self.name, self.console, self.debug, self.icon, self.versrsrc, + self.strip, self.upx, mtime(self.name)), f) + f.close() + return 1 + +class NonELFEXE(ELFEXE): + def assemble(self): + print "building NonELFEXE", os.path.basename(self.out) + trash = [] + exe = 'support/run' + if not self.console: + exe = exe + 'w' + if self.debug: + exe = exe + '_d' + exe = os.path.join(HOMEPATH, exe) + exe = checkCache(exe, self.strip, self.upx and config['hasUPX']) + shutil.copy2(exe, self.name) + os.chmod(self.name, 0755) + shutil.copy2(self.pkg.name, self.name+'.pkg') + f = open(self.out, 'w') + pprint.pprint((self.name, self.console, self.debug, self.icon, self.versrsrc, + self.strip, self.upx, mtime(self.name)), f) + f.close() + for fnm in trash: + os.remove(fnm) + return 1 + +if config['useELFEXE']: + EXE = ELFEXE +else: + EXE = NonELFEXE + +class COLLECT(Target): + def __init__(self, *args, **kws): + Target.__init__(self) + self.name = kws.get('name',None) + if self.name is None: + self.name = 'dist_' + self.out[:-4] + self.strip_binaries = kws.get('strip',0) + self.upx_binaries = kws.get('upx',0) + if not os.path.isabs(self.name): + self.name = os.path.join(SPECPATH, self.name) + self.toc = TOC() + for arg in args: + if isinstance(arg, TOC): + self.toc.extend(arg) + elif isinstance(arg, Target): + self.toc.append((os.path.basename(arg.name), arg.name, arg.typ)) + if isinstance(arg, NonELFEXE): + self.toc.append((os.path.basename(arg.name)+'.pkg', arg.name+'.pkg', 'PKG')) + self.toc.extend(arg.dependencies) + else: + self.toc.extend(arg) + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + try: + name, strip_binaries, upx_binaries, toc = eval(open(self.out, 'r').read()) + except: + print "building %s because %s missing" % (outnm, outnm) + return 1 + if name != self.name: + print "building %s because name changed" % outnm + return 1 + if strip_binaries != self.strip_binaries: + print "building %s because strip_binaries option changed" % outnm + return 1 + if upx_binaries != self.upx_binaries: + print "building %s because upx_binaries option changed" % outnm + return 1 + if toc != self.toc: + print "building %s because toc changed" % outnm + return 1 + for inm, fnm, typ in self.toc: + if typ == 'EXTENSION': + ext = os.path.splitext(fnm)[1] + test = os.path.join(self.name, inm+ext) + else: + test = os.path.join(self.name, os.path.basename(fnm)) + if not os.path.exists(test): + print "building %s because %s is missing" % (outnm, test) + return 1 + if mtime(fnm) > mtime(test): + print "building %s because %s is more recent" % (outnm, fnm) + return 1 + return 0 + def assemble(self): + print "building COLLECT", os.path.basename(self.out) + if not os.path.exists(self.name): + os.mkdir(self.name) + toc = TOC() + for inm, fnm, typ in self.toc: + if typ == 'EXTENSION': + binext = os.path.splitext(fnm)[1] + if not os.path.splitext(inm)[1] == binext: + inm = inm + binext + toc.append((inm, fnm, typ)) + for inm, fnm, typ in toc: + tofnm = os.path.join(self.name, inm) + todir = os.path.dirname(tofnm) + if not os.path.exists(todir): + os.makedirs(todir) + if typ in ('EXTENSION', 'BINARY'): + fnm = checkCache(fnm, self.strip_binaries, + self.upx_binaries and ( iswin or cygwin ) + and config['hasUPX']) + shutil.copy2(fnm, tofnm) + if typ in ('EXTENSION', 'BINARY'): + os.chmod(tofnm, 0755) + f = open(self.out, 'w') + pprint.pprint((self.name, self.strip_binaries, self.upx_binaries, self.toc), f) + f.close() + return 1 + +import UserList +class TOC(UserList.UserList): + def __init__(self, initlist=None): + UserList.UserList.__init__(self) + self.fltr = {} + if initlist: + for tpl in initlist: + self.append(tpl) + def append(self, tpl): + try: + if not self.fltr.get(tpl[0]): + self.data.append(tpl) + self.fltr[tpl[0]] = 1 + except TypeError: + print "TOC found a %s, not a tuple" % tpl + raise + def insert(self, pos, tpl): + if not self.fltr.get(tpl[0]): + self.data.insert(pos, tpl) + self.fltr[tpl[0]] = 1 + def __add__(self, other): + rslt = TOC(self.data) + rslt.extend(other) + return rslt + def __radd__(self, other): + rslt = TOC(other) + rslt.extend(self.data) + return rslt + def extend(self, other): + for tpl in other: + self.append(tpl) + def __sub__(self, other): + fd = self.fltr.copy() + # remove from fd if it's in other + for tpl in other: + if fd.get(tpl[0],0): + del fd[tpl[0]] + rslt = TOC() + # return only those things still in fd (preserve order) + for tpl in self.data: + if fd.get(tpl[0],0): + rslt.append(tpl) + return rslt + def __rsub__(self, other): + rslt = TOC(other) + return rslt.__sub__(self) + def intersect(self, other): + rslt = TOC() + for tpl in other: + if self.fltr.get(tpl[0],0): + rslt.append(tpl) + return rslt + +class Tree(Target, TOC): + def __init__(self, root=None, prefix=None, excludes=None): + Target.__init__(self) + TOC.__init__(self) + self.root = root + self.prefix = prefix + self.excludes = excludes + if excludes is None: + self.excludes = [] + self.__postinit__() + def check_guts(self, last_build): + outnm = os.path.basename(self.out) + try: + root, prefix, excludes, toc = eval(open(self.out, 'r').read()) + except: + print "building %s because %s is missing / bad" % (outnm, outnm) + return 1 + if root != self.root: + print "building %s because root changed" % outnm + return 1 + if prefix != self.prefix: + print "building %s because prefix changed" % outnm + return 1 + if excludes != self.excludes: + print "building %s because excludes changed" % outnm + return 1 + stack = [root] + while stack: + d = stack.pop() + if mtime(d) > last_build: + print "building %s because directory %s changed" % (outnm, d) + return 1 + for nm in os.listdir(d): + path = os.path.join(d, nm) + if os.path.isdir(path): + stack.append(path) + self.data = toc + return 0 + def assemble(self): + print "building Tree", os.path.basename(self.out) + stack = [(self.root, self.prefix)] + excludes = {} + xexcludes = {} + for nm in self.excludes: + if nm[0] == '*': + xexcludes[nm[1:]] = 1 + else: + excludes[nm] = 1 + rslt = [] + while stack: + dir, prefix = stack.pop() + for fnm in os.listdir(dir): + if excludes.get(fnm, 0) == 0: + ext = os.path.splitext(fnm)[1] + if xexcludes.get(ext,0) == 0: + fullfnm = os.path.join(dir, fnm) + rfnm = prefix and os.path.join(prefix, fnm) or fnm + if os.path.isdir(fullfnm): + stack.append((fullfnm, rfnm)) + else: + rslt.append((rfnm, fullfnm, 'DATA')) + try: + oldstuff = eval(open(self.out, 'r').read()) + except: + oldstuff = None + if oldstuff != (self.root, self.prefix, self.excludes, rslt): + outf = open(self.out, 'w') + pprint.pprint((self.root, self.prefix, self.excludes, rslt), outf) + outf.close() + self.data = rslt + return 1 + print self.out, "no change!" + return 0 + +def TkTree(): + tclroot = config['TCL_root'] + tclnm = os.path.join('_MEI', os.path.basename(tclroot)) + tkroot = config['TK_root'] + tknm = os.path.join('_MEI', os.path.basename(tkroot)) + tcltree = Tree(tclroot, tclnm, excludes=['demos','encoding','*.lib']) + tktree = Tree(tkroot, tknm, excludes=['demos','encoding','*.lib']) + return tcltree + tktree + +def TkPKG(): + return PKG(TkTree(), name='tk.pkg') + +usage = """\ +Usage: python %s + +See doc/specfiles.html for details. +""" + +if __name__ == '__main__': + if len(sys.argv) < 2: + print usage % sys.argv[0] + else: + build(sys.argv[1]) + + + + diff --git a/Configure.py b/Configure.py new file mode 100644 index 0000000..bd7b6d0 --- /dev/null +++ b/Configure.py @@ -0,0 +1,202 @@ +#! /usr/bin/env python + +import os, sys, string, shutil +HOME = os.path.dirname(sys.argv[0]) +iswin = sys.platform[:3] == 'win' +cygwin = sys.platform == 'cygwin' +configfile = os.path.join(HOME, 'config.dat') +try: + config = eval(open(configfile, 'r').read()) +except IOError: + config = {'useELFEXE':1} # if not set by Make.py we can assume Windows + +import mf, bindepend + +# EXE_dependencies +print "I: computing EXE_dependencies" +python = sys.executable +if not iswin: + while os.path.islink(python): + python = os.readlink(python) + if not os.path.isabs(python): + for dir in string.split(os.environ['PATH'], os.pathsep): + test = os.path.join(dir, python) + if os.path.exists(test): + python = test + break +toc = bindepend.Dependencies([('', python, '')]) +if iswin and sys.version[:3] == '1.5': + import exceptions + toc.append((os.path.basename(exceptions.__file__), exceptions.__file__, 'BINARY')) +config['EXE_dependencies'] = toc[1:] + +_useTK = """\ +import os, sys +try: + basedir = os.environ['_MEIPASS2'] +except KeyError: + basedir = sys.path[0] +tcldir = os.path.join(basedir, '_MEI', 'tcl%s') +tkdir = os.path.join(basedir, '_MEI', 'tk%s') +os.environ["TCL_LIBRARY"] = tcldir +os.environ["TK_LIBRARY"] = tkdir +os.putenv("TCL_LIBRARY", tcldir) +os.putenv("TK_LIBRARY", tkdir) +""" + +# TCL_root, TK_root and support/useTK.py +print "I: Finding TCL/TK..." +if not iswin: + saveexcludes = bindepend.excludes + bindepend.excludes = {} +import re +pattern = [r'libtcl(\d\.\d)?\.so', r'(?i)tcl(\d\d)\.dll'][iswin] +a = mf.ImportTracker() +a.analyze_r('Tkinter') +binaries = [] +for modnm, mod in a.modules.items(): + if isinstance(mod, mf.ExtensionModule): + binaries.append((mod.__name__, mod.__file__, 'EXTENSION')) +binaries.extend(bindepend.Dependencies(binaries)) +binaries.extend(bindepend.Dependencies([('', sys.executable, '')])) +for nm, fnm, typ in binaries: + mo = re.match(pattern, nm) + if mo: + ver = mo.group(1) + tclbindir = os.path.dirname(fnm) + if iswin: + ver = ver[0] + '.' + ver[1:] + elif ver is None: + # we found "libtcl.so.0" so we need to get the version from the lib directory + for name in os.listdir(tclbindir): + mo = re.match(r'tcl(\d.\d)', name) + if mo: + ver = mo.group(1) + print "I: found TCL/TK version %s" % ver + open(os.path.join(HOME, 'support/useTK.py'), 'w').write(_useTK % (ver, ver)) + tclnm = 'tcl%s' % ver + tknm = 'tk%s' % ver + # Linux: /usr/lib with the .tcl files in /usr/lib/tcl8.3 and /usr/lib/tk8.3 + # Windows: Python21/DLLs with the .tcl files in Python21/tcl/tcl8.3 and Python21/tcl/tk8.3 + # or D:/Programs/Tcl/bin with the .tcl files in D:/Programs/Tcl/lib/tcl8.0 and D:/Programs/Tcl/lib/tk8.0 + if iswin: + for attempt in ['../tcl', '../lib']: + if os.path.exists(os.path.join(tclbindir, attempt, tclnm)): + config['TCL_root'] = os.path.join(tclbindir, attempt, tclnm) + config['TK_root'] = os.path.join(tclbindir, attempt, tknm) + break + else: + config['TCL_root'] = os.path.join(tclbindir, tclnm) + config['TK_root'] = os.path.join(tclbindir, tknm) + break +else: + print "I: could not find TCL/TK" +if not iswin: + bindepend.excludes = saveexcludes + +#useZLIB +print "I: testing for Zlib..." +try: + import zlib +except ImportError: + config['useZLIB'] = 0 + print 'I: ... Zlib unavailable' +else: + config['useZLIB'] = 1 + print 'I: ... Zlib available' + +#hasRsrcUpdate +if iswin: + # only available on windows + print "I: Testing for ability to set icons, version resources..." + try: + import win32api, icon, versionInfo + except ImportError, detail: + config['hasRsrcUpdate'] = 0 + print 'I: ... resource update unavailable -', detail + else: + test_exe = os.path.join(HOME, r'support\run.exe') + if not os.path.exists( test_exe ): + config['hasRsrcUpdate'] = 0 + print 'E: ... resource update unavailable - %s not found' % test_exe + else: + # The test_exe may be read-only + # make a writable copy and test using that + rw_test_exe = os.path.join( os.environ['TEMP'], 'me_test_exe.tmp' ) + shutil.copyfile( test_exe, rw_test_exe ) + try: + hexe = win32api.BeginUpdateResource(rw_test_exe,0) + except: + config['hasRsrcUpdate'] = 0 + print 'I: ... resource update unavailable - win32api.BeginUpdateResource failed' + else: + win32api.EndUpdateResource(hexe, 1) + config['hasRsrcUpdate'] = 1 + print 'I: ... resource update available' + os.remove(rw_test_exe) +else: + config['hasRsrcUpdate'] = 0 + +#hasUnicode +print 'I: Testing for Unicode support...' +try: + import codecs + config['hasUnicode'] = 1 + print 'I: ... Unicode available' +except ImportError: + config['hasUnicode'] = 0 + print 'I: ... Unicode unavailable' + +#hasUPX +print 'I: testing for UPX...' +hasUPX = 0 +try: + if iswin: + os.system('upx -V >upx.txt') + txt = open('upx.txt','r').read() + os.remove('upx.txt') + if txt[:3] == 'upx': + hasUPX = 1 + else: + rc = os.system('upx -V >/dev/null') + hasUPX = ( rc == 0 ) + print 'I: ...UPX %s' % (('unavailable','available')[hasUPX]) +except Exception, e: + print 'I: ...exception result in testing for UPX' + print e, e.args +config['hasUPX'] = hasUPX + +# now write out config, so Build can load +outf = open(configfile, 'w') +import pprint +pprint.pprint(config, outf) +outf.close() + +import Build + +# PYZ_dependencies +print "I: computing PYZ dependencies..." +a = mf.ImportTracker([os.path.join(HOME, 'support')]) +a.analyze_r('archive') +mod = a.modules['archive'] +toc = Build.TOC([(mod.__name__, mod.__file__, 'PYMODULE')]) +for i in range(len(toc)): + nm, fnm, typ = toc[i] + mod = a.modules[nm] + tmp = [] + for importednm, isdelayed, isconditional in mod.imports: + if not isconditional: + realnms = a.analyze_one(importednm, nm) + for realnm in realnms: + imported = a.modules[realnm] + if not isinstance(imported, mf.BuiltinModule): + tmp.append((imported.__name__, imported.__file__, imported.typ)) + toc.extend(tmp) +toc.reverse() +config['PYZ_dependencies'] = toc.data + +outf = open(configfile, 'w') +import pprint +pprint.pprint(config, outf) +outf.close() + diff --git a/GrabVersion.py b/GrabVersion.py new file mode 100644 index 0000000..8931b26 --- /dev/null +++ b/GrabVersion.py @@ -0,0 +1,14 @@ +import versionInfo + +import sys +if len(sys.argv) < 2: + print "Usage: >python GrabVersion.py " + print " where: is the fullpathname of a Windows executable." + print " The printed output may be saved to a file, editted and " + print " used as the input for a verion resource on any of the " + print " executable targets in an Installer config file." + print " Note that only NT / Win2K can set version resources." +else: + vs = versionInfo.decode(sys.argv[1]) + print vs + diff --git a/MakeCOMServer_old.py b/MakeCOMServer_old.py new file mode 100644 index 0000000..309b6ec --- /dev/null +++ b/MakeCOMServer_old.py @@ -0,0 +1,150 @@ +import string, os, sys, win32api, Makespec + +modspec = """\ + %(mod)s.%(klass)s._reg_class_spec_ = "%(mod)s.%(klass)s" + if (not hasattr(%(mod)s.%(klass)s, '_reg_clsctx_') or + %(mod)s.%(klass)s._reg_clsctx_ & pythoncom.CLSCTX_INPROC): + %(mod)s.%(klass)s._reg_options_ = {'InprocServer32': + os.path.abspath( + os.path.join( + os.path.dirname(sys.executable), "%(dllname)s"))} +""" #mod, klass, dllname +tmplt = """\ +import sys +import string +import os +inprocess = getattr(sys, 'frozen', None) +%(modimports)s + +register = 0 +for i in range(1, len(sys.argv)): + arg = sys.argv[i] + if string.find(arg, "reg") > -1: + register = 1 + if arg == '/unreg': + sys.argv[i] = '--unregister' +if register: + import pythoncom + pythoncom.frozen = 1 +%(modspecs)s + from win32com.server import register + register.UseCommandLine(%(regspecs)s, %(flags)s) +else: + #older Python's need to force this import before pythoncom does it + import win32com.server.policy + if inprocess == 'dll': + pass + else: + import win32com.server.localserver + win32com.server.localserver.main() + +""" #modimports, modspecs regspecs, flags + +def create(scripts, debug, verbosity, workdir, ascii=0): + infos = [] # (path, module, klasses) + for script in scripts: + infos.append(analscriptname(script)) + outfnm = 'drive%s.py' % infos[0][1] + dllname = 'drive%s.dll' % infos[0][1] + if not os.path.exists(workdir): + os.makedirs(workdir) + outfnm = os.path.join(workdir, outfnm) + outf = open(outfnm, 'w') + modspecs = [] + regspecs = [] + modimports = [] + flags = 'debug=0, quiet=%s' % (verbosity==0) + paths = [] + for path, module, klasses in infos: + if path: + paths.append(path) + for klass in klasses: + d = { 'mod':module, 'klass':klass, 'dllname':dllname } + modspecs.append(modspec % d) + regspecs.append('%(mod)s.%(klass)s' % d) + modimports.append("import %(mod)s" % d) + for i in range(len(paths)): + path = paths[i] + paths[i] = win32api.GetShortPathName(os.path.normpath(path)) + modspecs = string.join(modspecs, '\n') + modimports = string.join(modimports, '\n') + regspecs = string.join(regspecs, ', ') + d = { 'modspecs':modspecs, + 'regspecs':regspecs, + 'modimports':modimports, + 'flags':flags } + outf.write( tmplt % d ) + outf.close() + print "**********************************" + print "Driver script %s created" % outfnm + specfnm = Makespec.main([outfnm], console=debug, debug=debug, + workdir=workdir, pathex=paths, comserver=1, ascii=ascii) + print "Spec file %s created" % specfnm + +def analscriptname(script): + # return (path, module, klasses) + path, basename = os.path.split(script) + module = os.path.splitext(basename)[0] + while ispkgdir(path): + path, basename = os.path.split(path) + module = '%s.%s' % (basename, module) + try: + __import__(module) + except ImportError: + oldpath = sys.path[:] + sys.path.insert(0, path) + try: + __import__(module) + finally: + sys.path = oldpath + else: + path = None + m = sys.modules[module] + klasses = [] + for nm, thing in m.__dict__.items(): + if hasattr(thing, '_reg_clsid_'): + klasses.append(nm) + return (path, module, klasses) + +def ispkgdir(path): + try: + open(os.path.join(path, '__init__.py'), 'r') + except IOError: + try: + open(os.path.join(path, '__init__.pyc'), 'rb') + except IOError: + return 0 + return 1 + +usage = """\ +Usage: python %s [options] .py [.py ...] + --debug -> use debug console build and register COM servers with debug + --verbose -> use verbose flag in COM server registration + --out dir -> generate script and spec file in dir + +The next step is to run Build.py against the generated spec file. +See doc/begin.html for details. +""" + +if __name__ == '__main__': + #scripts, debug, verbosity, workdir + debug = verbosity = ascii = 0 + workdir = '.' + import getopt + opts, args = getopt.getopt(sys.argv[1:], '', ['debug', 'verbose', 'ascii', 'out=']) + for opt, val in opts: + if opt == '--debug': + debug = 1 + elif opt == '--verbose': + verbosity = 1 + elif opt == '--out': + workdir = val + elif opt == '--ascii': + ascii = 1 + else: + print usage % sys.argv[0] + sys.exit(1) + if not args: + print usage % sys.argv[0] + else: + create(args, debug, verbosity, workdir, ascii) diff --git a/MakeComServer.py b/MakeComServer.py new file mode 100644 index 0000000..1edf59a --- /dev/null +++ b/MakeComServer.py @@ -0,0 +1,150 @@ +import string, os, sys, win32api, Makespec + +tmplt = """\ +import sys +import string +import os +import pythoncom +pythoncom.frozen = 1 +inprocess = getattr(sys, 'frozen', None) + +%(modules)s +klasses = (%(klasses)s,) + +def DllRegisterServer(): + import win32com.server.register + win32com.server.register.RegisterClasses(*klasses) + return 0 + +def DllUnregisterServer(): + import win32com.server.register + win32com.server.register.UnregisterClasses(*klasses) + return 0 + +if sys.frozen!="dll": + import win32com.server.localserver + for i in range(1, len(sys.argv)): + arg = string.lower(sys.argv[i]) + if string.find(arg, "/reg") > -1 or string.find(arg, "--reg") > -1: + DllRegisterServer() + break + + if string.find(arg, "/unreg") > -1 or string.find(arg, "--unreg") > -1: + DllUnregisterServer() + break + + # MS seems to like /automate to run the class factories. + if string.find(arg, "/automate") > -1: + clsids = [] + for k in klasses: + clsids.append(k._reg_clsid_) + win32com.server.localserver.serve(clsids) + break + else: + # You could do something else useful here. + import win32api + win32api.MessageBox(0, "This program hosts a COM Object and\\r\\nis started automatically", "COM Object") +""" + +def create(scripts, debug, verbosity, workdir, ascii=0): + infos = [] # (path, module, klasses) + for script in scripts: + infos.append(analscriptname(script)) + if not os.path.exists(workdir): + os.makedirs(workdir) + outfnm = 'drive%s.py' % infos[0][1] + outfnm = os.path.join(workdir, outfnm) + outf = open(outfnm, 'w') + klassspecs = [] + modimports = [] + flags = 'debug=%s, quiet=%s' % (debug, verbosity==0) + paths = [] + for path, module, klasses in infos: + if path: + paths.append(path) + modimports.append("import %s" % (module,)) + for klass in klasses: + klassspecs.append("%s.%s" % (module, klass)) + for i in range(len(paths)): + path = paths[i] + paths[i] = win32api.GetShortPathName(os.path.normpath(path)) + modimports = string.join(modimports, '\n') + klassspecs = string.join(klassspecs, ', ') + d = { 'modules':modimports, + 'klasses':klassspecs, + } + outf.write( tmplt % d ) + outf.close() + print "**********************************" + print "Driver script %s created" % outfnm + specfnm = Makespec.main([outfnm], console=debug, debug=debug, + workdir=workdir, pathex=paths, comserver=1, ascii=ascii) + print "Spec file %s created" % specfnm + +def analscriptname(script): + # return (path, module, klasses) + path, basename = os.path.split(script) + module = os.path.splitext(basename)[0] + while ispkgdir(path): + path, basename = os.path.split(path) + module = '%s.%s' % (basename, module) + try: + __import__(module) + except ImportError: + oldpath = sys.path[:] + sys.path.insert(0, path) + try: + __import__(module) + finally: + sys.path = oldpath + else: + path = None + m = sys.modules[module] + klasses = [] + for nm, thing in m.__dict__.items(): + if hasattr(thing, '_reg_clsid_'): + klasses.append(nm) + return (path, module, klasses) + +def ispkgdir(path): + try: + open(os.path.join(path, '__init__.py'), 'r') + except IOError: + try: + open(os.path.join(path, '__init__.pyc'), 'rb') + except IOError: + return 0 + return 1 + +usage = """\ +Usage: python %s [options] .py [.py ...] + --debug -> use debug console build and register COM servers with debug + --verbose -> use verbose flag in COM server registration + --out dir -> generate script and spec file in dir + +The next step is to run Build.py against the generated spec file. +See doc/begin.html for details. +""" + +if __name__ == '__main__': + #scripts, debug, verbosity, workdir + debug = verbosity = ascii = 0 + workdir = '.' + import getopt + opts, args = getopt.getopt(sys.argv[1:], '', ['debug', 'verbose', 'ascii', 'out=']) + for opt, val in opts: + if opt == '--debug': + debug = 1 + elif opt == '--verbose': + verbosity = 1 + elif opt == '--out': + workdir = val + elif opt == '--ascii': + ascii = 1 + else: + print usage % sys.argv[0] + sys.exit(1) + if not args: + print usage % sys.argv[0] + else: + create(args, debug, verbosity, workdir, ascii) diff --git a/Makespec.py b/Makespec.py new file mode 100644 index 0000000..64b3724 --- /dev/null +++ b/Makespec.py @@ -0,0 +1,251 @@ +#! /usr/bin/env/python + +import sys, os, string + +freezetmplt = """\ +a = Analysis(%(scripts)s, + pathex=%(pathex)s) +pyz = PYZ(a.pure) +exe = EXE(%(tkpkg)s pyz, + a.scripts, + a.binaries, + name='%(exename)s', + debug=%(debug)s, + strip=%(strip)s, + upx=%(upx)s, + console=%(console)s %(exe_options)s) +""" # pathex scripts exename tkpkg debug console + +collecttmplt = """\ +a = Analysis(%(scripts)s, + pathex=%(pathex)s) +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + exclude_binaries=1, + name='%(builddir)s/%(exename)s', + debug=%(debug)s, + strip=%(strip)s, + upx=%(upx)s, + console=%(console)s %(exe_options)s) +coll = COLLECT(%(tktree)s exe, + a.binaries, + strip=%(strip)s, + upx=%(upx)s, + name='%(distdir)s') +""" # scripts pathex, exename, debug, console tktree distdir + +comsrvrtmplt = """\ +a = Analysis(%(scripts)s, + pathex=%(pathex)s) +pyz = PYZ(a.pure) +exe = EXE(pyz, + a.scripts, + exclude_binaries=1, + name='%(builddir)s/%(exename)s', + debug=%(debug)s, + strip=%(strip)s, + upx=%(upx)s, + console=%(console)s %(exe_options)s) +dll = DLL(pyz, + a.scripts, + exclude_binaries=1, + name='%(builddir)s/%(dllname)s', + debug=%(debug)s) +coll = COLLECT(exe, dll, + a.binaries, + strip=%(strip)s, + upx=%(upx)s, + name='%(distdir)s') +""" # scripts pathex, exename, debug, console tktree distdir +HOME = os.path.dirname(sys.argv[0]) +if HOME == '': + HOME = os.getcwd() +if not os.path.isabs(HOME): + HOME = os.path.abspath(HOME) +iswin = sys.platform[:3] == "win" +cygwin = sys.platform == "cygwin" +try: + config = eval(open(os.path.join(HOME, 'config.dat'), 'r').read()) +except IOError: + print "You must run Configure.py before building!" + sys.exit(1) + +def quote_win_filepath( path ): + # quote all \ with another \ after using normpath to clean up the path + return string.join( string.split( os.path.normpath( path ), '\\' ), '\\\\' ) + +# Support for trying to avoid hard-coded paths in the .spec files. +# Eg, all files rooted in the Installer directory tree will be +# written using "HOMEPATH", thus allowing this spec file to +# be used with any Installer installation. +# Same thing could be done for other paths too. +path_conversions = ( + (HOME, "HOMEPATH"), + # Add Tk etc? + ) + +def make_variable_path(filename, conversions = path_conversions): + for (from_path, to_name) in conversions: + assert os.path.abspath(from_path)==from_path, \ + "path '%s' should already be absolute" % (from_path,) + if filename.startswith(from_path): + rest = filename[len(from_path):] + if rest[0] in "\\/": + rest = rest[1:] + return to_name, rest + return None, filename + +# An object used in place of a "path string" which knows how to repr() +# itself using variable names instead of hard-coded paths. +class Path: + def __init__(self, *parts): + self.path = os.path.join(*parts) + self.variable_prefix = self.filename_suffix = None + def __repr__(self): + if self.filename_suffix is None: + self.variable_prefix, self.filename_suffix = make_variable_path(self.path) + if self.variable_prefix is None: + return repr(self.path) + return "os.path.join(" + self.variable_prefix + "," + repr(self.filename_suffix) + ")" + +def main(scripts, name=None, tk=0, freeze=0, console=1, debug=0, strip=0, upx=0, + comserver=0, ascii=0, workdir=None, pathex=None, version_file=None, icon_file=None): + if name is None: + name = os.path.splitext(os.path.basename(scripts[0]))[0] + distdir = "dist%s" % name + builddir = "build%s" % name + if pathex is None: + pathex = [] + elif type(pathex) is type(''): + if iswin: + pathex = string.split(pathex, ';') + else: + pathex = string.split(pathex, ':') + if workdir is None: + workdir = os.getcwd() + pathex.append(workdir) + else: + pathex.append(os.getcwd()) + if workdir == HOME: + workdir = os.path.join(HOME, name) + if not os.path.exists(workdir): + os.makedirs(workdir) + exe_options = '' + if version_file: + exe_options = "%s, version='%s'" % (exe_options, quote_win_filepath(version_file)) + if icon_file: + exe_options = "%s, icon='%s'" % (exe_options, quote_win_filepath(icon_file)) + if not ascii and config['hasUnicode']: + scripts.insert(0, os.path.join(HOME, 'support', 'useUnicode.py')) + for i in range(len(scripts)): + scripts[i] = Path(scripts[i]) + d = {'tktree':'', + 'tkpkg' :'', + 'scripts':scripts, + 'pathex' :pathex, + 'exename': '', + 'distdir': distdir, + 'builddir': builddir, + 'debug': debug, + 'strip': strip, + 'upx' : upx, + 'console': console or debug, + 'exe_options': exe_options} + if tk: + d['tktree'] = "TkTree()," + if freeze: + scripts.insert(0, Path(HOME, 'support', 'useTK.py')) + scripts.insert(0, Path(HOME, 'support', 'unpackTK.py')) + scripts.append(Path(HOME, 'support', 'removeTK.py')) + d['tkpkg'] = "TkPKG()," + else: + scripts.insert(0, Path(HOME, 'support', 'useTK.py')) + scripts.insert(0, Path(HOME, 'support', '_mountzlib.py')) + if iswin or cygwin: + d['exename'] = name+'.exe' + d['dllname'] = name+'.dll' + else: + d['exename'] = name + d['console'] = 1 + specfnm = os.path.join(workdir, name+'.spec') + specfile = open(specfnm, 'w') + if freeze: + specfile.write(freezetmplt % d) + elif comserver: + specfile.write(comsrvrtmplt % d) + else: + specfile.write(collecttmplt % d) + specfile.close() + return specfnm + +usage = """\ +Usage: python %s [options] [ ...] + --onefile -> create a single file deployment + --onedir -> create a single directory deployment (default) + --tk -> include TCL/TK in the deployment + --noconsole -> use a Windows subsystem executable (Windows only) + --ascii -> do NOT include unicode encodings (default: included if available) + --debug -> use the debug (verbose) build of the executable + --strip -> strip the exe and shared libs (don't try this on Windows) + --upx -> use UPX if available (works differently Windows / Linux) + --out dir -> gemerate the spec file in dir + --paths pathstring -> like using PYTHONPATH + --icon file.ico -> add the icon in file.ico to the exe (Windows only) + --icon file.exe,id -> add the icon with id from file.exe to the exe (Windows only) + --version verfile -> add a version resource from verfile to the exe (Windows only) +The next step is to run Build.py against the generated spec file. +See doc/begin.html for details. +""" + +#scripts, name=None, tk=0, freeze=0, console=1, debug=0,workdir=None, pathex=None +if __name__ == '__main__': + import getopt + tk = freeze = debug = ascii = strip = upx = 0 + console = 1 + workdir = name = pathex = None + icon_file = None + version_file = None + opts, args = getopt.getopt(sys.argv[1:], '', + ['onefile', 'onedir', 'tk', 'noconsole', 'debug', 'ascii', + 'strip', 'upx', 'out=', 'name=', 'paths=', 'version=', 'icon=']) + for opt, val in opts: + if opt == '--onefile': + freeze = 1 + elif opt == '--onedir': + freeze = 0 + elif opt == '--tk': + tk = 1 + elif opt == '--noconsole': + console = 0 + elif opt == '--debug': + debug = 1 + elif opt == '--out': + workdir = val + elif opt == '--name': + name = val + elif opt == '--ascii': + ascii = 1 + elif opt == '--strip': + strip = 1 + elif opt == '--upx': + upx = 1 + elif opt == '--icon': + icon_file = val + elif opt == '--version': + version_file = val + elif opt == '--paths': + pathex = val + else: + print "bad option: %s" % (opt, val) + print usage % sys.argv[0] + sys.exit(1) + if not args: + print usage % sys.argv[0] + else: + nm = main(args, name=name, tk=tk, freeze=freeze, console=console, + debug=debug, strip=strip, upx=upx, ascii=ascii, + workdir=workdir, pathex=pathex, + version_file=version_file, icon_file=icon_file) + print "wrote %s" % nm + diff --git a/McGUI.py b/McGUI.py new file mode 100644 index 0000000..f95333f --- /dev/null +++ b/McGUI.py @@ -0,0 +1,100 @@ +#!/usr/bin/python + +# Tkinter interface to the McMillan installer +# (c) 2003 Alan James Salmoni - yes, all this bad code is all mine!!! +# released under the MIT license + +import os, os.path +from Tkinter import * +import tkFileDialog +import FileDialog + +class McGUI: + def __init__(self): + root = Tk() + fr1 = Frame(root) + fr1["width"] = 200 + fr1["height"] = 100 + fr1.pack(side="top") + fr2 = Frame(root) + fr2["width"] = 200 + fr2["height"] = 300 + fr2["borderwidth"] = 2 + fr2["relief"] = "ridge" + fr2.pack() + fr4 = Frame(root) + fr4["width"]=200 + fr4["height"]=100 + fr4.pack(side="bottom") + getFileButton = Button(fr1) + getFileButton["text"] = "Script..." + getFileButton.bind("