*** empty log message ***
This commit is contained in:
parent
259683160c
commit
ec3ac7ffad
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) ")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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())
|
||||
|
||||
|
||||
|
|
@ -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()
|
||||
|
|
@ -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]"
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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))
|
||||
Loading…
Reference in New Issue