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)
42 def template_from_code(environment, code, globals, uptodate=None,
44 """Generate a new template object from code. It's used in the
45 template constructor and the loader `load` implementation.
47 t = object.__new__(template_class or environment.template_class)
49 'environment': environment,
50 '__jinja_template__': t
52 exec code in namespace
53 t.environment = environment
54 t.name = namespace['name']
55 t.filename = code.co_filename
56 t.root_render_func = namespace['root']
57 t.blocks = namespace['blocks']
60 # debug and loader helpers
61 t._debug_info = namespace['debug_info']
62 t._uptodate = uptodate
67 class Environment(object):
68 """The Jinja environment.
70 The core component of Jinja is the `Environment`. It contains
71 important shared variables like configuration, filters, tests,
75 #: if this environment is sandboxed. Modifying this variable won't make
76 #: the environment sandboxed though. For a real sandboxed environment
77 #: have a look at jinja2.sandbox
80 #: shared environments have this set to `True`. A shared environment
81 #: must not be modified
85 block_start_string='{%',
86 block_end_string='%}',
87 variable_start_string='{{',
88 variable_end_string='}}',
89 comment_start_string='{#',
90 comment_end_string='#}',
91 line_statement_prefix=None,
98 # !!Important notice!!
99 # The constructor accepts quite a few arguments that should be
100 # passed by keyword rather than position. However it's important to
101 # not change the order of arguments because it's used at least
102 # internally in those cases:
103 # - spontaneus environments (i18n extension and Template)
105 # If parameter changes are required only add parameters at the end
106 # and don't change the arguments (or the defaults!) of the arguments
107 # up to (but excluding) loader.
108 """Here the possible initialization parameters:
110 ========================= ============================================
111 `block_start_string` the string marking the begin of a block.
112 this defaults to ``'{%'``.
113 `block_end_string` the string marking the end of a block.
114 defaults to ``'%}'``.
115 `variable_start_string` the string marking the begin of a print
116 statement. defaults to ``'{{'``.
117 `comment_start_string` the string marking the begin of a
118 comment. defaults to ``'{#'``.
119 `comment_end_string` the string marking the end of a comment.
120 defaults to ``'#}'``.
121 `line_statement_prefix` If given and a string, this will be used as
122 prefix for line based statements. See the
123 documentation for more details.
124 `trim_blocks` If this is set to ``True`` the first newline
125 after a block is removed (block, not
126 variable tag!). Defaults to ``False``.
127 `extensions` List of Jinja extensions to use.
128 `optimized` should the optimizer be enabled? Default is
130 `undefined` a subclass of `Undefined` that is used to
131 represent undefined variables.
132 `finalize` A callable that finalizes the variable. Per
133 default this is `unicode`, other useful
134 builtin finalizers are `escape`.
135 `loader` the loader which should be used.
136 ========================= ============================================
140 assert issubclass(undefined, Undefined), 'undefined must be ' \
141 'a subclass of undefined because filters depend on it.'
142 assert block_start_string != variable_start_string != \
143 comment_start_string, 'block, variable and comment ' \
144 'start strings must be different'
146 # lexer / parser information
147 self.block_start_string = block_start_string
148 self.block_end_string = block_end_string
149 self.variable_start_string = variable_start_string
150 self.variable_end_string = variable_end_string
151 self.comment_start_string = comment_start_string
152 self.comment_end_string = comment_end_string
153 self.line_statement_prefix = line_statement_prefix
154 self.trim_blocks = trim_blocks
156 # runtime information
157 self.undefined = undefined
158 self.optimized = optimized
159 self.finalize = finalize
162 self.filters = DEFAULT_FILTERS.copy()
163 self.tests = DEFAULT_TESTS.copy()
164 self.globals = DEFAULT_NAMESPACE.copy()
166 # set the loader provided
170 self.lexer = Lexer(self)
174 for extension in extensions:
175 if isinstance(extension, basestring):
176 extension = import_string(extension)
177 self.extensions.append(extension(self))
179 def subscribe(self, obj, argument):
180 """Get an item or attribute of an object."""
182 return getattr(obj, str(argument))
183 except (AttributeError, UnicodeError):
186 except (TypeError, LookupError):
187 return self.undefined(obj=obj, name=argument)
189 def parse(self, source, name=None):
190 """Parse the sourcecode and return the abstract syntax tree. This tree
191 of nodes is used by the compiler to convert the template into
192 executable source- or bytecode.
194 return Parser(self, source, name).parse()
196 def lex(self, source, name=None):
197 """Lex the given sourcecode and return a generator that yields tokens.
198 The stream returned is not usable for Jinja but can be used if
199 Jinja templates should be processed by other tools (for example
200 syntax highlighting etc)
202 The tuples are returned in the form ``(lineno, token, value)``.
204 return self.lexer.tokeniter(source, name)
206 def compile(self, source, name=None, filename=None, globals=None,
208 """Compile a node or source. The name is the load name of the
209 template after it was joined using `join_path` if necessary,
210 filename is the estimated filename of the template on the file
211 system. If the template came from a database or memory this
214 if isinstance(source, basestring):
215 source = self.parse(source, name)
217 node = optimize(source, self, globals or {})
218 source = generate(node, self, name, filename)
222 filename = '<template>'
223 elif isinstance(filename, unicode):
224 filename = filename.encode('utf-8')
225 return compile(source, filename, 'exec')
227 def join_path(self, template, parent):
228 """Join a template with the parent. By default all the lookups are
229 relative to the loader root, but if the paths should be relative this
230 function can be used to calculate the real filename."""
233 def get_template(self, name, parent=None, globals=None):
234 """Load a template."""
235 if self.loader is None:
236 raise TypeError('no loader for this environment specified')
237 if parent is not None:
238 name = self.join_path(name, parent)
239 return self.loader.load(self, name, self.make_globals(globals))
241 def from_string(self, source, globals=None, template_class=None):
242 """Load a template from a string."""
243 globals = self.make_globals(globals)
244 return template_from_code(self, self.compile(source, globals=globals),
245 globals, None, template_class)
247 def make_globals(self, d):
248 """Return a dict for the globals."""
251 return dict(self.globals, **d)
254 class Template(object):
255 """The central template object. This class represents a compiled template
256 and is used to evaluate it.
258 Normally the template object is generated from an `Environment` but it
259 also has a constructor that makes it possible to create a template
260 instance directly using the constructor. It takes the same arguments as
261 the environment constructor but it's not possible to specify a loader.
263 Every template object has a few methods and members that are guaranteed
264 to exist. However it's important that a template object should be
265 considered immutable. Modifications on the object are not supported.
267 Template objects created from the constructor rather than an environment
268 do have an `environment` attribute that points to a temporary environment
269 that is probably shared with other templates created with the constructor
270 and compatible settings.
272 >>> template = Template('Hello {{ name }}!')
273 >>> template.render(name='John Doe')
276 >>> stream = template.stream(name='John Doe')
280 Traceback (most recent call last):
285 def __new__(cls, source,
286 block_start_string='{%',
287 block_end_string='%}',
288 variable_start_string='{{',
289 variable_end_string='}}',
290 comment_start_string='{#',
291 comment_end_string='#}',
292 line_statement_prefix=None,
298 env = get_spontaneous_environment(
299 block_start_string, block_end_string, variable_start_string,
300 variable_end_string, comment_start_string, comment_end_string,
301 line_statement_prefix, trim_blocks, tuple(extensions), optimized,
303 return env.from_string(source, template_class=cls)
305 def render(self, *args, **kwargs):
306 """Render the template into a string."""
308 return concat(self.generate(*args, **kwargs))
310 # hide the `generate` frame
311 exc_type, exc_value, tb = sys.exc_info()
312 raise exc_type, exc_value, tb.tb_next
314 def stream(self, *args, **kwargs):
315 """Return a `TemplateStream` that generates the template."""
317 return TemplateStream(self.generate(*args, **kwargs))
319 # hide the `generate` frame
320 exc_type, exc_value, tb = sys.exc_info()
321 raise exc_type, exc_value, tb.tb_next
323 def generate(self, *args, **kwargs):
324 """Return a generator that generates the template."""
325 # assemble the context
326 context = dict(*args, **kwargs)
328 # if the environment is using the optimizer locals may never
329 # override globals as optimizations might have happened
330 # depending on values of certain globals. This assertion goes
331 # away if the python interpreter is started with -O
332 if __debug__ and self.environment.optimized:
333 overrides = set(context) & set(self.globals)
335 plural = len(overrides) != 1 and 's' or ''
336 raise AssertionError('the per template variable%s %s '
337 'override%s global variable%s. '
338 'With an enabled optimizer this '
339 'will lead to unexpected results.' %
340 (plural, ', '.join(overrides), plural or ' a', plural))
343 for event in self.root_render_func(self.new_context(context)):
346 exc_type, exc_value, tb = translate_exception(sys.exc_info())
347 raise exc_type, exc_value, tb
349 def new_context(self, vars=None, shared=False):
350 """Create a new template context for this template. The vars
351 provided will be passed to the template. Per default the globals
352 are added to the context, if shared is set to `True` the data
353 provided is used as parent namespace. This is used to share the
354 same globals in multiple contexts without consuming more memory.
355 (This works because the context does not modify the parent dict)
362 parent = dict(self.globals, **vars)
363 return TemplateContext(self.environment, parent, self.name,
366 def include(self, vars=None):
367 """Include this template. When passed a template context or dict
368 the template is evaluated in that context and an `IncludedTemplate`
369 object is returned. This object then exposes all the exported
370 variables as attributes and renders the contents of the template
371 when converted to unicode.
373 if isinstance(vars, TemplateContext):
374 context = TemplateContext(self.environment, vars.parent,
375 self.name, self.blocks)
377 context = self.new_context(vars)
378 return IncludedTemplate(self, context)
380 def get_corresponding_lineno(self, lineno):
381 """Return the source line number of a line number in the
382 generated bytecode as they are not in sync.
384 for template_line, code_line in reversed(self.debug_info):
385 if code_line <= lineno:
390 def is_up_to_date(self):
391 """If this variable is `False` there is a newer version available."""
392 if self._uptodate is None:
394 return self._uptodate()
397 def debug_info(self):
398 """The debug info mapping."""
399 return [tuple(map(int, x.split('='))) for x in
400 self._debug_info.split('&')]
403 if self.name is None:
404 name = 'memory:%x' % id(self)
406 name = repr(self.name)
407 return '<%s %s>' % (self.__class__.__name__, name)
410 class IncludedTemplate(object):
411 """Represents an included template. All the exported names of the
412 template are available as attributes on this object. Additionally
413 converting it into an unicode- or bytestrings renders the contents.
416 def __init__(self, template, context):
417 self.__body_stream = tuple(template.root_render_func(context))
418 self.__dict__.update(context.get_exported())
419 self.__name__ = template.name
421 __html__ = lambda x: Markup(concat(x.__body_stream))
422 __unicode__ = lambda x: unicode(concat(x.__body_stream))
425 return unicode(self).encode('utf-8')
428 if self.__name__ is None:
429 name = 'memory:%x' % id(self)
431 name = repr(self.name)
432 return '<%s %s>' % (self.__class__.__name__, name)
435 class TemplateStream(object):
436 """This class wraps a generator returned from `Template.generate` so that
437 it's possible to buffer multiple elements so that it's possible to return
438 them from a WSGI application which flushes after each iteration.
441 def __init__(self, gen):
443 self._next = gen.next
444 self.buffered = False
446 def disable_buffering(self):
447 """Disable the output buffering."""
448 self._next = self._gen.next
449 self.buffered = False
451 def enable_buffering(self, size=5):
452 """Enable buffering. Buffer `size` items before yielding them."""
454 raise ValueError('buffer size too small')
460 next = self._gen.next
467 except StopIteration:
475 self._next = generator().next
484 # hook in default template class. if anyone reads this comment: ignore that
485 # it's possible to use custom templates ;-)
486 Environment.template_class = Template