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 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 __unpackArchive(self, step): """ Unpacks any files in the archive that want to be unpacked to disk. Yields one of stepComplete, stepFailed, restartDownload, or stepContinue. """ if not self.extracts: # Nothing to extract. self.hasPackage = True yield self.stepComplete return if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: # We're not allowed to! yield self.stepFailed return self.updated = True mfPathname = Filename(self.getPackageDir(), self.uncompressedArchive.filename) self.notify.info("Unpacking %s" % (mfPathname)) mf = Multifile() if not mf.openRead(mfPathname): self.notify.warning("Couldn't open %s" % (mfPathname)) yield self.stepFailed return allExtractsOk = True step.bytesDone = 0 for file in self.extracts: i = mf.findSubfile(file.filename) if i == -1: self.notify.warning("Not in Multifile: %s" % (file.filename)) allExtractsOk = False continue targetPathname = Filename(self.getPackageDir(), file.filename) targetPathname.setBinary() targetPathname.unlink() if not mf.extractSubfile(i, targetPathname): self.notify.warning("Couldn't extract: %s" % (file.filename)) allExtractsOk = False continue if not file.quickVerify(self.getPackageDir(), notify=self.notify): self.notify.warning("After extracting, still incorrect: %s" % (file.filename)) allExtractsOk = False continue # Make sure it's executable, and not writable. os.chmod(targetPathname.toOsSpecific(), 0555) step.bytesDone += file.size self.__updateStepProgress(step) if taskMgr.destroyed: # If the task manager has been destroyed, we must # be shutting down. Get out of here. self.notify.warning( "Task Manager destroyed, aborting unpacking %s" % (mfPathname)) yield self.stepFailed return yield self.stepContinue if not allExtractsOk: yield self.stepFailed return self.hasPackage = True yield self.stepComplete return
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 __unpackArchive(self, step): """ Unpacks any files in the archive that want to be unpacked to disk. Yields one of stepComplete, stepFailed, restartDownload, or stepContinue. """ if not self.extracts: # Nothing to extract. self.hasPackage = True yield self.stepComplete; return if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever: # We're not allowed to! yield self.stepFailed; return self.updated = True mfPathname = Filename(self.getPackageDir(), self.uncompressedArchive.filename) self.notify.info("Unpacking %s" % (mfPathname)) mf = Multifile() if not mf.openRead(mfPathname): self.notify.warning("Couldn't open %s" % (mfPathname)) yield self.stepFailed; return allExtractsOk = True step.bytesDone = 0 for file in self.extracts: i = mf.findSubfile(file.filename) if i == -1: self.notify.warning("Not in Multifile: %s" % (file.filename)) allExtractsOk = False continue targetPathname = Filename(self.getPackageDir(), file.filename) targetPathname.unlink() if not mf.extractSubfile(i, targetPathname): self.notify.warning("Couldn't extract: %s" % (file.filename)) allExtractsOk = False continue if not file.quickVerify(self.getPackageDir(), notify = self.notify): self.notify.warning("After extracting, still incorrect: %s" % (file.filename)) allExtractsOk = False continue # Make sure it's executable, and not writable. os.chmod(targetPathname.toOsSpecific(), 0555) step.bytesDone += file.size self.__updateStepProgress(step) if taskMgr.destroyed: # If the task manager has been destroyed, we must # be shutting down. Get out of here. self.notify.warning("Task Manager destroyed, aborting unpacking %s" % (mfPathname)) yield self.stepFailed; return yield self.stepContinue if not allExtractsOk: yield self.stepFailed; return self.hasPackage = True yield self.stepComplete; return
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 __init__(self, p3dfile, shortname, fullname, version, tokens={}): if not shortname: shortname = p3dfile.getBasenameWoExtension() self.shortname = shortname self.fullname = fullname self.version = str(version) self.includeRequires = False self.licensename = "" self.licensefile = Filename() self.authorid = "org.panda3d" self.authorname = os.environ.get("DEBFULLNAME", "") self.authoremail = os.environ.get("DEBEMAIL", "") # Try to determine a default author name ourselves. uname = None if pwd is not None and hasattr(os, "getuid"): uinfo = pwd.getpwuid(os.getuid()) if uinfo: uname = uinfo.pw_name if not self.authorname: self.authorname = uinfo.pw_gecos.split(",", 1)[0] # Fallbacks in case that didn't work or wasn't supported. if not uname: uname = getpass.getuser() if not self.authorname: self.authorname = uname if not self.authoremail and " " not in uname: self.authoremail = "%s@%s" % (uname, socket.gethostname()) self.standalone = Standalone(p3dfile, tokens) self.tempDir = Filename.temporary("", self.shortname, "") + "/" self.tempDir.makeDir() self.__linuxRoot = None # Load the p3d file to read out the required packages mf = Multifile() if not mf.openRead(p3dfile): Installer.notify.error("Not a Panda3D application: %s" % (p3dFilename)) return # Now load the p3dInfo file. self.hostUrl = PandaSystem.getPackageHostUrl() if not self.hostUrl: self.hostUrl = self.standalone.host.hostUrl self.requires = [] i = mf.findSubfile("p3d_info.xml") if i >= 0: stream = mf.openReadSubfile(i) p3dInfo = readXmlStream(stream) mf.closeReadSubfile(stream) if p3dInfo: p3dPackage = p3dInfo.FirstChildElement("package") p3dHost = p3dPackage.FirstChildElement("host") if p3dHost.Attribute("url"): self.hostUrl = p3dHost.Attribute("url") p3dRequires = p3dPackage.FirstChildElement("requires") while p3dRequires: self.requires.append( (p3dRequires.Attribute("name"), p3dRequires.Attribute("version"), p3dRequires.Attribute("host")) ) p3dRequires = p3dRequires.NextSiblingElement("requires") if not self.fullname: p3dConfig = p3dPackage.FirstChildElement("config") if p3dConfig: self.fullname = p3dConfig.Attribute("display_name") if not self.fullname: self.fullname = self.shortname
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 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 __init__(self, p3dfile, shortname, fullname, version, tokens={}): if not shortname: shortname = p3dfile.getBasenameWoExtension() self.shortname = shortname self.fullname = fullname self.version = str(version) self.includeRequires = False self.licensename = "" self.licensefile = Filename() self.authorid = "org.panda3d" self.authorname = os.environ.get("DEBFULLNAME", "") self.authoremail = os.environ.get("DEBEMAIL", "") # Try to determine a default author name ourselves. uname = None if pwd is not None and hasattr(os, 'getuid'): uinfo = pwd.getpwuid(os.getuid()) if uinfo: uname = uinfo.pw_name if not self.authorname: self.authorname = \ uinfo.pw_gecos.split(',', 1)[0] # Fallbacks in case that didn't work or wasn't supported. if not uname: uname = getpass.getuser() if not self.authorname: self.authorname = uname if not self.authoremail and ' ' not in uname: self.authoremail = "%s@%s" % (uname, socket.gethostname()) self.standalone = Standalone(p3dfile, tokens) self.tempDir = Filename.temporary("", self.shortname, "") + "/" self.tempDir.makeDir() self.__linuxRoot = None # Load the p3d file to read out the required packages mf = Multifile() if not mf.openRead(p3dfile): Installer.notify.error("Not a Panda3D application: %s" % (p3dFilename)) return # Now load the p3dInfo file. self.hostUrl = PandaSystem.getPackageHostUrl() if not self.hostUrl: self.hostUrl = self.standalone.host.hostUrl self.requires = [] i = mf.findSubfile('p3d_info.xml') if i >= 0: stream = mf.openReadSubfile(i) p3dInfo = readXmlStream(stream) mf.closeReadSubfile(stream) if p3dInfo: p3dPackage = p3dInfo.FirstChildElement('package') p3dHost = p3dPackage.FirstChildElement('host') if p3dHost.Attribute('url'): self.hostUrl = p3dHost.Attribute('url') p3dRequires = p3dPackage.FirstChildElement('requires') while p3dRequires: self.requires.append((p3dRequires.Attribute('name'), p3dRequires.Attribute('version'), p3dRequires.Attribute('host'))) p3dRequires = p3dRequires.NextSiblingElement('requires') if not self.fullname: p3dConfig = p3dPackage.FirstChildElement('config') if p3dConfig: self.fullname = p3dConfig.Attribute('display_name') if not self.fullname: self.fullname = self.shortname