1 # -*- coding: utf-8 -*-
6 Provides a class that holds runtime and parsing time options.
8 :copyright: 2007 by Armin Ronacher.
9 :license: BSD, see LICENSE for more details.
11 from jinja2.lexer import Lexer
12 from jinja2.parser import Parser
13 from jinja2.optimizer import optimize
14 from jinja2.compiler import generate
15 from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
18 class Environment(object):
19 """The Jinja environment.
21 The core component of Jinja is the `Environment`. It contains
22 important shared variables like configuration, filters, tests,
27 block_start_string='{%',
28 block_end_string='%}',
29 variable_start_string='{{',
30 variable_end_string='}}',
31 comment_start_string='{#',
32 comment_end_string='#}',
33 line_statement_prefix=None,
36 """Here the possible initialization parameters:
38 ========================= ============================================
39 `block_start_string` the string marking the begin of a block.
40 this defaults to ``'{%'``.
41 `block_end_string` the string marking the end of a block.
43 `variable_start_string` the string marking the begin of a print
44 statement. defaults to ``'{{'``.
45 `comment_start_string` the string marking the begin of a
46 comment. defaults to ``'{#'``.
47 `comment_end_string` the string marking the end of a comment.
49 `line_statement_prefix` If given and a string, this will be used as
50 prefix for line based statements. See the
51 documentation for more details.
52 `trim_blocks` If this is set to ``True`` the first newline
53 after a block is removed (block, not
54 variable tag!). Defaults to ``False``.
55 `loader` the loader which should be used.
56 ========================= ============================================
59 # lexer / parser information
60 self.block_start_string = block_start_string
61 self.block_end_string = block_end_string
62 self.variable_start_string = variable_start_string
63 self.variable_end_string = variable_end_string
64 self.comment_start_string = comment_start_string
65 self.comment_end_string = comment_end_string
66 self.line_statement_prefix = line_statement_prefix
67 self.trim_blocks = trim_blocks
70 self.filters = DEFAULT_FILTERS.copy()
71 self.tests = DEFAULT_TESTS.copy()
72 self.globals = DEFAULT_NAMESPACE.copy()
74 # if no finalize function/method exists we default to unicode. The
75 # compiler check if the finalize attribute *is* unicode, if yes no
76 # finalizaion is written where it can be avoided.
77 if not hasattr(self, 'finalize'):
78 self.finalize = unicode
80 # set the loader provided
84 self.lexer = Lexer(self)
86 def parse(self, source, filename=None):
87 """Parse the sourcecode and return the abstract syntax tree. This tree
88 of nodes is used by the compiler to convert the template into
89 executable source- or bytecode.
91 parser = Parser(self, source, filename)
94 def lex(self, source, filename=None):
95 """Lex the given sourcecode and return a generator that yields tokens.
96 The stream returned is not usable for Jinja but can be used if
97 Jinja templates should be processed by other tools (for example
98 syntax highlighting etc)
100 The tuples are returned in the form ``(lineno, token, value)``.
102 return self.lexer.tokeniter(source, filename)
104 def compile(self, source, filename=None, raw=False):
105 """Compile a node or source."""
106 if isinstance(source, basestring):
107 source = self.parse(source, filename)
108 node = optimize(source, self)
109 source = generate(node, self, filename)
112 if isinstance(filename, unicode):
113 filename = filename.encode('utf-8')
114 return compile(source, filename, 'exec')
116 def join_path(self, template, parent):
117 """Join a template with the parent. By default all the lookups are
118 relative to the loader root, but if the paths should be relative this
119 function can be used to calculate the real filename."""
122 def get_template(self, name, parent=None):
123 """Load a template."""
124 if self.loader is None:
125 raise TypeError('no loader for this environment specified')
126 if parent is not None:
127 name = self.join_path(name, parent)
128 return self.loader.load(self, name)
130 def from_string(self, source, filename='<string>'):
131 """Load a template from a string."""
132 return Template(self, self.compile(source, filename))
135 class Template(object):
136 """Represents a template."""
138 def __init__(self, environment, code):
140 'environment': environment
142 exec code in namespace
143 self.environment = environment
144 self.name = namespace['filename']
145 self.root_render_func = namespace['root']
146 self.blocks = namespace['blocks']
148 def render(self, *args, **kwargs):
149 return u''.join(self.stream(*args, **kwargs))
151 def stream(self, *args, **kwargs):
152 gen = self.root_render_func(dict(*args, **kwargs))
153 # skip the first item which is a reference to the stream