*** empty log message ***

This commit is contained in:
Joe Shochet 2001-04-16 07:26:45 +00:00
parent 259683160c
commit ec3ac7ffad
16 changed files with 2550 additions and 11 deletions

View File

@ -47,20 +47,20 @@ class DirectNotify:
"""
Check to see if this category has a dconfig variable
to set the notify severity and then set that level. You cannot
set these until base.config is set.
set these until config is set.
"""
# We cannot check dconfig variables until base.config has been
# set. Once base.config is set in ShowBase.py, it tries to set
# all the levels again in case some were created before base.config
# We cannot check dconfig variables until config has been
# set. Once config is set in ShowBase.py, it tries to set
# all the levels again in case some were created before config
# was created.
try:
base.config
config
except:
return 0
dconfigParam = ("notify-level-" + categoryName)
level = base.config.GetString(dconfigParam, "")
level = config.GetString(dconfigParam, "")
if level:
print ("Setting DirectNotify category: " + dconfigParam +
" to severity: " + level)

View File

@ -1281,7 +1281,7 @@ filter."
(concat
(mapconcat 'identity py-which-args " ") " ")
))))
(switch-to-buffer-other-window
(switch-to-buffer ;; -other-window
(apply 'make-comint py-which-bufname py-which-shell nil args))
(make-local-variable 'comint-prompt-regexp)
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
@ -1308,7 +1308,7 @@ filter."
(concat
(mapconcat 'identity py-which-args " ") " ")
))))
(switch-to-buffer-other-window
(switch-to-buffer ;; -other-window
(apply 'make-comint py-which-bufname pyd-which-shell nil args))
(make-local-variable 'comint-prompt-regexp)
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
@ -1337,7 +1337,7 @@ filter."
(concat
(mapconcat 'identity py-which-args " ") " ")
))))
(switch-to-buffer-other-window
(switch-to-buffer ;; -other-window
(apply 'make-comint py-which-bufname ppy-which-shell nil args))
(make-local-variable 'comint-prompt-regexp)
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")

View File

@ -1,9 +1,11 @@
"""DistributedObject module: contains the DistributedObject class"""
from PandaObject import *
from DirectNotifyGlobal import *
class DistributedObject(PandaObject):
"""Distributed Object class:"""
notify = directNotify.newCategory("DistributedObject")
def __init__(self, cr):
try:
self.DistributedObject_initialized
@ -33,6 +35,13 @@ class DistributedObject(PandaObject):
self.deleteImminent = 0
return None
def __del__(self):
"""
For debugging purposes, this just prints out what got deleted
"""
DistributedObject.notify.debug("Destructing: " + self.__class__.__name__ +
" id: " + str(self.doId))
def setNeverDisable(self, bool):
assert((bool == 1) or (bool == 0))
self.neverDisable = bool

View File

@ -15,8 +15,8 @@ if sys.argv[1:]:
# If you do not run from the command line, we just load all of them
# or you can hack this up for your own purposes.
else:
# hoods = ['TT', 'DD', 'BR', 'DG', 'DL', 'MM']
hoods = ['BR' ]
hoods = ['TT', 'DD', 'BR', 'DG', 'DL', 'MM']
# hoods = ['DL' ]
print "Loading LevelEditor for hoods: ", hoods

View File

@ -0,0 +1,503 @@
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, 'support', 'imputil.py')])
imputil = resource.makeresource('imputil.py', [os.path.join(pyinsthome, 'support')])
self._dependencies.append(imputil)
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'support', 'archive_rt.py')])
archmodule = resource.makeresource('archive_rt.py', [os.path.join(pyinsthome, 'support')])
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, 'support', 'carchive_rt.py')])
carchmodule = resource.makeresource('carchive_rt.py', [os.path.join(pyinsthome, 'support')])
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", `script`
rsrc = resource.makeresource(script, self.pathprefix)
rsrc = resource.scriptresource(rsrc.name, rsrc.path)
#print " resource is", `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" % `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)

View File

@ -0,0 +1,246 @@
#
# Gordon McMillan (as inspired and influenced by Greg Stein)
#
# subclasses may not need marshal or struct, but since they're
# builtin, importing is safe.
#
# While an Archive is really an abstraction for any "filesystem
# within a file", it is tuned for use with imputil.FuncImporter.
# This assumes it contains python code objects, indexed by the
# the internal name (ie, no '.py').
# See carchive.py for a more general archive (contains anything)
# that can be understood by a C program.
import marshal
import struct
class Archive:
""" A base class for a repository of python code objects.
The get_code method is used by imputil.FuntionImporter
to get code objects by name.
Archives are flat namespaces, so conflict between module
names in different packages are possible. Use a different
Archive for each package.
"""
MAGIC = 'PYL\0'
HDRLEN = 12 # default is MAGIC followed by python's magic, int pos of toc
TOCPOS = 8
TRLLEN = 0 # default - no trailer
TOCTMPLT = {} #
os = None
def __init__(self, path=None, start=0):
"""
Initialize an Archive. If path is omitted, it will be an empty Archive.
start is the seek position within path where the Archive starts."""
self.toc = None
self.path = path
self.start = start
import imp
self.pymagic = imp.get_magic()
if path is not None:
self.lib = open(self.path, 'rb')
self.checkmagic()
self.loadtoc()
####### Sub-methods of __init__ - override as needed #############
def checkmagic(self):
"""Verify version and validity of file.
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:
raise RuntimeError, "%s has version mismatch to dll" % (self.path)
def loadtoc(self):
"""Load the table of contents.
Overridable.
Default: After magic comes an int (4 byte native) giving the
position of the TOC within self.lib.
Default: The TOC is a marshal-able string.
"""
self.lib.seek(self.start + self.TOCPOS)
(offset,) = struct.unpack('=i', self.lib.read(4))
self.lib.seek(self.start + offset)
self.toc = marshal.load(self.lib)
######## This is what is called by FuncImporter #######
## Since an Archive is flat, we ignore parent and modname.
def get_code(self, parent, modname, fqname):
"""The import hook.
Called by imputil.FunctionImporter.
Override extract to tune getting code from the Archive."""
rslt = self.extract(fqname) # None if not found, (ispkg, code) otherwise
if rslt is None:
return None
ispkg, code = rslt
if ispkg:
return ispkg, code, {'__path__' : []}
return rslt
####### Core method - Override as needed #########
def extract(self, name):
""" Get the object corresponding to name, or None.
NAME is the name as specified in an 'import name'.
'import a.b' will become:
extract('a') (return None because 'a' is not a code object)
extract('a.__init__') (return a code object)
extract('a.b') (return a code object)
Default implementation:
self.toc is a dict
self.toc[name] is pos
self.lib has the code object marshal-ed at pos
"""
ispkg, pos = self.toc.get(name, (0,None))
if pos is None:
return None
self.lib.seek(self.start + pos)
return ispkg, marshal.load(self.lib)
########################################################################
# Informational methods
def contents(self):
"""Return a list of the contents.
Default implementation assumes self.toc is a dict like object.
"""
return self.toc.keys()
########################################################################
# Building
####### Top level method - shouldn't need overriding #######
def build(self, path, lTOC):
"""Create an archive file of name PATH from LTOC.
lTOC is a 'logical TOC' - a list of (name, path, ...)
where name is the internal (import) name,
and path is a file to get the object from, eg './a.pyc'.
"""
self.path = path
self.lib = open(path, 'wb')
#reserve space for the header
if self.HDRLEN:
self.lib.write('\0'*self.HDRLEN)
#create an empty toc
if type(self.TOCTMPLT) == type({}):
self.toc = {}
else: # assume callable
self.toc = self.TOCTMPLT()
for tocentry in lTOC:
self.add(tocentry) # the guts of the archive
tocpos = self.lib.tell()
self.save_toc(tocpos)
if self.TRLLEN:
self.save_trailer(tocpos)
if self.HDRLEN:
self.update_headers(tocpos)
self.lib.close()
####### manages keeping the internal TOC and the guts in sync #######
def add(self, entry):
"""Add an entry to the archive.
Override this to influence the mechanics of the Archive.
Assumes entry is a seq beginning with (nm, pth, ...) where
nm is the key by which we'll be asked for the object.
pth is the name of where we find the object.
"""
if self.os is None:
import os
self.os = os
nm = entry[0]
pth = entry[1]
ispkg = self.os.path.splitext(self.os.path.basename(pth))[0] == '__init__'
self.toc[nm] = (ispkg, self.lib.tell())
f = open(entry[1], 'rb')
f.seek(8) #skip magic and timestamp
self.lib.write(f.read())
def save_toc(self, tocpos):
"""Save the table of contents.
Default - toc is a dict
Gets marshaled to self.lib
"""
marshal.dump(self.toc, self.lib)
def save_trailer(self, tocpos):
"""Placeholder for Archives with trailers."""
pass
def update_headers(self, tocpos):
"""Update any header data.
Default header is MAGIC + Python's magic + tocpos"""
self.lib.seek(self.start)
self.lib.write(self.MAGIC)
self.lib.write(self.pymagic)
self.lib.write(struct.pack('=i', tocpos))
##############################################################
#
# ZlibArchive - an archive with compressed entries
#
class ZlibArchive(Archive):
"""A subclass of Archive that compresses entries with zlib
and uses a (marshalled) dict as a table of contents"""
MAGIC = 'PYZ\0'
TOCPOS = 8
HDRLEN = 12
TRLLEN = 0
TOCTMPLT = {}
LEVEL = 9
def __init__(self, path=None, offset=0):
Archive.__init__(self, path, offset)
# dynamic import so not imported if not needed
global zlib
import zlib
def extract(self, name):
"""Get the code object for NAME.
Return None if name is not in the table of contents.
Otherwise, return a tuple (ispkg, code)"""
(ispkg, pos, lngth) = self.toc.get(name, (0, None, 0))
if pos is None:
return None
self.lib.seek(self.start + pos)
return ispkg, marshal.loads(zlib.decompress(self.lib.read(lngth)))
def add(self, entry):
"""Add an entry.
ENTRY is a sequence where entry[0] is name and entry[1] is full path name.
zlib compress the code object, and build a toc entry"""
if self.os is None:
import os
self.os = os
nm = entry[0]
pth = entry[1]
ispkg = self.os.path.splitext(self.os.path.basename(pth))[0] == '__init__'
f = open(pth, 'rb')
f.seek(8) #skip magic and timestamp
obj = zlib.compress(f.read(), self.LEVEL)
self.toc[nm] = (ispkg, self.lib.tell(), len(obj))
self.lib.write(obj)

View File

@ -0,0 +1,81 @@
# copyright 1999 McMillan Enterprises, Inc.
# license: use as you please. No warranty.
# Gordon McMillan gmcm@hypernet.com
#
# A collection of routines for building a logical Table Of Contents
# that Archive (subclasses) use to build themselves.
# A logical Table of Contents is a sequence, each element of which is
# a sequence, with at least 2 entries - "name" and "path".
import os
import string
import py_compile
def GetCompiled(seq, lvl='c'):
"""SEQ is a list of .py files, or a logical TOC.
Return as .pyc or .pyo files (LVL) after ensuring their existence"""
if len(seq) == 0:
return seq
rslt = []
isTOC = 0
if type(seq[0]) == type(()):
isTOC = 1
for py in seq:
if isTOC:
(nm, fnm), rest = py[:2], py[2:]
else:
fnm = py
fnm = os.path.splitext(fnm)[0] + '.py'
cmpl = 1
pyc = fnm + lvl
if os.path.exists(pyc):
pytm = long(os.stat(fnm)[8])
ctm = long(os.stat(pyc)[8])
if pytm < ctm:
cmpl = 0
if cmpl:
py_compile.compile(fnm, pyc)
if isTOC:
rslt.append((nm, pyc)+rest)
else:
rslt.append(pyc)
return rslt
import modulefinder
MF = modulefinder
import sys
def Dependencies(script):
"""Get a logical TOC directly from the dependencies of a script.
The returned TOC does NOT contain the script.
It does contain extension modules. Uses modulefinder."""
rslt = []
(dir, name) = os.path.split(script)
if dir:
ppath = [os.path.normpath(dir)] + sys.path
else:
ppath = sys.path[:]
mf = MF.ModuleFinder(ppath, 0)
try:
mf.run_script(script)
except IOError:
print " Script not found:", script
return []
del mf.modules['__main__']
for (k, v) in mf.modules.items():
if v.__file__ is None:
del mf.modules[k] # a builtin
for (k, v) in mf.modules.items():
#ispkg = os.path.basename(v.__file__) == '__init__.py'
d = os.path.dirname(v.__file__)
if not d:
v.__file__ = os.path.join(os.getcwd(), v.__file__)
#if ispkg:
# rslt.append(k+'.__init__', v.__file__)
#else:
rslt.append( (k, v.__file__) )
return rslt

View File

@ -0,0 +1,169 @@
# copyright 1999 McMillan Enterprises, Inc.
# license: use as you please. No warranty.
#
# use dumpbin.exe (if present) to find the binary
# dependencies of an extension module.
# if dumpbin not available, pick apart the PE hdr of the binary
# while this appears to work well, it is complex and subject to
# problems with changes to PE hdrs (ie, this works only on 32 bit Intel
# Windows format binaries)
#
# Note also that you should check the results to make sure that the
# dlls are redistributable. I've listed most of the common MS dlls
# under "excludes" below; add to this list as necessary (or use the
# "excludes" option in the INSTALL section of the config file).
import os
import time
import string
import sys
import tempfile
import finder
seen = {}
excludes = {'KERNEL32.DLL':1,
'ADVAPI.DLL':1,
'MSVCRT.DLL':1,
'ADVAPI32.DLL':1,
'COMCTL32.DLL':1,
'CRTDLL.DLL':1,
'GDI32.DLL':1,
'MFC42.DLL':1,
'NTDLL.DLL':1,
'OLE32.DLL':1,
'OLEAUT32.DLL':1,
'RPCRT4.DLL':1,
'SHELL32.DLL':1,
'USER32.DLL':1,
'WINSPOOL.DRV':1,
'WS2HELP.DLL':1,
'WS2_32.DLL':1,
'WSOCK32.DLL':1,
'WINMM.DLL':1,
'COMDLG32.DLL':1,
'ZLIB.DLL':1,
'ODBC32.DLL':1,
'VERSION.DLL':1}
def getfullnameof(mod, xtrapath = None):
"""Return the full path name of MOD.
MOD is the basename of a dll or pyd.
XTRAPATH is a path or list of paths to search first.
Return the full path name of MOD.
Will search the full Windows search path, as well as sys.path"""
epath = finder.getpath()
if mod[-4:] in ('.pyd', '.PYD'):
epath = epath + sys.path
if xtrapath is not None:
if type(xtrapath) == type(''):
epath.insert(0, xtrapath)
else:
epath = xtrapath + epath
for p in epath:
npth = os.path.join(p, mod)
if os.path.exists(npth):
return npth
return ''
def getImports1(pth):
"""Find the binary dependencies of PTH.
This implementation (not used right now) uses the MSVC utility dumpbin"""
rslt = []
tmpf = tempfile.mktemp()
os.system('dumpbin /IMPORTS "%s" >%s' %(pth, tmpf))
time.sleep(0.1)
txt = open(tmpf,'r').readlines()
os.remove(tmpf)
i = 0
while i < len(txt):
tokens = string.split(txt[i])
if len(tokens) == 1 and string.find(tokens[0], '.') > 0:
rslt.append(string.strip(tokens[0]))
i = i + 1
return rslt
def getImports2(pth):
"""Find the binary dependencies of PTH.
This implementation walks through the PE header"""
import struct
rslt = []
try:
f = open(pth, 'rb').read()
pehdrd = struct.unpack('l', f[60:64])[0]
magic = struct.unpack('l', f[pehdrd:pehdrd+4])[0]
numsecs = struct.unpack('h', f[pehdrd+6:pehdrd+8])[0]
numdirs = struct.unpack('l', f[pehdrd+116:pehdrd+120])[0]
idata = ''
if magic == 17744:
importsec, sz = struct.unpack('2l', f[pehdrd+128:pehdrd+136])
secttbl = pehdrd + 120 + 8*numdirs
secttblfmt = '8s7l2h'
seclist = []
for i in range(numsecs):
seclist.append(struct.unpack(secttblfmt, f[secttbl+i*40:secttbl+(i+1)*40]))
#nm, vsz, va, rsz, praw, preloc, plnnums, qrelocs, qlnnums, flags \
# = seclist[-1]
for i in range(len(seclist)-1):
if seclist[i][2] <= importsec < seclist[i+1][2]:
break
vbase = seclist[i][2]
raw = seclist[i][4]
idatastart = raw + importsec - vbase
idata = f[idatastart:idatastart+seclist[i][1]]
i = 0
while 1:
vsa = struct.unpack('5l', idata[i*20:i*20+20])[3]
if vsa == 0:
break
sa = raw + vsa - vbase
end = string.find(f, '\000', sa)
rslt.append(f[sa:end])
i = i + 1
except IOError:
print "bindepend cannot analyze %s - file not found!"
except struct.error:
print "bindepend cannot analyze %s - error walking thru pehdr"
return rslt
def Dependencies(lTOC):
"""Expand LTOC to include all the closure of binary dependencies.
LTOC is a logical table of contents, ie, a seq of tuples (name, path).
Return LTOC expanded by all the binary dependencies of the entries
in LTOC, except those listed in the module global EXCLUDES"""
for (nm, pth) in lTOC:
fullnm = string.upper(os.path.basename(pth))
if seen.get(string.upper(nm),0):
continue
print "analyzing", nm
seen[string.upper(nm)] = 1
dlls = getImports(pth)
for lib in dlls:
print " found", lib
if excludes.get(string.upper(lib),0):
continue
if seen.get(string.upper(lib),0):
continue
npth = getfullnameof(lib)
if npth:
lTOC.append((lib, npth))
else:
print " lib not found:", lib, "dependency of",
return lTOC
##if getfullnameof('dumpbin.exe') == '':
## def getImports(pth):
## return getImports2(pth)
##else:
## def getImports(pth):
## return getImports1(pth)
def getImports(pth):
"""Forwards to either getImports1 or getImports2
"""
return getImports2(pth)

View File

@ -0,0 +1,204 @@
# copyright 1999 McMillan Enterprises, Inc.
# license: use as you please. No warranty.
#
# A subclass of Archive that can be understood
# by a C program. See uplaunch.cpp for unpacking
# from C.
import archive
import struct
import zlib
import strop
class CTOC:
"""A class encapsulating the table of contents of a CArchive.
When written to disk, it is easily read from C."""
ENTRYSTRUCT = 'iiiibc' #(structlen, dpos, dlen, ulen, flag, typcd) followed by name
def __init__(self):
self.data = []
def frombinary(self, s):
"""Decode the binary string into an in memory list.
S is a binary string."""
entrylen = struct.calcsize(self.ENTRYSTRUCT)
p = 0
while p<len(s):
(slen, dpos, dlen, ulen, flag, typcd) = struct.unpack(self.ENTRYSTRUCT,
s[p:p+entrylen])
nmlen = slen - entrylen
p = p + entrylen
(nm,) = struct.unpack(`nmlen`+'s', s[p:p+nmlen])
p = p + nmlen
self.data.append((dpos, dlen, ulen, flag, typcd, nm[:-1]))
def tobinary(self):
"""Return self as a binary string."""
import string
entrylen = struct.calcsize(self.ENTRYSTRUCT)
rslt = []
for (dpos, dlen, ulen, flag, typcd, nm) in self.data:
nmlen = len(nm) + 1 # add 1 for a '\0'
rslt.append(struct.pack(self.ENTRYSTRUCT+`nmlen`+'s',
nmlen+entrylen, dpos, dlen, ulen, flag, typcd, nm+'\0'))
return string.join(rslt, '')
def add(self, dpos, dlen, ulen, flag, typcd, nm):
"""Add an entry to the table of contents.
DPOS is data position.
DLEN is data length.
ULEN is the uncompressed data len.
FLAG says if the data is compressed.
TYPCD is the "type" of the entry (used by the C code)
NM is the entry's name."""
self.data.append((dpos, dlen, ulen, flag, typcd, nm))
def get(self, ndx):
"""return the toc entry (tuple) at index NDX"""
return self.data[ndx]
def __getitem__(self, ndx):
return self.data[ndx]
def find(self, name):
"""Return the index of the toc entry with name NAME.
Return -1 for failure."""
for i in range(len(self.data)):
if self.data[i][-1] == name:
return i
return -1
class CArchive(archive.Archive):
"""An Archive subclass that an hold arbitrary data.
Easily handled from C or from Python."""
MAGIC = 'MEI\014\013\012\013\015'
HDRLEN = 0
TOCTMPLT = CTOC
TRLSTRUCT = '8siii'
TRLLEN = 20
LEVEL = 9
def __init__(self, path=None, start=0, len=0):
"""Constructor.
PATH is path name of file (create an empty CArchive if path is None).
START is the seekposition within PATH.
LEN is the length of the CArchive (if 0, then read till EOF). """
self.len = len
archive.Archive.__init__(self, path, start)
def checkmagic(self):
"""Verify that self is a valid CArchive.
Magic signature is at end of the archive."""
#magic is at EOF; if we're embedded, we need to figure where that is
if self.len:
self.lib.seek(self.start+self.len, 0)
else:
self.lib.seek(0, 2)
filelen = self.lib.tell()
if self.len:
self.lib.seek(self.start+self.len-self.TRLLEN, 0)
else:
self.lib.seek(-self.TRLLEN, 2)
(magic, totallen, tocpos, toclen) = struct.unpack(self.TRLSTRUCT,
self.lib.read(self.TRLLEN))
if magic != self.MAGIC:
raise RuntimeError, "%s is not a valid %s archive file" \
% (self.path, self.__class__.__name__)
self.pkgstart = filelen - totallen
if self.len:
if totallen != self.len or self.pkgstart != self.start:
raise RuntimeError, "Problem with embedded archive in %s" % self.path
self.tocpos, self.toclen = tocpos, toclen
def loadtoc(self):
"""Load the table of contents into memory."""
self.toc = self.TOCTMPLT()
self.lib.seek(self.pkgstart+self.tocpos)
tocstr = self.lib.read(self.toclen)
self.toc.frombinary(tocstr)
def extract(self, name):
"""Get the contents of an entry.
NAME is an entry name.
Return the tuple (ispkg, contents).
For non-Python resoures, ispkg is meaningless (and 0).
Used by the import mechanism."""
if type(name) == type(''):
ndx = self.toc.find(name)
if ndx == -1:
return None
else:
ndx = name
(dpos, dlen, ulen, flag, typcd, nm) = self.toc.get(ndx)
self.lib.seek(self.pkgstart+dpos)
rslt = self.lib.read(dlen)
if flag == 1:
rslt = zlib.decompress(rslt)
if typcd == 'M':
return (1, rslt)
return (0, rslt)
def contents(self):
"""Return the names of the entries"""
rslt = []
for (dpos, dlen, ulen, flag, typcd, nm) in self.toc:
rslt.append(nm)
return rslt
def add(self, entry):
"""Add an ENTRY to the CArchive.
ENTRY must have:
entry[0] is name (under which it will be saved).
entry[1] is fullpathname of the file.
entry[2] is a flag for it's storage format (0==uncompressed,
1==compressed, 2==Python source format)
entry[3] is the entry's type code."""
(nm, pathnm, flag, typcd) = entry[:4]
if flag == 2:
s = open(pathnm, 'r').read()
s = s + '\n\0'
else:
s = open(pathnm, 'rb').read()
ulen = len(s)
if flag == 1:
s = zlib.compress(s, self.LEVEL)
dlen = len(s)
where = self.lib.tell()
if typcd == 'm':
if strop.find(pathnm, '.__init__.py') > -1:
typcd = 'M'
self.toc.add(where, dlen, ulen, flag, typcd, nm)
self.lib.write(s)
def save_toc(self, tocpos):
"""Save the table of contents to disk."""
self.tocpos = tocpos
tocstr = self.toc.tobinary()
self.toclen = len(tocstr)
self.lib.write(tocstr)
def save_trailer(self, tocpos):
"""Save the trailer to disk.
CArchives can be opened from the end - the trailer points
back to the start. """
totallen = tocpos + self.toclen + self.TRLLEN
trl = struct.pack(self.TRLSTRUCT, self.MAGIC, totallen,
tocpos, self.toclen)
self.lib.write(trl)
def openEmbedded(self, name):
"""Open a CArchive of name NAME embedded within this CArchive."""
ndx = self.toc.find(name)
if ndx == -1:
raise KeyError, "Member '%s' not found in %s" % (name, self.path)
(dpos, dlen, ulen, flag, typcd, nm) = self.toc.get(ndx)
if flag:
raise ValueError, "Cannot open compressed archive %s in place"
return CArchive(self.path, self.pkgstart+dpos, dlen)

178
direct/src/pyinst/finder.py Normal file
View File

@ -0,0 +1,178 @@
# copyright McMillan Enterprises, 1999
import os, sys
import string
SCRIPT = 1
GSCRIPT = 2
MODULE = 3
PACKAGE = 4
PBINARY = 5
BINARY = 6
ZLIB = 7
DIRECTORY = 8
DATA = 9
_bpath = None
_ppath = None
_pcache = {}
def _locate(nm, xtrapath=None, base=None):
"""Find a file / directory named NM in likely places.
XTRAPATH is a list of paths to prepend to BASE.
If BASE is None, sys.path (as extended by packages) is used."""
ppath = base
if base is None:
ppath = _ppath
if xtrapath:
ppath = xtrapath + ppath
for pth in ppath:
fullnm = os.path.join(pth, nm)
#print " _locate trying", fullnm
if os.path.exists(fullnm):
break
else:
return ''
return fullnm
def _locatepython(name, xtrapath=None):
"""Locate a Python resource named NAME.
All of the standard file extensions will be tried.
XTRAPATH is prepended to sys.path."""
for ext in ('.py', '.pyc', '.pyw', '.pyo', '.pyd', '.dll'):
fullnm = _locate(name+ext, xtrapath)
if fullnm:
break
else:
for ext in ('.pyd', '.dll'):
fullnm = _locate(name+ext, [], _bpath)
if fullnm:
break
return fullnm
def ispackage(name):
"""Determine if NAME is the name of a package."""
if os.path.exists(os.path.join(name, '__init__.py')):
return 1
if os.path.exists(os.path.join(name, '__init__.pyc')):
return 1
if os.path.exists(os.path.join(name, '__init__.pyo')):
return 1
return 0
def idtype(fullnm):
"""Figure out what type of resource FULLNM refers to."""
if os.path.isdir(fullnm):
if ispackage(fullnm):
return PACKAGE
return DIRECTORY
ext = os.path.splitext(fullnm)[1]
if ext:
if ext == '.pyd':
return PBINARY
if ext == '.dll':
return BINARY
if ext in ('.pyc', '.pyo'):
return MODULE
if ext == '.py':
return SCRIPT
if ext == '.pyw':
return GSCRIPT
if ext == '.pyz':
return ZLIB
return DATA
def identify(name, xtrapath=None):
"""Find, and identify the type of NAME, using XTRAPATH as the
first place to look.
Return type, name and full path name.
NAME can be a logical or physical name. However, the logical
name of a Python module can easily conflict with the physical
name of something else, so beware."""
if os.path.exists(name):
fullnm = name
else:
if xtrapath is None:
xtra = []
elif _pcache.has_key(id(xtrapath)):
xtra = _pcache[id(xtrapath)]
else:
xtra = expand(xtrapath)
_pcache[id(xtrapath)] = xtra
fullnm = _locate(name, xtra)
if not fullnm:
fullnm = _locate(name, [], _bpath)
if not fullnm:
ext = os.path.splitext(name)[1]
if not ext:
fullnm = _locatepython(name, xtra)
if not fullnm:
raise ValueError, "%s not found" % name
else:
nm = name
while string.count(nm, '.'):
nm = string.replace(nm, '.', '/', 1)
fullnm = _locatepython(nm, xtra)
if fullnm:
break
else:
raise ValueError, "%s not found" % name
typ = idtype(fullnm)
nm = name
if typ in (GSCRIPT, SCRIPT, MODULE, PACKAGE, PBINARY):
dir, nm = os.path.split(fullnm)
nm = os.path.splitext(nm)[0]
if typ == SCRIPT:
if os.path.exists(fullnm+'c') or os.path.exists(fullnm+'o'):
typ = MODULE
if typ in (MODULE, PACKAGE):
while idtype(dir) == PACKAGE:
dir, lnode = os.path.split(dir)
nm = lnode+'.'+nm
elif typ == BINARY:
nm = os.path.basename(fullnm)
return typ, nm, fullnm
def expand(plist):
""" expand a list of paths (like sys.path) to include all the
directories that qualify as packages """
pkgdirs = []
for pth in plist:
os.path.walk(pth, pkgfinder, pkgdirs)
return plist + pkgdirs
def pkgfinder(pkgdirs, dir, fnms):
i = 0
while i < len(fnms):
fnm = os.path.join(dir, fnms[i])
if os.path.isdir(fnm):
if ispackage(fnm):
pkgdirs.append(fnm)
i = i + 1
else:
del fnms[i]
else:
i = i + 1
if _bpath is None:
try:
import win32api
except ImportError:
print "Cannot determine your Windows or System directories"
print "Please add them to your PATH if .dlls are not found"
_bpath = []
else:
sysdir = win32api.GetSystemDirectory()
sysdir2 = os.path.join(sysdir, '../SYSTEM')
windir = win32api.GetWindowsDirectory()
_bpath = [sysdir, sysdir2, windir]
_bpath.extend(string.split(os.environ.get('PATH', ''), ';'))
if _ppath is None:
_ppath = expand(sys.path)
def getpath():
"""Return the path that Windows will search for dlls."""
return _bpath

138
direct/src/pyinst/icon.py Normal file
View File

@ -0,0 +1,138 @@
# This code is courtesy of Thomas Heller, who
# has kindly donated it to this project.
RT_ICON = 3
RT_GROUP_ICON = 14
LOAD_LIBRARY_AS_DATAFILE = 2
import struct
class Structure:
def __init__ (self):
size = self._sizeInBytes = struct.calcsize (self._format_)
self._fields_ = list (struct.unpack (self._format_, '\000' * size))
indexes = self._indexes_ = {}
for i in range (len (self._names_)):
indexes[self._names_[i]] = i
def dump (self):
print "DUMP of", self
for name in self._names_:
if name[0] != '_':
print "%20s = %s" % (name, getattr (self, name))
print
def __getattr__ (self, name):
if name in self._names_:
index = self._indexes_[name]
return self._fields_[index]
try:
return self.__dict__[name]
except KeyError:
raise AttributeError, name
def __setattr__ (self, name, value):
if name in self._names_:
index = self._indexes_[name]
self._fields_[index] = value
else:
self.__dict__[name] = value
def tostring (self):
return apply (struct.pack, [self._format_,] + self._fields_)
def fromfile (self, file):
data = file.read (self._sizeInBytes)
self._fields_ = list (struct.unpack (self._format_, data))
class ICONDIRHEADER (Structure):
_names_ = "idReserved", "idType", "idCount"
_format_ = "hhh"
class ICONDIRENTRY (Structure):
_names_ = "bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "dwImageOffset"
_format_ = "bbbbhhii"
class GRPICONDIR (Structure):
_names_ = "idReserved", "idType", "idCount"
_format_ = "hhh"
class GRPICONDIRENTRY (Structure):
_names_ = "bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "nID"
_format_ = "bbbbhhih"
class IconFile:
def __init__ (self, path):
self.path = path
file = open (path, "rb")
self.entries = []
self.images = []
header = self.header = ICONDIRHEADER()
header.fromfile (file)
for i in range (header.idCount):
entry = ICONDIRENTRY()
entry.fromfile (file)
self.entries.append (entry)
for e in self.entries:
file.seek (e.dwImageOffset, 0)
self.images.append (file.read (e.dwBytesInRes))
def grp_icon_dir (self):
return self.header.tostring()
def grp_icondir_entries (self):
data = ""
i = 1
for entry in self.entries:
e = GRPICONDIRENTRY()
for n in e._names_[:-1]:
setattr(e, n, getattr (entry, n))
e.nID = i
i = i + 1
data = data + e.tostring()
return data
def CopyIcons_FromIco (dstpath, srcpath):
f = IconFile (srcpath)
print "Updating icons from", srcpath, "to", dstpath
import win32api #, win32con
hdst = win32api.BeginUpdateResource (dstpath, 0)
data = f.grp_icon_dir()
data = data + f.grp_icondir_entries()
win32api.UpdateResource (hdst, RT_GROUP_ICON, 1, data)
print "Writing RT_GROUP_ICON resource with %d bytes" % len (data)
i = 1
for data in f.images:
win32api.UpdateResource (hdst, RT_ICON, i, data)
print "Writing RT_ICON resource with %d bytes" % len (data)
i = i + 1
win32api.EndUpdateResource (hdst, 0)
def CopyIcons (dstpath, srcpath):
import os.path, string
index = None
try:
srcpath, index = map (string.strip, string.split (srcpath, ','))
index = int (index)
except:
pass
print "PATH, INDEX", srcpath, index
srcext = os.path.splitext (srcpath)[1]
if string.lower (srcext) == '.ico':
return CopyIcons_FromIco (dstpath, srcpath)
if index is not None:
print "Updating icons from", srcpath, ", %d to" % index, dstpath
else:
print "Updating icons from", srcpath, "to", dstpath
import win32api #, win32con
hdst = win32api.BeginUpdateResource (dstpath, 0)
hsrc = win32api.LoadLibraryEx (srcpath, 0, LOAD_LIBRARY_AS_DATAFILE)
if index is None:
grpname = win32api.EnumResourceNames (hsrc, RT_GROUP_ICON)[0]
elif index >= 0:
grpname = win32api.EnumResourceNames (hsrc, RT_GROUP_ICON)[index]
else:
grpname = -index
data = win32api.LoadResource (hsrc, RT_GROUP_ICON, grpname)
win32api.UpdateResource (hdst, RT_GROUP_ICON, grpname, data)
for iconname in win32api.EnumResourceNames (hsrc, RT_ICON):
data = win32api.LoadResource (hsrc, RT_ICON, iconname)
win32api.UpdateResource (hdst, RT_ICON, iconname, data)
win32api.FreeLibrary (hsrc)
win32api.EndUpdateResource (hdst, 0)

85
direct/src/pyinst/ltoc.py Normal file
View File

@ -0,0 +1,85 @@
import os, sys, UserList
from MEInc.Dist import finder, tocfilter, resource
class lTOC(UserList.UserList):
""" A class for managing lists of resources.
Should be a UserList subclass. Doh.
Like a list, but has merge(other) and filter() methods """
def __init__(self, reslist=None, filters=None):
UserList.UserList.__init__(self, reslist)
self.filters = []
if filters is not None:
self.filters = filters[:]
def prepend(self, res):
self.resources.insert(0, res)
def merge(self, other):
' merge in another ltoc, discarding dups and preserving order '
tmp = {}
for res in self.data:
tmp[res.name] = 0
for res in other:
if tmp.get(res.name, 1):
self.data.append(res)
tmp[res.name] = 0
def filter(self):
' invoke all filters '
for i in range(len(self.data)):
res = self.data[i]
if res:
for f in self.filters:
if f.matches(res):
self.data[i] = None
break
self.data = filter(None, self.data)
return self
def unique(self):
' remove all duplicate entries, preserving order '
new = self.__class__()
new.merge(self)
self.data = new.data
def toList(self):
' return self as a list of (name, path, typ) '
tmp = []
for res in self.data:
tmp.append((res.name, res.path, res.typ))
return tmp
def addFilter(self, filter):
if type(filter) == type(''):
self.filters.append(finder.makeresource(filter).asFilter())
else:
if type(filter) == type(self):
if isinstance(filter, tocfilter._Filter):
self.filters.append(filter)
elif isinstance(filter, resource.resource):
self.filters.append(filter.asFilter())
else:
raise ValueError, "can't make filter from %s", repr(filter)
else:
raise ValueError, "can't make filter from %s", repr(filter)
print " added filter", `self.filters[-1]`
if __name__ == '__main__':
sys.path.insert(0, '.')
import finder
import pprint
s = finder.scriptresource('finder.py', './finder.py')
## pyltoc = lTOC(s.modules)
## l1 = pyltoc.toList()
## print "Raw py ltoc:", pprint.pprint(l1)
## f1 = ModFilter(['dospath', 'macpath', 'posixpath'])
## l2 = lTOC(s.modules).filter(f1).toList()
## print "Filter out dospath, macpath, posixpath:", pprint.pprint(l2)
## f2 = DirFilter(['.'])
## l3 = lTOC(s.modules).filter(f2).toList()
## print "Filter out current dir:", pprint.pprint(l3)
## f3 = StdLibFilter()
## l4 = lTOC(s.modules).filter(f3).toList()
## print "Filter out stdlib:", pprint.pprint(l4)
## #print "Filter out current dir and stdlib:", lTOC(s.modules).filter(f2, f3).toList()
binltoc = lTOC(s.binaries)
print "Raw bin ltoc:", pprint.pprint(binltoc.toList())
binltoc.addFilter('c:/winnt/system32')
pprint.pprint(binltoc.filter().toList())

View File

@ -0,0 +1,42 @@
import MkWrap
import imputil
import strop
import zlib
import os
import marshal
class MkImporter:
def __init__(self, db, viewnm='pylib'):
self.db = db
self.view = db.getas(viewnm+'[name:S,ispkg:I,code:M]') # an MkWrap view object
def setImportHooks(self):
imputil.FuncImporter(self.get_code).install()
def get_code(self, parent, modname, fqname):
if self.view is None:
return None
ndx = self.view.search(name=fqname)
if ndx < len(self.view):
row = self.view[ndx]
if row.name == fqname:
return (row.ispkg, marshal.loads(zlib.decompress(row.code)))
return None
def build(self, lTOC):
for entry in lTOC:
nm, fnm = entry[0], entry[1]
ispkg = os.path.splitext(os.path.basename(fnm))[0] == '__init__'
ndx = self.view.search(name=nm)
if ndx < len(self.view):
row = self.view[ndx]
if row.name != nm:
self.view.insert(ndx, {})
row = self.view[ndx]
else:
ndx = self.view.append({})
row = self.view[ndx]
row.name = nm
row.ispkg = ispkg
f = open(fnm, 'rb')
f.seek(8)
obj = zlib.compress(f.read(), 9)
row.code = obj
self.db.commit()

View File

@ -0,0 +1,436 @@
"""Find modules used by a script, using introspection."""
import dis
import imp
import marshal
import os
import re
import string
import sys
if sys.platform=="win32":
# On Windows, we can locate modules in the registry with
# the help of the win32api package.
try:
import win32api
except ImportError:
print "The win32api module is not available - modules listed"
print "in the registry will not be found."
win32api = None
IMPORT_NAME = dis.opname.index('IMPORT_NAME')
IMPORT_FROM = dis.opname.index('IMPORT_FROM')
# Modulefinder does a good job at simulating Python's, but it can not
# handle __path__ modifications packages make at runtime. Therefore there
# is a mechanism whereby you can register extra paths in this map for a
# package, and it will be honoured.
# Note this is a mapping is lists of paths.
packagePathMap = {}
# A Public interface
def AddPackagePath(packagename, path):
paths = packagePathMap.get(packagename, [])
paths.append(path)
packagePathMap[packagename] = paths
class Module:
def __init__(self, name, file=None, path=None):
self.__name__ = name
self.__file__ = file
self.__path__ = path
self.__code__ = None
def __repr__(self):
s = "Module(%s" % `self.__name__`
if self.__file__ is not None:
s = s + ", %s" % `self.__file__`
if self.__path__ is not None:
s = s + ", %s" % `self.__path__`
s = s + ")"
return s
class ModuleFinder:
def __init__(self, path=None, debug=0, excludes = []):
if path is None:
path = sys.path
self.path = path
self.modules = {}
self.badmodules = {}
self.debug = debug
self.indent = 0
self.excludes = excludes
def msg(self, level, str, *args):
if level <= self.debug:
for i in range(self.indent):
print " ",
print str,
for arg in args:
print repr(arg),
print
def msgin(self, *args):
level = args[0]
if level <= self.debug:
self.indent = self.indent + 1
apply(self.msg, args)
def msgout(self, *args):
level = args[0]
if level <= self.debug:
self.indent = self.indent - 1
apply(self.msg, args)
def run_script(self, pathname):
self.msg(2, "run_script", pathname)
fp = open(pathname)
stuff = ("", "r", imp.PY_SOURCE)
self.load_module('__main__', fp, pathname, stuff)
def load_file(self, pathname):
dir, name = os.path.split(pathname)
name, ext = os.path.splitext(name)
fp = open(pathname)
stuff = (ext, "r", imp.PY_SOURCE)
self.load_module(name, fp, pathname, stuff)
def import_hook(self, name, caller=None, fromlist=None):
self.msg(3, "import_hook", name, caller, fromlist)
parent = self.determine_parent(caller)
q, tail = self.find_head_package(parent, name)
m = self.load_tail(q, tail)
if not fromlist:
return q
if m.__path__:
self.ensure_fromlist(m, fromlist)
def determine_parent(self, caller):
self.msgin(4, "determine_parent", caller)
if not caller:
self.msgout(4, "determine_parent -> None")
return None
pname = caller.__name__
if caller.__path__:
parent = self.modules[pname]
assert caller is parent
self.msgout(4, "determine_parent ->", parent)
return parent
if '.' in pname:
i = string.rfind(pname, '.')
pname = pname[:i]
parent = self.modules[pname]
assert parent.__name__ == pname
self.msgout(4, "determine_parent ->", parent)
return parent
self.msgout(4, "determine_parent -> None")
return None
def find_head_package(self, parent, name):
self.msgin(4, "find_head_package", parent, name)
if '.' in name:
i = string.find(name, '.')
head = name[:i]
tail = name[i+1:]
else:
head = name
tail = ""
if parent:
qname = "%s.%s" % (parent.__name__, head)
else:
qname = head
q = self.import_module(head, qname, parent)
if q:
self.msgout(4, "find_head_package ->", (q, tail))
return q, tail
if parent:
qname = head
parent = None
q = self.import_module(head, qname, parent)
if q:
self.msgout(4, "find_head_package ->", (q, tail))
return q, tail
self.msgout(4, "raise ImportError: No module named", qname)
raise ImportError, "No module named " + qname
def load_tail(self, q, tail):
self.msgin(4, "load_tail", q, tail)
m = q
while tail:
i = string.find(tail, '.')
if i < 0: i = len(tail)
head, tail = tail[:i], tail[i+1:]
mname = "%s.%s" % (m.__name__, head)
m = self.import_module(head, mname, m)
if not m:
self.msgout(4, "raise ImportError: No module named", mname)
raise ImportError, "No module named " + mname
self.msgout(4, "load_tail ->", m)
return m
def ensure_fromlist(self, m, fromlist, recursive=0):
self.msg(4, "ensure_fromlist", m, fromlist, recursive)
for sub in fromlist:
if sub == "*":
if not recursive:
all = self.find_all_submodules(m)
if all:
self.ensure_fromlist(m, all, 1)
elif not hasattr(m, sub):
subname = "%s.%s" % (m.__name__, sub)
submod = self.import_module(sub, subname, m)
if not submod:
raise ImportError, "No module named " + subname
def find_all_submodules(self, m):
if not m.__path__:
return
modules = {}
suffixes = [".py", ".pyc", ".pyo"]
for dir in m.__path__:
try:
names = os.listdir(dir)
except os.error:
self.msg(2, "can't list directory", dir)
continue
for name in names:
mod = None
for suff in suffixes:
n = len(suff)
if name[-n:] == suff:
mod = name[:-n]
break
if mod and mod != "__init__":
modules[mod] = mod
return modules.keys()
def import_module(self, partname, fqname, parent):
self.msgin(3, "import_module", partname, fqname, parent)
try:
m = self.modules[fqname]
except KeyError:
pass
else:
self.msgout(3, "import_module ->", m)
return m
if self.badmodules.has_key(fqname):
self.msgout(3, "import_module -> None")
self.badmodules[fqname][parent.__name__] = None
return None
try:
fp, pathname, stuff = self.find_module(partname,
parent and parent.__path__)
except ImportError:
self.msgout(3, "import_module ->", None)
return None
try:
m = self.load_module(fqname, fp, pathname, stuff)
finally:
if fp: fp.close()
if parent:
setattr(parent, partname, m)
self.msgout(3, "import_module ->", m)
return m
def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
self.msgin(2, "load_module", fqname, fp and "fp", pathname)
if type == imp.PKG_DIRECTORY:
m = self.load_package(fqname, pathname)
self.msgout(2, "load_module ->", m)
return m
if type == imp.PY_SOURCE:
co = compile(fp.read()+'\n', pathname, 'exec')
elif type == imp.PY_COMPILED:
if fp.read(4) != imp.get_magic():
self.msgout(2, "raise ImportError: Bad magic number", pathname)
raise ImportError, "Bad magic number in %s", pathname
fp.read(4)
co = marshal.load(fp)
else:
co = None
m = self.add_module(fqname)
m.__file__ = pathname
if co:
m.__code__ = co
self.scan_code(co, m)
self.msgout(2, "load_module ->", m)
return m
def scan_code(self, co, m):
code = co.co_code
n = len(code)
i = 0
lastname = None
while i < n:
c = code[i]
i = i+1
op = ord(c)
if op >= dis.HAVE_ARGUMENT:
oparg = ord(code[i]) + ord(code[i+1])*256
i = i+2
if op == IMPORT_NAME:
name = lastname = co.co_names[oparg]
if not self.badmodules.has_key(lastname):
try:
self.import_hook(name, m)
except ImportError, msg:
self.msg(2, "ImportError:", str(msg))
if not self.badmodules.has_key(name):
self.badmodules[name] = {}
self.badmodules[name][m.__name__] = None
elif op == IMPORT_FROM:
name = co.co_names[oparg]
assert lastname is not None
if not self.badmodules.has_key(lastname):
try:
self.import_hook(lastname, m, [name])
except ImportError, msg:
self.msg(2, "ImportError:", str(msg))
fullname = lastname + "." + name
if not self.badmodules.has_key(fullname):
self.badmodules[fullname] = {}
self.badmodules[fullname][m.__name__] = None
else:
lastname = None
for c in co.co_consts:
if isinstance(c, type(co)):
self.scan_code(c, m)
def load_package(self, fqname, pathname):
self.msgin(2, "load_package", fqname, pathname)
m = self.add_module(fqname)
m.__file__ = pathname
m.__path__ = [pathname]
# As per comment at top of file, simulate runtime __path__ additions.
m.__path__ = m.__path__ + packagePathMap.get(fqname, [])
fp, buf, stuff = self.find_module("__init__", m.__path__)
self.load_module(fqname, fp, buf, stuff)
self.msgout(2, "load_package ->", m)
return m
def add_module(self, fqname):
if self.modules.has_key(fqname):
return self.modules[fqname]
self.modules[fqname] = m = Module(fqname)
return m
def find_module(self, name, path):
if name in self.excludes:
self.msgout(3, "find_module -> Excluded")
raise ImportError, name
if path is None:
if name in sys.builtin_module_names:
return (None, None, ("", "", imp.C_BUILTIN))
# Emulate the Registered Module support on Windows.
if sys.platform=="win32" and win32api is not None:
HKEY_LOCAL_MACHINE = 0x80000002
try:
pathname = win32api.RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Python\\PythonCore\\%s\\Modules\\%s" % (sys.winver, name))
fp = open(pathname, "rb")
# XXX - To do - remove the hard code of C_EXTENSION.
stuff = "", "rb", imp.C_EXTENSION
return fp, pathname, stuff
except win32api.error:
pass
path = self.path
return imp.find_module(name, path)
def report(self):
print
print " %-25s %s" % ("Name", "File")
print " %-25s %s" % ("----", "----")
# Print modules found
keys = self.modules.keys()
keys.sort()
for key in keys:
m = self.modules[key]
if m.__path__:
print "P",
else:
print "m",
print "%-25s" % key, m.__file__ or ""
# Print missing modules
keys = self.badmodules.keys()
keys.sort()
for key in keys:
# ... but not if they were explicitely excluded.
if key not in self.excludes:
mods = self.badmodules[key].keys()
mods.sort()
print "?", key, "from", string.join(mods, ', ')
def test():
# Parse command line
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")
except getopt.error, msg:
print msg
return
# Process options
debug = 1
domods = 0
addpath = []
exclude = []
for o, a in opts:
if o == '-d':
debug = debug + 1
if o == '-m':
domods = 1
if o == '-p':
addpath = addpath + string.split(a, os.pathsep)
if o == '-q':
debug = 0
if o == '-x':
exclude.append(a)
# Provide default arguments
if not args:
script = "hello.py"
else:
script = args[0]
# Set the path based on sys.path and the script directory
path = sys.path[:]
path[0] = os.path.dirname(script)
path = addpath + path
if debug > 1:
print "path:"
for item in path:
print " ", `item`
# Create the module finder and turn its crank
mf = ModuleFinder(path, debug, exclude)
for arg in args[1:]:
if arg == '-m':
domods = 1
continue
if domods:
if arg[-2:] == '.*':
mf.import_hook(arg[:-2], None, ["*"])
else:
mf.import_hook(arg)
else:
mf.load_file(arg)
mf.run_script(script)
mf.report()
if __name__ == '__main__':
try:
test()
except KeyboardInterrupt:
print "\n[interrupt]"

View File

@ -0,0 +1,317 @@
import os
import string
import archivebuilder
import carchive
import tocfilter
import bindepend
import finder
_cache = {}
def makeresource(name, xtrapath=None):
"""Factory function that returns a resource subclass.
NAME is the logical or physical name of a resource.
XTRAPTH is a path or list of paths to search first.
return one of the resource subclasses.
Warning - logical names can conflict; archive might return a directory,
when the module archive.py was desired."""
typ, nm, fullname = finder.identify(name, xtrapath)
fullname = os.path.normpath(fullname)
if _cache.has_key(fullname):
return _cache[fullname]
elif typ in (finder.SCRIPT, finder.GSCRIPT):
rsrc = scriptresource(nm, fullname)
elif typ == finder.MODULE:
rsrc = moduleresource(nm, fullname)
elif typ == finder.PACKAGE:
rsrc = pkgresource(nm, fullname)
elif typ in (finder.PBINARY, finder.BINARY):
rsrc = binaryresource(nm, fullname)
elif typ == finder.ZLIB:
rsrc = zlibresource(nm, fullname)
elif typ == finder.DIRECTORY:
rsrc = dirresource(nm, fullname)
else:
try:
carchive.CArchive(fullname)
except:
rsrc = dataresource(nm, fullname)
else:
rsrc = archiveresource(nm, fullname)
_cache[fullname] = rsrc
return rsrc
class resource:
""" Base class for all resources.
contents() returns of list of what's contained (eg files in dirs)
dependencies() for Python resources returns a list of moduleresources
and binaryresources """
def __init__(self, name, path, typ):
"""NAME is the logical name of the resource.
PATH is the full path to the resource.
TYP is the type code.
No editting or sanity checks."""
self.name = name
self.path = path
self.typ = typ
def __repr__(self):
return "(%(name)s, %(path)s, %(typ)s)" % self.__dict__
def contents(self):
"""A list of resources within this resource.
Overridable.
Base implementation returns [self]"""
return [self]
def dependencies(self):
"""A list of resources this resource requires.
Overridable.
Base implementation returns []"""
return []
def __cmp__(self, other):
if not isinstance(other, self.__class__):
return -1
return cmp((self.typ, self.name), (other.typ, other.name))
def asFilter(self):
"""Create a tocfilter based on self.
Pure virtual"""
raise NotImplementedError
def asSource(self):
"""Return self in source form.
Base implementation returns self"""
return self
def asBinary(self):
"""Return self in binary form.
Base implementation returns self"""
return self
class pythonresource(resource):
"""An empty base class.
Used to classify resources."""
pass
class scriptresource(pythonresource):
""" A top-level python resource.
Has (lazily computed) attributes, modules and binaries, which together
are the scripts dependencies() """
def __init__(self, name, fullname):
resource.__init__(self, name, fullname, 's')
def __getattr__(self, name):
if name == 'modules':
print "Analyzing python dependencies of", self.name, self.path
self.modules = []
self._binaries = []
nodes = string.split(self.name, '.')[:-1] # MEInc.Dist.archive -> ['MEInc', 'Dist']
for i in range(len(nodes)):
nm = string.join(nodes[:i+1], '.')
rsrc = makeresource(nm+'.__init__')
rsrc.name = nm
self.modules.append(rsrc)
for (nm, path) in archivebuilder.Dependencies(self.path):
path = os.path.normcase(os.path.abspath(path))
if os.path.splitext(path)[1] == '.py':
self.modules.append(moduleresource(nm, path))
else:
self._binaries.append(binaryresource(nm, path))
return self.modules
elif name == 'binaries':
x = self.modules
tmp = {}
for br in self._binaries:
tmp[br.name] = br
for br2 in br.dependencies():
tmp[br2.name] = br2
self.binaries = tmp.values()
return self.binaries
else:
raise AttributeError, "%s" % name
def dependencies(self):
"""Return all dependencies (Python and binary) of self."""
return self.modules + self.binaries
def asFilter(self):
"""Return a ModFilter based on self."""
return tocfilter.ModFilter([self.name])
def asSource(self):
"""Return self as a dataresource (ie, a text file wrapper)."""
r = dataresource(self.path)
r.name = apply(os.path.join, string.split(self.name, '.')[:-1]+[r.name])
return r
class moduleresource(scriptresource):
""" A module resource (differs from script in that it will generally
be worked with as a .pyc instead of in source form) """
def __init__(self, name, fullname):
resource.__init__(self, name, fullname, 'm')
def asBinary(self):
"""Return self as a dataresource (ie, a binary file wrapper)."""
r = dataresource(self.path)
r.name = os.path.basename(r.name)
r.typ = 'b'
return r
def asSource(self):
"""Return self as a scriptresource (ie, uncompiled form)."""
return scriptresource(self.name, self.path[:-1]).asSource()
class binaryresource(resource):
"""A .dll or .pyd.
dependencies() yields more binaryresources """
def __init__(self, name, fullname):
if string.find(name, '.') == -1:
pth, bnm = os.path.split(fullname)
junk, ext = os.path.splitext(bnm)
fullname = os.path.join(pth, name + ext)
resource.__init__(self, name, fullname, 'b')
self._depends = None
def dependencies(self):
"""Return a list of binary dependencies."""
if self._depends is not None:
return self._depends
self._depends = []
for (lib, path) in bindepend.Dependencies([(self.name, self.path)]):
self._depends.append(binaryresource(lib, path))
return self._depends
def asFilter(self):
"""Create a FileFilter from self."""
return tocfilter.FileFilter([self.name])
class dataresource(resource):
"""A subclass for arbitrary files. """
def __init__(self, name, fullname=None):
resource.__init__(self, name, fullname or name, 'x')
def asFilter(self):
"""Create a FileFilter from self."""
return tocfilter.FileFilter([self.name])
class archiveresource(dataresource):
"""A sublcass for CArchives. """
def __init__(self, name, fullname=None):
resource.__init__(self, name, fullname or name, 'a')
class zlibresource(dataresource):
"""A subclass for ZlibArchives. """
def __init__(self, name, fullname=None):
resource.__init__(self, name, fullname or name, 'z')
class dirresource(resource):
"""A sublcass for a directory.
Generally transformed to a list of files through
contents() and filtered by file extensions or resource type.
Note that contents() is smart enough to regard a .py and .pyc
as the same resource. """
RECURSIVE = 0
def __init__(self, name, fullname=None):
resource.__init__(self, name, fullname or name, 'd')
self._contents = None
def contents(self, prefix=''):
"""Return the list of (typed) resources in self.name"""
if self._contents is not None:
return self._contents
self._contents = []
flist = os.listdir(self.path)
for fnm in flist:
try:
bnm, ext = os.path.splitext(fnm)
if ext == '.py' and (bnm+'.pyc' in flist or bnm+'.pyo' in flist):
pass
elif ext == '.pyo' and (bnm + '.pyc' in flist):
pass
else:
rsrc = makeresource(os.path.join(self.path,fnm))
if isinstance(rsrc, pkgresource):
rsrc = self.__class__(rsrc.path)
if self.RECURSIVE:
if isinstance(rsrc, moduleresource) or isinstance(rsrc, scriptresource):
rsrc = rsrc.asSource()
fnm = os.path.basename(rsrc.path)
rsrc.name = os.path.join(prefix, fnm)
if rsrc.typ == 'd':
rsrc.RECURSIVE = 1
self._contents.extend(rsrc.contents(rsrc.name))
else:
self._contents.append(rsrc)
else:
self._contents.append(rsrc)
except ValueError,e:
raise RuntimeError, "Can't make resource from %s\n ValueError: %s" \
% (os.path.join(self.path, fnm), `e.args`)
return self._contents
def asFilter(self):
return tocfilter.DirFilter([self.path])
class treeresource(dirresource):
"""A subclass for a directory and subdirectories."""
RECURSIVE = 1
def __init__(self, name, fullname=None):
dirresource.__init__(self, name, fullname)
class pkgresource(pythonresource):
"""A Python package.
Note that contents() can be fooled by fancy __path__ statements. """
def __init__(self, nm, fullname):
resource.__init__(self, nm, fullname, 'p')
self._contents = None
self._depends = None
def contents(self, parent=None):
"""Return a list of subpackages and modules in self."""
if self._contents is not None:
return self._contents
if parent is None:
parent = self.name
self._contents = []
cheat = treeresource(self.path)
for rsrc in cheat.contents():
if os.path.splitext(rsrc.path)[1] == '.py':
rsrc = moduleresource(string.replace(rsrc.name[:-3], os.sep, '.'),
rsrc.path)
if rsrc.name[-8:] == '__init__':
rsrc.name = rsrc.name[:-9]
elif os.path.isdir(rsrc.path):
rsrc = makeresource(rsrc.path)
else:
continue
if rsrc.name:
rsrc.name = parent + '.' + rsrc.name
else:
rsrc.name = parent
if rsrc.typ == 'm':
self._contents.append(rsrc)
elif rsrc.typ == 'p':
self._contents.extend(rsrc.contents(rsrc.name))
return self._contents
def dependencies(self):
"""Return the list of accumulated dependencies of all modules in self."""
if self._depends is not None:
return self._depends
self._depends = []
tmp = {}
for rsrc in self.contents():
for r in rsrc.dependencies():
tmp[r.name] = r
self._depends = tmp.values()
return self._depends
def asFilter(self):
"""Create a PkgFilter from self."""
return tocfilter.PkgFilter([os.path.dirname(self.path)])
if __name__ == '__main__':
s = scriptresource('finder.py', './finder.py')
print "s.modules:", s.modules
print "s.binaries:", s.binaries

View File

@ -0,0 +1,131 @@
import os
import finder
import re
import sys
def makefilter(name, xtrapath=None):
typ, nm, fullname = finder.identify(name, xtrapath)
if typ in (finder.SCRIPT, finder.GSCRIPT, finder.MODULE):
return ModFilter([os.path.splitext(nm)[0]])
if typ == finder.PACKAGE:
return PkgFilter([fullname])
if typ == finder.DIRECTORY:
return DirFilter([fullname])
if typ in (finder.BINARY, finder.PBINARY):
return FileFilter([nm])
return FileFilter([fullname])
class _Filter:
def __repr__(self):
return '<'+self.__class__.__name__+' '+repr(self.elements)+'>'
class _NameFilter(_Filter):
""" A filter mixin that matches (exactly) on name """
def matches(self, res):
return self.elements.get(res.name, 0)
class _PathFilter(_Filter):
""" A filter mixin that matches if the resource is below any of the paths"""
def matches(self, res):
p = os.path.normcase(os.path.abspath(res.path))
while len(p) > 3:
p = os.path.dirname(p)
if self.elements.get(p, 0):
return 1
return 0
class _ExtFilter(_Filter):
""" A filter mixin that matches based on file extensions (either way) """
include = 0
def matches(self, res):
fnd = self.elements.get(os.path.splitext(res.path)[1], 0)
if self.include:
return not fnd
return fnd
class _TypeFilter(_Filter):
""" A filter mixin that matches on resource type (either way) """
include = 0
def matches(self, res):
fnd = self.elements.get(res.typ, 0)
if self.include:
return not fnd
return fnd
class _PatternFilter(_Filter):
""" A filter that matches if re.search succeeds on the resource path """
def matches(self, res):
for regex in self.elements:
if regex.search(res.path):
return 1
return 0
class ExtFilter(_ExtFilter):
""" A file extension filter.
ExtFilter(extlist, include=0)
where extlist is a list of file extensions """
def __init__(self, extlist, include=0):
self.elements = {}
for ext in extlist:
if ext[0:1] != '.':
ext = '.'+ext
self.elements[ext] = 1
self.include = include
class TypeFilter(_TypeFilter):
""" A filter for resource types.
TypeFilter(typlist, include=0)
where typlist is a subset of ['a','b','d','m','p','s','x','z'] """
def __init__(self, typlist, include=0):
self.elements = {}
for typ in typlist:
self.elements[typ] = 1
self.include = include
class FileFilter(_NameFilter):
""" A filter for data files """
def __init__(self, filelist):
self.elements = {}
for f in filelist:
self.elements[f] = 1
class ModFilter(_NameFilter):
""" A filter for Python modules.
ModFilter(modlist) where modlist is eg ['macpath', 'dospath'] """
def __init__(self, modlist):
self.elements = {}
for mod in modlist:
self.elements[mod] = 1
class DirFilter(_PathFilter):
""" A filter based on directories.
DirFilter(dirlist)
dirs may be relative and will be normalized.
Subdirectories of dirs will be excluded. """
def __init__(self, dirlist):
self.elements = {}
for pth in dirlist:
pth = os.path.normcase(os.path.abspath(pth))
self.elements[pth] = 1
class PkgFilter(_PathFilter):
"""At this time, identical to a DirFilter (being lazy) """
def __init__(self, pkglist):
#warning - pkgs are expected to be full directories
self.elements = {}
for pkg in pkglist:
pth = os.path.normcase(os.path.abspath(pkg))
self.elements[pth] = 1
class StdLibFilter(_PathFilter):
""" A filter that excludes anything found in the standard library """
def __init__(self):
pth = os.path.normcase(os.path.join(sys.exec_prefix, 'lib'))
self.elements = {pth:1}
class PatternFilter(_PatternFilter):
""" A filter that excludes if any pattern is found in resource's path """
def __init__(self, patterns):
self.elements = []
for pat in patterns:
self.elements.append(re.compile(pat))