def __getFolderResources(self): self._editionFolder = str(Path(self._iDeviceDir).basename() + '/edition/') self._exportFolder = str(Path(self._iDeviceDir).basename() + '/export/') for editionFile in os.listdir(self._iDeviceDir + '/edition'): self._editionResources.append(editionFile) for exportFile in os.listdir(self._iDeviceDir + '/export'): self._exportResources.append(exportFile)
def _overrideDefaultVals(self): """Sets the default values for windows""" exeDir = self.exePath.dirname() self.browserPath = exeDir/'Mozilla Firefox'/'firefox.exe' if not self.browserPath.isfile(): programFiles = Path(self.__getWinFolder(PROGRAMFILES)) self.browserPath = programFiles/'Mozilla Firefox'/'firefox.exe' self.dataDir = Path(self.__getWinFolder(MYDOCUMENTS)) self.configDir = Path(self.__getWinFolder(APPDATA))/'exe'
def _overrideDefaultVals(self): """ Setup with our default settings """ # Override the default settings if Path("/usr/share/exe").isdir(): self.webDir = Path("/usr/share/exe") self.jsDir = Path("/usr/share/exe") # 'usr/share/exe/locale/' breaks the FHS - jrf # jrf - experimental # self.localeDir = Path("/usr/share/exe/locale") self.localeDir = Path("/usr/share/locale") self.mediaProfilePath = Path("/usr/share/exe/mediaprofiles") self.dataDir = Path(os.environ['HOME']) self.configDir = Path(self.dataDir)/'.exe' self.stylesDir = Path(self.configDir)/'style' self.lastDir = Path(os.environ['HOME']) # Media converters - defaults for now self.videoMediaConverter_ogv = "" self.videoMediaConverter_3gp = '/usr/bin/ffmpeg -i %(infile)s -s qcif -vcodec h263 -acodec libvo_aacenc -ac 1 -ar 8000 -r 25 -ab 32 -y %(outfile)s' self.videoMediaConverter_mpg = "/usr/bin/ffmpeg -i %(infile)s -s qcif -vcodec mpeg1 -acodec wav -ac 1 -ar 8000 -r 25 -ab 32 -y %(outfile)s" self.audioMediaConverter_au = "/usr/bin/sox %(infile)s %(outfile)s" self.audioMediaConverter_wav = "/usr/bin/sox %(infile)s %(outfile)s" self.audioMediaConverter_mp3 = "/usr/bin/sox %(infile)s -t wav - | /usr/bin/lame -b 32 - %(outfile)s" self.ffmpegPath = "/usr/bin/ffmpeg"
def _overrideDefaultVals(self): """ Sets default mac values. Uses LinuxConfig's _getConfigPathOptions. """ # Override the default settings self.webDir = Path("../Resources/exe") self.xulDir = Path("../Resources/exe") self.localeDir = Path("../Resources/exe/locale") self.dataDir = Path(os.environ['HOME']) self.configDir = Path(self.dataDir) / '.exe' self.browserPath = self.webDir / 'firefox/Firefox.app/Contents/MacOS/firefox'
def get_dirname(self): dirname = "" if Path(self._iDeviceDir) == Path(self._iDeviceDir).basename(): if "\\" in self._iDeviceDir: dirname = self._iDeviceDir.split("\\")[-1] else: dirname = str(Path(self._iDeviceDir).basename()) else: dirname = str(Path(self._iDeviceDir).basename()) self._iDeviceDir = dirname return self._iDeviceDir
def __loadIdevice(self): """ Load IDevice configuration from its config.xml file """ try: if self._valid: # Check if the folder has a config.xml file configFile = self.get_jsidevice_dir() / 'config.xml' if configFile.exists(): # Get config data configData = open(configFile).read() try: newConfigData = configData.decode() except UnicodeDecodeError: configCharset = chardet.detect(configData) newConfigData = configData.decode( configCharset['encoding'], 'replace') # Parse the XML file xmlConfig = minidom.parseString(newConfigData) # Get main element xmlIdevice = xmlConfig.getElementsByTagName('idevice') # Initialize results variable result = dict() # If there is a main element tag if (len(xmlIdevice) > 0): # Go over all the child nodes for tag in xmlIdevice[0].childNodes: # Only process the node if it is an Element # This means only tags get processed if (isinstance(tag, minidom.Element)): # Add the tag name and value to the result dictionary result.update( {tag.tagName: tag.firstChild.nodeValue}) if 'title' in result and 'css-class' in result: return result else: raise InvalidConfigJsIdevice( Path(self.get_dirname()), 'Mandatory fields not found.') else: raise InvalidConfigJsIdevice( Path(self.get_dirname()), 'config.xml file doesn\'t exist.') except IOError as ioerror: # If we can't load an iDevice, we simply continue with the rest (and log it) log.debug("iDevice " + Path(self.get_dirname()) + " doesn't appear to have a valid \"config.xml\" file") raise InvalidConfigJsIdevice(Path(self.get_dirname()), ioerror.message)
def set_footerImg(self, value): """Set the footer image for this package""" if self._footerImg: self._footerImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._footerImg = Resource(self, Path(imgFile)) else: self._footerImg = u''
def __init__(self, config, styleDir, filename): """ 'stylesDir' is the directory where we can copy the stylesheets from 'outputDir' is the directory that will be [over]written with the website """ self.config = config self.imagesDir = config.webDir / "images" self.scriptsDir = config.webDir / "scripts" self.templatesDir = config.webDir / "templates" self.stylesDir = Path(styleDir) self.filename = Path(filename) self.pages = []
def __init__(self, config, styleDir, filename): """ Initialize 'styleDir' is the directory from which we will copy our style sheets (and some gifs) """ self.config = config self.imagesDir = config.webDir/"images" self.scriptsDir = config.webDir/"scripts" self.templatesDir = config.webDir/"templates" self.schemasDir = config.webDir/"schemas/ims" self.styleDir = Path(styleDir) self.filename = Path(filename) self.pages = []
def _overrideDefaultVals(self): """ Setup with our default settings """ # Override the default settings self.webDir = Path("/usr/share/exe") self.xulDir = Path("/usr/share/exe") self.localeDir = Path("/usr/share/exe/locale") self.dataDir = Path(os.environ['HOME']) self.configDir = Path(self.dataDir)/'.exe' browserPath = self.webDir/'firefox'/'firefox' if browserPath.isfile(): self.browserPath = browserPath
def __renderIcons(self, style): """ Return xhtml string for dispay all icons """ iconpath = Path(G.application.config.stylesDir / style) iconfiles = iconpath.files("icon_*") html = '<div id="styleIcons"><div style="height:300px;overflow:auto">' for iconfile in iconfiles: iconname = iconfile.namebase icon = iconname.split("_", 1)[1] iconExists = False iconExtension = "gif" myIcon = Path(G.application.config.stylesDir / style / iconname + ".gif") if myIcon.exists(): iconExists = True iconValue = icon + '.' + iconExtension iconSrc = '/style/%s/icon_%s' % (style, iconValue) else: myIcon = Path(G.application.config.stylesDir / style / iconname + ".png") if myIcon.exists(): iconExists = True iconExtension = "png" iconValue = icon + '.' + iconExtension iconSrc = '/style/%s/icon_%s' % (style, iconValue) else: myIcon = Path(G.application.config.stylesDir / style / iconname + ".svg") if myIcon.exists(): iconExists = True iconExtension = "svg" iconValue = icon + '.' + iconExtension iconSrc = '/style/%s/icon_%s' % (style, iconValue) if iconExists: filename = "/style/%s/%s.%s" % (style, iconname, iconExtension) html += u'<div style="float:left; text-align:center; width:105px;\n' html += u'margin-right:10px; margin-bottom:15px" > ' html += u'<img src="%s" \n' % filename html += u"style=\"border:1px solid #E8E8E8;padding:5px;cursor:pointer;max-width:60px;height:auto\" onclick=\"window[0].selectStyleIcon('%s',this, '%s', '%s')\" title=\"%s.%s\">\n" % ( icon, iconSrc, self.id, icon, iconExtension) html += u'<br /><span style="display:inline-block;width:100px;overflow:hidden;text-overflow:ellipsis">%s.%s</span></div>\n' % ( icon, iconExtension) html += '</div></div>' return html
def testAuthoringPage(self): """ Generates a page of idevices and checks each ones xhtml individually """ # TODO: Once we have pyxpcom, break this test out into # TestFreeTextBlock, TestImageWithTextBlock etc. # And actually do some interactive DOM testing... allHtml = self.createPackage() checker = HTMLChecker(self.ignoreErrorMsgs) mainOk = checker.check(allHtml, False, False) if self.quickCheck: if mainOk: return True else: self.fail( 'Main XHTML failed, check tmp.html and tmp.html.errors') return False # Backup tmp.html Path('tmp.html').rename('tmpall.html') # Check all the idevices and blocks like each other ln = len(self.package.currentNode.idevices) assert ln >= 1, 'Should be at least one idevice, only %s' % ln idevice = self.package.currentNode.idevices[0] ln = len(self.mainpage.authoringPage.blocks) assert ln >= 1, 'Should be at least one block, only %s' % ln chunks = zip(self.mainpage.authoringPage.blocks, self.package.currentNode.idevices) for i, (block, idevice) in enumerate(chunks): assert block.idevice is idevice viewHTML = block.renderView('default') previewHTML = block.renderPreview('default') editHTML = block.renderEdit('default') if not checker.check(viewHTML, True, False): self.fail('Block "%s" generated bad view XHTML' % idevice.title) return False if not checker.check(previewHTML, True, True): self.fail('Block "%s" generated bad preview XHTML' % idevice.title) return False if not checker.check(editHTML, True, True): self.fail('Block "%s" generated bad edit XHTML' % idevice.title) return False if not mainOk: # Even if all the blocks pass, still the main html is bad Path('tmpall.html').rename('tmp.html') self.fail('Authoring Page generated bad XHTML, but all the blocks ' 'were good')
def __getFolderResources(self): self._editionFolder = str( Path(self._iDeviceDir).basename() + '/edition/') for editionFile in os.listdir(self._iDeviceDir + '/edition'): self._editionResources.append(editionFile) # Check if export directory exists if (Path(self._iDeviceDir) / 'export').exists(): self._exportFolder = str( Path(self._iDeviceDir).basename() + '/export/') for exportFile in os.listdir(self._iDeviceDir + '/export'): self._exportResources.append(exportFile) else: self._exportFolder = None
def dataFiles(baseSourceDir, baseDestDir, sourceDirs, excludes=[]): """Recursively get all the files in these directories""" baseSourceDir = Path(baseSourceDir) baseDestDir = Path(baseDestDir) sourceDirs = map(Path, sourceDirs) for sourceDir in sourceDirs: sourceDir = baseSourceDir / sourceDir for subDir in list(sourceDir.walkdirs()) + [sourceDir]: if '.svn' in subDir.splitall(): continue newExtDir = baseSourceDir.relpathto(subDir) fileList = files.setdefault(baseDestDir / newExtDir, []) for file in subDir.files(): if file.name not in excludes: fileList.append(file)
def dataFiles(baseSourceDir, baseDestDir, sourceDirs): """Recursively get all the files in these directories""" global files from exe.engine.path import Path baseSourceDir = Path(baseSourceDir) baseDestDir = Path(baseDestDir) sourceDirs = map(Path, sourceDirs) for sourceDir in sourceDirs: sourceDir = baseSourceDir / sourceDir for subDir in list(sourceDir.walkdirs()) + [sourceDir]: if set(('CVS', '.svn')) & set(subDir.splitall()): continue newExtDir = baseSourceDir.relpathto(subDir) fileList = files.setdefault(baseDestDir / newExtDir, []) fileList += subDir.files()
def _overrideDefaultVals(self): """ Setup with our default settings """ self.exePath = Path(sys.argv[0]) if self.exePath.isfile(): self.exePath = self.exePath.dirname() exePath = self.exePath # Override the default settings self.webDir = exePath self.configDir = exePath / 'config' self.localeDir = exePath / 'locale' self.stylesDir = Path(exePath / 'style').abspath() self.styles = [] self.lastDir = exePath
def overwriteLocalStyle(self, style_dir, filename): """ Overwrites an already installed style with a new version from file """ log.debug(u"Overwriting style %s with style from %s" % (style_dir, filename)) try: # Delete local style style_path = Path(style_dir) styleDelete = Style(style_path) self.__deleteStyle(styleDelete) # Import downloaded style self.doImportStyle(filename) self.client.sendScript("Ext.MessageBox.alert('%s', '%s')" % (_('Correct'), _('Style updated correctly'))) except: self.client.sendScript("Ext.MessageBox.alert('%s', '%s')" % (_('Error'), _('An unexpected error has occurred'))) finally: Path(filename).remove()
def __renderIcons(self): """ Return xhtml string for dispay all icons """ iconpath = self.style.get_style_dir() iconfiles = iconpath.files("icon_*") html = '<div id="styleIcons"><div style="height:300px;overflow:auto">' for iconfile in iconfiles: iconname = iconfile.namebase icon = iconname.split("_", 1)[1] iconExists = False iconExtension = "gif" myIcon = Path(G.application.config.stylesDir / self.style.get_dirname() / iconname + ".gif") if myIcon.exists(): iconExists = True else: myIcon = Path(G.application.config.stylesDir / self.style.get_dirname() / iconname + ".png") if myIcon.exists(): iconExists = True iconExtension = "png" else: myIcon = Path(G.application.config.stylesDir / self.style.get_dirname() / iconname + ".svg") if myIcon.exists(): iconExists = True iconExtension = "svg" if iconExists: filename = "/style/%s/%s.%s" % (self.style.get_dirname(), iconname, iconExtension) html += u'<div style="float:left; text-align:center; width:105px;\n' html += u'margin-right:10px; margin-bottom:15px" > ' html += u'<img src="%s" \n' % filename # html += u' alt="%s" ' % _("Submit") # window[1] because we use Ext.MessageBox instead of libot_drag.js html += u"style=\"border:1px solid #E8E8E8;padding:5px;cursor:pointer;max-width:60px;max-height:60px;height:auto\" onclick=\"window[1].selectStyleIcon('%s',this)\" title=\"%s.%s\">\n" % ( icon, icon, iconExtension) # html += u"style=\"cursor:pointer\" onclick=\"window[1].submitLink('selectIcon','%s',1)\">\n" % icon html += u'<br /><span style="display:inline-block;width:100px;overflow:hidden;text-overflow:ellipsis">%s.%s</span></div>\n' % ( icon, iconExtension) html += '</div></div>' return html
def testExport(self): # Delete the output dir outdir = TempDirPath() # Load a package package = Package.load('testPackage.elp') # Do the export exporter = WebsiteExport('../exe/webui/style/default', outdir, '../exe/webui/images', '../exe/webui/scripts', '../exe/webui/templates') exporter.export(package) # Check that it all exists now assert outdir.isdir() assert (outdir / 'index.html').isfile() # Check that the style sheets have been copied for filename in Path('../exe/webui/style/default').files(): assert ((outdir / filename.basename()).exists(), 'Style file "%s" not copied' % (outdir / filename.basename())) # Check that each node in the package has had a page made pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, outdir)
def do_export(self, inputf, outputf): if hasattr(self, 'export_' + self.options["export"]): LOG.debug("Exporting to type %s, in: %s, out: %s, overwrite: %s" \ % (self.options["export"], inputf, outputf, str(self.options["overwrite"]))) if not outputf: if self.options["export"] in ('website', 'singlepage'): outputf = inputf.rsplit(".elp")[0] else: outputf = inputf + self.extensions[self.options["export"]] outputfp = Path(outputf) if outputfp.exists() and not self.options["overwrite"]: error = _(u'"%s" already exists.\nPlease try again \ with a different filename') % outputf raise Exception(error.encode(sys.stdout.encoding)) else: if outputfp.exists() and self.options["overwrite"]: if outputfp.isdir(): for filen in outputfp.walkfiles(): filen.remove() outputfp.rmdir() else: outputfp.remove() pkg = Package.load(inputf) LOG.debug("Package %s loaded" % (inputf)) if not pkg: error = _(u"Invalid input package") raise Exception(error.encode(sys.stdout.encoding)) self.styles_dir = self.web_dir.joinpath('style', pkg.style) LOG.debug("Styles dir: %s" % (self.styles_dir)) getattr(self, 'export_' + self.options["export"])(pkg, outputf) return outputf else: raise Exception(_(u"Export format not implemented")\ .encode(sys.stdout.encoding))
def _addOurselvesToPackage(self, oldPath): """ Adds ourselves into self._package.resources. Don't call if self._package is None. Does no copying or anything. Just sticks us in the list and sets our storage name """ # new safety mechanism for old corrupt packages which # have non-existent resources that are being deleted and such: if not hasattr(self, 'checksum') or self.checksum is None: if self._package is None: log.warn("Resource " + repr(self) + " has no checksum " \ + "(probably no source file), but is being removed "\ + "anyway, so ignoring.") return else: if oldPath.isfile(): log.warn("Resource " + repr(self) + " has no checksum; " \ + " adding and continuing...") # see if a few basic checks here can get it going to add: self.checksum = oldPath.md5 else: log.warn("Resource " + repr(self) + " has no checksum " \ + "(and no source file), and was being added to "\ + "package " + repr(self._package) + "; ignoring.") return # Add ourselves to our new package's list of resources if not hasattr(self._package, 'resources'): log.error("_AddOurselvesToPackage called with an invalid package: " + " no resources on package " + repr(self._package) + "; possibly after a deepcopy") return if not hasattr(self._package, 'resourceDir'): log.error("_AddOurselvesToPackage called with an invalid package: " + " no resourceDir on package " + repr(self._package) + "; possibly an old/corrupt resource or package") return siblings = self._package.resources.setdefault(self.checksum, []) if siblings: # If we're in the resource dir, and already have a filename that's different to our siblings, delete the original file # It probably means we're upgrading from pre-single-file-resources or someone has created the file to be imported inside the resource dir # We are assuming that it's not a file used by other resources... newName = siblings[0]._storageName if oldPath.dirname() == self._package.resourceDir and self._storageName != newName: oldPath.remove() self._storageName = newName else: if Path(oldPath).dirname() == self._package.resourceDir: log.debug(u"StorageName=%s was already in self._package resources" % self._storageName) else: filename = (self._package.resourceDir/oldPath.basename()) storageName = self._fn2ascii(filename) storageName = (self._package.resourceDir/storageName).unique() self._storageName = str(storageName.basename()) oldPath.copyfile(self.path) if self not in siblings: # prevent doubling-up (as might occur when cleaning corrupt files) siblings.append(self)
def _fn2ascii(self, filename): """ Changes any filename to pure ascii, returns only the basename """ nameBase, ext = Path(Path(filename).basename()).splitext() # Check if the filename is ascii so that twisted can serve it try: nameBase.encode('ascii') except UnicodeEncodeError: nameBase = nameBase.encode('utf-8').encode('hex') # Encode the extension separately so that you can keep file types a bit # at least try: ext = ext.encode('ascii') except UnicodeEncodeError: ext = ext.encode('utf8').encode('hex') return str(nameBase + ext)
def _process(self, request): """ Delegates processing of args to blocks """ # Still need to call parent (mainpage.py) process # because the idevice pane needs to know that new idevices have been # added/edited.. self.parent.process(request) if ("action" in request.args and request.args["action"][0] == u"saveChange"): log.debug(u"process savachange:::::") self.package.save() log.debug(u"package name: " + self.package.name) for block in self.blocks: block.process(request) # now that each block and corresponding elements have been processed, # it's finally safe to remove any images/etc which made it into # tinyMCE's previews directory, as they have now had their # corresponding resources created: webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') for root, dirs, files in os.walk(previewDir, topdown=False): for name in files: os.remove(os.path.join(root, name)) log.debug(u"After authoringPage process" + repr(request.args))
def doStyleImportURL(self, url, style_name=''): """ Download style from url and import into styles directory """ def successDownload(result): filename = result[0] try: log.debug("Installing style %s from %s" % (style_name, filename)) self.doImportStyle(filename) self.client.sendScript( 'Ext.getCmp("stylemanagerwin").down("form").refreshStylesList(%s, \'%s\')' % (json.dumps(self.rep_styles), style_name)) self.alert(_(u'Success'), _(u'Style successfully downloaded and installed')) Path(filename).remove() except ImportStyleExistsError, e: # This might retry installation from already downloaded file, do not delete warnLocalStyleExists(e.absolute_style_dir, filename) except Exception, e: log.error("Error when installing style %s from %s: %s" % (style_name, filename, str(e))) self.client.sendScript( 'Ext.getCmp("stylemanagerwin").down("form").refreshStylesList(%s, \'%s\')' % (json.dumps(self.rep_styles), style_name)) self.alert(_(u'Error'), _(u'Error while installing style')) Path(filename).remove()
def exportIpod(self, client, filename): """ Export 'client' to an iPod Notes folder tree 'webDir' is just read from config.webDir """ try: # filename is a directory where we will export the notes to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != self.package.name: filename /= self.package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert( _(u'Filename %s is a file, cannot replace it') % filename) log.error("Couldn't export web page: " + "Filename %s is a file, cannot replace it" % filename) return else: client.alert( _(u'Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.' ) % filename) return # Now do the export ipodExport = IpodExport(self.config, filename) ipodExport.export(self.package) except Exception, e: client.alert(_('EXPORT FAILED!\n%s') % str(e)) raise
def __setConfigPath(self): """ sets self.configPath to the filename of the config file that we'll use. In descendant classes set self.configFileOptions to a list of directories where the configDir should be in order of preference. If no config files can be found in these dirs, it will force creation of the config file in the top dir """ # If there's an EXECONF environment variable, use it self.configPath = None configFileOptions = map(Path, self._getConfigPathOptions()) if "EXECONF" in os.environ: envconf = Path(os.environ["EXECONF"]) if envconf.isfile(): self.configPath = os.environ["EXECONF"] # Otherwise find the most appropriate existing file if self.configPath is None: for confPath in configFileOptions: if confPath.isfile(): self.configPath = confPath break else: # If no config files exist, create and use the # first one on the list self.configPath = configFileOptions[0] folder = self.configPath.abspath().dirname() if not folder.exists(): folder.makedirs() self.configPath.touch() # Now make our configParser self.configParser.read(self.configPath) self.configParser.autoWrite = True
def _parseSpecialResources(self): """ Parse every page and search for special resources like: - Linked images - Iframes' sources """ # We have to get the rendered view of all idevices across all pages for page in self.pages: for idevice in page.node.idevices: block = g_blockFactory.createBlock(None, idevice) div = block.renderView(self.package.style) # Find iframes src_list = re.findall(r'<iframe[^>]*\ssrc="(.*?)"', div) if src_list: self.specialResources['external'].append(page.name) # Find links src_list = re.findall(r'<a[^>]*\shref="(.*?)"', div) if src_list: for src in src_list: # Only include it if is a internal link if Path(self.outputDir / src).exists(): self.specialResources['linked_resources'].append( src)
def doTest(self, ExporterClass): """Exports a package with meta data""" # Load our test package package = Package.load('testPackage.elp') # Do the export outFilename = Path('scormtest.zip') exporter = ExporterClass(self.app.config, '../exe/webui/style/default', outFilename) exporter.export(package) # Check that it made a nice zip file assert outFilename.exists() # See if the manifest file was created zipped = ZipFile(outFilename) filenames = zipped.namelist() assert 'imsmanifest.xml' in filenames, filenames self._testManifest(zipped.read('imsmanifest.xml')) # Test that all the node's html files have been generated pagenodes = Set([p.node for p in exporter.pages]) othernodes = Set(self._getNodes([], package.root)) assert pagenodes == othernodes for page in exporter.pages: self._testPage(page, zipped) # Clean up zipped.close()
def handleSavePackage(self, client, filename=None, onDone=None): """ Save the current package 'filename' is the filename to save the package to 'onDone' will be evaled after saving instead or redirecting to the new location (in cases of package name changes). (This is used where the user goes file|open when their package is changed and needs saving) """ filename = Path(filename) saveDir = filename.dirname() if saveDir and not saveDir.isdir(): client.alert( _(u'Cannot access directory named ') + unicode(saveDir) + _(u'. Please use ASCII names.')) return oldName = self.package.name # If the script is not passing a filename to us, # Then use the last filename that the package was loaded from/saved to if not filename: filename = self.package.filename assert ( filename, 'Somehow save was called without a filename on a package that has no default filename.' ) # Add the extension if its not already there and give message if not saved filename = self.b4save(client, filename, '.elp', _(u'SAVE FAILED!')) try: self.package.save(filename) # This can change the package name except Exception, e: client.alert(_('SAVE FAILED!\n%s' % str(e))) raise
def createChild(self, template_path=None, title="New Page", auto_save=True): new_html_filename = self.opf.find_free_filename( EPUBNavItem.DEFAULT_PAGENAME, ".xhtml") new_html_path = os.path.join(os.path.dirname(self.opf.href), new_html_filename) if template_path is None: from exe import globals as G template_path = G.application.config.webDir / "templates" / "blank.xhtml" Path(template_path).copyfile(new_html_path) self.opf.add_item_to_manifest( self.opf.get_id_for_href(new_html_filename), "application/xhtml+xml", new_html_filename, ['scripted']) namespace = self.element.nsmap.get(None) if self.ol_element is None: etree.SubElement(self.element, "{%s}ol" % namespace) new_li_item = etree.SubElement(self.ol_element, "{%s}li" % namespace) a_el = etree.SubElement(new_li_item, "{%s}a" % namespace, href=new_html_filename) a_el.text = title if auto_save: self.opf.get_navigation().save() self.opf.update_spine() self.opf.set_package_changed() return EPUBNavItem(self.opf, new_li_item)