:copyright: 2006 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
+from jinja.environment import Environment
+from jinja.template import Template
+
+__all__ = ['Environment', 'Template']
(string_re, 'string', None)
]
+ # assamble the root lexing rule. because "|" is ungreedy
+ # we have to sort by length so that the lexer continues working
+ # as expected when we have parsing rules like <% for block and
+ # <%= for variables. (if someone wants asp like syntax)
+ root_tag_rules = [
+ ('comment', environment.comment_start_string),
+ ('block', environment.block_start_string),
+ ('variable', environment.variable_start_string)
+ ]
+ root_tag_rules.sort(lambda a, b: cmp(len(b[1]), len(a[1])))
+
# global parsing rules
self.rules = {
'root': [
- (c('(.*?)(?:(?P<comment_begin>' +
- e(environment.comment_start_string) +
- ')|(?P<block_begin>' +
- e(environment.block_start_string) +
- ')|(?P<variable_begin>' +
- e(environment.variable_start_string) +
- '))'), ('data', '#bygroup'), '#bygroup'),
+ (c('(.*?)(?:%s)' % '|'.join([
+ '(?P<%s_begin>%s)' % (n, e(r)) for n, r in root_tag_rules
+ ])), ('data', '#bygroup'), '#bygroup'),
+ #(c('(.*?)(?:(?P<comment_begin>' +
+ # e(environment.comment_start_string) +
+ # ')|(?P<block_begin>' +
+ # e(environment.block_start_string) +
+ # ')|(?P<variable_begin>' +
+ # e(environment.variable_start_string) +
+ # '))'), ('data', '#bygroup'), '#bygroup'),
(c('.+'), 'data', None)
],
'comment_begin': [
# first token *must* be a name token
if token != 'name':
- raise TemplateSyntaxError('unexpected %r token' % token, lineno)
+ raise TemplateSyntaxError('unexpected %r token (%r)' % (
+ token, data), lineno)
# if a test function is passed to subparse we check if we
# reached the end of such a requested block.
# so this should be unreachable code
else:
- raise AssertionError('unexpected token %r(%r)' % (token, data))
+ raise AssertionError('unexpected token %r (%r)' % (token, data))
# still here and a test function is provided? raise and error
if test is not None:
:license: BSD, see LICENSE for more details.
"""
+from jinja.nodes import Node
from jinja.datastructure import Context
+from jinja.translators.python import parse_and_translate, translate
+
+
+def evaluate_source(source):
+ """
+ Evaluate a sourcecode and return the generate function.
+ """
+ ns = {}
+ exec source in ns
+ return ns['generate']
class Template(object):
Represents a finished template.
"""
- def __init__(self, environment, generate_func):
+ def __init__(self, environment, source):
+ if isinstance(source, basestring):
+ self.source = parse_and_translate(environment, source)
+ elif isinstance(source, Node):
+ self.source = translate(environment, source)
+ else:
+ raise TypeError('unsupported source type %r' %
+ source.__class__.__name__)
self.environment = environment
- self.generate_func = generate_func
+ self.generate_func = None
def render(self, *args, **kwargs):
+ """
+ Render a template.
+ """
+ if self.generate_func is None:
+ self.generate_func = evaluate_source(self.source)
result = []
ctx = Context(self.environment, *args, **kwargs)
self.generate_func(ctx, result.append)
"""
from compiler import ast
from jinja import nodes
+from jinja.parser import Parser
from jinja.exceptions import TemplateSyntaxError
Do the translation to python.
"""
return PythonTranslator(environment, node).translate()
+
+
+def parse_and_translate(environment, source, filename=None):
+ """
+ Parse sourcecode and translate it to python
+ """
+ node = Parser(environment, source, filename).parse()
+ return PythonTranslator(environment, node).translate()
def load_template(x):
from jinja.template import Template
- from jinja.parser import Parser
- from jinja.translators.python import translate
- code = translate(e, Parser(e, x).parse())
- ns = {}
- exec code in ns
- return Template(e, ns['generate'])
+ return Template(e, x)