some cleanup

This commit is contained in:
David Rose 2009-08-15 00:13:55 +00:00
parent 9b4f4aa8c6
commit 936ff2455e
11 changed files with 284 additions and 159 deletions

View File

@ -1155,7 +1155,7 @@ report_package_info_ready(P3DPackage *package) {
////////////////////////////////////////////////////////////////////
void P3DInstance::
start_next_download() {
while (_download_package_index < _downloading_packages.size()) {
while (_download_package_index < (int)_downloading_packages.size()) {
P3DPackage *package = _downloading_packages[_download_package_index];
if (package->get_failed()) {
// Too bad. TODO: fail.
@ -1211,12 +1211,10 @@ start_next_download() {
////////////////////////////////////////////////////////////////////
void P3DInstance::
report_package_progress(P3DPackage *package, double progress) {
if (_download_package_index >= _downloading_packages.size() ||
if (_download_package_index >= (int)_downloading_packages.size() ||
package != _downloading_packages[_download_package_index]) {
// Got a report from an unexpected package.
nout << "Got download progress report from " << package->get_package_name()
<< ", not at download head (head is " << _download_package_index
<< ")\n";
// Quietly ignore a download progress report from an unexpected
// package.
return;
}

View File

@ -22,7 +22,6 @@
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "find_root_dir.h"
#include "mkdir_complete.h"
#include "fileSpec.h"
#include "get_tinyxml.h"

View File

@ -45,7 +45,7 @@ P3DPackage(const string &package_name,
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_package_fullname = _package_name;
_package_dir = inst_mgr->get_root_dir() + string("/") + _package_name;
_package_dir = inst_mgr->get_root_dir() + string("/packages/") + _package_name;
if (!_package_platform.empty()) {
_package_fullname += string("_") + _package_platform;
_package_dir += string("/") + _package_platform;

View File

@ -25,6 +25,9 @@
#include "p3dConcreteSequence.h"
#include "p3dConcreteStruct.h"
#include "binaryXml.h"
#include "mkdir_complete.h"
#include <ctype.h>
#ifndef _WIN32
#include <fcntl.h>
@ -49,6 +52,7 @@ P3DSession(P3DInstance *inst) {
_session_key = inst->get_session_key();
_python_version = inst->get_python_version();
_start_dir = inst_mgr->get_root_dir() + "/start";
_p3dpython_running = false;
_started_read_thread = false;
@ -660,6 +664,28 @@ start_p3dpython(P3DInstance *inst) {
_python_root_dir = inst->_panda3d->get_package_dir();
mkdir_complete(_start_dir, nout);
// Build up a search path that includes all of the required packages
// that have already been installed.
string search_path;
size_t pi = 0;
assert(pi < inst->_packages.size());
search_path = inst->_packages[pi]->get_package_dir();
++pi;
while (pi < inst->_packages.size()) {
#ifdef _WIN32
search_path += ';';
#else
search_path += ':';
#endif // _WIN32
search_path += inst->_packages[pi]->get_package_dir();
++pi;
}
nout << "Search path is " << search_path << "\n";
string p3dpython = P3D_PLUGIN_P3DPYTHON;
if (p3dpython.empty()) {
p3dpython = _python_root_dir + "/p3dpython";
@ -692,42 +718,58 @@ start_p3dpython(P3DInstance *inst) {
// Define some new environment variables.
env += "PATH=";
env += _python_root_dir;
env += search_path;
env += '\0';
env += "LD_LIBRARY_PATH=";
env += _python_root_dir;
env += search_path;
env += '\0';
env += "DYLD_LIBRARY_PATH=";
env += _python_root_dir;
env += search_path;
env += '\0';
env += "PYTHONPATH=";
env += _python_root_dir;
env += search_path;
env += '\0';
env += "PYTHONHOME=";
env += _python_root_dir;
env += '\0';
env += "PRC_DIR=";
env += _python_root_dir;
env += "PRC_PATH=";
env += search_path;
env += '\0';
env += "PANDA_PRC_DIR=";
env += _python_root_dir;
env += "PANDA_PRC_PATH=";
env += search_path;
env += '\0';
// Define each package's root directory in an environment variable
// named after the package, for the convenience of the packages in
// setting up their config files.
for (size_t pi = 0; pi < inst->_packages.size(); ++pi) {
P3DPackage *package = inst->_packages[pi];
const string package_name = package->get_package_name();
for (string::const_iterator si = package_name.begin();
si != package_name.end();
++si) {
env += toupper(*si);
}
env += string("_ROOT=");
env += package->get_package_dir();
env += '\0';
}
nout << "Attempting to start python from " << p3dpython << "\n";
#ifdef _WIN32
_p3dpython_handle = win_create_process
(p3dpython, _python_root_dir, env, _output_filename,
(p3dpython, _start_dir, env, _output_filename,
_pipe_read, _pipe_write);
bool started_p3dpython = (_p3dpython_handle != INVALID_HANDLE_VALUE);
#else
_p3dpython_pid = posix_create_process
(p3dpython, _python_root_dir, env, _output_filename,
(p3dpython, _start_dir, env, _output_filename,
_pipe_read, _pipe_write);
bool started_p3dpython = (_p3dpython_pid > 0);
#endif

View File

@ -92,6 +92,7 @@ private:
string _python_version;
string _output_filename;
string _python_root_dir;
string _start_dir;
typedef map<int, P3DInstance *> Instances;
Instances _instances;

View File

@ -56,13 +56,17 @@ int Panda3D::
run(int argc, char *argv[]) {
extern char *optarg;
extern int optind;
const char *optstr = "u:p:fl:t:s:o:h";
// We prefix a "+" sign to tell gnu getopt not to parse options
// following the first not-option parameter. (These will be passed
// into the sub-process.)
const char *optstr = "+mu:p:ft:s:o:h";
bool allow_multiple = false;
string download_url = P3D_PLUGIN_DOWNLOAD;
string this_platform = DTOOL_PLATFORM;
bool force_download = false;
Filename output_filename;
P3D_window_type window_type = P3D_WT_toplevel;
int win_x = 0, win_y = 0;
int win_width = 0, win_height = 0;
@ -71,6 +75,10 @@ run(int argc, char *argv[]) {
while (flag != EOF) {
switch (flag) {
case 'm':
allow_multiple = true;
break;
case 'u':
download_url = optarg;
break;
@ -83,10 +91,6 @@ run(int argc, char *argv[]) {
force_download = true;
break;
case 'l':
output_filename = Filename::from_os_specific(optarg);
break;
case 't':
if (strcmp(optarg, "toplevel") == 0) {
window_type = P3D_WT_toplevel;
@ -118,6 +122,7 @@ run(int argc, char *argv[]) {
case 'h':
case '?':
case '+':
default:
usage();
return 1;
@ -143,7 +148,24 @@ run(int argc, char *argv[]) {
return 1;
}
int num_instances = argc - 1;
int num_instance_filenames, num_instance_args;
char **instance_filenames, **instance_args;
if (allow_multiple) {
// With -m, the remaining arguments are all instance filenames.
num_instance_filenames = argc - 1;
instance_filenames = argv + 1;
num_instance_args = 0;
instance_args = argv + argc;
} else {
// Without -m, there is one instance filename, and everything else
// gets delivered to that instance.
num_instance_filenames = 1;
instance_filenames = argv + 1;
num_instance_args = argc - 2;
instance_args = argv + 2;
}
P3D_window_handle parent_window;
if (window_type == P3D_WT_embedded) {
@ -168,8 +190,8 @@ run(int argc, char *argv[]) {
#endif
// Subdivide the window into num_x_spans * num_y_spans sub-windows.
int num_y_spans = int(sqrt((double)num_instances));
int num_x_spans = (num_instances + num_y_spans - 1) / num_y_spans;
int num_y_spans = int(sqrt((double)num_instance_filenames));
int num_x_spans = (num_instance_filenames + num_y_spans - 1) / num_y_spans;
int inst_width = win_width / num_x_spans;
int inst_height = win_height / num_y_spans;
@ -177,7 +199,7 @@ run(int argc, char *argv[]) {
for (int yi = 0; yi < num_y_spans; ++yi) {
for (int xi = 0; xi < num_x_spans; ++xi) {
int i = yi * num_x_spans + xi;
if (i >= num_instances) {
if (i >= num_instance_filenames) {
continue;
}
@ -186,20 +208,20 @@ run(int argc, char *argv[]) {
int inst_y = win_y + yi * inst_height;
P3D_instance *inst = create_instance
(argv[i + 1], P3D_WT_embedded,
(instance_filenames[i], P3D_WT_embedded,
inst_x, inst_y, inst_width, inst_height, parent_window,
output_filename);
instance_args, num_instance_args);
_instances.insert(inst);
}
}
} else {
// Not an embedded window. Create each window with the same parameters.
for (int i = 0; i < num_instances; ++i) {
for (int i = 0; i < num_instance_filenames; ++i) {
P3D_instance *inst = create_instance
(argv[i + 1], window_type,
(instance_filenames[i], window_type,
win_x, win_y, win_width, win_height, parent_window,
output_filename);
instance_args, num_instance_args);
_instances.insert(inst);
}
}
@ -579,12 +601,8 @@ make_parent_window(P3D_window_handle &parent_window,
P3D_instance *Panda3D::
create_instance(const string &arg, P3D_window_type window_type,
int win_x, int win_y, int win_width, int win_height,
P3D_window_handle parent_window,
const Filename &output_filename) {
string os_output_filename = output_filename.to_os_specific();
P3D_window_handle parent_window, char **args, int num_args) {
P3D_token tokens[] = {
{ "output_filename", os_output_filename.c_str() },
{ "src", arg.c_str() },
};
int num_tokens = sizeof(tokens) / sizeof(P3D_token);
@ -645,18 +663,24 @@ void Panda3D::
usage() {
cerr
<< "\nUsage:\n"
<< " panda3d [opts] file.p3d [file_b.p3d file_c.p3d ...]\n\n"
<< " panda3d [opts] file.p3d [args]\n\n"
<< " panda3d -m [opts] file_a.p3d file_b.p3d [file_c.p3d ...]\n\n"
<< "This program is used to execute a Panda3D application bundle stored\n"
<< "in a .p3d file. Normally you only run one p3d bundle at a time,\n"
<< "but it is possible to run multiple bundles simultaneously.\n\n"
<< "in a .p3d file. In the first form, without a -m option, it\n"
<< "executes one application; remaining arguments following the\n"
<< "application name are passed into the application. In the second\n"
<< "form, with a -m option, it can execute multiple applications\n"
<< "simultaneously, though in this form arguments cannot be passed into\n"
<< "the applications.\n\n"
<< "Options:\n\n"
<< " -l output.log\n"
<< " Specify the name of the file to receive the log output of the\n"
<< " plugin process(es). The default is to send this output to the\n"
<< " console.\n\n"
<< " -m\n"
<< " Indicates that multiple application filenames will be passed on\n"
<< " the command line. All applications will be run at the same\n"
<< " time, but additional arguments may not be passed to any of the\n"
<< " applictions.\n\n"
<< " -t [toplevel|embedded|fullscreen|hidden]\n"
<< " Specify the type of graphic window to create. If you specify\n"

View File

@ -59,7 +59,7 @@ private:
int win_x, int win_y, int win_width,
int win_height,
P3D_window_handle parent_window,
const Filename &output_filename);
char **args, int num_args);
void delete_instance(P3D_instance *instance);
void usage();

View File

@ -9,6 +9,7 @@ import glob
import marshal
import new
import string
import types
from direct.showbase import Loader
from direct.showutil import FreezeTool
from direct.directnotify.DirectNotifyGlobal import *
@ -31,11 +32,13 @@ class Packager:
class PackFile:
def __init__(self, package, filename,
newName = None, deleteTemp = False,
compress = None, extract = None, executable = None):
explicit = False, compress = None, extract = None,
executable = None):
assert isinstance(filename, Filename)
self.filename = Filename(filename)
self.newName = newName
self.deleteTemp = deleteTemp
self.explicit = explicit
self.compress = compress
self.extract = extract
self.executable = executable
@ -58,7 +61,7 @@ class Packager:
if self.executable:
# Look up the filename along the system PATH, if necessary.
self.filename.resolveFilename(packager.dllPath)
self.filename.resolveFilename(packager.executablePath)
# Convert the filename to an unambiguous filename for
# searching.
@ -73,19 +76,27 @@ class Packager:
if self.newName in package.skipFilenames:
return True
basename = Filename(self.newName).getBasename()
if not package.packager.caseSensitive:
basename = basename.lower()
if basename in package.packager.excludeSystemFiles:
return True
if not self.explicit:
# Make sure it's not one of our auto-excluded system
# files. (But only make this check if this file was
# not explicitly added.)
for exclude in package.packager.excludeSystemGlobs:
if exclude.matches(basename):
basename = Filename(self.newName).getBasename()
if not package.packager.caseSensitive:
basename = basename.lower()
if basename in package.packager.excludeSystemFiles:
return True
for exclude in package.packager.excludeSystemGlobs:
if exclude.matches(basename):
return True
for exclude in package.excludedFilenames:
if exclude.matches(self.filename):
return True
# Also check if it was explicitly excluded. As above,
# omit this check for an explicitly-added file: if you
# both include and exclude a file, the file is
# included.
for exclude in package.excludedFilenames:
if exclude.matches(self.filename):
return True
return False
@ -115,12 +126,15 @@ class Packager:
self.version = None
self.platform = None
self.p3dApplication = False
self.displayName = None
self.compressionLevel = 0
self.importedMapsDir = 'imported_maps'
self.mainModule = None
self.requires = []
# This is the set of config variables assigned to the
# package.
self.configs = {}
# This is the set of files and modules, already included
# by required packages, that we can skip.
self.skipFilenames = {}
@ -369,7 +383,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(),
executable = True)
explicit = False, executable = True)
def __parseDependenciesWindows(self, tempFile):
""" Reads the indicated temporary file, the output from
@ -451,7 +465,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(),
executable = True)
explicit = False, executable = True)
def __parseDependenciesOSX(self, tempFile):
""" Reads the indicated temporary file, the output from
@ -522,7 +536,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(),
executable = True)
explicit = False, executable = True)
def __parseDependenciesPosix(self, tempFile):
""" Reads the indicated temporary file, the output from
@ -560,7 +574,8 @@ class Packager:
newName += '/' + filename.getBasename()
# Sometimes the PYTHONPATH has the wrong case in it.
filename.makeTrueCase()
self.addFile(filename, newName = newName, extract = True)
self.addFile(filename, newName = newName,
explicit = False, extract = True)
freezer.extras = []
@ -579,11 +594,14 @@ class Packager:
if self.version:
xpackage.SetAttribute('version', self.version)
if self.displayName:
xpackage.SetAttribute('display_name', self.displayName)
xpackage.SetAttribute('main_module', self.mainModule)
for variable, value in self.configs.items():
if isinstance(value, types.UnicodeType):
xpackage.SetAttribute(variable, value.encode('utf-8'))
else:
xpackage.SetAttribute(variable, str(value))
for package in self.requires:
xrequires = TiXmlElement('requires')
xrequires.SetAttribute('name', package.packageName)
@ -628,8 +646,11 @@ class Packager:
if self.version:
xpackage.SetAttribute('version', self.version)
if self.displayName:
xpackage.SetAttribute('display_name', self.displayName)
for variable, value in self.configs.items():
if isinstance(value, types.UnicodeType):
xpackage.SetAttribute(variable, value.encode('utf-8'))
else:
xpackage.SetAttribute(variable, str(value))
for package in self.requires:
xrequires = TiXmlElement('requires')
@ -872,7 +893,8 @@ class Packager:
self.importedMapsDir, filename.getBasenameWoExtension(),
uniqueId, filename.getExtension())
self.addFile(filename, newName = newName, compress = False)
self.addFile(filename, newName = newName, explicit = False,
compress = False)
def addComponent(self, file):
if file.platformSpecific:
@ -916,24 +938,25 @@ class Packager:
self.persistDir = None
# A search list of directories and/or URL's to search for
# installed packages.
self.installSearch = []
# installed packages. We query it from a config variable
# initially, but we may also be extending it at runtime.
self.installSearch = ConfigVariableSearchPath('pdef-path')
# The system PATH, for searching dll's and exe's.
self.dllPath = DSearchPath()
self.executablePath = DSearchPath()
if PandaSystem.getPlatform().startswith('win'):
self.addWindowsSearchPath(self.dllPath, "PATH")
self.addWindowsSearchPath(self.executablePath, "PATH")
elif PandaSystem.getPlatform().startswith('osx'):
self.addPosixSearchPath(self.dllPath, "DYLD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "PATH")
self.dllPath.appendDirectory('/lib')
self.dllPath.appendDirectory('/usr/lib')
self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.executablePath, "PATH")
self.executablePath.appendDirectory('/lib')
self.executablePath.appendDirectory('/usr/lib')
else:
self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "PATH")
self.dllPath.appendDirectory('/lib')
self.dllPath.appendDirectory('/usr/lib')
self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.executablePath, "PATH")
self.executablePath.appendDirectory('/lib')
self.executablePath.appendDirectory('/usr/lib')
# The platform string.
self.platform = PandaSystem.getPlatform()
@ -1286,6 +1309,32 @@ class Packager:
value = ExecutionEnvironment.expandString(value.strip())
ExecutionEnvironment.setEnvironmentVariable(variable, value)
def parse_model_path(self, words):
"""
model_path directory
"""
newName = None
try:
command, dirName = words
except ValueError:
raise ArgumentError
getModelPath().appendDirectory(Filename.fromOsSpecific(dirName))
def parse_reset_model_path(self, words):
"""
reset_model_path
"""
newName = None
try:
(command,) = words
except ValueError:
raise ArgumentError
getModelPath().clear()
def parse_begin_package(self, words):
"""
begin_package packageName [version=v]
@ -1338,20 +1387,23 @@ class Packager:
self.endPackage(packageName, p3dApplication = True)
def parse_display_name(self, words):
def parse_config(self, words):
"""
display_name "name"
config variable=value
"""
try:
command, displayName = words
command, assign = words
except ValueError:
raise ArgumentError
raise ArgumentNumber
try:
variable, value = assign.split('=', 1)
except ValueError:
raise PackagerError, 'Equals sign required in assignment'
if not self.currentPackage:
raise OutsideOfPackageError
self.currentPackage.displayName = displayName
variable = variable.strip()
self.config(variable, value)
def parse_require(self, words):
"""
@ -1368,32 +1420,6 @@ class Packager:
version = args.get('version', None)
self.require(packageName, version = version)
def parse_model_path(self, words):
"""
model_path directory
"""
newName = None
try:
command, dirName = words
except ValueError:
raise ArgumentError
getModelPath().appendDirectory(Filename.fromOsSpecific(dirName))
def parse_reset_model_path(self, words):
"""
reset_model_path
"""
newName = None
try:
(command,) = words
except ValueError:
raise ArgumentError
getModelPath().clear()
def parse_module(self, words):
"""
module moduleName [newName]
@ -1624,10 +1650,10 @@ class Packager:
return package
# Look on the searchlist.
for path in self.installSearch:
package = self.__scanPackageDir(path, packageName, platform, version, requires = requires)
for dirname in self.installSearch.getDirectories():
package = self.__scanPackageDir(dirname, packageName, platform, version, requires = requires)
if not package:
package = self.__scanPackageDir(path, packageName, None, version, requires = requires)
package = self.__scanPackageDir(dirname, packageName, None, version, requires = requires)
if package:
package = self.packages.setdefault((package.packageName, package.platform, package.version), package)
@ -1727,9 +1753,9 @@ class Packager:
if not requires:
return True
# Really, we only check the panda3d package for now. The
# other packages will list this as a dependency, and this is
# all that matters.
# Really, we only check the panda3d package. The other
# packages will list this as a dependency, and this is all
# that matters.
panda1 = self.__findPackageInList('panda3d', [package] + package.requires)
panda2 = self.__findPackageInList('panda3d', requires)
@ -1760,6 +1786,17 @@ class Packager:
return None
def config(self, variable, value):
""" Sets the indicated p3d config variable to the given value.
This will be written into the p3d_info.xml file at the top of
the application, or to the package desc file for a package
file. """
if not self.currentPackage:
raise OutsideOfPackageError
self.currentPackage.configs[variable] = value
def require(self, packageName, version = None):
""" Indicates a dependency on the named package, supplied as
a name.
@ -1878,7 +1915,7 @@ class Packager:
basename = freezer.generateCode(basename, compileToExe = compileToExe)
package.addFile(Filename(basename), newName = dirname + basename,
deleteTemp = True, extract = True)
deleteTemp = True, explicit = True, extract = True)
package.addExtensionModules()
if not package.platform:
package.platform = PandaSystem.getPlatform()
@ -1924,6 +1961,7 @@ class Packager:
files = glob.glob(filename.toOsSpecific())
if not files:
files = [filename.toOsSpecific()]
explicit = (len(files) == 1)
newName = None
prefix = ''
@ -1946,7 +1984,7 @@ class Packager:
self.currentPackage.addFile(
filename, newName = name, extract = extract,
executable = executable)
explicit = explicit, executable = executable)
def exclude(self, filename):
""" Marks the indicated filename as not to be included. The
@ -1996,7 +2034,8 @@ class Packager:
# It's a file name. Add it.
ext = filename.getExtension()
if ext == 'py':
self.currentPackage.addFile(filename, newName = newName)
self.currentPackage.addFile(filename, newName = newName,
explicit = False)
else:
if ext == 'pz':
# Strip off an implicit .pz extension.
@ -2006,4 +2045,5 @@ class Packager:
ext = newFilename.getExtension()
if ext in self.knownExtensions:
self.currentPackage.addFile(filename, newName = newName)
self.currentPackage.addFile(filename, newName = newName,
explicit = False)

View File

@ -78,7 +78,7 @@ def makePackedApp(args):
elif option == '-r':
requires.append(value)
elif option == '-s':
packager.installSearch.append(Filename.fromOsSpecific(value))
packager.installSearch.appendDirectory(Filename.fromOsSpecific(value))
elif option == '-x':
versionIndependent = True
elif option == '-h':

View File

@ -83,7 +83,7 @@ for opt, arg in opts:
if opt == '-i':
packager.installDir = Filename.fromOsSpecific(arg)
elif opt == '-s':
packager.installSearch.append(Filename.fromOsSpecific(arg))
packager.installSearch.appendDirectory(Filename.fromOsSpecific(arg))
elif opt == '-d':
packager.persistDir = Filename.fromOsSpecific(arg)
elif opt == '-p':
@ -108,7 +108,7 @@ packageDef = Filename.fromOsSpecific(args[0])
if not packager.installDir:
packager.installDir = Filename('install')
packager.installSearch = [packager.installDir] + packager.installSearch
packager.installSearch.prependDirectory(packager.installDir)
packager.setup()
packages = packager.readPackageDef(packageDef)

View File

@ -65,6 +65,8 @@ class AppRunner(DirectObject):
self.windowOpened = False
self.windowPrc = None
self.fullDiskAccess = False
self.Undefined = Undefined
self.ConcreteStruct = ConcreteStruct
@ -139,22 +141,36 @@ class AppRunner(DirectObject):
vfs = VirtualFileSystem.getGlobalPtr()
# Clear *all* the mount points, including "/", so that we no
# longer access the disk directly.
vfs.unmountAll()
# Unmount directories we don't need. This doesn't provide
# actual security, since it only disables this stuff for users
# who go through the vfs; a malicious programmer can always
# get to the underlying true file I/O operations. Still, it
# can help prevent honest developers from accidentally getting
# stuck where they don't belong.
if not self.fullDiskAccess:
# Clear *all* the mount points, including "/", so that we
# no longer access the disk directly.
vfs.unmountAll()
# Make sure the directories on our standard Python path are mounted
# read-only, so we can still load Python.
for dirname in sys.path:
vfs.mount(dirname, dirname, vfs.MFReadOnly)
# Make sure the directories on our standard Python path
# are mounted read-only, so we can still load Python.
# Note: read-only actually doesn't have any effect on the
# vfs right now; careless application code can still write
# to these directories inadvertently.
for dirname in sys.path:
vfs.mount(dirname, dirname, vfs.MFReadOnly)
# Also mount some standard directories read-write (temporary and
# app-data directories).
tdir = Filename.temporary('', '')
for dirname in set([ tdir.getDirname(),
Filename.getTempDirectory().cStr(),
Filename.getUserAppdataDirectory().cStr(),
Filename.getCommonAppdataDirectory().cStr() ]):
# Also mount some standard directories read-write
# (temporary and app-data directories).
tdir = Filename.temporary('', '')
for dirname in set([ tdir.getDirname(),
Filename.getTempDirectory().cStr(),
Filename.getUserAppdataDirectory().cStr(),
Filename.getCommonAppdataDirectory().cStr() ]):
vfs.mount(dirname, dirname, 0)
# And we might need the current working directory.
dirname = ExecutionEnvironment.getCwd()
vfs.mount(dirname, dirname, 0)
# Now set up Python to import this stuff.
@ -257,12 +273,30 @@ class AppRunner(DirectObject):
raise ArgumentError, "No such file: %s" % (p3dFilename)
fname.makeAbsolute()
self.initPackedAppEnvironment()
mf = Multifile()
if not mf.openRead(fname):
raise ArgumentError, "Not a Panda Multifile: %s" % (p3dFilename)
# 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:
self.p3dPackage = self.p3dInfo.FirstChildElement('package')
if self.p3dPackage:
fullDiskAccess = self.p3dPackage.Attribute('full_disk_access')
try:
self.fullDiskAccess = int(fullDiskAccess)
except ValueError:
pass
self.initPackedAppEnvironment()
# Mount the Multifile under /mf, by convention.
vfs.mount(mf, MultifileRoot, vfs.MFReadOnly)
@ -278,19 +312,6 @@ 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.