def filename(self): """ The filename that this object should create Objects that don't create new files should simply return `None`. """ r = self.renderer try: return r.files[self] except KeyError: pass filename = None override = None try: # Nothing in the plasTeX code base actually ever # sets a filenameoverride on a Node override = str(self.filenameoverride.encode('ascii','ignore')) if self.filenameoverride is not None else None if override: assert override is not None userdata = self.ownerDocument.userdata config = self.ownerDocument.config newFilename = Filenames(override, (config['files']['bad-chars'], config['files']['bad-chars-sub']), {'jobname': userdata.get('jobname','')}, r.fileExtension) newFilename.forceExtension = True filename = r.files[self] = newFilename() except (AttributeError, ValueError) as e: if isinstance( e, ValueError ): log.exception( "Failed to generate filename given override %s", override ) if not hasattr(self, 'config'): return level = getattr(self, 'splitlevel', self.config['files']['split-level']) # If our level doesn't invoke a split, don't return a filename if self.level > level: return # Populate vars of filename generator # and call the generator to get the filename. # FIXME: Eww, not thread safe. Not really even re-entrant. # Closely coupled to the implementation of `id` ns = r.newFilename.vars if hasattr(self, 'id') and getattr(self, '@hasgenid', None) is None: ns['id'] = self.id if hasattr(self, 'title'): if hasattr(self.title, 'textContent'): ns['title'] = self.title.textContent elif isinstance(self.title, string_types): ns['title'] = self.title r.files[self] = filename = r.newFilename() return filename
def filename(self): """ The filename that this object should create Objects that don't create new files should simply return `None`. """ r = Node.renderer try: return r.files[self] except (KeyError, TypeError): pass filename = None try: override = str(self.filenameoverride) if override: userdata = self.ownerDocument.userdata config = self.ownerDocument.config newFilename = Filenames( override, (config['files']['bad-chars'], config['files']['bad-chars-sub']), {'jobname': userdata.get('jobname', '')}, r.fileExtension) filename = r.files[self] = newFilename() except AttributeError as msg: if not hasattr(self, 'config'): return level = getattr(self, 'splitlevel', self.config['files']['split-level']) # If our level doesn't invoke a split, don't return a filename if self.level > level: return # Populate vars of filename generator # and call the generator to get the filename. ns = r.newFilename.variables if hasattr(self, 'id') and getattr(self, '@hasgenid', None) is None: ns['id'] = self.id if hasattr(self, 'title'): if hasattr(self.title, 'textContent'): ns['title'] = self.title.textContent elif isinstance(self.title, str): ns['title'] = self.title r.files[self] = filename = r.newFilename() # print type(self), filename return filename
def __init__(self, document): self.config = document.config self.ownerDocument = document # Images that are simply copied from the source directory self.staticimages = ordereddict() # Filename generator self.newFilename = Filenames( self.config['images'].get('filenames', raw=True), vars={'jobname': document.userdata.get('jobname', '')}, extension=self.fileExtension, invalid={})
def __init__(self, document, imageTypes=None): self.config = document.config self.ownerDocument = document if imageTypes is None: self.imageTypes = [self.fileExtension] else: self.imageTypes = imageTypes[:] # Dictionary that makes sure each image is only generated once. # The key is the LaTeX source and the value is the image instance. self._cache = {} usednames = {} # JAM: FIXME: This writes into some arbitrary directory that may or # may not be related to the document we are processing. It at least # needs to take document name/path into consideration (see below on # graphicspath) self._filecache = os.path.abspath( os.path.join('.cache', self.__class__.__name__ + '.images')) if self.config['images']['cache']: usednames = self._read_cache() # List of images in the order that they appear in the LaTeX file self.images = ordereddict() # Images that are simply copied from the source directory self.staticimages = ordereddict() # Filename generator self.newFilename = Filenames( self.config['images'].get('filenames', raw=True), vars={'jobname': document.userdata.get('jobname', '')}, extension=self.fileExtension, invalid=usednames) # Start the document with a preamble self.source = StringIO() self.source.write('\\batchmode\n') self.writePreamble(document) self.source.write('\\begin{document}\n') #We inject \graphicspath here because this processing occurs in some temp space but the image urls #are relative to the original working directory. #Documentation suggests that we could just set the TEXINPUTS environment variable but it does not work self.source.write('\\graphicspath{{%s/}}\n' % (self.ownerDocument.userdata['working-dir'])) # Set up additional options self._configOptions = self.formatConfigOptions(self.config['images'])
def __init__(self, document, imageTypes=None): self.config = document.config self.ownerDocument = document if imageTypes is None: self.imageTypes = [self.fileExtension] else: self.imageTypes = imageTypes[:] # Dictionary that makes sure each image is only generated once. # The key is the LaTeX source and the value is the image instance. self._cache = {} usednames = {} self._filecache = os.path.abspath( os.path.join('.cache', self.__class__.__name__ + '.images')) if self.config['images']['cache'] and os.path.isfile(self._filecache): try: self._cache = pickle.load(open(self._filecache, 'r')) for key, value in self._cache.items(): if not os.path.isfile(value.filename): del self._cache[key] continue usednames[value.filename] = None except ImportError: os.remove(self._filecache) # List of images in the order that they appear in the LaTeX file self.images = ordereddict() # Images that are simply copied from the source directory self.staticimages = ordereddict() # Filename generator self.newFilename = Filenames( self.config['images'].get('filenames', raw=True), vars={'jobname': document.userdata.get('jobname', '')}, extension=self.fileExtension, invalid=usednames) # Start the document with a preamble self.source = StringIO() self.source.write('\\scrollmode\n') self.writePreamble(document) self.source.write('\\begin{document}\n') # Set up additional options self._configOptions = self.formatConfigOptions(self.config['images'])
def __init__(self, document): self.config = document.config self.ownerDocument = document # Cache of already seen images self.staticimages = {} # Filename generator # Python 2 compatibility: the second keyword argument for the Filenames # class changed name from vars to variables in Python 3 version. When # Python 2 compatibility is dropped, change the following command to # self.newFilename = Filenames(self.config['images'].get('filenames', raw=True), # variables={'jobname': document.userdata.get('jobname', '')}, # extension=self.fileExtension, invalid={}) self.newFilename = Filenames( self.config['images'].get('filenames', raw=True), None, {'jobname': document.userdata.get('jobname', '')}, extension=self.fileExtension, invalid={})
def render(self, document, postProcess=None): """ Invoke the rendering process This method invokes the rendering process as well as handling the setup and shutdown of image processing. Required Arguments: document -- the document object to render postProcess -- a function that will be called with the content of """ config = document.config # If there are no keys, print a warning. # This is most likely a problem. if not list(self.keys()): log.warning('There are no keys in the renderer. ' + 'All objects will use the default rendering method.') # Mix in required methods and members mixin(Node, type(self).renderableClass) Node.renderer = self # Create a filename generator self.newFilename = Filenames(config['files'].get('filename', raw=True), (config['files']['bad-chars'], config['files']['bad-chars-sub']), {'jobname':document.userdata.get('jobname', '')}, self.fileExtension) self.cacheFilenames(document) # Instantiate appropriate imager names = [x for x in config['images']['imager'].split() if x] for name in names: if name == 'none': break elif name == 'dvipng': from plasTeX.Imagers.dvipng import Imager elif name == 'dvi2bitmap': from plasTeX.Imagers.dvi2bitmap import Imager elif name == 'pdftoppm': from plasTeX.Imagers.pdftoppm import Imager elif name == 'gspdfpng': from plasTeX.Imagers.gspdfpng import Imager elif name == 'gsdvipng': from plasTeX.Imagers.gsdvipng import Imager elif name == 'OSXCoreGraphics': from plasTeX.Imagers.OSXCoreGraphics import Imager else: log.warning("Invalid imager '%s'" % name) continue self.imager = Imager(document, self.imageTypes) # Make sure that this imager works on this machine if self.imager.verify(): log.info('Using the imager "%s".' % name) break # Still no imager? Just use the default. if self.imager is None: if 'none' not in names: log.warning('Could not find a valid imager in the list: %s. The default imager will be used.' % ', '.join(names)) from plasTeX.Imagers import Imager self.imager = Imager(document, self.imageTypes) if self.imageTypes and self.imager.fileExtension not in self.imageTypes: self.imager.fileExtension = self.imageTypes[0] if self.imageAttrs and not self.imager.imageAttrs: self.imager.imageAttrs = self.imageAttrs if self.imageUnits and not self.imager.imageUnits: self.imager.imageUnits = self.imageUnits # Instantiate appropriate vector imager names = [x for x in config['images']['vector-imager'].split() if x] for name in names: if name == 'none': break elif name == 'dvisvgm': from plasTeX.Imagers.dvisvgm import Imager as VectorImager elif name == 'pdf2svg': from plasTeX.Imagers.pdf2svg import Imager as VectorImager else: log.warning("Invalid imager '%s'" % name) continue self.vectorImager = VectorImager(document, self.vectorImageTypes) # Make sure that this imager works on this machine if self.vectorImager.verify(): log.info('Using the vector imager "%s".' % name) break self.vectorImager = None # Still no vector imager? Just use the default. if self.vectorImager is None: if 'none' not in names: log.warning('Could not find a valid vector imager in the list: %s. The default vector imager will be used.' % ', '.join(names)) from plasTeX.Imagers import VectorImager self.vectorImager = VectorImager(document, self.vectorImageTypes) if self.vectorImageTypes and \ self.vectorImager.fileExtension not in self.vectorImageTypes: self.vectorImager.fileExtension = self.vectorImageTypes[0] if self.imageAttrs and not self.vectorImager.imageAttrs: self.vectorImager.imageAttrs = self.imageAttrs if self.imageUnits and not self.vectorImager.imageUnits: self.vectorImager.imageUnits = self.imageUnits # Invoke the rendering process if type(self).renderMethod: getattr(document, type(self).renderMethod)() else: str(document) # Finish rendering images self.imager.close() self.vectorImager.close() # Run any cleanup activities self.cleanup(document, list(self.files.values()), postProcess=postProcess) # Write out auxilliary information pauxname = os.path.join(document.userdata.get('working-dir','.'), '%s.paux' % document.userdata.get('jobname','')) rname = config['general']['renderer'] document.context.persist(pauxname, rname) # Remove mixins del Node.renderer unmix(Node, type(self).renderableClass)
def render(self, document, postProcess=None): """ Invoke the rendering process This method invokes the rendering process as well as handling the setup and shutdown of image processing. Required Arguments: document -- the document object to render postProcess -- a function that will be called with the content of """ config = document.config # If there are no keys, print a warning. # This is most likely a problem. if not bool(self): log.warning('There are no keys in the renderer. ' + 'All objects will use the default rendering method.') document.renderer = self # JAM: Make thread safe. See above # XXX JAM FIXME: Not thread safe because this manipulates # the Node class system wide # We can get very close to being thread safe by instead # operating on a zope proxy object that extends self.renderableClass # and takes care to wrap self.childNodes, but this # ultimately fails because some things like SectionUtils # are already mixed-in to the node and depend on things defined # by renderableClass (filename)...thus they can only be used # during the rendering process anyway, but they don't get to # work on the proxy object. Obviously that's a design flaw # to rectify. mixin(Node, self.renderableClass) try: # Create a filename generator self.newFilename = Filenames( config['files'].get('filename', raw=True), (config['files']['bad-chars'], config['files']['bad-chars-sub']), {'jobname': document.userdata.get('jobname', '')}, self.fileExtension) self.cacheFilenames(document) # Instantiate appropriate imager self.imager = _create_imager(config, document, DefaultImager, self.imageTypes, self.imageUnits, self.imageAttrs) # Instantiate appropriate vector imager self.vectorImager = _create_imager(config, document, DefaultVectorImager, self.vectorImageTypes, self.imageUnits, self.imageAttrs, kind='vector-imager') # Invoke the rendering process if self.renderMethod: getattr(document, self.renderMethod)() else: unicode(document) # Finish rendering images self.imager.close() self.vectorImager.close() # Run any cleanup activities self.cleanup(document, list(self.files.values()), postProcess=postProcess) # Write out auxilliary information pauxname = os.path.join( document.userdata.get('working-dir', '.'), '%s.paux' % document.userdata.get('jobname', '')) rname = config['general']['renderer'] document.context.persist(pauxname, rname) finally: # Remove mixins unmix(Node, self.renderableClass) del document.renderer
def filename(self): """ The filename that this object should create Objects that don't create new files should simply return `None`. """ r = self.renderer try: return r.files[self] except KeyError: pass filename = None override = None try: # Nothing in the plasTeX code base actually ever # sets a filenameoverride on a Node override = str(self.filenameoverride.encode( 'ascii', 'ignore')) if self.filenameoverride is not None else None if override: assert override is not None userdata = self.ownerDocument.userdata config = self.ownerDocument.config newFilename = Filenames( override, (config['files']['bad-chars'], config['files']['bad-chars-sub']), {'jobname': userdata.get('jobname', '')}, r.fileExtension) newFilename.forceExtension = True filename = r.files[self] = newFilename() except (AttributeError, ValueError) as e: if isinstance(e, ValueError): log.exception("Failed to generate filename given override %s", override) if not hasattr(self, 'config'): return level = getattr(self, 'splitlevel', self.config['files']['split-level']) # If our level doesn't invoke a split, don't return a filename if self.level > level: return # Populate vars of filename generator # and call the generator to get the filename. # FIXME: Eww, not thread safe. Not really even re-entrant. # Closely coupled to the implementation of `id` ns = r.newFilename.vars if hasattr(self, 'id') and getattr(self, '@hasgenid', None) is None: ns['id'] = self.id if hasattr(self, 'title'): if hasattr(self.title, 'textContent'): ns['title'] = self.title.textContent elif isinstance(self.title, string_types): ns['title'] = self.title r.files[self] = filename = r.newFilename() return filename