This commit is contained in:
David Rose 2005-04-28 16:56:43 +00:00
parent f5bf1a49c0
commit d4ba21fc11
14 changed files with 2770 additions and 2770 deletions

View File

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

View File

@ -1,226 +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)
##
#
# 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)
##

View File

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

View File

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

View File

@ -1,204 +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)
# 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)

View File

@ -1,157 +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)
# 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)

View File

@ -1,178 +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
# 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

View File

@ -1,9 +1,9 @@
# 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
# 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:

View File

@ -1,487 +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()
######################################################################
#
# 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()
######################################################################

View File

@ -1,91 +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)
# 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)

View File

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

View File

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

View File

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

View File

@ -1,131 +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))
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))