This commit is contained in:
David Rose 2008-11-12 03:59:09 +00:00
parent 0f52801b0c
commit d8641b3fdc
3 changed files with 86 additions and 22 deletions

View File

@ -1,18 +1,32 @@
""" This module will pack a Panda application, consisting of a """
This module will pack a Panda application, consisting of a
directory tree of .py files and models, into a multifile for directory tree of .py files and models, into a multifile for
distribution and running with RunAppMF.py. To run it, use: distribution and running with RunAppMF.py. To run it, use:
python MakeAppMF.py app.mf [application_root] python MakeAppMF.py [opts] app.mf
Options:
-r application_root
Specify the root directory of the application source; this is a
directory tree that contains all of your .py files and models.
If this is omitted, the default is the current directory.
-m main.py
Names the Python file that begins the application. This should
be a file within the root directory. If this is omitted, the
default is a file named "main.py", or if there is only one Python
file present, it is used. If this file contains a function
called main(), that function will be called after importing it
(this is preferable to having the module start itself immediately
upon importing).
where application_root is the root directory of the application. If
it is omitted, the default is the current directory. The root
directory should contain at a file named main.py, which is imported to
start the application. If main.py contains a function called main(),
this function is called after importing it; otherwise, taskMgr.run()
is called.
""" """
import sys import sys
import getopt
import direct import direct
from pandac.PandaModules import * from pandac.PandaModules import *
@ -52,13 +66,37 @@ class AppPacker:
for type in PNMFileTypeRegistry.getGlobalPtr().getTypes(): for type in PNMFileTypeRegistry.getGlobalPtr().getTypes():
self.image_extensions += type.getExtensions() self.image_extensions += type.getExtensions()
def scan(self, root): def scan(self, root, main):
self.root = Filename(root) self.root = Filename(root)
self.root.makeAbsolute(vfs.getCwd()) self.root.makeAbsolute(vfs.getCwd())
# Check if there is just one .py file.
pyFiles = self.findPyFiles(self.root)
if main == None:
if len(pyFiles) == 1:
main = pyFiles[0]
else:
main = 'main.py'
if main not in pyFiles:
raise StandardError, 'No file %s in root directory.' % (main)
self.main = Filename(self.root, main)
self._recurse(self.root) self._recurse(self.root)
self.multifile.repack() self.multifile.repack()
def findPyFiles(self, dirname):
""" Returns a list of Python filenames at the root directory
level. """
dirList = vfs.scanDirectory(dirname)
pyFiles = []
for file in dirList:
if file.getFilename().getExtension() == 'py':
pyFiles.append(file.getFilename().getBasename())
return pyFiles
def _recurse(self, filename): def _recurse(self, filename):
dirList = vfs.scanDirectory(filename) dirList = vfs.scanDirectory(filename)
if dirList: if dirList:
@ -95,7 +133,12 @@ class AppPacker:
def addPyFile(self, filename): def addPyFile(self, filename):
# For now, just add it as an ordinary file. Later we'll # For now, just add it as an ordinary file. Later we'll
# precompile these to .pyo's. # precompile these to .pyo's.
self.addTextFile(filename) if filename == self.main:
# This one is the "main.py"; the starter file.
self.multifile.addSubfile('main.py', filename, self.compression_level)
else:
# Any other Python file; add it normally.
self.addTextFile(filename)
def addEggFile(self, filename, outFilename): def addEggFile(self, filename, outFilename):
# Precompile egg files to bam's. # Precompile egg files to bam's.
@ -140,7 +183,9 @@ class AppPacker:
bamFile.getWriter().setFileTextureMode(BTMUnchanged) bamFile.getWriter().setFileTextureMode(BTMUnchanged)
bamFile.writeObject(node) bamFile.writeObject(node)
bamFile.close() bamFile.close()
node = None
# Clean the node out of memory.
node.removeAllChildren()
# Now we have an in-memory bam file. # Now we have an in-memory bam file.
rel = self.makeRelFilename(filename) rel = self.makeRelFilename(filename)
@ -223,6 +268,19 @@ class AppPacker:
def makePackedApp(args): def makePackedApp(args):
opts, args = getopt.getopt(args, 'r:m:h')
root = '.'
main = None
for option, value in opts:
if option == '-r':
root = value
elif option == '-m':
main = value
elif option == '-h':
print __doc__
sys.exit(1)
if not args: if not args:
raise ArgumentError, "No destination app specified. Use:\npython MakeAppMF.py app.mf" raise ArgumentError, "No destination app specified. Use:\npython MakeAppMF.py app.mf"
@ -235,7 +293,7 @@ def makePackedApp(args):
raise ArgumentError, "Too many arguments." raise ArgumentError, "Too many arguments."
p = AppPacker(multifile_name) p = AppPacker(multifile_name)
p.scan(root) p.scan(root = root, main = main)
if __name__ == '__main__': if __name__ == '__main__':
try: try:

View File

@ -14,7 +14,8 @@ Also see MakeAppMF.py.
import sys import sys
from direct.showbase import VFSImporter from direct.showbase import VFSImporter
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, ConfigPageManager, getModelPath from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, ConfigPageManager, getModelPath
from direct.stdpy.file import file, open from direct.stdpy import file
import os
import __builtin__ import __builtin__
MultifileRoot = '/mf' MultifileRoot = '/mf'
@ -70,13 +71,17 @@ def runPackedApp(args):
cpMgr.getSearchPath().prependDirectory(MultifileRoot) cpMgr.getSearchPath().prependDirectory(MultifileRoot)
cpMgr.reloadImplicitPages() cpMgr.reloadImplicitPages()
# Replace the builtin open and file symbols so code will get our # Replace the builtin open and file symbols so user code will get
# versions by default, which can open and read files out of the # our versions by default, which can open and read files out of
# multifile. # the multifile.
__builtin__.file = file __builtin__.file = file.file
__builtin__.open = open __builtin__.open = file.open
os.listdir = file.listdir
os.walk = file.walk
import main import main
if hasattr(main, 'main') and callable(main.main):
main.main()
if __name__ == '__main__': if __name__ == '__main__':
try: try:

View File

@ -34,7 +34,7 @@ class VFSImporter:
def find_module(self, fullname): def find_module(self, fullname):
basename = fullname.split('.')[-1] basename = fullname.split('.')[-1]
path = Filename(self.dir_path, Filename(basename)) path = Filename(self.dir_path, basename)
# First, look for Python files. # First, look for Python files.
filename = path filename = path
@ -66,12 +66,12 @@ class VFSImporter:
# Finally, consider a package, i.e. a directory containing # Finally, consider a package, i.e. a directory containing
# __init__.py. # __init__.py.
filename = Filename(path, Filename('__init__.py')) filename = Filename(path, '__init__.py')
vfile = vfs.getFile(filename, True) vfile = vfs.getFile(filename, True)
if vfile: if vfile:
return VFSLoader(self, vfile, filename, FTPythonSource, return VFSLoader(self, vfile, filename, FTPythonSource,
package = True) package = True)
filename = Filename(path, Filename('__init__.' + pycExtension)) filename = Filename(path, '__init__.' + pycExtension)
vfile = vfs.getFile(filename, True) vfile = vfs.getFile(filename, True)
if vfile: if vfile:
return VFSLoader(self, vfile, filename, FTPythonCompiled, return VFSLoader(self, vfile, filename, FTPythonCompiled,
@ -158,7 +158,8 @@ class VFSLoader:
else: else:
# It's a virtual file. Dump it. # It's a virtual file. Dump it.
filename = Filename.temporary('', self.filename.getBasenameWoExtension(), filename = Filename.temporary('', self.filename.getBasenameWoExtension(),
'.' + self.filename.getExtension()) '.' + self.filename.getExtension(),
type = Filename.TDso)
filename.setExtension(self.filename.getExtension()) filename.setExtension(self.filename.getExtension())
fin = open(vfile, 'rb') fin = open(vfile, 'rb')
fout = open(filename, 'wb') fout = open(filename, 'wb')