def getExtraFiles(self, platform): """ Returns a list of extra files that will need to be included with the standalone executable in order for it to run, such as dependent libraries. The returned paths are full absolute paths. """ package = self.host.getPackages(name="p3dembed", platform=platform)[0] if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] filenames = [] vfs = VirtualFileSystem.getGlobalPtr() for e in package.extracts: if e.basename not in [ "p3dembed", "p3dembed.exe", "p3dembed.exe.manifest", "p3dembedw.exe", "p3dembedw.exe.manifest", ]: filename = Filename(package.getPackageDir(), e.filename) filename.makeAbsolute() if vfs.exists(filename): filenames.append(filename) else: Standalone.notify.error("%s mentioned in xml, but does not exist" % e.filename) return filenames
def getExtraFiles(self, platform): """ Returns a list of extra files that will need to be included with the standalone executable in order for it to run, such as dependent libraries. The returned paths are full absolute paths. """ package = self.host.getPackages(name="p3dembed", platform=platform)[0] if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] filenames = [] vfs = VirtualFileSystem.getGlobalPtr() for e in package.extracts: if e.basename not in [ "p3dembed", "p3dembed.exe", "p3dembed.exe.manifest", "p3dembedw.exe", "p3dembedw.exe.manifest" ]: filename = Filename(package.getPackageDir(), e.filename) filename.makeAbsolute() if vfs.exists(filename): filenames.append(filename) else: Standalone.notify.error( "%s mentioned in xml, but does not exist" % e.filename) return filenames
def dummyAppRunner(tokens=[], argv=None): """ This function creates a dummy global AppRunner object, which is useful for testing running in a packaged environment without actually bothering to package up the application. Call this at the start of your application to enable it. It places the current working directory under /mf, as if it were mounted from a packed multifile. It doesn't convert egg files to bam files, of course; and there are other minor differences from running in an actual packaged environment. But it can be a useful first-look sanity check. """ if AppRunnerGlobal.appRunner: print "Already have AppRunner, not creating a new one." return AppRunnerGlobal.appRunner appRunner = AppRunner() appRunner.dummy = True AppRunnerGlobal.appRunner = appRunner platform = PandaSystem.getPlatform() version = PandaSystem.getPackageVersionString() hostUrl = PandaSystem.getPackageHostUrl() if platform.startswith('win'): rootDir = Filename(Filename.getUserAppdataDirectory(), 'Panda3D') elif platform.startswith('osx'): rootDir = Filename(Filename.getHomeDirectory(), 'Library/Caches/Panda3D') else: rootDir = Filename(Filename.getHomeDirectory(), '.panda3d') appRunner.rootDir = rootDir appRunner.logDirectory = Filename(rootDir, 'log') # Of course we will have the panda3d application loaded. appRunner.addPackageInfo('panda3d', platform, version, hostUrl) appRunner.tokens = tokens appRunner.tokenDict = dict(tokens) if argv is None: argv = sys.argv appRunner.argv = argv appRunner.altHost = appRunner.tokenDict.get('alt_host', None) appRunner.p3dInfo = None appRunner.p3dPackage = None # Mount the current directory under the multifileRoot, as if it # were coming from a multifile. cwd = ExecutionEnvironment.getCwd() vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(cwd, appRunner.multifileRoot, vfs.MFReadOnly) appRunner.initPackedAppEnvironment() return appRunner
def dummyAppRunner(tokens = [], argv = None): """ This function creates a dummy global AppRunner object, which is useful for testing running in a packaged environment without actually bothering to package up the application. Call this at the start of your application to enable it. It places the current working directory under /mf, as if it were mounted from a packed multifile. It doesn't convert egg files to bam files, of course; and there are other minor differences from running in an actual packaged environment. But it can be a useful first-look sanity check. """ if AppRunnerGlobal.appRunner: print "Already have AppRunner, not creating a new one." return AppRunnerGlobal.appRunner appRunner = AppRunner() appRunner.dummy = True AppRunnerGlobal.appRunner = appRunner platform = PandaSystem.getPlatform() version = PandaSystem.getPackageVersionString() hostUrl = PandaSystem.getPackageHostUrl() if platform.startswith('win'): rootDir = Filename(Filename.getUserAppdataDirectory(), 'Panda3D') elif platform.startswith('osx'): rootDir = Filename(Filename.getHomeDirectory(), 'Library/Caches/Panda3D') else: rootDir = Filename(Filename.getHomeDirectory(), '.panda3d') appRunner.rootDir = rootDir appRunner.logDirectory = Filename(rootDir, 'log') # Of course we will have the panda3d application loaded. appRunner.addPackageInfo('panda3d', platform, version, hostUrl) appRunner.tokens = tokens appRunner.tokenDict = dict(tokens) if argv is None: argv = sys.argv appRunner.argv = argv appRunner.altHost = appRunner.tokenDict.get('alt_host', None) appRunner.p3dInfo = None appRunner.p3dPackage = None # Mount the current directory under the multifileRoot, as if it # were coming from a multifile. cwd = ExecutionEnvironment.getCwd() vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(cwd, appRunner.multifileRoot, vfs.MFReadOnly) appRunner.initPackedAppEnvironment() return appRunner
def getResourceAsString(self, filename, fullPath = False): """ Returns a string that represents the file's contents. @param filename: The resource filename. @param fullPath: Specifies if the filename parameter denotes a full path or a base filename. """ vfs = VirtualFileSystem.getGlobalPtr() fs = vfs.readFile(Filename(filename), False) if fs is not None: return codecs.decode(fs, "utf-8")
def getResourceAsByteArray(self, filename, fullPath = False): """ Returns an array of bytes that represent the file's contents. It performs the same functionality with getResourceAsString since the str type is used to store byte arrays but it won't decode the string since it doesn't make sense for binary data. @param filename: The resource filename. @param fullPath: Specifies if the filename parameter denotes a full path or a base filename. """ vfs = VirtualFileSystem.getGlobalPtr() return vfs.readFile(Filename(filename))
def getResourceFullPath(self, filename): vfs = VirtualFileSystem.getGlobalPtr() resFile = Filename(filename) if vfs.exists(resFile): searchPath = DSearchPath() searchPath.appendDirectory(self.mountPoint) # if the filename was resolved, resFile is updated to include the full path if vfs.resolveFilename(resFile, searchPath): return resFile.getFullpath()
def build(self, output, platform=None, extraTokens={}): """ Builds a standalone executable and stores it into the path indicated by the 'output' argument. You can specify to build for a different platform by altering the 'platform' argument. """ if platform == None: platform = PandaSystem.getPlatform() vfs = VirtualFileSystem.getGlobalPtr() for package in self.host.getPackages(name="p3dembed", platform=platform): if not package.downloadDescFile(self.http): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue # Figure out where p3dembed might be now. if package.platform.startswith("win"): # Use p3dembedw unless console_environment was set. if extraTokens.get("console_environment", self.tokens.get("console_environment", 0)) != 0: p3dembed = Filename( self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename( self.host.hostDir, "p3dembed/%s/p3dembedw.exe" % package.platform) # Fallback for older p3dembed versions if not vfs.exists(p3dembed): Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed" % package.platform) if not vfs.exists(p3dembed): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue return self.embed(output, p3dembed, extraTokens) Standalone.notify.error("Failed to build standalone for platform %s" % platform)
def readFavIcon(self): vfs = VirtualFileSystem.getGlobalPtr() filename = Filename('favicon.ico') searchPath = DSearchPath() searchPath.appendDirectory(Filename('.')) searchPath.appendDirectory(Filename('etc')) searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('$DIRECT/src/http'))) searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('direct/src/http'))) searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('direct/http'))) found = vfs.resolveFilename(filename,searchPath) if not found: raise "Couldn't find direct/http/favicon.ico" return vfs.readFile(filename, 1)
def embed(self, output, p3dembed, extraTokens={}): """ Embeds the p3d file into the provided p3dembed executable. This function is not really useful - use build() or buildAll() instead. """ # Load the p3dembed data into memory size = p3dembed.getFileSize() p3dembed_data = VirtualFileSystem.getGlobalPtr().readFile( p3dembed, True) assert len(p3dembed_data) == size # Find the magic size string and replace it with the real size, # regardless of the endianness of the p3dembed executable. hex_size = hex(size)[2:].rjust(8, "0") enc_size = "".join([ chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2) ]) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1]) # Write the output file Standalone.notify.info("Creating %s..." % output) output.makeDir() ohandle = open(output.toOsSpecific(), "wb") ohandle.write(p3dembed_data) # Write out the tokens. Set log_basename to the basename by default tokens = {"log_basename": self.basename} tokens.update(self.tokens) tokens.update(extraTokens) for token in tokens.items(): ohandle.write("\0%s=%s" % token) ohandle.write("\0\0") # Buffer the p3d file to the output file. 1 MB buffer size. phandle = open(self.p3dfile.toOsSpecific(), "rb") buf = phandle.read(1024 * 1024) while len(buf) != 0: ohandle.write(buf) buf = phandle.read(1024 * 1024) ohandle.close() phandle.close() os.chmod(output.toOsSpecific(), 0755)
def readFavIcon(self): vfs = VirtualFileSystem.getGlobalPtr() filename = Filename('favicon.ico') searchPath = DSearchPath() searchPath.appendDirectory(Filename('.')) searchPath.appendDirectory(Filename('etc')) searchPath.appendDirectory( Filename.fromOsSpecific(os.path.expandvars('$DIRECT/src/http'))) searchPath.appendDirectory( Filename.fromOsSpecific(os.path.expandvars('direct/src/http'))) searchPath.appendDirectory( Filename.fromOsSpecific(os.path.expandvars('direct/http'))) found = vfs.resolveFilename(filename, searchPath) if not found: raise "Couldn't find direct/http/favicon.ico" return vfs.readFile(filename, 1)
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 _initFromFilename(self, filepath, filename): vfs = VirtualFileSystem.getGlobalPtr() filename = Filename(filename) searchPath = DSearchPath() #searchPath.appendDirectory(Filename('.')) #searchPath.appendDirectory(Filename('etc')) #searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('~'))) #searchPath.appendDirectory(Filename.fromOsSpecific(os.path.expandvars('$HOME'))) searchPath.appendDirectory( Filename.fromOsSpecific(os.path.expandvars(filepath))) found = vfs.resolveFilename(filename, searchPath) if not found: raise IOError, "File not found!" str = vfs.readFile(filename, 1) self._initFromString(str)
def fromFile(self, packageDir, filename, pathname=None, st=None): """ Reads the file information from the indicated file. If st is supplied, it is the result of os.stat on the filename. """ vfs = VirtualFileSystem.getGlobalPtr() filename = Filename(filename) if pathname is None: pathname = Filename(packageDir, filename) self.filename = filename.cStr() self.basename = filename.getBasename() if st is None: st = os.stat(pathname.toOsSpecific()) self.size = st.st_size self.timestamp = st.st_mtime self.readHash(pathname)
def fromFile(self, packageDir, filename, pathname = None, st = None): """ Reads the file information from the indicated file. If st is supplied, it is the result of os.stat on the filename. """ vfs = VirtualFileSystem.getGlobalPtr() filename = Filename(filename) if pathname is None: pathname = Filename(packageDir, filename) self.filename = filename.cStr() self.basename = filename.getBasename() if st is None: st = os.stat(pathname.toOsSpecific()) self.size = st.st_size self.timestamp = st.st_mtime self.readHash(pathname)
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 embed(self, output, p3dembed, extraTokens={}): """ Embeds the p3d file into the provided p3dembed executable. This function is not really useful - use build() or buildAll() instead. """ # Load the p3dembed data into memory size = p3dembed.getFileSize() p3dembed_data = VirtualFileSystem.getGlobalPtr().readFile(p3dembed, True) assert len(p3dembed_data) == size # Find the magic size string and replace it with the real size, # regardless of the endianness of the p3dembed executable. hex_size = hex(size)[2:].rjust(8, "0") enc_size = "".join([chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2)]) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1]) # Write the output file Standalone.notify.info("Creating %s..." % output) output.makeDir() ohandle = open(output.toOsSpecific(), "wb") ohandle.write(p3dembed_data) # Write out the tokens. Set log_basename to the basename by default tokens = {"log_basename": self.basename} tokens.update(self.tokens) tokens.update(extraTokens) for token in tokens.items(): ohandle.write("\0%s=%s" % token) ohandle.write("\0\0") # Buffer the p3d file to the output file. 1 MB buffer size. phandle = open(self.p3dfile.toOsSpecific(), "rb") buf = phandle.read(1024 * 1024) while len(buf) != 0: ohandle.write(buf) buf = phandle.read(1024 * 1024) ohandle.close() phandle.close() os.chmod(output.toOsSpecific(), 0755)
def _listResourcesImpl(self, parent, resType, fullPaths = True): resFiles = [] directories = [] vfs = VirtualFileSystem.getGlobalPtr() filesList = vfs.scanDirectory(parent) if filesList is None: return directories for i in xrange(filesList.getNumFiles()): fileEntry = filesList.getFile(i) if fileEntry.isDirectory(): directories.append(fileEntry.getFilename()) continue if ResourcesTypes.isExtensionOfType(fileEntry.getFilename().getExtension(), resType): resFiles.append(fileEntry.getFilename().getFullpath() if fullPaths else fileEntry.getFilename().getBasename()) for dir in directories: resFiles.extend(self._listResourcesImpl(dir, resType, fullPaths)) return resFiles
def build(self, output, platform=None, extraTokens={}): """ Builds a standalone executable and stores it into the path indicated by the 'output' argument. You can specify to build for a different platform by altering the 'platform' argument. """ if platform == None: platform = PandaSystem.getPlatform() vfs = VirtualFileSystem.getGlobalPtr() for package in self.host.getPackages(name="p3dembed", platform=platform): if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue # Figure out where p3dembed might be now. if package.platform.startswith("win"): # Use p3dembedw unless console_environment was set. if extraTokens.get("console_environment", self.tokens.get("console_environment", 0)) != 0: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembedw.exe" % package.platform) # Fallback for older p3dembed versions if not vfs.exists(p3dembed): Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed" % package.platform) if not vfs.exists(p3dembed): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue return self.embed(output, p3dembed, extraTokens) Standalone.notify.error("Failed to build standalone for platform %s" % platform)
def listResources(self, resType, fullPaths=True): ''' Returns a list of all resource filenames, of the given type, which are contained in this multifile. ''' vfs = VirtualFileSystem.getGlobalPtr() return self._listResourcesImpl(Filename(self.mountPoint), resType, fullPaths)
def installPackage(self, appRunner): """ Mounts the package and sets up system paths so it becomes available for use. Returns true on success, false on failure. """ assert self.hasPackage if self.installed: # Already installed. return True assert self not in appRunner.installedPackages mfPathname = Filename(self.getPackageDir(), self.uncompressedArchive.filename) mf = Multifile() if not mf.openRead(mfPathname): self.notify.warning("Couldn't open %s" % (mfPathname)) return False # We mount it under its actual location on disk. root = self.getPackageDir().cStr() vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(mf, root, vfs.MFReadOnly) # Add this to the Python search path, if it's not already # there. We have to take a bit of care to check if it's # already there, since there can be some ambiguity in # os-specific path strings. osRoot = self.getPackageDir().toOsSpecific() foundOnPath = False for p in sys.path: if osRoot == p: # Already here, exactly. foundOnPath = True break elif osRoot == Filename.fromOsSpecific(p).toOsSpecific(): # Already here, with some futzing. foundOnPath = True break if not foundOnPath: # Not already here; add it. sys.path.append(osRoot) # Put it on the model-path, too. We do this indiscriminantly, # because the Panda3D runtime won't be adding things to the # model-path, so it shouldn't be already there. getModelPath().appendDirectory(self.getPackageDir()) # Set the environment variable to reference the package root. envvar = '%s_ROOT' % (self.packageName.upper()) ExecutionEnvironment.setEnvironmentVariable(envvar, osRoot) # Add the package root to the system paths. if sys.platform.startswith('win'): path = os.environ.get('PATH', '') os.environ['PATH'] = "%s;%s" % (osRoot, path) else: path = os.environ.get('PATH', '') os.environ['PATH'] = "%s:%s" % (osRoot, path) path = os.environ.get('LD_LIBRARY_PATH', '') os.environ['LD_LIBRARY_PATH'] = "%s:%s" % (osRoot, path) if sys.platform == "darwin": path = os.environ.get('DYLD_LIBRARY_PATH', '') os.environ['DYLD_LIBRARY_PATH'] = "%s:%s" % (osRoot, path) # Now that the environment variable is set, read all of the # prc files in the package. appRunner.loadMultifilePrcFiles(mf, self.getPackageDir()) # Also, find any toplevel Python packages, and add these as # shared packages. This will allow different packages # installed in different directories to share Python files as # if they were all in the same directory. for filename in mf.getSubfileNames(): if filename.endswith('/__init__.pyc') or \ filename.endswith('/__init__.pyo') or \ filename.endswith('/__init__.py'): components = filename.split('/')[:-1] moduleName = '.'.join(components) VFSImporter.sharedPackages[moduleName] = True # Fix up any shared directories so we can load packages from # disparate locations. VFSImporter.reloadSharedPackages() self.installed = True appRunner.installedPackages.append(self) self.markUsed() return True
def installPackage(self, appRunner): """ Mounts the package and sets up system paths so it becomes available for use. Returns true on success, false on failure. """ assert self.hasPackage if self.installed: # Already installed. return True assert self not in appRunner.installedPackages mfPathname = Filename(self.getPackageDir(), self.uncompressedArchive.filename) mf = Multifile() if not mf.openRead(mfPathname): self.notify.warning("Couldn't open %s" % (mfPathname)) return False # We mount it under its actual location on disk. root = self.getPackageDir().cStr() vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(mf, root, vfs.MFReadOnly) # Add this to the Python search path, if it's not already # there. We have to take a bit of care to check if it's # already there, since there can be some ambiguity in # os-specific path strings. osRoot = self.getPackageDir().toOsSpecific() foundOnPath = False for p in sys.path: if osRoot == p: # Already here, exactly. foundOnPath = True break elif osRoot == Filename.fromOsSpecific(p).toOsSpecific(): # Already here, with some futzing. foundOnPath = True break if not foundOnPath: # Not already here; add it. sys.path.append(osRoot) # Put it on the model-path, too. We do this indiscriminantly, # because the Panda3D runtime won't be adding things to the # model-path, so it shouldn't be already there. getModelPath().appendDirectory(self.getPackageDir()) # Set the environment variable to reference the package root. envvar = '%s_ROOT' % (self.packageName.upper()) ExecutionEnvironment.setEnvironmentVariable(envvar, osRoot) # Now that the environment variable is set, read all of the # prc files in the package. appRunner.loadMultifilePrcFiles(mf, self.getPackageDir()) # Also, find any toplevel Python packages, and add these as # shared packages. This will allow different packages # installed in different directories to share Python files as # if they were all in the same directory. for filename in mf.getSubfileNames(): if filename.endswith('/__init__.pyc') or \ filename.endswith('/__init__.pyo') or \ filename.endswith('/__init__.py'): components = filename.split('/')[:-1] moduleName = '.'.join(components) VFSImporter.sharedPackages[moduleName] = True # Fix up any shared directories so we can load packages from # disparate locations. VFSImporter.reloadSharedPackages() self.installed = True appRunner.installedPackages.append(self) self.markUsed() return True
def containsResource(self, filename): vfs = VirtualFileSystem.getGlobalPtr() vfs.chdir(self.mountPoint) flag = vfs.exists(Filename(filename)) vfs.chdir(self.mountPoint) return flag
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')
def installPackagesInto(self, hostDir, platform): """ Installs the packages required by the .p3d file into the specified directory, for the given platform. """ if not self.includeRequires: return pkgTree = PackageTree(platform, hostDir, self.hostUrl) pkgTree.installPackage("images", None, self.standalone.host.hostUrl) for name, version, hostUrl in self.requires: pkgTree.installPackage(name, version, hostUrl) # Remove the extracted files from the compressed archive, to save space. vfs = VirtualFileSystem.getGlobalPtr() for package in pkgTree.packages.values(): if package.uncompressedArchive: archive = Filename(package.getPackageDir(), package.uncompressedArchive.filename) if not archive.exists(): continue mf = Multifile() # Make sure that it isn't mounted before altering it, just to be safe vfs.unmount(archive) os.chmod(archive.toOsSpecific(), 0644) if not mf.openReadWrite(archive): Installer.notify.warning("Failed to open archive %s" % (archive)) continue # We don't iterate over getNumSubfiles because we're # removing subfiles while we're iterating over them. subfiles = mf.getSubfileNames() for subfile in subfiles: # We do *NOT* call vfs.exists here in case the package is mounted. if Filename(package.getPackageDir(), subfile).exists(): Installer.notify.debug("Removing already-extracted %s from multifile" % (subfile)) mf.removeSubfile(subfile) # This seems essential for mf.close() not to crash later. mf.repack() # If we have no subfiles left, we can just remove the multifile. # if mf.getNumSubfiles() == 0: # Installer.notify.info("Removing empty archive %s" % (package.uncompressedArchive.filename)) # mf.close() # archive.unlink() # else: mf.close() try: os.chmod(archive.toOsSpecific(), 0444) except: pass # Write out our own contents.xml file. doc = TiXmlDocument() decl = TiXmlDeclaration("1.0", "utf-8", "") doc.InsertEndChild(decl) xcontents = TiXmlElement("contents") for package in pkgTree.packages.values(): xpackage = TiXmlElement("package") xpackage.SetAttribute("name", package.packageName) if package.platform: xpackage.SetAttribute("platform", package.platform) assert package.platform == platform if package.packageVersion: xpackage.SetAttribute("version", version) xpackage.SetAttribute( "filename", package.packageName + "/" + package.packageVersion + "/" + package.descFileBasename ) else: xpackage.SetAttribute("filename", package.packageName + "/" + package.descFileBasename) xcontents.InsertEndChild(xpackage) doc.InsertEndChild(xcontents) doc.SaveFile(Filename(hostDir, "contents.xml").toOsSpecific())
def dispose(self): vfs = VirtualFileSystem.getGlobalPtr() vfs.unmountPoint(Filename(self.mountPoint))
from pandac.PandaModules import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument vfs = VirtualFileSystem.getGlobalPtr() class ScanDirectoryNode: """ This class is used to scan a list of files on disk. """ def __init__(self, pathname, ignoreUsageXml=False): self.pathname = pathname self.filenames = [] self.fileSize = 0 self.nested = [] self.nestedSize = 0 xusage = None if not ignoreUsageXml: # Look for a usage.xml file in this directory. If we find # one, we read it for the file size and then stop here, as # an optimization. usageFilename = Filename(pathname, 'usage.xml') doc = TiXmlDocument(usageFilename.toOsSpecific()) if doc.LoadFile(): xusage = doc.FirstChildElement('usage') if xusage: diskSpace = xusage.Attribute('disk_space') try: diskSpace = int(diskSpace or '') except ValueError: diskSpace = None if diskSpace is not None: self.fileSize = diskSpace
def indexResources(self): vfs = VirtualFileSystem.getGlobalPtr() vfs.mount(Filename(self.filename), self.mountPoint, VirtualFileSystem.MFReadOnly)
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')
def installPackagesInto(self, hostDir, platform): """ Installs the packages required by the .p3d file into the specified directory, for the given platform. """ if not self.includeRequires: return pkgTree = PackageTree(platform, hostDir, self.hostUrl) pkgTree.installPackage("images", None, self.standalone.host.hostUrl) for name, version, hostUrl in self.requires: pkgTree.installPackage(name, version, hostUrl) # Remove the extracted files from the compressed archive, to save space. vfs = VirtualFileSystem.getGlobalPtr() for package in pkgTree.packages.values(): if package.uncompressedArchive: archive = Filename(package.getPackageDir(), package.uncompressedArchive.filename) if not archive.exists(): continue mf = Multifile() # Make sure that it isn't mounted before altering it, just to be safe vfs.unmount(archive) os.chmod(archive.toOsSpecific(), 0644) if not mf.openReadWrite(archive): Installer.notify.warning("Failed to open archive %s" % (archive)) continue # We don't iterate over getNumSubfiles because we're # removing subfiles while we're iterating over them. subfiles = mf.getSubfileNames() for subfile in subfiles: # We do *NOT* call vfs.exists here in case the package is mounted. if Filename(package.getPackageDir(), subfile).exists(): Installer.notify.debug( "Removing already-extracted %s from multifile" % (subfile)) mf.removeSubfile(subfile) # This seems essential for mf.close() not to crash later. mf.repack() # If we have no subfiles left, we can just remove the multifile. #if mf.getNumSubfiles() == 0: # Installer.notify.info("Removing empty archive %s" % (package.uncompressedArchive.filename)) # mf.close() # archive.unlink() #else: mf.close() try: os.chmod(archive.toOsSpecific(), 0444) except: pass # Write out our own contents.xml file. doc = TiXmlDocument() decl = TiXmlDeclaration("1.0", "utf-8", "") doc.InsertEndChild(decl) xcontents = TiXmlElement("contents") for package in pkgTree.packages.values(): xpackage = TiXmlElement('package') xpackage.SetAttribute('name', package.packageName) if package.platform: xpackage.SetAttribute('platform', package.platform) assert package.platform == platform if package.packageVersion: xpackage.SetAttribute('version', version) xpackage.SetAttribute( 'filename', package.packageName + "/" + package.packageVersion + "/" + package.descFileBasename) else: xpackage.SetAttribute( 'filename', package.packageName + "/" + package.descFileBasename) xcontents.InsertEndChild(xpackage) doc.InsertEndChild(xcontents) doc.SaveFile(Filename(hostDir, "contents.xml").toOsSpecific())
from pandac.PandaModules import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument vfs = VirtualFileSystem.getGlobalPtr() class ScanDirectoryNode: """ This class is used to scan a list of files on disk. """ def __init__(self, pathname, ignoreUsageXml = False): self.pathname = pathname self.filenames = [] self.fileSize = 0 self.nested = [] self.nestedSize = 0 xusage = None if not ignoreUsageXml: # Look for a usage.xml file in this directory. If we find # one, we read it for the file size and then stop here, as # an optimization. usageFilename = Filename(pathname, 'usage.xml') doc = TiXmlDocument(usageFilename.toOsSpecific()) if doc.LoadFile(): xusage = doc.FirstChildElement('usage') if xusage: diskSpace = xusage.Attribute('disk_space') try: diskSpace = int(diskSpace or '') except ValueError: diskSpace = None if diskSpace is not None: self.fileSize = diskSpace return
def runPackedApp(args): if not args: raise ArgumentError, "No Panda app specified. Use:\npython RunAppMF.py app.mf" vfs = VirtualFileSystem.getGlobalPtr() fname = Filename.fromOsSpecific(args[0]) if not vfs.exists(fname): raise ArgumentError, "No such file: %s" % (args[0]) mf = Multifile() if not mf.openRead(fname): raise ArgumentError, "Not a Panda Multifile: %s" % (args[0]) # Clear *all* the mount points, including "/", so that we no # longer access the disk directly. vfs.unmountAll() # Mount the Multifile under /mf, by convention, and make that our # "current directory". vfs.mount(mf, MultifileRoot, vfs.MFReadOnly) vfs.chdir(MultifileRoot) # 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) # 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) # Now set up Python to import this stuff. VFSImporter.register() sys.path = [MultifileRoot] + sys.path # Put our root directory on the model-path and prc-path, too. getModelPath().prependDirectory(MultifileRoot) # Load the implicit App.prc file. loadPrcFileData(AppPrcFilename, AppPrc) # Load any prc files in the root. We have to load them # explicitly, since the ConfigPageManager can't directly look # inside the vfs. for f in vfs.scanDirectory(MultifileRoot): if f.getFilename().getExtension() == 'prc': data = f.readFile(True) loadPrcFileData(f.getFilename().cStr(), data) # 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()
def getResourceStream(self, name): vfs = VirtualFileSystem.getGlobalPtr() istream = vfs.openReadFile(Filename(name)) return istream