mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
better support for pyc's
This commit is contained in:
parent
4456d45f62
commit
cce0129c7b
@ -23,11 +23,22 @@ Options:
|
||||
(this is preferable to having the module start itself immediately
|
||||
upon importing).
|
||||
|
||||
-c [py,pyc,pyo]
|
||||
|
||||
Specifies the compilation mode of python files. 'py' means to
|
||||
leave them as source files, 'pyc' and 'pyo' are equivalent, and
|
||||
mean to compile to byte code. pyc files will be written if the
|
||||
interpreter is running in normal debug mode, while pyo files will
|
||||
be written if it is running in optimize mode (-O or -OO).
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import getopt
|
||||
import imp
|
||||
import marshal
|
||||
import direct
|
||||
from direct.stdpy.file import open
|
||||
from pandac.PandaModules import *
|
||||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
@ -51,6 +62,9 @@ class AppPacker:
|
||||
# without compression.
|
||||
uncompressible_extensions = [ 'mp3' ]
|
||||
|
||||
# Specifies how or if python files are compiled.
|
||||
compilation_mode = 'pyc'
|
||||
|
||||
def __init__(self, multifile_name):
|
||||
# Make sure any pre-existing file is removed.
|
||||
Filename(multifile_name).unlink()
|
||||
@ -67,6 +81,12 @@ class AppPacker:
|
||||
self.image_extensions += type.getExtensions()
|
||||
|
||||
def scan(self, root, main):
|
||||
if self.compilation_mode != 'py':
|
||||
if __debug__:
|
||||
self.compilation_mode = 'pyc'
|
||||
else:
|
||||
self.compilation_mode = 'pyo'
|
||||
|
||||
self.root = Filename(root)
|
||||
self.root.makeAbsolute(vfs.getCwd())
|
||||
|
||||
@ -131,15 +151,30 @@ class AppPacker:
|
||||
self.addUncompressibleFile(filename)
|
||||
|
||||
def addPyFile(self, filename):
|
||||
# For now, just add it as an ordinary file. Later we'll
|
||||
# precompile these to .pyo's.
|
||||
targetFilename = self.makeRelFilename(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)
|
||||
targetFilename = Filename('main.py')
|
||||
|
||||
if self.compilation_mode == 'py':
|
||||
# Add python files as source files.
|
||||
self.multifile.addSubfile(targetFilename.cStr(), filename, self.compression_level)
|
||||
elif self.compilation_mode == 'pyc' or self.compilation_mode == 'pyo':
|
||||
# Compile it to bytecode.
|
||||
targetFilename.setExtension(self.compilation_mode)
|
||||
source = open(filename, 'r').read()
|
||||
if source and source[-1] != '\n':
|
||||
source = source + '\n'
|
||||
code = compile(source, targetFilename.cStr(), 'exec')
|
||||
data = imp.get_magic() + '\0\0\0\0' + marshal.dumps(code)
|
||||
|
||||
stream = StringStream(data)
|
||||
self.multifile.addSubfile(targetFilename.cStr(), stream, self.compression_level)
|
||||
self.multifile.flush()
|
||||
else:
|
||||
raise StandardError, 'Unsupported compilation mode %s' % (self.compilation_mode)
|
||||
|
||||
def addEggFile(self, filename, outFilename):
|
||||
# Precompile egg files to bam's.
|
||||
node = loadEggFile(filename)
|
||||
@ -268,15 +303,18 @@ class AppPacker:
|
||||
|
||||
|
||||
def makePackedApp(args):
|
||||
opts, args = getopt.getopt(args, 'r:m:h')
|
||||
opts, args = getopt.getopt(args, 'r:m:c:h')
|
||||
|
||||
root = '.'
|
||||
main = None
|
||||
compilation_mode = AppPacker.compilation_mode
|
||||
for option, value in opts:
|
||||
if option == '-r':
|
||||
root = value
|
||||
elif option == '-m':
|
||||
main = value
|
||||
elif option == '-c':
|
||||
compilation_mode = value
|
||||
elif option == '-h':
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
@ -289,6 +327,7 @@ def makePackedApp(args):
|
||||
raise ArgumentError, "Too many arguments."
|
||||
|
||||
p = AppPacker(multifile_name)
|
||||
p.compilation_mode = compilation_mode
|
||||
p.scan(root = root, main = main)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -17,11 +17,11 @@ FTPythonSource = 0
|
||||
FTPythonCompiled = 1
|
||||
FTCompiledModule = 2
|
||||
|
||||
pycExtension = 'pyc'
|
||||
compiledExtensions = [ 'pyc', 'pyo' ]
|
||||
if not __debug__:
|
||||
# In optimized mode, we actually operate on .pyo files, not .pyc
|
||||
# files.
|
||||
pycExtension = 'pyo'
|
||||
# In optimized mode, we prefer loading .pyo files over .pyc files.
|
||||
# We implement that by reversing the extension names.
|
||||
compiledExtensions = [ 'pyo', 'pyc' ]
|
||||
|
||||
class VFSImporter:
|
||||
""" This class serves as a Python importer to support loading
|
||||
@ -45,11 +45,12 @@ class VFSImporter:
|
||||
|
||||
# If there's no .py file, but there's a .pyc file, load that
|
||||
# anyway.
|
||||
filename = Filename(path)
|
||||
filename.setExtension(pycExtension)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(self, vfile, filename, FTPythonCompiled)
|
||||
for ext in compiledExtensions:
|
||||
filename = Filename(path)
|
||||
filename.setExtension(ext)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(self, vfile, filename, FTPythonCompiled)
|
||||
|
||||
# Look for a compiled C/C++ module.
|
||||
for desc in imp.get_suffixes():
|
||||
@ -71,11 +72,12 @@ class VFSImporter:
|
||||
if vfile:
|
||||
return VFSLoader(self, vfile, filename, FTPythonSource,
|
||||
packagePath = path)
|
||||
filename = Filename(path, '__init__.' + pycExtension)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(self, vfile, filename, FTPythonCompiled,
|
||||
packagePath = path)
|
||||
for ext in compiledExtensions:
|
||||
filename = Filename(path, '__init__.' + ext)
|
||||
vfile = vfs.getFile(filename, True)
|
||||
if vfile:
|
||||
return VFSLoader(self, vfile, filename, FTPythonCompiled,
|
||||
packagePath = path)
|
||||
|
||||
return None
|
||||
|
||||
@ -192,12 +194,14 @@ class VFSLoader:
|
||||
# It's a .py file (or an __init__.py file; same thing). Read
|
||||
# the .pyc file if it is available and current; otherwise read
|
||||
# the .py file and compile it.
|
||||
pycFilename = Filename(self.filename)
|
||||
pycFilename.setExtension(pycExtension)
|
||||
pycVfile = vfs.getFile(pycFilename, False)
|
||||
t_pyc = None
|
||||
if pycVfile:
|
||||
t_pyc = pycVfile.getTimestamp()
|
||||
for ext in compiledExtensions:
|
||||
pycFilename = Filename(self.filename)
|
||||
pycFilename.setExtension(ext)
|
||||
pycVfile = vfs.getFile(pycFilename, False)
|
||||
if pycVfile:
|
||||
t_pyc = pycVfile.getTimestamp()
|
||||
break
|
||||
|
||||
code = None
|
||||
if t_pyc and t_pyc >= self.timestamp:
|
||||
@ -233,7 +237,7 @@ class VFSLoader:
|
||||
|
||||
# try to cache the compiled code
|
||||
pycFilename = Filename(filename)
|
||||
pycFilename.setExtension(pycExtension)
|
||||
pycFilename.setExtension(compiledExtensions[0])
|
||||
try:
|
||||
f = open(pycFilename, 'wb')
|
||||
except IOError:
|
||||
|
Loading…
x
Reference in New Issue
Block a user