finish .mf support

This commit is contained in:
David Rose 2009-04-29 19:53:39 +00:00
parent e777b5db5d
commit 2e60e14eaf
2 changed files with 61 additions and 22 deletions

View File

@ -6,7 +6,6 @@ import sys
import os import os
import marshal import marshal
import imp import imp
import struct
import direct import direct
from pandac.PandaModules import * from pandac.PandaModules import *
@ -360,6 +359,19 @@ class Freezer:
else: else:
self.modules[moduleName] = self.MTExclude self.modules[moduleName] = self.MTExclude
def handleCustomPath(self, moduleName):
""" Indicates a module that may perform runtime manipulation
of its __path__ variable, and which must therefore be actually
imported at runtime in order to determine the true value of
__path__. """
str = 'import %s' % (moduleName)
exec str
module = sys.modules[moduleName]
for path in module.__path__:
modulefinder.AddPackagePath(moduleName, path)
def getModulePath(self, moduleName): def getModulePath(self, moduleName):
""" Looks for the indicated directory module and returns its """ Looks for the indicated directory module and returns its
__path__ member: the list of directories in which its python __path__ member: the list of directories in which its python
@ -582,16 +594,16 @@ class Freezer:
co = self.mf.replace_paths_in_code(module.__code__) co = self.mf.replace_paths_in_code(module.__code__)
module.__code__ = co; module.__code__ = co;
def __addPyc(self, mf, filename, code): def __addPyc(self, multifile, filename, code):
if code: if code:
data = imp.get_magic() + \ data = imp.get_magic() + '\0\0\0\0' + \
struct.pack('<I', self.timestamp) + \
marshal.dumps(code) marshal.dumps(code)
stream = StringStream(data) stream = StringStream(data)
mf.addSubfile(filename, stream, 0) multifile.addSubfile(filename, stream, 0)
multifile.flush()
def __addPythonDirs(self, mf, moduleDirs, dirnames): def __addPythonDirs(self, multifile, moduleDirs, dirnames):
""" Adds all of the names on dirnames as a module directory. """ """ Adds all of the names on dirnames as a module directory. """
if not dirnames: if not dirnames:
return return
@ -600,23 +612,40 @@ class Freezer:
if str not in moduleDirs: if str not in moduleDirs:
# Add an implicit __init__.py file. # Add an implicit __init__.py file.
moduleName = '.'.join(dirnames) moduleName = '.'.join(dirnames)
filename = '/'.join(dirnames) + '/__init__.pyc' filename = '/'.join(dirnames) + '/__init__.py'
code = compile('', moduleName, 'exec')
self.__addPyc(mf, filename, code)
moduleDirs[str] = True
self.__addPythonDirs(mf, moduleDirs, dirnames[:-1])
def __addPythonFile(self, mf, moduleDirs, moduleName): stream = StringStream('')
multifile.addSubfile(filename, stream, 0)
multifile.flush()
moduleDirs[str] = True
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1])
def __addPythonFile(self, multifile, moduleDirs, moduleName):
""" Adds the named module to the multifile as a .pyc file. """ """ Adds the named module to the multifile as a .pyc file. """
module = self.mf.modules.get(moduleName, None)
if getattr(module, '__path__', None) is not None:
# It's actually a package. In this case, we really write
# the file moduleName/__init__.py.
moduleName += '.__init__'
# First, split the module into its subdirectory names. # First, split the module into its subdirectory names.
dirnames = moduleName.split('.') dirnames = moduleName.split('.')
self.__addPythonDirs(mf, moduleDirs, dirnames[:-1]) self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1])
module = self.mf.modules.get(moduleName, None) # Attempt to add the original source file if we can.
code = getattr(module, "__code__", None) if getattr(module, '__file__', None):
sourceFilename = Filename.fromOsSpecific(module.__file__)
sourceFilename.setExtension("py")
if sourceFilename.exists():
filename = '/'.join(dirnames) + '.py'
multifile.addSubfile(filename, sourceFilename, 0)
return
# If we can't find the source file, add the compiled pyc instead.
filename = '/'.join(dirnames) + '.pyc' filename = '/'.join(dirnames) + '.pyc'
self.__addPyc(mf, filename, code) code = getattr(module, "__code__", None)
self.__addPyc(multifile, filename, code)
def writeMultifile(self, mfname): def writeMultifile(self, mfname):
@ -624,17 +653,19 @@ class Freezer:
code in a multifile. """ code in a multifile. """
self.__replacePaths() self.__replacePaths()
mf = Multifile() Filename(mfname).unlink()
if not mf.openWrite(mfname): multifile = Multifile()
if not multifile.openReadWrite(mfname):
raise StandardError raise StandardError
moduleDirs = {} moduleDirs = {}
for moduleName in self.__getModuleNames(): for moduleName in self.__getModuleNames():
token = self.modules[moduleName] token = self.modules[moduleName]
if token != self.MTForbid: if token != self.MTForbid:
self.__addPythonFile(mf, moduleDirs, moduleName) self.__addPythonFile(multifile, moduleDirs, moduleName)
mf.close() multifile.flush()
multifile.repack()
def generateCode(self, basename): def generateCode(self, basename):
self.__replacePaths() self.__replacePaths()

View File

@ -34,6 +34,11 @@ Options:
the resulting file, even if they do not appear to be referenced. the resulting file, even if they do not appear to be referenced.
You may also repeat the -i command for each module. You may also repeat the -i command for each module.
-p module[,module...]
Specifies a list of Python modules that do run-time manipulation
of the __path__ variable, and thus must be actually imported to
determine the true value of __path__.
""" """
import getopt import getopt
@ -52,7 +57,7 @@ if __name__ == '__main__':
basename = None basename = None
try: try:
opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:h') opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:h')
except getopt.error, msg: except getopt.error, msg:
usage(1, msg) usage(1, msg)
@ -65,6 +70,9 @@ if __name__ == '__main__':
elif opt == '-x': elif opt == '-x':
for module in arg.split(','): for module in arg.split(','):
freezer.excludeModule(module) freezer.excludeModule(module)
elif opt == '-p':
for module in arg.split(','):
freezer.handleCustomPath(module)
elif opt == '-h': elif opt == '-h':
usage(0) usage(0)