exclude, requires

This commit is contained in:
David Rose 2009-08-07 23:34:03 +00:00
parent b6db699737
commit 5b84a46753
2 changed files with 158 additions and 44 deletions

View File

@ -422,7 +422,7 @@ class Freezer:
constructor, but it may be called at any point during constructor, but it may be called at any point during
processing. """ processing. """
for key, value in freezer.modules: for key, value in freezer.modules.items():
self.previousModules[key] = value self.previousModules[key] = value
self.modules[key] = value self.modules[key] = value
@ -686,9 +686,26 @@ class Freezer:
def mangleName(self, moduleName): def mangleName(self, moduleName):
return 'M_' + moduleName.replace('.', '__').replace('-', '_') return 'M_' + moduleName.replace('.', '__').replace('-', '_')
def __getModuleDefs(self): def getAllModuleNames(self):
# Collect a list of all of the modules we will be explicitly """ Return a list of all module names that have been included
# referencing. or forbidden, either in this current pass or in a previous
pass. Module names that have been excluded are not included
in this list. """
moduleNames = []
for newName, mdef in self.modules.items():
if mdef.token != self.MTExclude:
moduleNames.append(newName)
moduleNames.sort()
return moduleNames
def getModuleDefs(self):
""" Return a list of all of the modules we will be explicitly
or implicitly including. The return value is actually a list
of tuples: (moduleName, moduleDef)."""
moduleDefs = [] moduleDefs = []
for newName, mdef in self.modules.items(): for newName, mdef in self.modules.items():
@ -831,7 +848,7 @@ class Freezer:
python code into the indicated Multifile. """ python code into the indicated Multifile. """
moduleDirs = {} moduleDirs = {}
for moduleName, mdef in self.__getModuleDefs(): for moduleName, mdef in self.getModuleDefs():
if mdef.token != self.MTForbid: if mdef.token != self.MTForbid:
self.__addPythonFile(multifile, moduleDirs, moduleName, mdef) self.__addPythonFile(multifile, moduleDirs, moduleName, mdef)
@ -874,7 +891,7 @@ class Freezer:
moduleDefs = [] moduleDefs = []
moduleList = [] moduleList = []
for moduleName, mdef in self.__getModuleDefs(): for moduleName, mdef in self.getModuleDefs():
token = mdef.token token = mdef.token
origName = mdef.moduleName origName = mdef.moduleName
if token == self.MTForbid: if token == self.MTForbid:

View File

@ -29,6 +29,7 @@ class Packager:
class PackFile: class PackFile:
def __init__(self, filename, newName = None, deleteTemp = False): def __init__(self, filename, newName = None, deleteTemp = False):
assert isinstance(filename, Filename)
self.filename = filename self.filename = filename
self.newName = newName self.newName = newName
self.deleteTemp = deleteTemp self.deleteTemp = deleteTemp
@ -37,37 +38,66 @@ class Packager:
def __init__(self, packageName, packager): def __init__(self, packageName, packager):
self.packageName = packageName self.packageName = packageName
self.packager = packager self.packager = packager
self.version = 'dev' self.version = None
self.platform = None
self.p3dApplication = False
self.files = [] self.files = []
self.compressionLevel = 0 self.compressionLevel = 0
self.importedMapsDir = 'imported_maps' self.importedMapsDir = 'imported_maps'
# This is the set of files and modules, already included
# by required packages, that we can skip.
self.skipFilenames = {}
self.skipModules = {}
# This records the current list of modules we have added so # This records the current list of modules we have added so
# far. # far.
self.freezer = FreezeTool.Freezer() self.freezer = FreezeTool.Freezer()
# Set this true to parse and build up the internal
# filelist, but not generate any output.
self.dryRun = False
def close(self): def close(self):
""" Writes out the contents of the current package. """ """ Writes out the contents of the current package. """
packageFilename = self.packageName packageFilename = self.packageName
packageFilename += '_' + self.version if self.platform:
packageFilename += '.mf' packageFilename += '_' + self.platform
if self.version:
packageFilename += '_' + self.version
if self.p3dApplication:
packageFilename += '.p3d'
else:
packageFilename += '.mf'
try: try:
os.unlink(packageFilename) os.unlink(packageFilename)
except OSError: except OSError:
pass pass
self.multifile = Multifile() if self.dryRun:
self.multifile.openReadWrite(packageFilename) self.multifile = None
else:
self.multifile = Multifile()
self.multifile.openReadWrite(packageFilename)
# Exclude modules already imported in a required package.
for moduleName in self.skipModules.keys():
self.freezer.excludeModule(moduleName)
# Build up a cross-reference of files we've already # Build up a cross-reference of files we've already
# discovered. # discovered.
self.sourceFilenames = {} self.sourceFilenames = {}
self.targetFilenames = {} self.targetFilenames = {}
processFiles = []
for file in self.files: for file in self.files:
if not file.newName: if not file.newName:
file.newName = file.filename file.newName = file.filename
if file.newName in self.skipFilenames:
# Skip this file.
continue
# Convert the source filename to an unambiguous # Convert the source filename to an unambiguous
# filename for searching. # filename for searching.
@ -76,12 +106,13 @@ class Packager:
self.sourceFilenames[filename] = file self.sourceFilenames[filename] = file
self.targetFilenames[file.newName] = file self.targetFilenames[file.newName] = file
processFiles.append(file)
for file in self.files: for file in processFiles:
ext = file.filename.getExtension() ext = file.filename.getExtension()
if ext == 'py': if ext == 'py':
self.addPyFile(file) self.addPyFile(file)
else: elif not self.dryRun:
if ext == 'pz': if ext == 'pz':
# Strip off an implicit .pz extension. # Strip off an implicit .pz extension.
filename = Filename(file.filename) filename = Filename(file.filename)
@ -100,22 +131,31 @@ class Packager:
self.addBamFile(file) self.addBamFile(file)
elif ext in self.packager.imageExtensions: elif ext in self.packager.imageExtensions:
self.addTexture(file) self.addTexture(file)
elif ext in self.packager.uncompressibleExtensions:
# An uncompressible file.
self.multifile.addSubfile(file.newName, file.filename, 0)
else: else:
# An ordinary file. # Any other file.
self.multifile.addSubfile(file.newName, file.filename, self.compressionLevel) self.multifile.addSubfile(file.newName, file.filename, self.compressionLevel)
# Pick up any unfrozen Python files. # Pick up any unfrozen Python files.
self.freezer.done() self.freezer.done()
self.freezer.addToMultifile(self.multifile)
self.multifile.repack() # Add known module names.
self.multifile.close() self.moduleNames = {}
for moduleName in self.freezer.getAllModuleNames():
self.moduleNames[moduleName] = True
if not self.dryRun:
self.freezer.addToMultifile(self.multifile)
self.multifile.repack()
self.multifile.close()
# Now that all the files have been packed, we can delete # Now that all the files have been packed, we can delete
# the temporary files. # the temporary files.
for file in self.files: for file in self.files:
if file.deleteTemp: if file.deleteTemp:
os.unlink(file.filename) file.filename.unlink()
def addPyFile(self, file): def addPyFile(self, file):
""" Adds the indicated python file, identified by filename """ Adds the indicated python file, identified by filename
@ -319,15 +359,21 @@ class Packager:
self.sfxManagerList = None self.sfxManagerList = None
self.musicManager = None self.musicManager = None
# This is filled in during readPackageDef().
self.packageList = None
# A table of all known packages by name.
self.packages = {}
self.dryRun = False
def setup(self): def setup(self):
""" Call this method to initialize the class after filling in """ Call this method to initialize the class after filling in
some of the values in the constructor. """ some of the values in the constructor. """
self.knownExtensions = self.imageExtensions + self.modelExtensions + self.textExtensions + self.binaryExtensions + self.uncompressibleExtensions self.knownExtensions = self.imageExtensions + self.modelExtensions + self.textExtensions + self.binaryExtensions + self.uncompressibleExtensions
# We need a stack of packages for managing begin_package
# .. end_package.
self.packageStack = []
self.currentPackage = None self.currentPackage = None
# The persist dir is the directory in which the results from # The persist dir is the directory in which the results from
@ -353,10 +399,13 @@ class Packager:
# created there # created there
os.chdir(self.persistDir.toOsSpecific()) os.chdir(self.persistDir.toOsSpecific())
def readPackageDef(self, packageDef): def readPackageDef(self, packageDef):
""" Reads the lines in packageDef and dispatches to the """ Reads the lines in the .pdef file named by packageDef and
appropriate handler method for each line. """ dispatches to the appropriate handler method for each
line. Returns the list of package files."""
assert self.packageList is None
self.packageList = []
self.notify.info('Reading %s' % (packageDef)) self.notify.info('Reading %s' % (packageDef))
file = open(packageDef.toOsSpecific()) file = open(packageDef.toOsSpecific())
@ -418,6 +467,11 @@ class Packager:
inst.args = (inst.args[0] + ' on line %s of %s' % (lineNum[0], packageDef),) inst.args = (inst.args[0] + ' on line %s of %s' % (lineNum[0], packageDef),)
raise raise
packageList = self.packageList
self.packageList = None
return packageList
def parse_setenv(self, lineList): def parse_setenv(self, lineList):
""" """
setenv variable value setenv variable value
@ -455,6 +509,23 @@ class Packager:
self.endPackage(packageName) self.endPackage(packageName)
def parse_require(self, lineList):
"""
require packageName
"""
try:
command, packageName = lineList
except ValueError:
raise ArgumentError
package = self.findPackage(packageName)
if not package:
message = "Unknown package %s" % (packageName)
raise PackagerError, message
self.require(package)
def parse_module(self, lineList): def parse_module(self, lineList):
""" """
module moduleName [newName] module moduleName [newName]
@ -534,11 +605,12 @@ class Packager:
basename of the package. Follow this with a number of calls basename of the package. Follow this with a number of calls
to file() etc., and close the package with endPackage(). """ to file() etc., and close the package with endPackage(). """
package = self.Package(packageName, self)
if self.currentPackage: if self.currentPackage:
package.freezer.excludeFrom(self.currentPackage.freezer) raise PackagerError, 'unmatched end_package %s' % (self.currentPackage.packageName)
package = self.Package(packageName, self)
package.dryRun = self.dryRun
self.packageStack.append(package)
self.currentPackage = package self.currentPackage = package
def endPackage(self, packageName): def endPackage(self, packageName):
@ -555,12 +627,36 @@ class Packager:
package = self.currentPackage package = self.currentPackage
package.close() package.close()
del self.packageStack[-1] self.packageList.append(package)
if self.packageStack: self.packages[package.packageName] = package
self.currentPackage = self.packageStack[-1] self.currentPackage = None
self.currentPackage.freezer.excludeFrom(package.freezer)
else: def findPackage(self, packageName, searchUrl = None):
self.currentPackage = None """ Searches for the named package from a previous publish
operation, either at the indicated URL or along the default
search path.
Returns the Package object, or None if the package cannot be
located. """
# Is it a package we already have resident?
package = self.packages.get(packageName, None)
if package:
return package
return None
def require(self, package):
""" Indicates a dependency on the indicated package.
Attempts to install this package will implicitly install the
named package also. Files already included in the named
package will be omitted from this one. """
for filename in package.targetFilenames.keys():
self.currentPackage.skipFilenames[filename] = True
for moduleName in package.moduleNames.keys():
self.currentPackage.skipModules[moduleName] = True
def module(self, moduleName, newName = None): def module(self, moduleName, newName = None):
""" Adds the indicated Python module to the current package. """ """ Adds the indicated Python module to the current package. """
@ -584,14 +680,15 @@ class Packager:
freezer = package.freezer freezer = package.freezer
freezer.done() freezer.done()
dirname = '' if not package.dryRun:
basename = filename dirname = ''
if '/' in basename: basename = filename
dirname, basename = filename.rsplit('/', 1) if '/' in basename:
dirname += '/' dirname, basename = filename.rsplit('/', 1)
basename = freezer.generateCode(basename, compileToExe = compileToExe) dirname += '/'
basename = freezer.generateCode(basename, compileToExe = compileToExe)
package.files.append(self.PackFile(basename, newName = dirname + basename, deleteTemp = True)) package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True))
# Reset the freezer for more Python files. # Reset the freezer for more Python files.
freezer.reset() freezer.reset()