# <b>pod</b> - Rendering templates

# Rendering a pod template

In order to render a pod template, the first thing to do is to create a renderer (create a appy.pod.Renderer instance). The constructor for this class looks like this:

class Renderer:
def __init__(self, template, context, result, pythonWithUnoPath=None,
ooPort=2002, stylesMapping={}, forceOoCall=False,
finalizeFunction=None, overwriteExisting=False,
imageResolver=None):
'''This Python Open Document Renderer (PodRenderer) loads a document
template (p_template) which is an ODT 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, 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, 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 result. This way,
you can still perform some actions on the content of the ODT file
before it is zipped and potentially converted. This function must
accept one arg: the absolute path to the temporary folder containing
the un-zipped content of the ODT result.
- 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.
- 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.
'''

For the template and the result, you can specify absolute or relative paths. I guess it is better to always specify absolute paths.

The context may be either a dict, UserDict, or an instance. If it is an instance, its __dict__ attribute is used. For example, context may be the result of calling globals() or locals(). Every (key, value) pair defined in the context corresponds to a name (the key) that you can use within your template within pod statements or expressions. Those names may refer to any Python object: a function, a variable, an object, a module, etc.

Once you have the Renderer instance, simply call its run method. This method may raise a appy.pod.PodError exception.

Since pod 0.0.2, you may put a XHTML document somewhere in the context and ask pod to convert it as a chunk of OpenDocument into the resulting OpenDocument. You may want to customize the mapping between XHTML and OpenDocument styles. This can be done through the stylesMapping parameter. A detailed explanation about the "XHTML to OpenDocument" abilities of pod may be found here.

# Result formats

If result ends with .odt, LibreOffice will NOT be called (unless forceOoCall is True). pod does not need LibreOffice to generate a result in ODT format, excepted in the following cases:

- you need to update fields in the result (ie a table of contents);
- you need to include external documents into the result (ODT, PDF, Word, ...) by using special function document.

If result ends with:

- .pdf,
- .doc (Microsoft Word 97),
- .rtf or
- .txt,

LibreOffice will be called in order to convert a temporary ODT file rendered by pod into the desired format. This will work only if your Python interpreter knows about the Python UNO bindings. UNO is the OpenOffice API. If typing import uno at the interpreter prompt does not produce an error, your interpreter is UNO-enabled. If not, there is probably a UNO-enabled Python interpreter within your LibreOffice copy (in <LibreOfficePath>/program). In this case you can specify this path in the pythonWithUnoPath parameter of the Renderer constructor. Note that when using a UNO-disabled interpreter, there will be one additional process fork for launching a Python-enabled interpreter.

During rendering, pod uses a temp folder located at <result>.temp.

# Launching LibreOffice in server mode

You launch LibreOffice in server mode by running the command (under Linux):

soffice -invisible -headless "-accept=socket,host=localhost,port=2002;urp;"

Under Windows it may look like:

"[path_to_lo]\program\soffice" -invisible -headless "-accept=socket,host=localhost,port=2002;urp;"

Of course, use any port number you prefer.