mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-24 20:22:33 -06:00
504 lines
19 KiB
Python
504 lines
19 KiB
Python
import string
|
|
import pprint
|
|
import sys
|
|
import os
|
|
import ConfigParser
|
|
import pprint
|
|
import shutil
|
|
import tempfile
|
|
import ltoc
|
|
import tocfilter
|
|
import resource
|
|
import archive
|
|
import archivebuilder
|
|
import carchive
|
|
|
|
logfile = None
|
|
autopath = []
|
|
built = {}
|
|
copyFile = None
|
|
|
|
class Target:
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
self.children = []
|
|
self._dependencies = ltoc.lTOC() # the stuff an outer package will need to use me
|
|
self.cfg = cfg
|
|
self.__name__ = 'joe'
|
|
for optnm in cfg.options(sectnm):
|
|
cnvrt = cnvrts.get(optnm, 'getstringlist')
|
|
if cnvrt:
|
|
f = getattr(self, cnvrt, None)
|
|
if f:
|
|
self.__dict__[optnm] = f(cfg.get(sectnm, optnm))
|
|
if not hasattr(self, 'name'):
|
|
self.name = self.__name__
|
|
print "Initializing", self.__name__
|
|
self.pathprefix = autopath + self.pathprefix
|
|
self.pathprefix.append(os.path.join(pyinsthome, 'support'))
|
|
for z in self.zlib:
|
|
if z in self.cfg.sections():
|
|
self.children.append(z)
|
|
else:
|
|
raise ValueError, "%s - zlib '%s' does not refer to a sections" \
|
|
% (self.name, z)
|
|
for i in range(len(self.misc)):
|
|
x = self.misc[i]
|
|
if x in self.cfg.sections():
|
|
if self.cfg.get(x, "type") == 'PYZ':
|
|
self.zlib.append(x)
|
|
self.misc[i] = None
|
|
self.children.append(x)
|
|
self.misc = filter(None, self.misc)
|
|
self.edit()
|
|
self.toc = ltoc.lTOC()
|
|
for thingie in self.excludes:
|
|
try:
|
|
fltr = tocfilter.makefilter(thingie, self.pathprefix)
|
|
except ValueError:
|
|
print "Warning: '%s' not found - no filter created" % thingie
|
|
else:
|
|
self.toc.addFilter(fltr)
|
|
if self.exstdlib:
|
|
self.toc.addFilter(tocfilter.StdLibFilter())
|
|
if self.extypes:
|
|
self.toc.addFilter(tocfilter.ExtFilter(self.extypes))
|
|
if self.expatterns:
|
|
self.toc.addFilter(tocfilter.PatternFilter(self.expatterns))
|
|
|
|
##------utilities------##
|
|
def dump(self):
|
|
logfile.write("---- %s: %s -----\n" % (self.__class__.__name__, self.name))
|
|
pprint.pprint(self.__dict__, logfile)
|
|
def getstringlist(self, opt):
|
|
tmp = string.split(opt, ',')
|
|
return filter(None, map(string.strip, tmp))
|
|
def getstring(self, opt):
|
|
return opt
|
|
def getbool(self, opt):
|
|
if opt in ('0','f','F','n','N'):
|
|
return 0
|
|
return 1
|
|
##-----framework-----##
|
|
def build(self):
|
|
print "Gathering components of %s" % self.name
|
|
self.gather()
|
|
logfile.write("Final Table of Contents for %s:\n" % self.name)
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
print "Creating %s" % self.name
|
|
self.assemble()
|
|
##-----overrideables-----##
|
|
def edit(self):
|
|
pass
|
|
def gather(self):
|
|
pass
|
|
def assemble(self):
|
|
pass
|
|
|
|
class PYZTarget(Target):
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
Target.__init__(self, cfg, sectnm, cnvrts)
|
|
# to use a PYZTarget, you'll need imputil and archive
|
|
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'imputil.py')])
|
|
print "pyinsthome:", pyinsthome
|
|
imputil = resource.makeresource('imputil.py', [pyinsthome])
|
|
self._dependencies.append(imputil)
|
|
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'archive_rt.py')])
|
|
archmodule = resource.makeresource('archive_rt.py', [pyinsthome])
|
|
self._dependencies.merge(archmodule.dependencies())
|
|
self._dependencies.append(archmodule)
|
|
self.toc.addFilter(archmodule)
|
|
self.toc.addFilter(imputil)
|
|
for mod in archmodule.modules:
|
|
self.toc.addFilter(mod)
|
|
def edit(self):
|
|
if self.extypes:
|
|
print "PYZ target %s ignoring extypes = %s" % (self.__name__, self.extypes)
|
|
|
|
def gather(self):
|
|
for script in self.dependencies:
|
|
rsrc = resource.makeresource(script, self.pathprefix)
|
|
if not isinstance(rsrc, resource.scriptresource):
|
|
print "Bug alert - Made %s from %s!" % (rsrc, script)
|
|
self.toc.merge(rsrc.modules)
|
|
logfile.write("lTOC after expanding 'depends':\n")
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
for thingie in self.includes + self.directories + self.packages:
|
|
rsrc = resource.makeresource(thingie, self.pathprefix)
|
|
## if not isinstance(rsrc, resource.pythonresource):
|
|
## print "PYZ target %s ignoring include %s" % (self.name, thingie)
|
|
## else:
|
|
self.toc.merge(rsrc.contents())
|
|
logfile.write("lTOC after includes, dir, pkgs:\n")
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
self.toc.addFilter(tocfilter.ExtFilter(['.py', '.pyc', '.pyo'], 1))
|
|
logfile.write("Applying the following filters:\n")
|
|
pprint.pprint(self.toc.filters, logfile)
|
|
self.toc.filter()
|
|
|
|
def assemble(self):
|
|
contents = self.toc.toList()
|
|
if contents:
|
|
lib = archive.ZlibArchive()
|
|
lib.build(self.name, archivebuilder.GetCompiled(self.toc.toList()))
|
|
|
|
class CollectTarget(Target):
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
Target.__init__(self, cfg, sectnm, cnvrts)
|
|
|
|
_rsrcdict = {'COLLECT': resource.dirresource, 'PYZ': resource.zlibresource, 'CARCHIVE': resource.archiveresource}
|
|
|
|
def gather(self):
|
|
if self.support:
|
|
# the bare minimum
|
|
self.toc.merge([resource.makeresource('python20.dll')])
|
|
self.toc.merge([resource.makeresource('exceptions.pyc').asBinary()])
|
|
# zlib, bindepends, misc, trees, destdir
|
|
for i in range(len(self.zlib)):
|
|
# z refers to the section name
|
|
z = self.zlib[i]
|
|
nm = self.cfg.get(z, 'name')
|
|
try:
|
|
self.toc.merge([resource.makeresource(nm, ['.'])])
|
|
except ValueError:
|
|
# zlibs aren't written if they turn out to be empty
|
|
self.zlib[i] = None
|
|
self.zlib = filter(None, self.zlib)
|
|
if self.zlib:
|
|
target = built.get(self.zlib[0], None)
|
|
if target:
|
|
self.toc.merge(target._dependencies)
|
|
for script in self.bindepends:
|
|
rsrc = resource.makeresource(script, self.pathprefix)
|
|
self.toc.merge(rsrc.binaries)
|
|
logfile.write('ltoc after bindepends:\n')
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
for thingie in self.misc:
|
|
if thingie in self.cfg.sections():
|
|
name = self.cfg.get(thingie, "name")
|
|
typ = self.cfg.get(thingie, "type")
|
|
klass = self._rsrcdict.get(typ, resource.dataresource)
|
|
rsrc = apply(klass, (name, name))
|
|
#now make sure we have the stuff the resource requires
|
|
target = built.get(thingie, None)
|
|
if target:
|
|
self.toc.merge(target._dependencies)
|
|
else:
|
|
rsrc = resource.makeresource(thingie, self.pathprefix)
|
|
self.toc.merge(rsrc.contents())
|
|
logfile.write('ltoc after misc:\n')
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
for script in self.script:
|
|
if string.find(script, '.') == -1:
|
|
script = script + '.py'
|
|
rsrc = resource.makeresource(script, self.pathprefix)
|
|
if rsrc.typ == 'm':
|
|
rsrc.typ = 's'
|
|
self.toc.merge([rsrc])
|
|
logfile.write('ltoc after scripts:\n')
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
for tree in self.trees:
|
|
try:
|
|
rsrc = resource.treeresource('.', tree)
|
|
except ValueError:
|
|
print "tree %s not found" % tree
|
|
else:
|
|
self.toc.merge(rsrc.contents())
|
|
logfile.write('ltoc after trees:\n')
|
|
pprint.pprint(self.toc.toList(), logfile)
|
|
self.toc.addFilter(tocfilter.TypeFilter(['d']))
|
|
logfile.write("Applying the following filters:\n")
|
|
pprint.pprint(self.toc.filters, logfile)
|
|
self.toc.filter()
|
|
#don't dupe stuff in a zlib that's part of this target
|
|
if self.zlib:
|
|
ztoc = ltoc.lTOC()
|
|
for zlibnm in self.zlib:
|
|
target = built.get(zlibnm, None)
|
|
if target:
|
|
ztoc.merge(target.toc)
|
|
for i in range(len(self.toc)-1, -1, -1):
|
|
rsrc = self.toc[i]
|
|
if isinstance(rsrc, resource.moduleresource) and rsrc in ztoc:
|
|
del self.toc[i]
|
|
|
|
def assemble(self):
|
|
if os.path.exists(self.name):
|
|
if os.path.isdir(self.name):
|
|
for fnm in os.listdir(self.name):
|
|
try:
|
|
os.remove(os.path.join(self.name, fnm))
|
|
except:
|
|
print "Could not delete file %s" % os.path.join(self.name, fnm)
|
|
else:
|
|
os.makedirs(self.name)
|
|
mysite = []
|
|
for nm, path, typ in self.toc.toList():
|
|
shutil.copy2(path, self.name)
|
|
if typ == 'z':
|
|
mysite.append('imputil.FuncImporter(archive.ZlibArchive("%s", 0).get_code).install()' % nm)
|
|
if mysite:
|
|
mysite.insert(0, 'import archive, imputil')
|
|
open(os.path.join(self.name, 'site.py'),'w').write(string.join(mysite, '\n'))
|
|
|
|
|
|
class ArchiveTarget(CollectTarget):
|
|
usefullname = 1
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
CollectTarget.__init__(self, cfg, sectnm, cnvrts)
|
|
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'carchive_rt.py')])
|
|
carchmodule = resource.makeresource('carchive_rt.py', [pyinsthome])
|
|
self._dependencies.merge(carchmodule.dependencies())
|
|
self._dependencies.append(carchmodule)
|
|
|
|
def edit(self):
|
|
if self.destdir:
|
|
print "Warning 'destdir = %s' ignored for %s" % (self.destdir, self.name)
|
|
|
|
def gather(self):
|
|
CollectTarget.gather(self)
|
|
|
|
_cdict = {'s':2,'m':1,'b':1,'x':1,'a':0,'z':0, 'p':1}
|
|
|
|
def assemble(self, pkgnm=None):
|
|
if pkgnm is None:
|
|
pkgnm = self.name
|
|
arch = carchive.CArchive()
|
|
toc = []
|
|
pytoc = []
|
|
for nm, path, typ in self.toc.toList():
|
|
compress = self._cdict[typ]
|
|
if typ == 'b' or (self.usefullname and typ in 'ms'):
|
|
nm = os.path.basename(path)
|
|
if typ == 'm':
|
|
pytoc.append((nm, path, compress, typ))
|
|
else:
|
|
toc.append((nm, path, compress, typ))
|
|
toc = toc + archivebuilder.GetCompiled(pytoc)
|
|
arch.build(pkgnm, toc)
|
|
return arch
|
|
|
|
class FullExeTarget(ArchiveTarget):
|
|
usefullname = 0
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
ArchiveTarget.__init__(self, cfg, sectnm, cnvrts)
|
|
|
|
def gather(self):
|
|
for script in self.script:
|
|
#print "FullExeTarget.gather: script is", repr(script)
|
|
rsrc = resource.makeresource(script, self.pathprefix)
|
|
rsrc = resource.scriptresource(rsrc.name, rsrc.path)
|
|
#print " resource is", repr(rsrc)
|
|
self.toc.merge(rsrc.binaries)
|
|
ArchiveTarget.gather(self)
|
|
if not self.zlib:
|
|
self.toc.merge(rsrc.modules)
|
|
self._dependencies = ltoc.lTOC()
|
|
|
|
_cdict = {'s':2,'m':0,'b':1,'x':0,'a':0,'z':0}
|
|
_edict = { (1, 1):'Runw_d.exe', (1, 0):'Runw.exe', (0, 1):'Run_d.exe', (0, 0):'Run.exe'}
|
|
|
|
def assemble(self):
|
|
pkgname = tempfile.mktemp()
|
|
arch = ArchiveTarget.assemble(self, pkgname)
|
|
exe = self._edict[(self.userunw, self.debug)]
|
|
exe = os.path.normpath(os.path.join(pyinsthome, 'support', exe))
|
|
## copyFile([exe, pkgname], self.name)
|
|
## os.remove(pkgname)
|
|
# Thomas Heller's icon code
|
|
# my version
|
|
if self.icon:
|
|
myexe = tempfile.mktemp()
|
|
copyFile (exe, myexe)
|
|
try:
|
|
from icon import CopyIcons
|
|
CopyIcons(myexe, self.icon)
|
|
except ImportError:
|
|
print "win32api is required for updating icons"
|
|
print "You should have win32api.pyd and PyWinTypes20.dll"
|
|
print "in the installation directory."
|
|
print "Please copy them to Python's DLLS subdirectory"
|
|
print "(or install Mark Hammond's Win32 extensions)."
|
|
## iconfile = None
|
|
## for name in self.cfg.sections():
|
|
## if self.cfg.get (name, "type") == "STANDALONE":
|
|
## try:
|
|
## iconfile = self.cfg.get (name, "iconfile")
|
|
## except:
|
|
## pass
|
|
## if iconfile:
|
|
## from icon import CopyIcons
|
|
## CopyIcons (myexe, iconfile)
|
|
copyFile ([myexe, pkgname], self.name)
|
|
os.remove(myexe)
|
|
else:
|
|
copyFile([exe, pkgname], self.name)
|
|
#os.remove(pkgname)
|
|
|
|
class ExeTarget(FullExeTarget):
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
FullExeTarget.__init__(self, cfg, sectnm, cnvrts)
|
|
|
|
def edit(self):
|
|
if not self.script:
|
|
raise ValueError, "EXE target %s requires 'script= <script>'" % self.__name__
|
|
|
|
def gather(self):
|
|
FullExeTarget.gather(self)
|
|
for i in range(len(self.toc)-1, -1, -1):
|
|
rsrc = self.toc[i]
|
|
if rsrc.typ == 'b':
|
|
self._dependencies.append(rsrc)
|
|
del self.toc[i]
|
|
|
|
installpreamble = """\
|
|
import sys, os
|
|
import installutils
|
|
import carchive_rt
|
|
idir = installutils.getinstalldir()
|
|
me = sys.argv[0]
|
|
if me[:-4] != '.exe':
|
|
me = me + '.exe'
|
|
this = carchive_rt.CArchive(sys.argv[0])
|
|
here = sys.path[0]
|
|
"""
|
|
mvfile = "installutils.copyFile(os.path.join(here, '%s'), os.path.join(idir, '%s'))\n"
|
|
extractfile = "open(os.path.join(idir, '%s'), 'wb').write(this.extract('%s')[1])\n"
|
|
sitepreamble = """\
|
|
import archive_rt
|
|
import imputil
|
|
import sys
|
|
"""
|
|
importzlib = "imputil.FuncImporter(archive_rt.ZlibArchive(sys.path[0]+'/%s').get_code).install()\n"
|
|
|
|
class InstallTarget(FullExeTarget):
|
|
def __init__(self, cfg, sectnm, cnvrts):
|
|
FullExeTarget.__init__(self, cfg, sectnm, cnvrts)
|
|
|
|
def edit(self):
|
|
if not self.script:
|
|
open('gen_install.py', 'w').write(installpreamble)
|
|
self.script = ['gen_install.py']
|
|
|
|
def gather(self):
|
|
FullExeTarget.gather(self)
|
|
if self.script[0] == 'gen_install.py':
|
|
f = open(self.script[0], 'a')
|
|
for rsrc in self.toc:
|
|
if isinstance(rsrc, resource.binaryresource):
|
|
nm = os.path.basename(rsrc.path)
|
|
f.write(mvfile % (nm, nm))
|
|
elif isinstance(rsrc, resource.pythonresource):
|
|
pass
|
|
elif isinstance(rsrc, resource.zlibresource):
|
|
pass
|
|
else:
|
|
f.write(extractfile % (rsrc.name, rsrc.name))
|
|
if isinstance(rsrc, resource.archiveresource):
|
|
#did it come with an install script?
|
|
target = built.get(rsrc.name, None)
|
|
if target:
|
|
if hasattr(target, "installscript"):
|
|
for script in target.installscript:
|
|
s = resource.makeresource(script, self.pathprefix)
|
|
txt = open(s.path, 'r').read()
|
|
f.write(txt)
|
|
f.close()
|
|
|
|
dispatch = {
|
|
'PYZ': PYZTarget,
|
|
'CARCHIVE': ArchiveTarget,
|
|
'COLLECT': CollectTarget,
|
|
'STANDALONE': ExeTarget,
|
|
'INSTALL': InstallTarget,
|
|
'FULLEXE': FullExeTarget,
|
|
}
|
|
|
|
|
|
def makeTarget(cfg, section):
|
|
return dispatch[cfg.get(section, 'type')](cfg, section, optcnvrts)
|
|
|
|
optdefaults = { 'type':'PYZ',
|
|
'script':'', # INSTALL (opt) & STANDALONE (required)
|
|
'zlib':'', # INSTALL, STANDALONE, COLLECT
|
|
'bindepends':'', # INSTALL, COLLECT
|
|
'misc':'', # INSTALL. COLLECT
|
|
'includetk': '0', # INSTALL, COLLECT
|
|
'userunw': '0', # STANDALONE
|
|
'dependencies':'', # PYZ
|
|
'directories':'', # PYZ
|
|
'excludes':'', # PYZ, INSTALL, COLLECT
|
|
'expatterns': '',
|
|
'exstdlib': '0',
|
|
'extypes': '',
|
|
'includes':'', # PYZ
|
|
'packages':'', # PYZ
|
|
'destdir':'', # COLLECT
|
|
'pathprefix': '',
|
|
'trees': '',
|
|
'debug': '0',
|
|
'support': '1', # include python20.dll & exceptons.pyc at a minimum
|
|
'icon': '',
|
|
}
|
|
|
|
optcnvrts = { 'type':'',
|
|
'name': 'getstring',
|
|
'exstdlib': 'getbool',
|
|
'console': 'getbool',
|
|
'analyze': 'getbool',
|
|
'debug': 'getbool',
|
|
'includetk': 'getbool',
|
|
'userunw': 'getbool',
|
|
'destdir': 'getstring',
|
|
'support': 'getbool',
|
|
'__name__': 'getstring',
|
|
'icon': 'getstring',
|
|
}
|
|
def main(opts, args):
|
|
global pyinsthome
|
|
global copyFile
|
|
pyinsthome = os.path.abspath(os.path.dirname(sys.argv[0]))
|
|
# sys.path.insert(0, os.path.join(pyinsthome, 'support'))
|
|
import installutils
|
|
copyFile = installutils.copyFile
|
|
global logfile
|
|
logfile = open('Builder.log','w')
|
|
targets = []
|
|
xref = {}
|
|
cfg = ConfigParser.ConfigParser(optdefaults)
|
|
for arg in args:
|
|
dirnm = os.path.dirname(arg)
|
|
if dirnm == '':
|
|
dirnm = '.'
|
|
autopath.append(os.path.abspath(dirnm))
|
|
cfg.read(args)
|
|
for section in cfg.sections():
|
|
target = makeTarget(cfg, section)
|
|
targets.append(target)
|
|
xref[section] = target
|
|
while targets:
|
|
for i in range(len(targets)):
|
|
target = targets[i]
|
|
for child in target.children:
|
|
if xref[child] in targets:
|
|
break
|
|
else: #no break - ready to build
|
|
target.dump()
|
|
target.build()
|
|
built[target.__name__] = target
|
|
built[target.name] = target
|
|
targets[i] = None
|
|
break
|
|
else: #no break - couldn't find anything to build
|
|
names = map(lambda x: getattr(x, 'name'), targets)
|
|
raise RuntimeError, "circular dependencies in %s" % repr(names)
|
|
targets = filter(None, targets)
|
|
|
|
def run(file):
|
|
main ([], file)
|
|
|
|
if __name__ == '__main__':
|
|
import getopt
|
|
(opts, args) = getopt.getopt(sys.argv[1:], 'dv')
|
|
print "opts:", opts
|
|
print "args:", args
|
|
main(opts, args)
|