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, ParserExtension
14 from jinja2.optimizer import optimize
15 from jinja2.compiler import generate
16 from jinja2.runtime import Undefined
17 from jinja2.debug import translate_exception
18 from jinja2.utils import import_string
19 from jinja2.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
22 class Environment(object):
23 """The Jinja environment.
25 The core component of Jinja is the `Environment`. It contains
26 important shared variables like configuration, filters, tests,
30 #: if this environment is sandboxed. Modifying this variable won't make
31 #: the environment sandboxed though. For a real sandboxed environment
32 #: have a look at jinja2.sandbox
36 block_start_string='{%',
37 block_end_string='%}',
38 variable_start_string='{{',
39 variable_end_string='}}',
40 comment_start_string='{#',
41 comment_end_string='#}',
42 line_statement_prefix=None,
49 """Here the possible initialization parameters:
51 ========================= ============================================
52 `block_start_string` the string marking the begin of a block.
53 this defaults to ``'{%'``.
54 `block_end_string` the string marking the end of a block.
56 `variable_start_string` the string marking the begin of a print
57 statement. defaults to ``'{{'``.
58 `comment_start_string` the string marking the begin of a
59 comment. defaults to ``'{#'``.
60 `comment_end_string` the string marking the end of a comment.
62 `line_statement_prefix` If given and a string, this will be used as
63 prefix for line based statements. See the
64 documentation for more details.
65 `trim_blocks` If this is set to ``True`` the first newline
66 after a block is removed (block, not
67 variable tag!). Defaults to ``False``.
68 `optimized` should the optimizer be enabled? Default is
70 `undefined` a subclass of `Undefined` that is used to
71 represent undefined variables.
72 `loader` the loader which should be used.
73 `parser_extensions` List of parser extensions to use.
74 `finalize` A callable that finalizes the variable. Per
75 default this is `unicode`, other useful
76 builtin finalizers are `escape`.
77 ========================= ============================================
81 assert issubclass(undefined, Undefined), 'undefined must be ' \
82 'a subclass of undefined because filters depend on it.'
83 assert block_start_string != variable_start_string != \
84 comment_start_string, 'block, variable and comment ' \
85 'start strings must be different'
87 # lexer / parser information
88 self.block_start_string = block_start_string
89 self.block_end_string = block_end_string
90 self.variable_start_string = variable_start_string
91 self.variable_end_string = variable_end_string
92 self.comment_start_string = comment_start_string
93 self.comment_end_string = comment_end_string
94 self.line_statement_prefix = line_statement_prefix
95 self.trim_blocks = trim_blocks
96 self.parser_extensions = {}
97 for extension in parser_extensions:
98 if isinstance(extension, basestring):
99 extension = import_string(extension)
100 self.parser_extensions[extension.tag] = extension
103 # runtime information
104 self.undefined = undefined
105 self.optimized = optimized
106 self.finalize = finalize
109 self.filters = DEFAULT_FILTERS.copy()
110 self.tests = DEFAULT_TESTS.copy()
111 self.globals = DEFAULT_NAMESPACE.copy()
113 # set the loader provided
117 self.lexer = Lexer(self)
119 def subscribe(self, obj, argument):
120 """Get an item or attribute of an object."""
122 return getattr(obj, str(argument))
123 except (AttributeError, UnicodeError):
126 except (TypeError, LookupError):
127 return self.undefined(obj=obj, name=argument)
129 def parse(self, source, name=None):
130 """Parse the sourcecode and return the abstract syntax tree. This tree
131 of nodes is used by the compiler to convert the template into
132 executable source- or bytecode.
134 return Parser(self, source, name).parse()
136 def lex(self, source, name=None):
137 """Lex the given sourcecode and return a generator that yields tokens.
138 The stream returned is not usable for Jinja but can be used if
139 Jinja templates should be processed by other tools (for example
140 syntax highlighting etc)
142 The tuples are returned in the form ``(lineno, token, value)``.
144 return self.lexer.tokeniter(source, name)
146 def compile(self, source, name=None, filename=None, globals=None,
148 """Compile a node or source. The name is the load name of the
149 template after it was joined using `join_path` if necessary,
150 filename is the estimated filename of the template on the file
151 system. If the template came from a database or memory this
154 if isinstance(source, basestring):
155 source = self.parse(source, name)
157 node = optimize(source, self, globals or {})
158 source = generate(node, self, name, filename)
162 filename = '<template>'
163 elif isinstance(filename, unicode):
164 filename = filename.encode('utf-8')
165 return compile(source, filename, 'exec')
167 def join_path(self, template, parent):
168 """Join a template with the parent. By default all the lookups are
169 relative to the loader root, but if the paths should be relative this
170 function can be used to calculate the real filename."""
173 def get_template(self, name, parent=None, globals=None):
174 """Load a template."""
175 if self.loader is None:
176 raise TypeError('no loader for this environment specified')
177 if parent is not None:
178 name = self.join_path(name, parent)
179 globals = self.make_globals(globals)
180 return self.loader.load(self, name, globals)
182 def from_string(self, source, globals=None):
183 """Load a template from a string."""
184 globals = self.make_globals(globals)
185 return Template(self, self.compile(source, globals=globals),
188 def make_globals(self, d):
189 """Return a dict for the globals."""
192 return dict(self.globals, **d)
195 class Template(object):
196 """Represents a template."""
198 def __init__(self, environment, code, globals, uptodate=None):
200 'environment': environment,
201 '__jinja_template__': self
203 exec code in namespace
204 self.environment = environment
205 self.name = namespace['name']
206 self.filename = code.co_filename
207 self.root_render_func = namespace['root']
208 self.blocks = namespace['blocks']
209 self.globals = globals
211 # debug and loader helpers
212 self._get_debug_info = namespace['get_debug_info']
213 self._uptodate = uptodate
215 def render(self, *args, **kwargs):
216 """Render the template into a string."""
218 return u''.join(self.generate(*args, **kwargs))
220 # hide the `generate` frame
221 exc_type, exc_value, tb = sys.exc_info()
222 raise exc_type, exc_value, tb.tb_next
224 def stream(self, *args, **kwargs):
225 """Return a `TemplateStream` that generates the template."""
227 return TemplateStream(self.generate(*args, **kwargs))
229 # hide the `generate` frame
230 exc_type, exc_value, tb = sys.exc_info()
231 raise exc_type, exc_value, tb.tb_next
233 def generate(self, *args, **kwargs):
234 """Return a generator that generates the template."""
235 # assemble the context
236 context = dict(*args, **kwargs)
238 # if the environment is using the optimizer locals may never
239 # override globals as optimizations might have happened
240 # depending on values of certain globals. This assertion goes
241 # away if the python interpreter is started with -O
242 if __debug__ and self.environment.optimized:
243 overrides = set(context) & set(self.globals)
245 plural = len(overrides) != 1 and 's' or ''
246 raise AssertionError('the per template variable%s %s '
247 'override%s global variable%s. '
248 'With an enabled optimizer this '
249 'will lead to unexpected results.' %
250 (plural, ', '.join(overrides), plural or ' a', plural))
251 gen = self.root_render_func(dict(self.globals, **context))
252 # skip the first item which is a reference to the context
259 exc_info = translate_exception(sys.exc_info())
260 raise exc_info[0], exc_info[1], exc_info[2]
262 def get_corresponding_lineno(self, lineno):
263 """Return the source line number of a line number in the
264 generated bytecode as they are not in sync.
266 for template_line, code_line in reversed(self._get_debug_info()):
267 if code_line <= lineno:
272 def is_up_to_date(self):
273 """Check if the template is still up to date."""
274 if self._uptodate is None:
276 return self._uptodate()
280 self.__class__.__name__,
285 class TemplateStream(object):
286 """Wraps a genererator for outputing template streams."""
288 def __init__(self, gen):
290 self._next = gen.next
291 self.buffered = False
293 def disable_buffering(self):
294 """Disable the output buffering."""
295 self._next = self._gen.next
296 self.buffered = False
298 def enable_buffering(self, size=5):
299 """Enable buffering. Buffer `size` items before yielding them."""
301 raise ValueError('buffer size too small')
304 def buffering_next():
308 next = self._gen.next
317 raise StopIteration()
318 except StopIteration:
323 self._next = buffering_next