p3d_info.xml
This commit is contained in:
parent
9ae42186d1
commit
0e596fe4e2
|
|
@ -754,16 +754,16 @@ class Freezer:
|
|||
co = self.mf.replace_paths_in_code(module.__code__)
|
||||
module.__code__ = co;
|
||||
|
||||
def __addPyc(self, multifile, filename, code):
|
||||
def __addPyc(self, multifile, filename, code, compressionLevel):
|
||||
if code:
|
||||
data = imp.get_magic() + '\0\0\0\0' + \
|
||||
marshal.dumps(code)
|
||||
|
||||
stream = StringStream(data)
|
||||
multifile.addSubfile(filename, stream, 0)
|
||||
multifile.addSubfile(filename, stream, compressionLevel)
|
||||
multifile.flush()
|
||||
|
||||
def __addPythonDirs(self, multifile, moduleDirs, dirnames):
|
||||
def __addPythonDirs(self, multifile, moduleDirs, dirnames, compressionLevel):
|
||||
""" Adds all of the names on dirnames as a module directory. """
|
||||
if not dirnames:
|
||||
return
|
||||
|
|
@ -785,17 +785,18 @@ class Freezer:
|
|||
else:
|
||||
filename += '.pyo'
|
||||
code = compile('', moduleName, 'exec')
|
||||
self.__addPyc(multifile, filename, code)
|
||||
self.__addPyc(multifile, filename, code, compressionLevel)
|
||||
|
||||
moduleDirs[str] = True
|
||||
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1])
|
||||
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
|
||||
|
||||
def __addPythonFile(self, multifile, moduleDirs, moduleName, mdef):
|
||||
def __addPythonFile(self, multifile, moduleDirs, moduleName, mdef,
|
||||
compressionLevel):
|
||||
""" Adds the named module to the multifile as a .pyc file. """
|
||||
|
||||
# First, split the module into its subdirectory names.
|
||||
dirnames = moduleName.split('.')
|
||||
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1])
|
||||
self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
|
||||
|
||||
filename = '/'.join(dirnames)
|
||||
|
||||
|
|
@ -823,7 +824,7 @@ class Freezer:
|
|||
if self.storePythonSource:
|
||||
if sourceFilename and sourceFilename.exists():
|
||||
filename += '.py'
|
||||
multifile.addSubfile(filename, sourceFilename, 0)
|
||||
multifile.addSubfile(filename, sourceFilename, compressionLevel)
|
||||
return
|
||||
|
||||
# If we can't find the source file, add the compiled pyc instead.
|
||||
|
|
@ -844,16 +845,17 @@ class Freezer:
|
|||
source = source + '\n'
|
||||
code = compile(source, sourceFilename.cStr(), 'exec')
|
||||
|
||||
self.__addPyc(multifile, filename, code)
|
||||
self.__addPyc(multifile, filename, code, compressionLevel)
|
||||
|
||||
def addToMultifile(self, multifile):
|
||||
def addToMultifile(self, multifile, compressionLevel = 0):
|
||||
""" After a call to done(), this stores all of the accumulated
|
||||
python code into the indicated Multifile. """
|
||||
|
||||
moduleDirs = {}
|
||||
for moduleName, mdef in self.getModuleDefs():
|
||||
if mdef.token != self.MTForbid:
|
||||
self.__addPythonFile(multifile, moduleDirs, moduleName, mdef)
|
||||
self.__addPythonFile(multifile, moduleDirs, moduleName, mdef,
|
||||
compressionLevel)
|
||||
|
||||
def writeMultifile(self, mfname):
|
||||
""" After a call to done(), this stores all of the accumulated
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@ class Packager:
|
|||
notify = directNotify.newCategory("Packager")
|
||||
|
||||
class PackFile:
|
||||
def __init__(self, filename, newName = None, deleteTemp = False):
|
||||
def __init__(self, filename, newName = None, deleteTemp = False,
|
||||
extract = False):
|
||||
assert isinstance(filename, Filename)
|
||||
self.filename = filename
|
||||
self.newName = newName
|
||||
self.deleteTemp = deleteTemp
|
||||
self.extract = extract
|
||||
|
||||
class Package:
|
||||
def __init__(self, packageName, packager):
|
||||
|
|
@ -44,6 +46,8 @@ class Packager:
|
|||
self.files = []
|
||||
self.compressionLevel = 0
|
||||
self.importedMapsDir = 'imported_maps'
|
||||
self.mainModule = None
|
||||
self.requires = []
|
||||
|
||||
# This is the set of files and modules, already included
|
||||
# by required packages, that we can skip.
|
||||
|
|
@ -148,12 +152,23 @@ class Packager:
|
|||
# Any other file.
|
||||
self.addComponent(file)
|
||||
|
||||
if not self.mainModule and self.p3dApplication:
|
||||
message = 'No main_module specified for application %s' % (self.packageName)
|
||||
raise PackagerError, message
|
||||
if self.mainModule:
|
||||
if self.mainModule not in self.freezer.modules:
|
||||
self.freezer.addModule(self.mainModule)
|
||||
|
||||
# Pick up any unfrozen Python files.
|
||||
self.freezer.done()
|
||||
|
||||
# Add known module names.
|
||||
self.moduleNames = {}
|
||||
for moduleName in self.freezer.getAllModuleNames():
|
||||
if moduleName == '__main__':
|
||||
# Ignore this special case.
|
||||
continue
|
||||
|
||||
self.moduleNames[moduleName] = True
|
||||
|
||||
xmodule = TiXmlElement('module')
|
||||
|
|
@ -161,7 +176,9 @@ class Packager:
|
|||
self.components.append(xmodule)
|
||||
|
||||
if not self.dryRun:
|
||||
self.freezer.addToMultifile(self.multifile)
|
||||
self.freezer.addToMultifile(self.multifile, self.compressionLevel)
|
||||
if self.p3dApplication:
|
||||
self.makeP3dInfo()
|
||||
self.multifile.repack()
|
||||
self.multifile.close()
|
||||
|
||||
|
|
@ -176,6 +193,43 @@ class Packager:
|
|||
if file.deleteTemp:
|
||||
file.filename.unlink()
|
||||
|
||||
def makeP3dInfo(self):
|
||||
""" Makes the p3d_info.xml file that defines the
|
||||
application startup parameters and such. """
|
||||
|
||||
doc = TiXmlDocument()
|
||||
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
||||
doc.InsertEndChild(decl)
|
||||
|
||||
xpackage = TiXmlElement('package')
|
||||
xpackage.SetAttribute('name', self.packageName)
|
||||
if self.platform:
|
||||
xpackage.SetAttribute('platform', self.platform)
|
||||
if self.version:
|
||||
xpackage.SetAttribute('version', self.version)
|
||||
|
||||
xpackage.SetAttribute('main_module', self.mainModule)
|
||||
|
||||
for package in self.requires:
|
||||
xrequires = TiXmlElement('requires')
|
||||
xrequires.SetAttribute('name', package.packageName)
|
||||
if package.platform:
|
||||
xrequires.SetAttribute('platform', package.platform)
|
||||
if package.version:
|
||||
xrequires.SetAttribute('version', package.version)
|
||||
xpackage.InsertEndChild(xrequires)
|
||||
|
||||
doc.InsertEndChild(xpackage)
|
||||
|
||||
# Write the xml file to a temporary file on disk, so we
|
||||
# can add it to the multifile.
|
||||
filename = Filename.temporary('', 'p3d_', '.xml')
|
||||
doc.SaveFile(filename.toOsSpecific())
|
||||
self.multifile.addSubfile('p3d_info.xml', filename, self.compressionLevel)
|
||||
self.multifile.flush()
|
||||
filename.unlink()
|
||||
|
||||
|
||||
def compressMultifile(self):
|
||||
""" Compresses the .mf file into an .mf.pz file. """
|
||||
|
||||
|
|
@ -435,8 +489,14 @@ class Packager:
|
|||
ext = Filename(file.newName).getExtension()
|
||||
if ext in self.packager.uncompressibleExtensions:
|
||||
compressible = False
|
||||
|
||||
extract = file.extract
|
||||
if ext in self.packager.extractExtensions:
|
||||
extract = True
|
||||
|
||||
if ext in self.packager.platformSpecificExtensions:
|
||||
if not self.platform:
|
||||
self.platform = PandaSystem.getPlatform()
|
||||
|
||||
compressionLevel = 0
|
||||
if compressible:
|
||||
|
|
@ -451,6 +511,19 @@ class Packager:
|
|||
xcomponent.SetAttribute('filename', file.newName)
|
||||
self.components.append(xcomponent)
|
||||
|
||||
def requirePackage(self, package):
|
||||
""" Indicates a dependency on the given package. """
|
||||
|
||||
if package in self.requires:
|
||||
# Already on the list.
|
||||
return
|
||||
|
||||
self.requires.append(package)
|
||||
for filename in package.targetFilenames.keys():
|
||||
self.skipFilenames[filename] = True
|
||||
for moduleName in package.moduleNames.keys():
|
||||
self.skipModules[moduleName] = True
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# The following are config settings that the caller may adjust
|
||||
|
|
@ -513,6 +586,9 @@ class Packager:
|
|||
# Files that should be extracted to disk.
|
||||
self.extractExtensions = [ 'dll', 'so', 'dylib', 'exe' ]
|
||||
|
||||
# Files that indicate a platform dependency.
|
||||
self.platformSpecificExtensions = [ 'dll', 'so', 'dylib', 'exe' ]
|
||||
|
||||
# Binary files that are considered uncompressible, and are
|
||||
# copied without compression.
|
||||
self.uncompressibleExtensions = [ 'mp3', 'ogg' ]
|
||||
|
|
@ -633,30 +709,40 @@ class Packager:
|
|||
|
||||
return packageList
|
||||
|
||||
def parse_setenv(self, lineList):
|
||||
def parse_set(self, lineList):
|
||||
"""
|
||||
setenv variable value
|
||||
set variable=value
|
||||
"""
|
||||
|
||||
try:
|
||||
command, variable, value = lineList
|
||||
command, assign = lineList
|
||||
except ValueError:
|
||||
raise ArgumentNumber
|
||||
|
||||
try:
|
||||
variable, value = assign.split('=', 1)
|
||||
except ValueError:
|
||||
raise PackagerError, 'Equals sign required in assignment'
|
||||
|
||||
value = ExecutionEnvironment.expandString(value)
|
||||
variable = variable.strip()
|
||||
value = ExecutionEnvironment.expandString(value.strip())
|
||||
ExecutionEnvironment.setEnvironmentVariable(variable, value)
|
||||
|
||||
def parse_begin_package(self, lineList):
|
||||
"""
|
||||
begin_package packageName
|
||||
begin_package packageName [version=v]
|
||||
"""
|
||||
|
||||
|
||||
args = self.parseArgs(lineList, ['version'])
|
||||
|
||||
try:
|
||||
command, packageName = lineList
|
||||
except ValueError:
|
||||
raise ArgumentNumber
|
||||
|
||||
self.beginPackage(packageName)
|
||||
version = args.get('version', None)
|
||||
|
||||
self.beginPackage(packageName, version = version, p3dApplication = False)
|
||||
|
||||
def parse_end_package(self, lineList):
|
||||
"""
|
||||
|
|
@ -668,11 +754,23 @@ class Packager:
|
|||
except ValueError:
|
||||
raise ArgumentError
|
||||
|
||||
self.endPackage(packageName)
|
||||
self.endPackage(packageName, p3dApplication = False)
|
||||
|
||||
def parse_require(self, lineList):
|
||||
def parse_begin_p3d(self, lineList):
|
||||
"""
|
||||
require packageName
|
||||
begin_p3d appName
|
||||
"""
|
||||
|
||||
try:
|
||||
command, packageName = lineList
|
||||
except ValueError:
|
||||
raise ArgumentNumber
|
||||
|
||||
self.beginPackage(packageName, p3dApplication = True)
|
||||
|
||||
def parse_end_p3d(self, lineList):
|
||||
"""
|
||||
end_p3d appName
|
||||
"""
|
||||
|
||||
try:
|
||||
|
|
@ -680,12 +778,22 @@ class Packager:
|
|||
except ValueError:
|
||||
raise ArgumentError
|
||||
|
||||
package = self.findPackage(packageName)
|
||||
if not package:
|
||||
message = "Unknown package %s" % (packageName)
|
||||
raise PackagerError, message
|
||||
self.endPackage(packageName, p3dApplication = True)
|
||||
|
||||
self.require(package)
|
||||
def parse_require(self, lineList):
|
||||
"""
|
||||
require packageName [version=v]
|
||||
"""
|
||||
|
||||
args = self.parseArgs(lineList, ['version'])
|
||||
|
||||
try:
|
||||
command, packageName = lineList
|
||||
except ValueError:
|
||||
raise ArgumentError
|
||||
|
||||
version = args.get('version', None)
|
||||
self.require(packageName, version = version)
|
||||
|
||||
def parse_module(self, lineList):
|
||||
"""
|
||||
|
|
@ -703,6 +811,18 @@ class Packager:
|
|||
|
||||
self.module(moduleName, newName = newName)
|
||||
|
||||
def parse_main_module(self, lineList):
|
||||
"""
|
||||
main_module moduleName
|
||||
"""
|
||||
|
||||
try:
|
||||
command, moduleName = lineList
|
||||
except ValueError:
|
||||
raise ArgumentError
|
||||
|
||||
self.mainModule(moduleName)
|
||||
|
||||
def parse_freeze_exe(self, lineList):
|
||||
"""
|
||||
freeze_exe path/to/basename
|
||||
|
|
@ -760,8 +880,31 @@ class Packager:
|
|||
raise ArgumentError
|
||||
|
||||
self.dir(dirname, newDir = newDir)
|
||||
|
||||
def parseArgs(self, lineList, argList):
|
||||
args = {}
|
||||
|
||||
while len(lineList) > 1:
|
||||
arg = lineList[-1]
|
||||
if '=' not in arg:
|
||||
return args
|
||||
|
||||
parameter, value = arg.split('=', 1)
|
||||
parameter = parameter.strip()
|
||||
value = value.strip()
|
||||
if parameter not in argList:
|
||||
message = 'Unknown parameter %s' % (parameter)
|
||||
raise PackagerError, message
|
||||
if parameter in args:
|
||||
message = 'Duplicate parameter %s' % (parameter)
|
||||
raise PackagerError, message
|
||||
|
||||
args[parameter] = value
|
||||
|
||||
del lineList[-1]
|
||||
|
||||
|
||||
def beginPackage(self, packageName):
|
||||
def beginPackage(self, packageName, version = None, p3dApplication = False):
|
||||
""" Begins a new package specification. packageName is the
|
||||
basename of the package. Follow this with a number of calls
|
||||
to file() etc., and close the package with endPackage(). """
|
||||
|
|
@ -769,12 +912,27 @@ class Packager:
|
|||
if self.currentPackage:
|
||||
raise PackagerError, 'unmatched end_package %s' % (self.currentPackage.packageName)
|
||||
|
||||
# A special case for the Panda3D package. We enforce that the
|
||||
# version number matches what we've been compiled with.
|
||||
if packageName == 'panda3d':
|
||||
if version is None:
|
||||
version = PandaSystem.getPackageVersionString()
|
||||
else:
|
||||
if version != PandaSystem.getPackageVersionString():
|
||||
message = 'mismatched Panda3D version: requested %s, but Panda3D is built as %s' % (version, PandaSystem.getPackageVersionString())
|
||||
raise PackageError, message
|
||||
|
||||
package = self.Package(packageName, self)
|
||||
package.version = version
|
||||
package.p3dApplication = p3dApplication
|
||||
if package.p3dApplication:
|
||||
# Default compression level for an app.
|
||||
package.compressionLevel = 6
|
||||
package.dryRun = self.dryRun
|
||||
|
||||
self.currentPackage = package
|
||||
|
||||
def endPackage(self, packageName):
|
||||
def endPackage(self, packageName, p3dApplication = False):
|
||||
""" Closes a package specification. This actually generates
|
||||
the package file. The packageName must match the previous
|
||||
call to beginPackage(). """
|
||||
|
|
@ -784,6 +942,11 @@ class Packager:
|
|||
if self.currentPackage.packageName != packageName:
|
||||
raise PackagerError, 'end_package %s where %s expected' % (
|
||||
packageName, self.currentPackage.packageName)
|
||||
if self.currentPackage.p3dApplication != p3dApplication:
|
||||
if p3dApplication:
|
||||
raise PackagerError, 'end_p3d where end_package expected'
|
||||
else:
|
||||
raise PackagerError, 'end_package where end_p3d expected'
|
||||
|
||||
package = self.currentPackage
|
||||
package.close()
|
||||
|
|
@ -807,105 +970,49 @@ class Packager:
|
|||
|
||||
# Look on the searchlist.
|
||||
for path in self.installSearch:
|
||||
packageDir = Filename(path, packageName)
|
||||
if packageDir.isDirectory():
|
||||
# Hey, this package appears to exist!
|
||||
package = self.scanPackageDir(packageDir, packageName, version)
|
||||
if package:
|
||||
self.packages[(packageName, version)] = package
|
||||
return package
|
||||
package = self.scanPackageDir(path, packageName, version, self.platform)
|
||||
if package:
|
||||
self.packages[(packageName, version)] = package
|
||||
return package
|
||||
package = self.scanPackageDir(path, packageName, version, None)
|
||||
if package:
|
||||
self.packages[(packageName, version)] = package
|
||||
return package
|
||||
|
||||
return None
|
||||
|
||||
def scanPackageDir(self, packageDir, packageName, packageVersion):
|
||||
def scanPackageDir(self, rootDir, packageName, version, platform):
|
||||
""" Scans a directory on disk, looking for _import.xml files
|
||||
that match the indicated packageName and option version. If a
|
||||
suitable xml file is found, reads it and returns the assocated
|
||||
Package definition. """
|
||||
|
||||
bestVersion = None
|
||||
bestPackage = None
|
||||
|
||||
# First, look for a platform-specific file.
|
||||
platformDir = Filename(packageDir, self.platform)
|
||||
prefix = '%s_%s_' % (packageName, self.platform)
|
||||
|
||||
if packageVersion:
|
||||
# Do we have a specific version request?
|
||||
basename = prefix + '%s_import.xml' % (packageVersion)
|
||||
filename = Filename(platformDir, basename)
|
||||
if filename.exists():
|
||||
# Got it!
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if package:
|
||||
return package
|
||||
else:
|
||||
# Look for a generic version request. Get the highest
|
||||
# version available.
|
||||
files = vfs.scanDirectory(platformDir) or []
|
||||
for file in files:
|
||||
filename = file.getFilename()
|
||||
basename = filename.getBasename()
|
||||
if not basename.startswith(prefix) or \
|
||||
not basename.endswith('_import.xml'):
|
||||
continue
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if not package:
|
||||
continue
|
||||
|
||||
parts = basename.split('_')
|
||||
if len(parts) == 3:
|
||||
# No version number.
|
||||
if bestVersion is None:
|
||||
bestPackage = package
|
||||
|
||||
elif len(parts) == 4:
|
||||
# Got a version number.
|
||||
version = self.parseVersionForCompare(parts[2])
|
||||
if bestVersion > version:
|
||||
bestVersion = version
|
||||
bestPackage = package
|
||||
|
||||
# Didn't find a suitable platform-specific file, so look for a
|
||||
# platform-nonspecific one.
|
||||
prefix = '%s_' % (packageName)
|
||||
if packageVersion:
|
||||
# Do we have a specific version request?
|
||||
basename = prefix + '%s_import.xml' % (packageVersion)
|
||||
filename = Filename(packageDir, basename)
|
||||
if filename.exists():
|
||||
# Got it!
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if package:
|
||||
return package
|
||||
else:
|
||||
# Look for a generic version request. Get the highest
|
||||
# version available.
|
||||
files = vfs.scanDirectory(packageDir) or []
|
||||
for file in files:
|
||||
filename = file.getFilename()
|
||||
basename = filename.getBasename()
|
||||
if not basename.startswith(prefix) or \
|
||||
not basename.endswith('_import.xml'):
|
||||
continue
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if not package:
|
||||
continue
|
||||
packageDir = Filename(rootDir, packageName)
|
||||
basename = packageName
|
||||
|
||||
parts = basename.split('_')
|
||||
if len(parts) == 2:
|
||||
# No version number.
|
||||
if bestVersion is None:
|
||||
bestPackage = package
|
||||
if platform:
|
||||
packageDir = Filename(packageDir, platform)
|
||||
basename += '_%s' % (platform)
|
||||
|
||||
elif len(parts) == 3:
|
||||
# Got a version number.
|
||||
version = self.parseVersionForCompare(parts[1])
|
||||
if bestVersion > version:
|
||||
bestVersion = version
|
||||
bestPackage = package
|
||||
if version:
|
||||
packageDir = Filename(packageDir, version)
|
||||
basename += '_%s' % (version)
|
||||
|
||||
return bestPackage
|
||||
basename += '_import.xml'
|
||||
filename = Filename(packageDir, basename)
|
||||
if filename.exists():
|
||||
# It exists in the nested directory.
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if package:
|
||||
return package
|
||||
filename = Filename(rootDir, basename)
|
||||
if filename.exists():
|
||||
# It exists in the root directory.
|
||||
package = self.readPackageImportDescFile(filename)
|
||||
if package:
|
||||
return package
|
||||
|
||||
return None
|
||||
|
||||
def readPackageImportDescFile(self, filename):
|
||||
""" Reads the named xml file as a Package, and returns it if
|
||||
|
|
@ -917,26 +1024,51 @@ class Packager:
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def parseVersionForCompare(self, version):
|
||||
""" Given a formatted version string, breaks it up into a
|
||||
tuple, grouped so that putting the tuples into sorted order
|
||||
will put the order numbers in increasing order. """
|
||||
|
||||
# TODO. For now, we just use a dumb string compare.
|
||||
return (version,)
|
||||
|
||||
def require(self, package):
|
||||
""" Indicates a dependency on the indicated package.
|
||||
def require(self, packageName, version = None):
|
||||
""" Indicates a dependency on the named package, supplied as
|
||||
name.
|
||||
|
||||
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
|
||||
# A special case for the Panda3D package. We enforce that the
|
||||
# version number matches what we've been compiled with.
|
||||
if packageName == 'panda3d':
|
||||
if version is None:
|
||||
version = PandaSystem.getPackageVersionString()
|
||||
|
||||
package = self.findPackage(packageName, version = version)
|
||||
if not package:
|
||||
message = "Unknown package %s" % (packageName)
|
||||
raise PackagerError, message
|
||||
|
||||
self.requirePackage(package)
|
||||
|
||||
def requirePackage(self, package):
|
||||
""" Indicates a dependency on the indicated package, supplied
|
||||
as a Package object.
|
||||
|
||||
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. """
|
||||
|
||||
# A special case for the Panda3D package. We enforce that the
|
||||
# version number matches what we've been compiled with.
|
||||
if package.packageName == 'panda3d':
|
||||
if package.version != PandaSystem.getPackageVersionString():
|
||||
if not PandaSystem.getPackageVersionString():
|
||||
# We haven't been compiled with any particular
|
||||
# version of Panda. This is a warning, not an
|
||||
# error.
|
||||
print "Warning: requiring panda3d version %s, which may or may not match the current build of Panda. Recommend that you use only the official Panda3D build for making distributable applications to ensure compatibility." % (package.version)
|
||||
else:
|
||||
# This particular version of Panda doesn't match
|
||||
# the requested version. Again, a warning, not an
|
||||
# error.
|
||||
print "Warning: requiring panda3d version %s, which does not match the current build of Panda, which is version %s." % (package, PandaSystem.getPackageVersionString())
|
||||
|
||||
self.currentPackage.requirePackage(package)
|
||||
|
||||
def module(self, moduleName, newName = None):
|
||||
""" Adds the indicated Python module to the current package. """
|
||||
|
|
@ -946,6 +1078,19 @@ class Packager:
|
|||
|
||||
self.currentPackage.freezer.addModule(moduleName, newName = newName)
|
||||
|
||||
def mainModule(self, moduleName, newName = None):
|
||||
""" Names the indicated module as the "main" module of the
|
||||
application or exe. """
|
||||
|
||||
if not self.currentPackage:
|
||||
raise OutsideOfPackageError
|
||||
|
||||
if self.currentPackage.mainModule and self.currentPackage.mainModule != moduleName:
|
||||
self.notify.warning("Replacing main_module %s with %s" % (
|
||||
self.currentPackage.mainModule, moduleName))
|
||||
|
||||
self.currentPackage.mainModule = moduleName
|
||||
|
||||
def freeze(self, filename, compileToExe = False):
|
||||
""" Freezes all of the current Python code into either an
|
||||
executable (if compileToExe is true) or a dynamic library (if
|
||||
|
|
@ -958,6 +1103,19 @@ class Packager:
|
|||
|
||||
package = self.currentPackage
|
||||
freezer = package.freezer
|
||||
|
||||
if package.mainModule and not compileToExe:
|
||||
self.notify.warning("Ignoring main_module for dll %s" % (filename))
|
||||
package.mainModule = None
|
||||
if not package.mainModule and compileToExe:
|
||||
message = "No main_module specified for exe %s" % (filename)
|
||||
raise PackagerError, message
|
||||
|
||||
if package.mainModule:
|
||||
if package.mainModule not in freezer.modules:
|
||||
freezer.addModule(package.mainModule, newName = '__main__')
|
||||
else:
|
||||
freezer.modules['__main__'] = freezer.modules[package.mainModule]
|
||||
freezer.done()
|
||||
|
||||
if not package.dryRun:
|
||||
|
|
@ -966,12 +1124,16 @@ class Packager:
|
|||
if '/' in basename:
|
||||
dirname, basename = filename.rsplit('/', 1)
|
||||
dirname += '/'
|
||||
|
||||
basename = freezer.generateCode(basename, compileToExe = compileToExe)
|
||||
|
||||
package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True))
|
||||
package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True, extract = True))
|
||||
if not package.platform:
|
||||
package.platform = PandaSystem.getPlatform()
|
||||
|
||||
# Reset the freezer for more Python files.
|
||||
freezer.reset()
|
||||
package.mainModule = None
|
||||
|
||||
|
||||
def file(self, filename, newNameOrDir = None):
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ See pack3d.py for a script that generates these p3d files.
|
|||
import sys
|
||||
from direct.showbase import VFSImporter
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, HTTPClient, Thread, WindowProperties
|
||||
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, HTTPClient, Thread, WindowProperties, readXmlStream
|
||||
from direct.stdpy import file
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.showbase.MessengerGlobal import messenger
|
||||
|
|
@ -192,7 +192,25 @@ class AppRunner(DirectObject):
|
|||
# Hang a hook so we know when the window is actually opened.
|
||||
self.acceptOnce('window-event', self.windowEvent)
|
||||
|
||||
import main
|
||||
# Look for the startup Python file. This may be a magic
|
||||
# filename (like "__main__", or any filename that contains
|
||||
# invalid module characters), so we can't just import it
|
||||
# directly; instead, we go through the low-level importer.
|
||||
|
||||
# If there's no p3d_info.xml file, we look for "main".
|
||||
moduleName = 'main'
|
||||
if self.p3dPackage:
|
||||
mainName = self.p3dPackage.Attribute('main_module')
|
||||
if mainName:
|
||||
moduleName = mainName
|
||||
|
||||
v = VFSImporter.VFSImporter(MultifileRoot)
|
||||
loader = v.find_module(moduleName)
|
||||
if not loader:
|
||||
message = "No %s.py found in application." % (mainName)
|
||||
raise StandardError, message
|
||||
|
||||
main = loader.load_module(moduleName)
|
||||
if hasattr(main, 'main') and callable(main.main):
|
||||
main.main()
|
||||
|
||||
|
|
@ -233,31 +251,6 @@ class AppRunner(DirectObject):
|
|||
|
||||
# Now go load the applet.
|
||||
fname = Filename.fromOsSpecific(p3dFilename)
|
||||
if not p3dFilename:
|
||||
# If we didn't get a literal filename, we have to download it
|
||||
# from the URL. TODO: make this a smarter temporary filename?
|
||||
fname = Filename.temporary('', 'p3d_')
|
||||
fname.setExtension('p3d')
|
||||
p3dFilename = fname.toOsSpecific()
|
||||
src = self.tokenDict.get('src', None)
|
||||
if not src:
|
||||
raise ArgumentError, "No Panda app specified."
|
||||
|
||||
http = HTTPClient.getGlobalPtr()
|
||||
hc = http.getDocument(src)
|
||||
if not hc.downloadToFile(fname):
|
||||
fname.unlink()
|
||||
raise ArgumentError, "Couldn't download %s" % (src)
|
||||
|
||||
# Set a hook on sys.exit to delete the temporary file.
|
||||
oldexitfunc = getattr(sys, 'exitfunc', None)
|
||||
def deleteTempFile(fname = fname, oldexitfunc = oldexitfunc):
|
||||
fname.unlink()
|
||||
if oldexitfunc:
|
||||
oldexitfunc()
|
||||
|
||||
sys.exitfunc = deleteTempFile
|
||||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
|
||||
if not vfs.exists(fname):
|
||||
|
|
@ -285,6 +278,19 @@ class AppRunner(DirectObject):
|
|||
data = open(pathname, 'r').read()
|
||||
loadPrcFileData(pathname, data)
|
||||
|
||||
# Now load the p3dInfo file.
|
||||
self.p3dInfo = None
|
||||
self.p3dPackage = None
|
||||
i = mf.findSubfile('p3d_info.xml')
|
||||
if i >= 0:
|
||||
stream = mf.openReadSubfile(i)
|
||||
self.p3dInfo = readXmlStream(stream)
|
||||
mf.closeReadSubfile(stream)
|
||||
if self.p3dInfo:
|
||||
p3dPackage = self.p3dInfo.FirstChild('package')
|
||||
if p3dPackage:
|
||||
self.p3dPackage = p3dPackage.ToElement()
|
||||
|
||||
self.gotP3DFilename = True
|
||||
|
||||
# Send this call to the main thread; don't call it directly.
|
||||
|
|
|
|||
Loading…
Reference in New Issue