Exemple #1
0
    def __init__(self, template, context, result, pythonWithUnoPath=None,
      ooPort=2002, stylesMapping={}, forceOoCall=False, finalizeFunction=None,
      overwriteExisting=False, raiseOnError=False, imageResolver=None,
      stylesTemplate=None, optimalColumnWidths=False, script=None,
      renamePageStyles=False):
        '''This Python Open Document Renderer (PodRenderer) loads a document
           template (p_template) which is an ODT or ODS file with some elements
           written in Python. Based on this template and some Python objects
           defined in p_context, the renderer generates an ODT file (p_result)
           that instantiates the p_template and fills it with objects from the
           p_context.

         - If p_result does not end with .odt or .ods, the Renderer will call
           LibreOffice to perform a conversion. If p_forceOoCall is True, even
           if p_result ends with .odt, LibreOffice will be called, not for
           performing a conversion, but for updating some elements like indexes
           (table of contents, etc) and sections containing links to external
           files (which is the case, for example, if you use the default
           function "document").

         - If the Python interpreter which runs the current script is not
           UNO-enabled, this script will run, in another process, a UNO-enabled
           Python interpreter (whose path is p_pythonWithUnoPath) which will
           call LibreOffice. In both cases, we will try to connect to
           LibreOffice in server mode on port p_ooPort.

         - If you plan to make "XHTML to OpenDocument" conversions (via the POD
           function "xhtml"), you may specify a styles mapping in
           p_stylesMapping.

         - If you specify a function in p_finalizeFunction, this function will
           be called by the renderer before re-zipping the ODT/S result. This
           way, you can still perform some actions on the content of the ODT/S
           file before it is zipped and potentially converted. This function
           must accept 2 args:
            * the absolute path to the temporary folder, containing the
              un-zipped content of the ODT/S result;
            * the Renderer instance.

         - If you set p_overwriteExisting to True, the renderer will overwrite
           the result file. Else, an exception will be thrown if the result file
           already exists.

         - If p_raiseOnError is False (the default value), any error encountered
           during the generation of the result file will be dumped into it, as
           a Python traceback within a note. Else, the error will be raised.

         - p_imageResolver allows POD to retrieve images, from "img" tags within
           XHTML content. Indeed, POD may not be able (ie, may not have the
           permission to) perform a HTTP GET on those images. Currently, the
           resolver can only be a Zope application object.

         - p_stylesTemplate can be the path to a LibreOffice file (ie, a .ott
           file) whose styles will be imported within the result.

         - p_optimalColumnWidths corresponds to the homonym option to
           converter.py, excepted that values "True" or "False" must be boolean
           values. Note that the POD function "xhtml" requires this parameter to
           be "OCW_.*" to be fully operational. When optimalColumnWidths is not
           False, forceOoCall is forced to True.

         - p_script is the absolute path to a Python script containing functions
           that the converter will call in order to customize the process of
           manipulating the document via the LibreOffice UNO interface. For more
           information, see appy/pod/converter.py, option "-s". Note that when
           such p_script is specified, p_forceOoCall is forced to True.

         - If this document is a sub-document to be included in a master one, it
           has sense to set parameter p_renamePageStyles to True. This way, when
           importing it into the master document, all page styles will be
           considered different and tied elements like headers and footers will
           correctly be imported into the master document. The "do... pod"
           statement automatically sets this parameter to True.
        '''
        self.template = template
        self.result = result
        self.contentXml = None # Content (string) of content.xml
        self.stylesXml = None # Content (string) of styles.xml
        self.stylesManager = None # Manages the styles defined into the ODT
        # template
        self.tempFolder = None
        self.env = None
        self.pyPath = pythonWithUnoPath
        self.ooPort = ooPort
        # p_forceOoCall may be forced to True
        self.forceOoCall = forceOoCall or \
                           bool(optimalColumnWidths) or bool(script)
        self.finalizeFunction = finalizeFunction
        self.overwriteExisting = overwriteExisting
        self.raiseOnError = raiseOnError
        self.imageResolver = imageResolver
        self.stylesTemplate = stylesTemplate
        self.optimalColumnWidths = optimalColumnWidths
        self.script = script
        self.renamePageStyles = renamePageStyles
        # Keep trace of the original context given to the renderer
        self.originalContext = context
        # Remember potential files or images that will be included through
        # "do ... from document" statements: we will need to declare them in
        # META-INF/manifest.xml. Keys are file names as they appear within the
        # ODT file (to dump in manifest.xml); values are original paths of
        # included images (used for avoiding to create multiple copies of a file
        # which is imported several times).
        self.fileNames = {}
        self.prepareFolders()
        # Unzip template
        self.unzipFolder = os.path.join(self.tempFolder, 'unzip')
        os.mkdir(self.unzipFolder)
        info = unzip(template, self.unzipFolder, odf=True)
        self.contentXml = info['content.xml']
        self.stylesXml = info['styles.xml']
        self.stylesManager = StylesManager(self)
        # From LibreOffice 3.5, it is not possible anymore to dump errors into
        # the resulting ods as annotations. Indeed, annotations can't reside
        # anymore within paragraphs. ODS files generated with pod and containing
        # error messages in annotations cause LibreOffice 3.5 and 4.0 to crash.
        # LibreOffice >= 4.1 simply does not show the annotation.
        if info['mimetype'] == utils.mimeTypes['ods']: self.raiseOnError = True
        # Create the parsers for content.xml and styles.xml
        nso = PodEnvironment.NS_OFFICE
        for name in ('content', 'styles'):
            styleTag = (name == 'content') and 'automatic-styles' or 'styles'
            inserts = (
              OdInsert(POD_FONTS, XmlElement('font-face-decls', nsUri=nso)),
              OdInsert(POD_STYLES[name], XmlElement(styleTag, nsUri=nso)))
            parser = self.createPodParser('%s.xml' % name, context, inserts)
            setattr(self, '%sParser' % name, parser)
        # Store the styles mapping
        self.setStylesMapping(stylesMapping)
        # While working, POD may identify "dynamic styles" to insert either in
        # the "automatic-styles" section of content.xml (ie, the column styles
        # of tables generated from XHTML tables via xhtml2odt.py), or in the
        # "styles" section of styles.xml (ie, bullet styles).
        self.dynamicStyles = {'content': [], 'styles': []}
Exemple #2
0
class Row(PodElement):
    OD = XmlElement('table-row', nsUri=ns.NS_TABLE)
    subTags = [Cell.OD, Text.OD]
Exemple #3
0
class Title(PodElement):
    OD = XmlElement('h', nsUri=ns.NS_TEXT)
    subTags = []
Exemple #4
0
class Section(PodElement):
    OD = XmlElement('section', nsUri=ns.NS_TEXT)
    subTags = [Text.OD]
    # When we must remove the Section element from a buffer, the deepest element
    # to remove is the Section element itself.
    DEEPEST_TO_REMOVE = OD
Exemple #5
0
class Text(PodElement):
    OD = XmlElement('p', nsUri=ns.NS_TEXT)
    # When generating an error we may need to surround it with a given tag and
    # sub-tags.
    subTags = []