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
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 getopt
import direct
from pandac.PandaModules import *
@ -52,13 +66,37 @@ class AppPacker:
for type in PNMFileTypeRegistry.getGlobalPtr().getTypes():
self.image_extensions += type.getExtensions()
def scan(self, root):
def scan(self, root, main):
self.root = Filename(root)
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.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):
dirList = vfs.scanDirectory(filename)
if dirList:
@ -95,7 +133,12 @@ class AppPacker:
def addPyFile(self, filename):
# For now, just add it as an ordinary file. Later we'll
# 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):
# Precompile egg files to bam's.
@ -140,7 +183,9 @@ class AppPacker:
bamFile.getWriter().setFileTextureMode(BTMUnchanged)
bamFile.writeObject(node)
bamFile.close()
node = None
# Clean the node out of memory.
node.removeAllChildren()
# Now we have an in-memory bam file.
rel = self.makeRelFilename(filename)
@ -223,6 +268,19 @@ class AppPacker:
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:
raise ArgumentError, "No destination app specified. Use:\npython MakeAppMF.py app.mf"
@ -235,7 +293,7 @@ def makePackedApp(args):
raise ArgumentError, "Too many arguments."
p = AppPacker(multifile_name)
p.scan(root)
p.scan(root = root, main = main)
if __name__ == '__main__':
try:

View File

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

View File

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