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.runtime import Undefined
16 from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
19 class Environment(object):
20 """The Jinja environment.
22 The core component of Jinja is the `Environment`. It contains
23 important shared variables like configuration, filters, tests,
27 #: if this environment is sandboxed. Modifying this variable won't make
28 #: the environment sandboxed though. For a real sandboxed environment
29 #: have a look at jinja2.sandbox
33 block_start_string='{%',
34 block_end_string='%}',
35 variable_start_string='{{',
36 variable_end_string='}}',
37 comment_start_string='{#',
38 comment_end_string='#}',
39 line_statement_prefix=None,
44 """Here the possible initialization parameters:
46 ========================= ============================================
47 `block_start_string` the string marking the begin of a block.
48 this defaults to ``'{%'``.
49 `block_end_string` the string marking the end of a block.
51 `variable_start_string` the string marking the begin of a print
52 statement. defaults to ``'{{'``.
53 `comment_start_string` the string marking the begin of a
54 comment. defaults to ``'{#'``.
55 `comment_end_string` the string marking the end of a comment.
57 `line_statement_prefix` If given and a string, this will be used as
58 prefix for line based statements. See the
59 documentation for more details.
60 `trim_blocks` If this is set to ``True`` the first newline
61 after a block is removed (block, not
62 variable tag!). Defaults to ``False``.
63 `optimized` should the optimizer be enabled? Default is
65 `undefined` a subclass of `Undefined` that is used to
66 represent undefined variables.
67 `loader` the loader which should be used.
68 ========================= ============================================
72 assert issubclass(undefined, Undefined), 'undefined must be ' \
73 'a subclass of undefined because filters depend on it.'
74 assert block_start_string != variable_start_string != \
75 comment_start_string, 'block, variable and comment ' \
76 'start strings must be different'
78 # lexer / parser information
79 self.block_start_string = block_start_string
80 self.block_end_string = block_end_string
81 self.variable_start_string = variable_start_string
82 self.variable_end_string = variable_end_string
83 self.comment_start_string = comment_start_string
84 self.comment_end_string = comment_end_string
85 self.line_statement_prefix = line_statement_prefix
86 self.trim_blocks = trim_blocks
87 self.undefined = undefined
88 self.optimized = optimized
91 self.filters = DEFAULT_FILTERS.copy()
92 self.tests = DEFAULT_TESTS.copy()
93 self.globals = DEFAULT_NAMESPACE.copy()
95 # if no finalize function/method exists we default to unicode. The
96 # compiler check if the finalize attribute *is* unicode, if yes no
97 # finalizaion is written where it can be avoided.
98 if not hasattr(self, 'finalize'):
99 self.finalize = unicode
101 # set the loader provided
105 self.lexer = Lexer(self)
107 def subscribe(self, obj, argument):
108 """Get an item or attribute of an object."""
110 return getattr(obj, str(argument))
111 except (AttributeError, UnicodeError):
114 except (TypeError, LookupError):
115 return self.undefined(obj, argument)
117 def parse(self, source, filename=None):
118 """Parse the sourcecode and return the abstract syntax tree. This tree
119 of nodes is used by the compiler to convert the template into
120 executable source- or bytecode.
122 parser = Parser(self, source, filename)
123 return parser.parse()
125 def lex(self, source, filename=None):
126 """Lex the given sourcecode and return a generator that yields tokens.
127 The stream returned is not usable for Jinja but can be used if
128 Jinja templates should be processed by other tools (for example
129 syntax highlighting etc)
131 The tuples are returned in the form ``(lineno, token, value)``.
133 return self.lexer.tokeniter(source, filename)
135 def compile(self, source, filename=None, raw=False, globals=None):
136 """Compile a node or source."""
137 if isinstance(source, basestring):
138 source = self.parse(source, filename)
140 node = optimize(source, self, globals or {})
141 source = generate(node, self, filename)
146 filename = '<from_string>'
147 elif isinstance(filename, unicode):
148 filename = filename.encode('utf-8')
149 return compile(source, filename, 'exec')
151 def join_path(self, template, parent):
152 """Join a template with the parent. By default all the lookups are
153 relative to the loader root, but if the paths should be relative this
154 function can be used to calculate the real filename."""
157 def get_template(self, name, parent=None, globals=None):
158 """Load a template."""
159 if self.loader is None:
160 raise TypeError('no loader for this environment specified')
161 if parent is not None:
162 name = self.join_path(name, parent)
163 globals = self.make_globals(globals)
164 return self.loader.load(self, name, globals)
166 def from_string(self, source, filename='<string>', globals=None):
167 """Load a template from a string."""
168 globals = self.make_globals(globals)
169 return Template(self, self.compile(source, filename, globals=globals),
172 def make_globals(self, d):
173 """Return a dict for the globals."""
176 return dict(self.globals, **d)
179 class Template(object):
180 """Represents a template."""
182 def __init__(self, environment, code, globals):
183 namespace = {'environment': environment}
184 exec code in namespace
185 self.environment = environment
186 self.name = namespace['filename']
187 self.root_render_func = namespace['root']
188 self.blocks = namespace['blocks']
189 self.globals = globals
191 def render(self, *args, **kwargs):
192 return u''.join(self.generate(*args, **kwargs))
194 def stream(self, *args, **kwargs):
195 return TemplateStream(self.generate(*args, **kwargs))
197 def generate(self, *args, **kwargs):
198 # assemble the context
199 context = dict(*args, **kwargs)
201 # if the environment is using the optimizer locals may never
202 # override globals as optimizations might have happened
203 # depending on values of certain globals. This assertion goes
204 # away if the python interpreter is started with -O
205 if __debug__ and self.environment.optimized:
206 overrides = set(context) & set(self.globals)
208 plural = len(overrides) != 1 and 's' or ''
209 raise AssertionError('the per template variable%s %s '
210 'override%s global variable%s. '
211 'With an enabled optimizer this '
212 'will lead to unexpected results.' %
213 (plural, ', '.join(overrides), plural or ' a', plural))
214 gen = self.root_render_func(dict(self.globals, **context))
215 # skip the first item which is a reference to the context
221 self.__class__.__name__,
226 class TemplateStream(object):
227 """Wraps a genererator for outputing template streams."""
229 def __init__(self, gen):
231 self._next = gen.next
232 self.buffered = False
234 def disable_buffering(self):
235 """Disable the output buffering."""
236 self._next = self._gen.next
237 self.buffered = False
239 def enable_buffering(self, size=5):
240 """Enable buffering. Buffer `size` items before yielding them."""
242 raise ValueError('buffer size too small')
245 def buffering_next():
249 next = self._gen.next
258 raise StopIteration()
259 except StopIteration:
264 self._next = buffering_next