*** empty log message ***
This commit is contained in:
parent
2c2eacc2ec
commit
7bb41d9131
|
|
@ -98,11 +98,12 @@ 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')])
|
||||
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'imputil.py')])
|
||||
print "pyinsthome:", pyinsthome
|
||||
imputil = resource.makeresource('imputil.py', [pyinsthome])
|
||||
self._dependencies.append(imputil)
|
||||
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'support', 'archive_rt.py')])
|
||||
archmodule = resource.makeresource('archive_rt.py', [os.path.join(pyinsthome, 'support')])
|
||||
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'archive_rt.py')])
|
||||
archmodule = resource.makeresource('archive_rt.py', [pyinsthome])
|
||||
self._dependencies.merge(archmodule.dependencies())
|
||||
self._dependencies.append(archmodule)
|
||||
self.toc.addFilter(archmodule)
|
||||
|
|
@ -244,8 +245,8 @@ 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')])
|
||||
archivebuilder.GetCompiled([os.path.join(pyinsthome, 'carchive_rt.py')])
|
||||
carchmodule = resource.makeresource('carchive_rt.py', [pyinsthome])
|
||||
self._dependencies.merge(carchmodule.dependencies())
|
||||
self._dependencies.append(carchmodule)
|
||||
|
||||
|
|
@ -456,7 +457,7 @@ 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'))
|
||||
# sys.path.insert(0, os.path.join(pyinsthome, 'support'))
|
||||
import installutils
|
||||
copyFile = installutils.copyFile
|
||||
global logfile
|
||||
|
|
|
|||
|
|
@ -0,0 +1,226 @@
|
|||
#
|
||||
# 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.
|
||||
|
||||
#archive_rt is a stripped down version of MEInc.Dist.archive.
|
||||
#It has had all building logic removed.
|
||||
#It's purpose is to bootstrap the Python installation.
|
||||
|
||||
import marshal
|
||||
import struct
|
||||
|
||||
class Archive:
|
||||
""" A base class for a repository of python code objects.
|
||||
The extract method is used by imputil.ArchiveImporter
|
||||
to get code objects by name (fully qualified name), so
|
||||
an enduser "import a.b" would become
|
||||
extract('a.__init__')
|
||||
extract('a.b')
|
||||
"""
|
||||
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."
|
||||
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):
|
||||
""" 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):
|
||||
""" 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):
|
||||
print "parent: ", parent
|
||||
print "modname: ", modname
|
||||
print "fqname: ", fqname
|
||||
return 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.
|
||||
For use with imputil ArchiveImporter, object is a python code object.
|
||||
'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.
|
||||
Not required by ArchiveImporter.
|
||||
"""
|
||||
return self.toc.keys()
|
||||
|
||||
########################################################################
|
||||
# Building
|
||||
|
||||
####### Top level method - shouldn't need overriding #######
|
||||
## def build(self, path, lTOC):
|
||||
## """Create an archive file of name 'path'.
|
||||
## lTOC is a 'logical TOC' - a list of (name, path, ...)
|
||||
## where name is the internal name, eg 'a'
|
||||
## 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):
|
||||
## """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. Overrides of
|
||||
## get_obj_from can make use of further elements in 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__'
|
||||
## 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):
|
||||
## """Default - toc is a dict
|
||||
## Gets marshaled to self.lib
|
||||
## """
|
||||
## marshal.dump(self.toc, self.lib)
|
||||
##
|
||||
## def save_trailer(self, tocpos):
|
||||
## """Default - not used"""
|
||||
## pass
|
||||
##
|
||||
## def update_headers(self, tocpos):
|
||||
## """Default - 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):
|
||||
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):
|
||||
(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):
|
||||
## 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,157 @@
|
|||
# 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.
|
||||
|
||||
#carchive_rt is a stripped down version of MEInc.Dist.carchive.
|
||||
#It has had all building logic removed.
|
||||
#It's purpose is to bootstrap the Python installation.
|
||||
|
||||
import archive_rt
|
||||
import struct
|
||||
import zlib
|
||||
import strop
|
||||
|
||||
class CTOC:
|
||||
ENTRYSTRUCT = 'iiiibc' #(structlen, dpos, dlen, ulen, flag, typcd) followed by name
|
||||
def __init__(self):
|
||||
self.data = []
|
||||
|
||||
def frombinary(self, s):
|
||||
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):
|
||||
## 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):
|
||||
## self.data.append(dpos, dlen, ulen, flag, typcd, nm)
|
||||
|
||||
def get(self, ndx):
|
||||
return self.data[ndx]
|
||||
|
||||
def __getitem__(self, ndx):
|
||||
return self.data[ndx]
|
||||
|
||||
def find(self, name):
|
||||
for i in range(len(self.data)):
|
||||
if self.data[i][-1] == name:
|
||||
return i
|
||||
return -1
|
||||
|
||||
class CArchive(archive_rt.Archive):
|
||||
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):
|
||||
self.len = len
|
||||
archive_rt.Archive.__init__(self, path, start)
|
||||
|
||||
def checkmagic(self):
|
||||
#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):
|
||||
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):
|
||||
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):
|
||||
rslt = []
|
||||
for (dpos, dlen, ulen, flag, typcd, nm) in self.toc:
|
||||
rslt.append(nm)
|
||||
return rslt
|
||||
|
||||
## def add(self, entry):
|
||||
## (nm, pathnm, flag, typcd) = entry[:4]
|
||||
## if flag == 2:
|
||||
## s = open(pathnm, 'r').read()
|
||||
## s = s + '\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):
|
||||
## self.tocpos = tocpos
|
||||
## tocstr = self.toc.tobinary()
|
||||
## self.toclen = len(tocstr)
|
||||
## self.lib.write(tocstr)
|
||||
##
|
||||
## def save_trailer(self, tocpos):
|
||||
## 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):
|
||||
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,487 @@
|
|||
#
|
||||
# imputil.py
|
||||
#
|
||||
# Written by Greg Stein. Public Domain.
|
||||
# No Copyright, no Rights Reserved, and no Warranties.
|
||||
#
|
||||
# Utilities to help out with custom import mechanisms.
|
||||
#
|
||||
# Additional modifications were contribed by Marc-Andre Lemburg and
|
||||
# Gordon McMillan.
|
||||
#
|
||||
|
||||
__version__ = '0.3'
|
||||
|
||||
# note: avoid importing non-builtin modules
|
||||
import imp
|
||||
import sys
|
||||
import strop
|
||||
import __builtin__ ### why this instead of just using __builtins__ ??
|
||||
|
||||
# for the DirectoryImporter
|
||||
import struct
|
||||
import marshal
|
||||
|
||||
class Importer:
|
||||
"Base class for replacing standard import functions."
|
||||
|
||||
def install(self):
|
||||
self.__chain_import = __builtin__.__import__
|
||||
self.__chain_reload = __builtin__.reload
|
||||
__builtin__.__import__ = self._import_hook
|
||||
__builtin__.reload = self._reload_hook
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# PRIVATE METHODS
|
||||
#
|
||||
def _import_hook(self, name, globals=None, locals=None, fromlist=None):
|
||||
"""Python calls this hook to locate and import a module.
|
||||
|
||||
This method attempts to load the (dotted) module name. If it cannot
|
||||
find it, then it delegates the import to the next import hook in the
|
||||
chain (where "next" is defined as the import hook that was in place
|
||||
at the time this Importer instance was installed).
|
||||
"""
|
||||
|
||||
# determine the context of this import
|
||||
parent = self._determine_import_context(globals)
|
||||
|
||||
# import the module within the context, or from the default context
|
||||
top, tail = self._import_top_module(parent, name)
|
||||
if top is None:
|
||||
# the module was not found; delegate to the next import hook
|
||||
return self.__chain_import(name, globals, locals, fromlist)
|
||||
|
||||
# the top module may be under the control of a different importer.
|
||||
# if so, then defer to that importer for completion of the import.
|
||||
# note it may be self, or is undefined so we (self) may as well
|
||||
# finish the import.
|
||||
importer = top.__dict__.get('__importer__', self)
|
||||
return importer._finish_import(top, tail, fromlist)
|
||||
|
||||
def _finish_import(self, top, tail, fromlist):
|
||||
# if "a.b.c" was provided, then load the ".b.c" portion down from
|
||||
# below the top-level module.
|
||||
bottom = self._load_tail(top, tail)
|
||||
|
||||
# if the form is "import a.b.c", then return "a"
|
||||
if not fromlist:
|
||||
# no fromlist: return the top of the import tree
|
||||
return top
|
||||
|
||||
# the top module was imported by self, or it was not imported through
|
||||
# the Importer mechanism and self is simply handling the import of
|
||||
# the sub-modules and fromlist.
|
||||
#
|
||||
# this means that the bottom module was also imported by self, or we
|
||||
# are handling things in the absence of a prior Importer
|
||||
#
|
||||
# ### why the heck are we handling it? what is the example scenario
|
||||
# ### where this happens? note that we can't determine is_package()
|
||||
# ### for non-Importer modules.
|
||||
#
|
||||
# since we imported/handled the bottom module, this means that we can
|
||||
# also handle its fromlist (and reliably determine is_package()).
|
||||
|
||||
# if the bottom node is a package, then (potentially) import some modules.
|
||||
#
|
||||
# note: if it is not a package, then "fromlist" refers to names in
|
||||
# the bottom module rather than modules.
|
||||
# note: for a mix of names and modules in the fromlist, we will
|
||||
# import all modules and insert those into the namespace of
|
||||
# the package module. Python will pick up all fromlist names
|
||||
# from the bottom (package) module; some will be modules that
|
||||
# we imported and stored in the namespace, others are expected
|
||||
# to be present already.
|
||||
if self._is_package(bottom.__dict__):
|
||||
self._import_fromlist(bottom, fromlist)
|
||||
|
||||
# if the form is "from a.b import c, d" then return "b"
|
||||
return bottom
|
||||
|
||||
def _reload_hook(self, module):
|
||||
"Python calls this hook to reload a module."
|
||||
|
||||
# reloading of a module may or may not be possible (depending on the
|
||||
# importer), but at least we can validate that it's ours to reload
|
||||
importer = module.__dict__.get('__importer__', None)
|
||||
if importer is not self:
|
||||
return self.__chain_reload(module)
|
||||
|
||||
# okay. it is ours, but we don't know what to do (yet)
|
||||
### we should blast the module dict and do another get_code(). need to
|
||||
### flesh this out and add proper docco...
|
||||
raise SystemError, "reload not yet implemented"
|
||||
|
||||
def _determine_import_context(self, globals):
|
||||
"""Returns the context in which a module should be imported.
|
||||
|
||||
The context could be a loaded (package) module and the imported module
|
||||
will be looked for within that package. The context could also be None,
|
||||
meaning there is no context -- the module should be looked for as a
|
||||
"top-level" module.
|
||||
"""
|
||||
|
||||
if not globals or \
|
||||
globals.get('__importer__', None) is not self:
|
||||
# globals does not refer to one of our modules or packages.
|
||||
# That implies there is no relative import context, and it
|
||||
# should just pick it off the standard path.
|
||||
return None
|
||||
|
||||
# The globals refer to a module or package of ours. It will define
|
||||
# the context of the new import. Get the module/package fqname.
|
||||
parent_fqname = globals['__name__']
|
||||
|
||||
# for a package, return itself (imports refer to pkg contents)
|
||||
if self._is_package(globals):
|
||||
parent = sys.modules[parent_fqname]
|
||||
assert globals is parent.__dict__
|
||||
return parent
|
||||
|
||||
i = strop.rfind(parent_fqname, '.')
|
||||
|
||||
# a module outside of a package has no particular import context
|
||||
if i == -1:
|
||||
return None
|
||||
|
||||
# for a module in a package, return the package (imports refer to siblings)
|
||||
parent_fqname = parent_fqname[:i]
|
||||
parent = sys.modules[parent_fqname]
|
||||
assert parent.__name__ == parent_fqname
|
||||
return parent
|
||||
|
||||
def _import_top_module(self, parent, name):
|
||||
"""Locate the top of the import tree (relative or absolute).
|
||||
|
||||
parent defines the context in which the import should occur. See
|
||||
_determine_import_context() for details.
|
||||
|
||||
Returns a tuple (module, tail). module is the loaded (top-level) module,
|
||||
or None if the module is not found. tail is the remaining portion of
|
||||
the dotted name.
|
||||
"""
|
||||
i = strop.find(name, '.')
|
||||
if i == -1:
|
||||
head = name
|
||||
tail = ""
|
||||
else:
|
||||
head = name[:i]
|
||||
tail = name[i+1:]
|
||||
if parent:
|
||||
fqname = "%s.%s" % (parent.__name__, head)
|
||||
else:
|
||||
fqname = head
|
||||
module = self._import_one(parent, head, fqname)
|
||||
if module:
|
||||
# the module was relative, or no context existed (the module was
|
||||
# simply found on the path).
|
||||
return module, tail
|
||||
if parent:
|
||||
# we tried relative, now try an absolute import (from the path)
|
||||
module = self._import_one(None, head, head)
|
||||
if module:
|
||||
return module, tail
|
||||
|
||||
# the module wasn't found
|
||||
return None, None
|
||||
|
||||
def _import_one(self, parent, modname, fqname):
|
||||
"Import a single module."
|
||||
|
||||
# has the module already been imported?
|
||||
try:
|
||||
return sys.modules[fqname]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# load the module's code, or fetch the module itself
|
||||
result = self.get_code(parent, modname, fqname)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
# did get_code() return an actual module? (rather than a code object)
|
||||
is_module = type(result[1]) is type(sys)
|
||||
|
||||
# use the returned module, or create a new one to exec code into
|
||||
if is_module:
|
||||
module = result[1]
|
||||
else:
|
||||
module = imp.new_module(fqname)
|
||||
|
||||
### record packages a bit differently??
|
||||
module.__importer__ = self
|
||||
module.__ispkg__ = result[0]
|
||||
|
||||
# if present, the third item is a set of values to insert into the module
|
||||
if len(result) > 2:
|
||||
module.__dict__.update(result[2])
|
||||
|
||||
# the module is almost ready... make it visible
|
||||
sys.modules[fqname] = module
|
||||
|
||||
# execute the code within the module's namespace
|
||||
if not is_module:
|
||||
exec result[1] in module.__dict__
|
||||
|
||||
# insert the module into its parent
|
||||
if parent:
|
||||
setattr(parent, modname, module)
|
||||
return module
|
||||
|
||||
def _load_tail(self, m, tail):
|
||||
"""Import the rest of the modules, down from the top-level module.
|
||||
|
||||
Returns the last module in the dotted list of modules.
|
||||
"""
|
||||
if tail:
|
||||
for part in strop.splitfields(tail, '.'):
|
||||
fqname = "%s.%s" % (m.__name__, part)
|
||||
m = self._import_one(m, part, fqname)
|
||||
if not m:
|
||||
raise ImportError, "No module named " + fqname
|
||||
return m
|
||||
|
||||
def _import_fromlist(self, package, fromlist):
|
||||
'Import any sub-modules in the "from" list.'
|
||||
|
||||
# if '*' is present in the fromlist, then look for the '__all__' variable
|
||||
# to find additional items (modules) to import.
|
||||
if '*' in fromlist:
|
||||
fromlist = list(fromlist) + list(package.__dict__.get('__all__', []))
|
||||
|
||||
for sub in fromlist:
|
||||
# if the name is already present, then don't try to import it (it
|
||||
# might not be a module!).
|
||||
if sub != '*' and not hasattr(package, sub):
|
||||
subname = "%s.%s" % (package.__name__, sub)
|
||||
submod = self._import_one(package, sub, subname)
|
||||
if not submod:
|
||||
raise ImportError, "cannot import name " + subname
|
||||
|
||||
def _is_package(self, module_dict):
|
||||
"""Determine if a given module (dictionary) specifies a package.
|
||||
|
||||
The package status is in the module-level name __ispkg__. The module
|
||||
must also have been imported by self, so that we can reliably apply
|
||||
semantic meaning to __ispkg__.
|
||||
|
||||
### weaken the test to issubclass(Importer)?
|
||||
"""
|
||||
return module_dict.get('__importer__', None) is self and \
|
||||
module_dict['__ispkg__']
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# METHODS TO OVERRIDE
|
||||
#
|
||||
def get_code(self, parent, modname, fqname):
|
||||
"""Find and retrieve the code for the given module.
|
||||
|
||||
parent specifies a parent module to define a context for importing. It
|
||||
may be None, indicating no particular context for the search.
|
||||
|
||||
modname specifies a single module (not dotted) within the parent.
|
||||
|
||||
fqname specifies the fully-qualified module name. This is a (potentially)
|
||||
dotted name from the "root" of the module namespace down to the modname.
|
||||
If there is no parent, then modname==fqname.
|
||||
|
||||
This method should return None, a 2-tuple, or a 3-tuple.
|
||||
|
||||
* If the module was not found, then None should be returned.
|
||||
|
||||
* The first item of the 2- or 3-tuple should be the integer 0 or 1,
|
||||
specifying whether the module that was found is a package or not.
|
||||
|
||||
* The second item is the code object for the module (it will be
|
||||
executed within the new module's namespace). This item can also
|
||||
be a fully-loaded module object (e.g. loaded from a shared lib).
|
||||
|
||||
* If present, the third item is a dictionary of name/value pairs that
|
||||
will be inserted into new module before the code object is executed.
|
||||
This provided in case the module's code expects certain values (such
|
||||
as where the module was found). When the second item is a module
|
||||
object, then these names/values will be inserted *after* the module
|
||||
has been loaded/initialized.
|
||||
"""
|
||||
raise RuntimeError, "get_code not implemented"
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Simple function-based importer
|
||||
#
|
||||
class FuncImporter(Importer):
|
||||
"Importer subclass to use a supplied function rather than method overrides."
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
def get_code(self, parent, modname, fqname):
|
||||
return self.func(parent, modname, fqname)
|
||||
|
||||
def install_with(func):
|
||||
FuncImporter(func).install()
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Base class for archive-based importing
|
||||
#
|
||||
class PackageArchiveImporter(Importer):
|
||||
"Importer subclass to import from (file) archives."
|
||||
|
||||
def get_code(self, parent, modname, fqname):
|
||||
if parent:
|
||||
# if a parent "package" is provided, then we are importing a sub-file
|
||||
# from the archive.
|
||||
result = self.get_subfile(parent.__archive__, modname)
|
||||
if result is None:
|
||||
return None
|
||||
if type(result) == type(()):
|
||||
return (0,) + result
|
||||
return 0, result
|
||||
|
||||
# no parent was provided, so the archive should exist somewhere on the
|
||||
# default "path".
|
||||
archive = self.get_archive(modname)
|
||||
if archive is None:
|
||||
return None
|
||||
return 1, "", {'__archive__':archive}
|
||||
|
||||
def get_archive(self, modname):
|
||||
"""Get an archive of modules.
|
||||
|
||||
This method should locate an archive and return a value which can be
|
||||
used by get_subfile to load modules from it. The value may be a simple
|
||||
pathname, an open file, or a complex object that caches information
|
||||
for future imports.
|
||||
|
||||
Return None if the archive was not found.
|
||||
"""
|
||||
raise RuntimeError, "get_archive not implemented"
|
||||
|
||||
def get_subfile(self, archive, modname):
|
||||
"""Get code from a subfile in the specified archive.
|
||||
|
||||
Given the specified archive (as returned by get_archive()), locate
|
||||
and return a code object for the specified module name.
|
||||
|
||||
A 2-tuple may be returned, consisting of a code object and a dict
|
||||
of name/values to place into the target module.
|
||||
|
||||
Return None if the subfile was not found.
|
||||
"""
|
||||
raise RuntimeError, "get_subfile not implemented"
|
||||
|
||||
|
||||
class PackageArchive(PackageArchiveImporter):
|
||||
"PackageArchiveImporter subclass that refers to a specific archive."
|
||||
|
||||
def __init__(self, modname, archive_pathname):
|
||||
self.__modname = modname
|
||||
self.__path = archive_pathname
|
||||
|
||||
def get_archive(self, modname):
|
||||
if modname == self.__modname:
|
||||
return self.__path
|
||||
return None
|
||||
|
||||
# get_subfile is passed the full pathname of the archive
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Emulate the standard directory-based import mechanism
|
||||
#
|
||||
|
||||
class DirectoryImporter(Importer):
|
||||
"Importer subclass to emulate the standard importer."
|
||||
|
||||
def __init__(self, dir):
|
||||
self.dir = dir
|
||||
self.ext_char = __debug__ and 'c' or 'o'
|
||||
self.ext = '.py' + self.ext_char
|
||||
|
||||
def get_code(self, parent, modname, fqname):
|
||||
if parent:
|
||||
dir = parent.__pkgdir__
|
||||
else:
|
||||
dir = self.dir
|
||||
|
||||
# pull the os module from our instance data. we don't do this at the
|
||||
# top-level, because it isn't a builtin module (and we want to defer
|
||||
# loading non-builtins until as late as possible).
|
||||
try:
|
||||
os = self.os
|
||||
except AttributeError:
|
||||
import os
|
||||
self.os = os
|
||||
|
||||
pathname = os.path.join(dir, modname)
|
||||
if os.path.isdir(pathname):
|
||||
values = { '__pkgdir__' : pathname }
|
||||
ispkg = 1
|
||||
pathname = os.path.join(pathname, '__init__')
|
||||
else:
|
||||
values = { }
|
||||
ispkg = 0
|
||||
|
||||
t_py = self._timestamp(pathname + '.py')
|
||||
t_pyc = self._timestamp(pathname + self.ext)
|
||||
if t_py is None and t_pyc is None:
|
||||
return None
|
||||
code = None
|
||||
if t_py is None or (t_pyc is not None and t_pyc >= t_py):
|
||||
f = open(pathname + self.ext, 'rb')
|
||||
if f.read(4) == imp.get_magic():
|
||||
t = struct.unpack('<I', f.read(4))[0]
|
||||
if t == t_py:
|
||||
code = marshal.load(f)
|
||||
f.close()
|
||||
if code is None:
|
||||
code = self._compile(pathname + '.py', t_py)
|
||||
return ispkg, code, values
|
||||
|
||||
def _timestamp(self, pathname):
|
||||
try:
|
||||
s = self.os.stat(pathname)
|
||||
except OSError:
|
||||
return None
|
||||
return long(s[8])
|
||||
|
||||
def _compile(self, pathname, timestamp):
|
||||
codestring = open(pathname, 'r').read()
|
||||
if codestring and codestring[-1] != '\n':
|
||||
codestring = codestring + '\n'
|
||||
code = __builtin__.compile(codestring, pathname, 'exec')
|
||||
|
||||
# try to cache the compiled code
|
||||
try:
|
||||
f = open(pathname + self.ext_char, 'wb')
|
||||
f.write('\0\0\0\0')
|
||||
f.write(struct.pack('<I', timestamp))
|
||||
marshal.dump(code, f)
|
||||
f.flush()
|
||||
f.seek(0, 0)
|
||||
f.write(imp.get_magic())
|
||||
f.close()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
return code
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
self.dir,
|
||||
id(self))
|
||||
|
||||
def _test_dir():
|
||||
"Debug/test function to create DirectoryImporters from sys.path."
|
||||
path = sys.path[:]
|
||||
path.reverse()
|
||||
for d in path:
|
||||
DirectoryImporter(d).install()
|
||||
|
||||
######################################################################
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
# copyright 1999 McMillan Enterprises, Inc.
|
||||
# demo code - use as you please.
|
||||
import os
|
||||
import stat
|
||||
|
||||
def copyFile(srcFiles, destFile, append=0):
|
||||
'''
|
||||
Copy one or more files to another file. If srcFiles is a list, then all
|
||||
will be concatenated together to destFile. The append flag is also valid
|
||||
for single file copies.
|
||||
|
||||
destFile will have the mode, ownership and timestamp of the last file
|
||||
copied/appended.
|
||||
'''
|
||||
if type(srcFiles) == type([]):
|
||||
# in case we need to overwrite on the first file...
|
||||
copyFile(srcFiles[0], destFile, append)
|
||||
for file in srcFiles[1:]:
|
||||
copyFile(file, destFile, 1)
|
||||
return
|
||||
|
||||
mode = 'wb'
|
||||
if append:
|
||||
mode = 'ab'
|
||||
print " ", srcFiles, "->",
|
||||
input = open(srcFiles, 'rb')
|
||||
if input:
|
||||
print destFile
|
||||
output = open(destFile, mode)
|
||||
while 1:
|
||||
bytesRead = input.read(8192)
|
||||
if bytesRead:
|
||||
output.write(bytesRead)
|
||||
else:
|
||||
break
|
||||
|
||||
input.close()
|
||||
output.close()
|
||||
|
||||
stats = os.stat(srcFiles)
|
||||
os.chmod(destFile, stats[stat.ST_MODE])
|
||||
try: # FAT16 file systems have only one file time
|
||||
os.utime(destFile, (stats[stat.ST_ATIME], stats[stat.ST_MTIME]))
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
os.chown(destFile, stats[stat.ST_UID], stats[stat.ST_GID])
|
||||
except:
|
||||
pass
|
||||
|
||||
def ensure(dirct):
|
||||
dirnm = dirct
|
||||
plist = []
|
||||
try:
|
||||
while not os.path.exists(dirnm):
|
||||
dirnm, base = os.path.split(dirnm)
|
||||
if base == '':
|
||||
break
|
||||
plist.insert(0, base)
|
||||
for d in plist:
|
||||
dirnm = os.path.join(dirnm, d)
|
||||
os.mkdir(dirnm)
|
||||
except:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def getinstalldir(prompt="Enter an installation directory: "):
|
||||
while 1:
|
||||
installdir = raw_input("Enter an installation directory: ")
|
||||
installdir = os.path.normpath(installdir)
|
||||
if ensure(installdir):
|
||||
break
|
||||
else:
|
||||
print installdir, "is not a valid pathname"
|
||||
r = raw_input("Try again (y/n)?: ")
|
||||
if r in 'nN':
|
||||
sys.exit(0)
|
||||
return installdir
|
||||
|
||||
def installCArchive(nm, basedir, suffixdir):
|
||||
import carchive_rt
|
||||
fulldir = os.path.join(basedir, suffixdir)
|
||||
if ensure(fulldir):
|
||||
pkg = carchive_rt.CArchive(nm)
|
||||
for fnm in pkg.contents():
|
||||
stuff = pkg.extract(fnm)[1]
|
||||
outnm = os.path.join(fulldir, fnm)
|
||||
if ensure(os.path.dirname(outnm)):
|
||||
open(outnm, 'wb').write(stuff)
|
||||
pkg = None
|
||||
os.remove(nm)
|
||||
|
|
@ -1,85 +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())
|
||||
|
||||
|
||||
import os, sys, UserList
|
||||
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())
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue