David Rose 20 years ago
parent
commit
d4ba21fc11

+ 246 - 246
direct/src/pyinst/archive.py

@@ -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)
+ 

+ 226 - 226
direct/src/pyinst/archive_rt.py

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

+ 81 - 81
direct/src/pyinst/archivebuilder.py

@@ -1,81 +1,81 @@
-# copyright 1999 McMillan Enterprises, Inc.
-# license: use as you please. No warranty.
-# Gordon McMillan [email protected]
-#
-# 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 [email protected]
+#
+# 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
+

+ 169 - 169
direct/src/pyinst/bindepend.py

@@ -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)
+ 

+ 204 - 204
direct/src/pyinst/carchive.py

@@ -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)

+ 157 - 157
direct/src/pyinst/carchive_rt.py

@@ -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)

+ 178 - 178
direct/src/pyinst/finder.py

@@ -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

+ 6 - 6
direct/src/pyinst/icon.py

@@ -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:

+ 487 - 487
direct/src/pyinst/imputil.py

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

+ 91 - 91
direct/src/pyinst/installutils.py

@@ -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)

+ 41 - 41
direct/src/pyinst/mkarchive.py

@@ -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()

+ 436 - 436
direct/src/pyinst/modulefinder.py

@@ -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]"

+ 317 - 317
direct/src/pyinst/resource.py

@@ -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
+    

+ 131 - 131
direct/src/pyinst/tocfilter.py

@@ -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))