Edgewall Software

source: tags/0.3.0/genshi/plugin.py

Last change on this file was 299, checked in by cmlenz, 17 years ago

Fixed EOL style.

  • Property svn:eol-style set to native
File size: 3.2 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2006 Edgewall Software
4# Copyright (C) 2006 Matthew Good
5# All rights reserved.
6#
7# This software is licensed as described in the file COPYING, which
8# you should have received as part of this distribution. The terms
9# are also available at http://genshi.edgewall.org/wiki/License.
10#
11# This software consists of voluntary contributions made by many
12# individuals. For the exact contribution history, see the revision
13# history and logs, available at http://genshi.edgewall.org/log/.
14
15"""Basic support for the template engine plugin API used by TurboGears and
16CherryPy/Buffet.
17"""
18
19from pkg_resources import resource_filename
20
21from genshi.core import Attrs, Stream, QName
22from genshi.eval import Undefined
23from genshi.input import HTML, XML
24from genshi.template import Context, MarkupTemplate, Template, TemplateLoader
25
26def ET(element):
27    """Converts the given ElementTree element to a markup stream."""
28    tag_name = element.tag
29    if tag_name.startswith('{'):
30        tag_name = tag_name[1:]
31    tag_name = QName(tag_name)
32    attrib = Attrs(element.items())
33
34    yield (Stream.START, (tag_name, attrib), (None, -1, -1))
35    if element.text:
36        yield Stream.TEXT, element.text, (None, -1, -1)
37    for child in element.getchildren():
38        for item in ET(child):
39            yield item
40    yield Stream.END, tag_name, (None, -1, -1)
41    if element.tail:
42        yield Stream.TEXT, element.tail, (None, -1, -1)
43
44
45class TemplateEnginePlugin(object):
46    """Implementation of the plugin API."""
47
48    def __init__(self, extra_vars_func=None, options=None):
49        if options is None:
50            options = {}
51        # TODO get loader_args from the options dict
52
53        self.loader = TemplateLoader(auto_reload=True)
54        self.options = options
55        self.get_extra_vars = extra_vars_func
56
57    def load_template(self, templatename, template_string=None):
58        """Find a template specified in python 'dot' notation, or load one from
59        a string.
60        """
61        if template_string is not None:
62            return MarkupTemplate(template_string)
63
64        divider = templatename.rfind('.')
65        if divider >= 0:
66            package = templatename[:divider]
67            basename = templatename[divider + 1:] + '.html'
68            templatename = resource_filename(package, basename)
69
70        return self.loader.load(templatename)
71
72    def render(self, info, format='html', fragment=False, template=None):
73        """Render the template to a string using the provided info."""
74        return self.transform(info, template).render(method=format)
75
76    def transform(self, info, template):
77        """Render the output to an event stream."""
78        if not isinstance(template, Template):
79            template = self.load_template(template)
80
81        data = {'ET': ET, 'HTML': HTML, 'XML': XML}
82        if self.get_extra_vars:
83            data.update(self.get_extra_vars())
84        data.update(info)
85        ctxt = Context(**data)
86
87        # Some functions for Kid compatibility
88        def defined(name):
89            return ctxt.get(name, Undefined) is not Undefined
90        ctxt['defined'] = defined
91        def value_of(name, default=None):
92            return ctxt.get(name, default)
93        ctxt['value_of'] = value_of
94
95        return template.generate(ctxt)
Note: See TracBrowser for help on using the repository browser.