Source code for jmb.core.utils.appypod_utils

# -*- coding: utf-8 -*-
"""
.. _appypod:

OpenOffice Utils via ``appy.pod``
=================================

.. note:: Nuovo

   Questo modulo rimpiazza :ref:`ooutils`

Il modulo utilizza la libreria appy.pod_ per generare documenti a partire da 
un template in formato ``.odt``. 

Esempio d'uso::

    from django.http import HttpResponse

    from jmb.core.utils.appypod import AppyPodTemplate

    def example_view_pdf(request):
        context = dict(first_name="<name>", last_name="<last_name>")
        template_file = "<path_to_template_file>"
        appy_pod_template = AppyPodTemplate(template_file, context)
        rendered_template = template.render()
        return HttpResponse(rendered_template, mimetype="application/pdf")

    def example_view_odt(request):
        context = dict(first_name="<name>", last_name="<last_name>")
        template_file = "<path_to_template_file>"
        appy_pod_template = AppyPodTemplate(template_file, context)
        rendered_template = template.render(file_type="odt")
        return HttpResponse(rendered_template, mimetype="application/vnd.oasis.opendocument.text")

.. autoclass:: JmbAppyPodTemplate
   :members:

.. autofunction:: convert

.. _appy.pod: http://appyframework.org/

"""
import os
import glob
import fnmatch
import logging
from tempfile import NamedTemporaryFile

import appy.pod
from appy.pod.converter import Converter, ConverterError
from appy.shared.utils import executeCommand
from django.conf import settings
from jmb.core.utils.functions import get_template_abspath
from appy.pod.renderer import Renderer

logger = logging.getLogger('jmb.core')

class AppyPodTemplate():
    """
    Interface to get handle templates in .odt, .ods
    """

    def __init__(self, template=None, context=None):
        """
        Object init function.

        :param template: (string) template file to render. Std django search is performed
        :param context: context to be used on template rendering
        """
        self.set_template(template)
        self.context = context

    def set_template(self, template):
        """
        Set template 

        :param template: (string) template file to render. Std djano search is applied
        """
        if not os.path.isabs(template):
            template = get_template_abspath(template)
        self.template = template

    def update_context(self, context):
        """
        Function to update context instance

        :param template: absolute path to template file to render (must be a string)
        """
        self.context.update(context)

    def render(self, file_type="pdf"):
        """
        Instance render function.

        :param file_type: output file extension
        :return: generated file stream if created, else None
        """
        result = None
        output = None
        with NamedTemporaryFile('rwb', suffix='.%s' % file_type, delete=False) as f:
            output = f.name
            renderer = Renderer(
                self.template, self.context, output, 
                ooPort=settings.JMB_OOO_SERVER_PORT, 
                overwriteExisting=True,
                pythonWithUnoPath=settings.JMB_OOO_UNO_PYTHON_PATH,
            )
            renderer.run()
        result = open(output, 'rb').read()
        if output and os.path.exists(output):
            os.unlink(output)
        return result

    def save_as(self, output_path):
        """
        Save the template into file

        :arg output_path: the output path
        :return: the open handler of the generated file
        """
        file_type = os.path.splitext(output_path)[1].lstrip('.')
        f = open(output_path, 'w')
        f.write(self.render(file_type=file_type))
        f.flush()
        return f


[docs]def convert(file_names, result_type='pdf', tree=None): """Call LibreOffice in server mode to convert or update the result. :arg file_names: the file name to be converted. A list, a set, a tuple or a glob pattern is accepted. If dir is defined is interpreted as a pattern. :arg file_type: the resul_type desired (default: pdf) :arg tree: if dir is defined the whole directory is searched for pattern and file_names is interpreted as a pattern """ # inject_app_defaults does not work here. PY_PATH = getattr(settings, 'JMB_OOO_UNO_PYTHON_PATH', None) OOO_PORT = getattr(settings, 'JMB_OOO_SERVER_PORT', 8100) if tree: file_names = recursive_glob(tree, file_names) elif not isinstance(file_names, (list, tuple, set)): if os.path.exists(file_names): file_names = [ file_names ] else: file_names = glob.glob(file_names) output_files = [] for file_name in file_names: name, ext = os.path.splitext(file_name) if not PY_PATH: try: Converter(file_name, result_type, OOO_PORT).run() except ConverterError, ce: raise PodError(CONVERT_ERROR % str(ce)) else: if not os.path.isfile(PY_PATH): raise PodError(PY_PATH_NOT_FILE % PY_PATH) if file_name.find(' ') != -1: qResultName = '"%s"' % file_name else: qResultName = file_name convScript = '%s/converter.py' % os.path.dirname(appy.pod.__file__) if convScript.find(' ') != -1: convScript = '"%s"' % convScript cmd = '%s %s %s %s -p%d' % \ (PY_PATH, convScript, qResultName, result_type, OOO_PORT) loOutput = executeCommand(cmd) output_files += ["%s.%s" % (name, result_type)] return output_files
def recursive_glob(treeroot, pattern): results = [] for base, dirs, files in os.walk(treeroot): goodfiles = fnmatch.filter(files, pattern) results.extend(os.path.join(base, f) for f in goodfiles) return results