def __startIfReady(self): """ Called internally to start the application. """ if self.started: return if self.gotWindow and self.gotP3DFilename: self.started = True # Now we can ignore future calls to startIfReady(). self.ignore('AppRunner_startIfReady') # Hang a hook so we know when the window is actually opened. self.acceptOnce('window-event', self.__windowEvent) # Look for the startup Python file. This might 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 # Temporarily set this flag while we import the app, so # that if the app calls run() within its own main.py, it # will properly get ignored by ShowBase. self.initialAppImport = True # Python won't let us import a module named __main__. So, # we have to do that manually, via the VFSImporter. if moduleName == '__main__': dirName = Filename(self.multifileRoot).toOsSpecific() importer = VFSImporter.VFSImporter(dirName) loader = importer.find_module('__main__') if loader is None: raise ImportError('No module named __main__') mainModule = loader.load_module('__main__') else: __import__(moduleName) mainModule = sys.modules[moduleName] # Check if it has a main() function. If so, call it. if hasattr(mainModule, 'main') and hasattr(mainModule.main, '__call__'): mainModule.main(self) # Now clear this flag. self.initialAppImport = False if self.interactiveConsole: # At this point, we have successfully loaded the app. # If the interactive_console flag is enabled, stop the # main loop now and give the user a Python prompt. taskMgr.stop()
def initPackedAppEnvironment(self): """ This function sets up the Python environment suitably for running a packed app. It should only run once in any given session (and it includes logic to ensure this). """ if self.packedAppEnvironmentInitialized: return self.packedAppEnvironmentInitialized = True vfs = VirtualFileSystem.getGlobalPtr() # Now set up Python to import this stuff. VFSImporter.register() sys.path.append(self.multifileRoot) # Make sure that $MAIN_DIR is set to the p3d root before we # start executing the code in this file. ExecutionEnvironment.setEnvironmentVariable( "MAIN_DIR", Filename(self.multifileRoot).toOsSpecific()) # Put our root directory on the model-path, too. getModelPath().appendDirectory(self.multifileRoot) if not self.trueFileIO: # 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 __builtin__.execfile = file.execfile os.listdir = file.listdir os.walk = file.walk os.path.join = file.join os.path.isfile = file.isfile os.path.isdir = file.isdir os.path.exists = file.exists os.path.lexists = file.lexists os.path.getmtime = file.getmtime os.path.getsize = file.getsize sys.modules['glob'] = glob self.checkDiskUsage()
def initPackedAppEnvironment(self): """ This function sets up the Python environment suitably for running a packed app. It should only run once in any given session (and it includes logic to ensure this). """ if self.packedAppEnvironmentInitialized: return self.packedAppEnvironmentInitialized = True vfs = VirtualFileSystem.getGlobalPtr() # Now set up Python to import this stuff. VFSImporter.register() sys.path.append(self.multifileRoot) # Make sure that $MAIN_DIR is set to the p3d root before we # start executing the code in this file. ExecutionEnvironment.setEnvironmentVariable("MAIN_DIR", Filename(self.multifileRoot).toOsSpecific()) # Put our root directory on the model-path, too. getModelPath().appendDirectory(self.multifileRoot) if not self.trueFileIO: # 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 __builtin__.execfile = file.execfile os.listdir = file.listdir os.walk = file.walk os.path.join = file.join os.path.isfile = file.isfile os.path.isdir = file.isdir os.path.exists = file.exists os.path.lexists = file.lexists os.path.getmtime = file.getmtime os.path.getsize = file.getsize sys.modules['glob'] = glob self.checkDiskUsage()
def setP3DFilename(self, p3dFilename, tokens, argv, instanceId, interactiveConsole, p3dOffset=0, p3dUrl=None): """ Called by the browser to specify the p3d file that contains the application itself, along with the web tokens and/or command-line arguments. Once this method has been called, the application is effectively started. """ # One day we will have support for multiple instances within a # Python session. Against that day, we save the instance ID # for this instance. self.instanceId = instanceId self.tokens = tokens self.argv = argv # We build up a token dictionary with care, so that if a given # token appears twice in the token list, we record only the # first value, not the second or later. This is consistent # with the internal behavior of the core API. self.tokenDict = {} for token, keyword in tokens: self.tokenDict.setdefault(token, keyword) # Also store the arguments on sys, for applications that # aren't instance-ready. sys.argv = argv # That means we now know the altHost in effect. self.altHost = self.tokenDict.get('alt_host', None) # Tell the browser that Python is up and running, and ready to # respond to queries. self.notifyRequest('onpythonload') # Now go load the applet. fname = Filename.fromOsSpecific(p3dFilename) vfs = VirtualFileSystem.getGlobalPtr() if not vfs.exists(fname): raise ArgumentError, "No such file: %s" % (p3dFilename) fname.makeAbsolute() fname.setBinary() mf = Multifile() if p3dOffset == 0: if not mf.openRead(fname): raise ArgumentError, "Not a Panda3D application: %s" % ( p3dFilename) else: if not mf.openRead(fname, p3dOffset): raise ArgumentError, "Not a Panda3D application: %s at offset: %s" % ( p3dFilename, p3dOffset) # Now load the p3dInfo file. self.p3dInfo = None self.p3dPackage = None self.p3dConfig = None self.allowPythonDev = False i = mf.findSubfile('p3d_info.xml') if i >= 0 and hasattr(core, 'readXmlStream'): stream = mf.openReadSubfile(i) self.p3dInfo = core.readXmlStream(stream) mf.closeReadSubfile(stream) if self.p3dInfo: self.p3dPackage = self.p3dInfo.FirstChildElement('package') if self.p3dPackage: self.p3dConfig = self.p3dPackage.FirstChildElement('config') xhost = self.p3dPackage.FirstChildElement('host') while xhost: self.__readHostXml(xhost) xhost = xhost.NextSiblingElement('host') if self.p3dConfig: allowPythonDev = self.p3dConfig.Attribute('allow_python_dev') if allowPythonDev: self.allowPythonDev = int(allowPythonDev) guiApp = self.p3dConfig.Attribute('gui_app') if guiApp: self.guiApp = int(guiApp) trueFileIO = self.p3dConfig.Attribute('true_file_io') if trueFileIO: self.trueFileIO = int(trueFileIO) # The interactiveConsole flag can only be set true if the # application has allow_python_dev set. if not self.allowPythonDev and interactiveConsole: raise StandardError, "Impossible, interactive_console set without allow_python_dev." self.interactiveConsole = interactiveConsole if self.allowPythonDev: # Set the fps text to remind the user that # allow_python_dev is enabled. ConfigVariableString('frame-rate-meter-text-pattern').setValue( 'allow_python_dev %0.1f fps') if self.guiApp: init_app_for_gui() self.initPackedAppEnvironment() # Mount the Multifile under self.multifileRoot. vfs.mount(mf, self.multifileRoot, vfs.MFReadOnly) self.p3dMultifile = mf VFSImporter.reloadSharedPackages() self.loadMultifilePrcFiles(mf, self.multifileRoot) self.gotP3DFilename = True self.p3dFilename = fname if p3dUrl: # The url from which the p3d file was downloaded is # provided if available. It is only for documentation # purposes; the actual p3d file has already been # downloaded to p3dFilename. self.p3dUrl = core.URLSpec(p3dUrl) # Send this call to the main thread; don't call it directly. messenger.send('AppRunner_startIfReady', taskChain='default')
def setP3DFilename(self, p3dFilename, tokens, argv, instanceId, interactiveConsole, p3dOffset = 0): """ Called by the browser to specify the p3d file that contains the application itself, along with the web tokens and/or command-line arguments. Once this method has been called, the application is effectively started. """ # One day we will have support for multiple instances within a # Python session. Against that day, we save the instance ID # for this instance. self.instanceId = instanceId self.tokens = tokens self.argv = argv # We build up a token dictionary with care, so that if a given # token appears twice in the token list, we record only the # first value, not the second or later. This is consistent # with the internal behavior of the core API. self.tokenDict = {} for token, keyword in tokens: self.tokenDict.setdefault(token, keyword) # Also store the arguments on sys, for applications that # aren't instance-ready. sys.argv = argv # That means we now know the altHost in effect. self.altHost = self.tokenDict.get('alt_host', None) # Tell the browser that Python is up and running, and ready to # respond to queries. self.notifyRequest('onpythonload') # Now go load the applet. fname = Filename.fromOsSpecific(p3dFilename) vfs = VirtualFileSystem.getGlobalPtr() if not vfs.exists(fname): raise ArgumentError, "No such file: %s" % (p3dFilename) fname.makeAbsolute() mf = Multifile() if p3dOffset == 0: if not mf.openRead(fname): raise ArgumentError, "Not a Panda3D application: %s" % (p3dFilename) else: if not mf.openRead(fname, p3dOffset): raise ArgumentError, "Not a Panda3D application: %s at offset: %s" % (p3dFilename, p3dOffset) # Now load the p3dInfo file. self.p3dInfo = None self.p3dPackage = None self.p3dConfig = None self.allowPythonDev = False i = mf.findSubfile('p3d_info.xml') if i >= 0 and hasattr(PandaModules, 'readXmlStream'): stream = mf.openReadSubfile(i) self.p3dInfo = PandaModules.readXmlStream(stream) mf.closeReadSubfile(stream) if self.p3dInfo: self.p3dPackage = self.p3dInfo.FirstChildElement('package') if self.p3dPackage: self.p3dConfig = self.p3dPackage.FirstChildElement('config') xhost = self.p3dPackage.FirstChildElement('host') while xhost: self.__readHostXml(xhost) xhost = xhost.NextSiblingElement('host') if self.p3dConfig: allowPythonDev = self.p3dConfig.Attribute('allow_python_dev') if allowPythonDev: self.allowPythonDev = int(allowPythonDev) guiApp = self.p3dConfig.Attribute('gui_app') if guiApp: self.guiApp = int(guiApp) trueFileIO = self.p3dConfig.Attribute('true_file_io') if trueFileIO: self.trueFileIO = int(trueFileIO) # The interactiveConsole flag can only be set true if the # application has allow_python_dev set. if not self.allowPythonDev and interactiveConsole: raise StandardError, "Impossible, interactive_console set without allow_python_dev." self.interactiveConsole = interactiveConsole if self.allowPythonDev: # Set the fps text to remind the user that # allow_python_dev is enabled. ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps') if self.guiApp: initAppForGui() self.initPackedAppEnvironment() # Mount the Multifile under self.multifileRoot. vfs.mount(mf, self.multifileRoot, vfs.MFReadOnly) VFSImporter.reloadSharedPackages() self.loadMultifilePrcFiles(mf, self.multifileRoot) self.gotP3DFilename = True # Send this call to the main thread; don't call it directly. messenger.send('AppRunner_startIfReady', taskChain = 'default')