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.
12 from jinja2.lexer import Lexer
13 from jinja2.parser import Parser
14 from jinja2.optimizer import optimize
15 from jinja2.compiler import generate
16 from jinja2.runtime import Undefined, TemplateContext, concat
17 from jinja2.debug import translate_exception
18 from jinja2.utils import import_string, LRUCache, Markup
19 from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
22 # for direct template usage we have up to ten living environments
23 _spontaneous_environments = LRUCache(10)
26 def get_spontaneous_environment(*args):
27 """Return a new spontaneus environment. A spontaneus environment is an
28 unnamed and unaccessable (in theory) environment that is used for
29 template generated from a string and not from the file system.
32 env = _spontaneous_environments.get(args)
34 return Environment(*args)
37 _spontaneous_environments[args] = env = Environment(*args)
41 def template_from_code(environment, code, globals, uptodate=None,
43 """Generate a new template object from code. It's used in the
44 template constructor and the loader `load` implementation.
46 t = object.__new__(template_class or environment.template_class)
48 'environment': environment,
49 '__jinja_template__': t
51 exec code in namespace
52 t.environment = environment
53 t.name = namespace['name']
54 t.filename = code.co_filename
55 t.root_render_func = namespace['root']
56 t.blocks = namespace['blocks']
59 # debug and loader helpers
60 t._debug_info = namespace['debug_info']
61 t._uptodate = uptodate
66 class Environment(object):
67 """The Jinja environment.
69 The core component of Jinja is the `Environment`. It contains
70 important shared variables like configuration, filters, tests,
74 #: if this environment is sandboxed. Modifying this variable won't make
75 #: the environment sandboxed though. For a real sandboxed environment
76 #: have a look at jinja2.sandbox
80 block_start_string='{%',
81 block_end_string='%}',
82 variable_start_string='{{',
83 variable_end_string='}}',
84 comment_start_string='{#',
85 comment_end_string='#}',
86 line_statement_prefix=None,
93 # !!Important notice!!
94 # The constructor accepts quite a few arguments that should be
95 # passed by keyword rather than position. However it's important to
96 # not change the order of arguments because it's used at least
97 # internally in those cases:
98 # - spontaneus environments (i18n extension and Template)
100 # If parameter changes are required only add parameters at the end
101 # and don't change the arguments (or the defaults!) of the arguments
102 # up to (but excluding) loader.
103 """Here the possible initialization parameters:
105 ========================= ============================================
106 `block_start_string` the string marking the begin of a block.
107 this defaults to ``'{%'``.
108 `block_end_string` the string marking the end of a block.
109 defaults to ``'%}'``.
110 `variable_start_string` the string marking the begin of a print
111 statement. defaults to ``'{{'``.
112 `comment_start_string` the string marking the begin of a
113 comment. defaults to ``'{#'``.
114 `comment_end_string` the string marking the end of a comment.
115 defaults to ``'#}'``.
116 `line_statement_prefix` If given and a string, this will be used as
117 prefix for line based statements. See the
118 documentation for more details.
119 `trim_blocks` If this is set to ``True`` the first newline
120 after a block is removed (block, not
121 variable tag!). Defaults to ``False``.
122 `extensions` List of Jinja extensions to use.
123 `optimized` should the optimizer be enabled? Default is
125 `undefined` a subclass of `Undefined` that is used to
126 represent undefined variables.
127 `finalize` A callable that finalizes the variable. Per
128 default this is `unicode`, other useful
129 builtin finalizers are `escape`.
130 `loader` the loader which should be used.
131 ========================= ============================================
135 assert issubclass(undefined, Undefined), 'undefined must be ' \
136 'a subclass of undefined because filters depend on it.'
137 assert block_start_string != variable_start_string != \
138 comment_start_string, 'block, variable and comment ' \
139 'start strings must be different'
141 # lexer / parser information
142 self.block_start_string = block_start_string
143 self.block_end_string = block_end_string
144 self.variable_start_string = variable_start_string
145 self.variable_end_string = variable_end_string
146 self.comment_start_string = comment_start_string
147 self.comment_end_string = comment_end_string
148 self.line_statement_prefix = line_statement_prefix
149 self.trim_blocks = trim_blocks
151 # runtime information
152 self.undefined = undefined
153 self.optimized = optimized
154 self.finalize = finalize
157 self.filters = DEFAULT_FILTERS.copy()
158 self.tests = DEFAULT_TESTS.copy()
159 self.globals = DEFAULT_NAMESPACE.copy()
161 # set the loader provided
165 self.lexer = Lexer(self)
169 for extension in extensions:
170 if isinstance(extension, basestring):
171 extension = import_string(extension)
172 self.extensions.append(extension(self))
174 def subscribe(self, obj, argument):
175 """Get an item or attribute of an object."""
177 return getattr(obj, str(argument))
178 except (AttributeError, UnicodeError):
181 except (TypeError, LookupError):
182 return self.undefined(obj=obj, name=argument)
184 def parse(self, source, name=None):
185 """Parse the sourcecode and return the abstract syntax tree. This tree
186 of nodes is used by the compiler to convert the template into
187 executable source- or bytecode.
189 return Parser(self, source, name).parse()
191 def lex(self, source, name=None):
192 """Lex the given sourcecode and return a generator that yields tokens.
193 The stream returned is not usable for Jinja but can be used if
194 Jinja templates should be processed by other tools (for example
195 syntax highlighting etc)
197 The tuples are returned in the form ``(lineno, token, value)``.
199 return self.lexer.tokeniter(source, name)
201 def compile(self, source, name=None, filename=None, globals=None,
203 """Compile a node or source. The name is the load name of the
204 template after it was joined using `join_path` if necessary,
205 filename is the estimated filename of the template on the file
206 system. If the template came from a database or memory this
209 if isinstance(source, basestring):
210 source = self.parse(source, name)
212 node = optimize(source, self, globals or {})
213 source = generate(node, self, name, filename)
217 filename = '<template>'
218 elif isinstance(filename, unicode):
219 filename = filename.encode('utf-8')
220 return compile(source, filename, 'exec')
222 def join_path(self, template, parent):
223 """Join a template with the parent. By default all the lookups are
224 relative to the loader root, but if the paths should be relative this
225 function can be used to calculate the real filename."""
228 def get_template(self, name, parent=None, globals=None):
229 """Load a template."""
230 if self.loader is None:
231 raise TypeError('no loader for this environment specified')
232 if parent is not None:
233 name = self.join_path(name, parent)
234 return self.loader.load(self, name, self.make_globals(globals))
236 def from_string(self, source, globals=None, template_class=None):
237 """Load a template from a string."""
238 globals = self.make_globals(globals)
239 return template_from_code(self, self.compile(source, globals=globals),
240 globals, None, template_class)
242 def make_globals(self, d):
243 """Return a dict for the globals."""
246 return dict(self.globals, **d)
249 class Template(object):
250 """The central template object. This class represents a compiled template
251 and is used to evaluate it.
253 Normally the template object is generated from an `Environment` but it
254 also has a constructor that makes it possible to create a template
255 instance directly using the constructor. It takes the same arguments as
256 the environment constructor but it's not possible to specify a loader.
258 Every template object has a few methods and members that are guaranteed
259 to exist. However it's important that a template object should be
260 considered immutable. Modifications on the object are not supported.
262 Template objects created from the constructor rather than an environment
263 do have an `environment` attribute that points to a temporary environment
264 that is probably shared with other templates created with the constructor
265 and compatible settings.
267 >>> template = Template('Hello {{ name }}!')
268 >>> template.render(name='John Doe')
271 >>> stream = template.stream(name='John Doe')
275 Traceback (most recent call last):
280 def __new__(cls, source,
281 block_start_string='{%',
282 block_end_string='%}',
283 variable_start_string='{{',
284 variable_end_string='}}',
285 comment_start_string='{#',
286 comment_end_string='#}',
287 line_statement_prefix=None,
293 env = get_spontaneous_environment(
294 block_start_string, block_end_string, variable_start_string,
295 variable_end_string, comment_start_string, comment_end_string,
296 line_statement_prefix, trim_blocks, tuple(extensions), optimized,
298 return env.from_string(source, template_class=cls)
300 def render(self, *args, **kwargs):
301 """Render the template into a string."""
303 return concat(self.generate(*args, **kwargs))
305 # hide the `generate` frame
306 exc_type, exc_value, tb = sys.exc_info()
307 raise exc_type, exc_value, tb.tb_next
309 def stream(self, *args, **kwargs):
310 """Return a `TemplateStream` that generates the template."""
312 return TemplateStream(self.generate(*args, **kwargs))
314 # hide the `generate` frame
315 exc_type, exc_value, tb = sys.exc_info()
316 raise exc_type, exc_value, tb.tb_next
318 def generate(self, *args, **kwargs):
319 """Return a generator that generates the template."""
320 # assemble the context
321 context = dict(*args, **kwargs)
323 # if the environment is using the optimizer locals may never
324 # override globals as optimizations might have happened
325 # depending on values of certain globals. This assertion goes
326 # away if the python interpreter is started with -O
327 if __debug__ and self.environment.optimized:
328 overrides = set(context) & set(self.globals)
330 plural = len(overrides) != 1 and 's' or ''
331 raise AssertionError('the per template variable%s %s '
332 'override%s global variable%s. '
333 'With an enabled optimizer this '
334 'will lead to unexpected results.' %
335 (plural, ', '.join(overrides), plural or ' a', plural))
338 for event in self.root_render_func(self.new_context(context)):
341 exc_type, exc_value, tb = translate_exception(sys.exc_info())
342 raise exc_type, exc_value, tb
344 def new_context(self, vars):
345 """Create a new template context for this template."""
346 return TemplateContext(self.environment, dict(self.globals, **vars),
347 self.name, self.blocks)
349 def include(self, context=None):
350 """Include this template. When passed a template context or dict
351 the template is evaluated in that context and an `IncludedTemplate`
352 object is returned. This object then exposes all the exported
353 variables as attributes and renders the contents of the template
354 when converted to unicode.
357 context = self.new_context({})
358 elif isinstance(context, TemplateContext):
359 context = self.new_context(context.get_root())
361 context = self.new_context(context)
362 return IncludedTemplate(self, context)
364 def get_corresponding_lineno(self, lineno):
365 """Return the source line number of a line number in the
366 generated bytecode as they are not in sync.
368 for template_line, code_line in reversed(self.debug_info):
369 if code_line <= lineno:
374 def is_up_to_date(self):
375 """If this variable is `False` there is a newer version available."""
376 if self._uptodate is None:
378 return self._uptodate()
381 def debug_info(self):
382 """The debug info mapping."""
383 return [tuple(map(int, x.split('='))) for x in
384 self._debug_info.split('&')]
387 if self.name is None:
388 name = 'memory:%x' % id(self)
390 name = repr(self.name)
391 return '<%s %s>' % (self.__class__.__name__, name)
394 class IncludedTemplate(object):
395 """Represents an included template. All the exported names of the
396 template are available as attributes on this object. Additionally
397 converting it into an unicode- or bytestrings renders the contents.
400 def __init__(self, template, context):
401 self.__body_stream = tuple(template.root_render_func(context))
402 self.__dict__.update(context.get_exported())
403 self.__name__ = template.name
405 __html__ = lambda x: Markup(concat(x.__body_stream))
406 __unicode__ = lambda x: unicode(concat(x.__body_stream))
409 return unicode(self).encode('utf-8')
412 if self.__name__ is None:
413 name = 'memory:%x' % id(self)
415 name = repr(self.name)
416 return '<%s %s>' % (self.__class__.__name__, name)
419 class TemplateStream(object):
420 """This class wraps a generator returned from `Template.generate` so that
421 it's possible to buffer multiple elements so that it's possible to return
422 them from a WSGI application which flushes after each iteration.
425 def __init__(self, gen):
427 self._next = gen.next
428 self.buffered = False
430 def disable_buffering(self):
431 """Disable the output buffering."""
432 self._next = self._gen.next
433 self.buffered = False
435 def enable_buffering(self, size=5):
436 """Enable buffering. Buffer `size` items before yielding them."""
438 raise ValueError('buffer size too small')
444 next = self._gen.next
451 except StopIteration:
459 self._next = generator().next
468 # hook in default template class. if anyone reads this comment: ignore that
469 # it's possible to use custom templates ;-)
470 Environment.template_class = Template