blob: ccf081175d123438cacdb3b90a65f4a64cbf68f5 [file] [log] [blame]
Armin Ronachere791c2a2008-04-07 18:39:54 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.compiler
4 ~~~~~~~~~~~~~~~
5
6 Compiles nodes into python code.
7
Armin Ronacher55494e42010-01-22 09:41:48 +01008 :copyright: (c) 2010 by the Jinja Team.
Armin Ronacher7af781c2010-02-09 16:05:08 +01009 :license: BSD, see LICENSE for more details.
Armin Ronachere791c2a2008-04-07 18:39:54 +020010"""
Armin Ronachere791c2a2008-04-07 18:39:54 +020011from cStringIO import StringIO
Armin Ronacherd1ff8582008-05-11 00:30:43 +020012from itertools import chain
Armin Ronacher74230e62009-10-25 12:46:31 +010013from copy import deepcopy
Armin Ronachere791c2a2008-04-07 18:39:54 +020014from jinja2 import nodes
15from jinja2.visitor import NodeVisitor, NodeTransformer
16from jinja2.exceptions import TemplateAssertionError
Armin Ronacherbd357722009-08-05 20:25:06 +020017from jinja2.utils import Markup, concat, escape, is_python_keyword, next
Armin Ronachere791c2a2008-04-07 18:39:54 +020018
19
20operators = {
21 'eq': '==',
22 'ne': '!=',
23 'gt': '>',
24 'gteq': '>=',
25 'lt': '<',
26 'lteq': '<=',
27 'in': 'in',
28 'notin': 'not in'
29}
30
Armin Ronacher3d8b7842008-04-13 13:16:50 +020031try:
32 exec '(0 if 0 else 0)'
33except SyntaxError:
34 have_condexpr = False
35else:
36 have_condexpr = True
37
38
Armin Ronacher0d242be2010-02-10 01:35:13 +010039# what method to iterate over items do we want to use for dict iteration
40# in generated code? on 2.x let's go with iteritems, on 3.x with items
41if hasattr(dict, 'iteritems'):
42 dict_item_iter = 'iteritems'
43else:
44 dict_item_iter = 'items'
45
46
Armin Ronacher821a4232010-02-17 07:59:38 +010047# does if 0: dummy(x) get us x into the scope?
48def unoptimize_before_dead_code():
49 x = 42
50 def f():
51 if 0: dummy(x)
52 return f
53unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
54
55
Armin Ronacher64b08a02010-03-12 03:17:41 +010056def generate(node, environment, name, filename, stream=None,
57 defer_init=False):
Armin Ronacherbcb7c532008-04-11 16:30:34 +020058 """Generate the python source for a node tree."""
Armin Ronacher023b5e92008-05-08 11:03:10 +020059 if not isinstance(node, nodes.Template):
60 raise TypeError('Can\'t compile non template nodes')
Armin Ronacher64b08a02010-03-12 03:17:41 +010061 generator = CodeGenerator(environment, name, filename, stream, defer_init)
Armin Ronachere791c2a2008-04-07 18:39:54 +020062 generator.visit(node)
63 if stream is None:
64 return generator.stream.getvalue()
65
66
Armin Ronacher4dfc9752008-04-09 15:03:29 +020067def has_safe_repr(value):
68 """Does the node have a safe representation?"""
Armin Ronacherd55ab532008-04-09 16:13:39 +020069 if value is None or value is NotImplemented or value is Ellipsis:
Armin Ronacher4dfc9752008-04-09 15:03:29 +020070 return True
Armin Ronacherd55ab532008-04-09 16:13:39 +020071 if isinstance(value, (bool, int, long, float, complex, basestring,
Armin Ronacher32a910f2008-04-26 23:21:03 +020072 xrange, Markup)):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020073 return True
Armin Ronacherd55ab532008-04-09 16:13:39 +020074 if isinstance(value, (tuple, list, set, frozenset)):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020075 for item in value:
76 if not has_safe_repr(item):
77 return False
78 return True
79 elif isinstance(value, dict):
80 for key, value in value.iteritems():
81 if not has_safe_repr(key):
82 return False
83 if not has_safe_repr(value):
84 return False
85 return True
86 return False
87
88
Armin Ronacherc9705c22008-04-27 21:28:03 +020089def find_undeclared(nodes, names):
90 """Check if the names passed are accessed undeclared. The return value
91 is a set of all the undeclared names from the sequence of names found.
92 """
93 visitor = UndeclaredNameVisitor(names)
94 try:
95 for node in nodes:
96 visitor.visit(node)
97 except VisitorExit:
98 pass
99 return visitor.undeclared
100
101
Armin Ronachere791c2a2008-04-07 18:39:54 +0200102class Identifiers(object):
103 """Tracks the status of identifiers in frames."""
104
105 def __init__(self):
106 # variables that are known to be declared (probably from outer
107 # frames or because they are special for the frame)
108 self.declared = set()
109
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200110 # undeclared variables from outer scopes
111 self.outer_undeclared = set()
112
Armin Ronachere791c2a2008-04-07 18:39:54 +0200113 # names that are accessed without being explicitly declared by
114 # this one or any of the outer scopes. Names can appear both in
115 # declared and undeclared.
116 self.undeclared = set()
117
118 # names that are declared locally
119 self.declared_locally = set()
120
121 # names that are declared by parameters
122 self.declared_parameter = set()
123
124 def add_special(self, name):
125 """Register a special name like `loop`."""
126 self.undeclared.discard(name)
127 self.declared.add(name)
128
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200129 def is_declared(self, name, local_only=False):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200130 """Check if a name is declared in this or an outer scope."""
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200131 if name in self.declared_locally or name in self.declared_parameter:
132 return True
133 if local_only:
134 return False
135 return name in self.declared
Armin Ronachere791c2a2008-04-07 18:39:54 +0200136
Armin Ronacher74230e62009-10-25 12:46:31 +0100137 def copy(self):
138 return deepcopy(self)
139
Armin Ronachere791c2a2008-04-07 18:39:54 +0200140
141class Frame(object):
Armin Ronacher75cfb862008-04-11 13:47:22 +0200142 """Holds compile time information for us."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200143
144 def __init__(self, parent=None):
145 self.identifiers = Identifiers()
Armin Ronacherfed44b52008-04-13 19:42:53 +0200146
Armin Ronacher75cfb862008-04-11 13:47:22 +0200147 # a toplevel frame is the root + soft frames such as if conditions.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200148 self.toplevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200149
Armin Ronacher75cfb862008-04-11 13:47:22 +0200150 # the root frame is basically just the outermost frame, so no if
151 # conditions. This information is used to optimize inheritance
152 # situations.
153 self.rootlevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200154
Armin Ronacher79668952008-09-23 22:52:46 +0200155 # in some dynamic inheritance situations the compiler needs to add
156 # write tests around output statements.
157 self.require_output_check = parent and parent.require_output_check
Armin Ronacherf40c8842008-09-17 18:51:26 +0200158
Armin Ronacherfed44b52008-04-13 19:42:53 +0200159 # inside some tags we are using a buffer rather than yield statements.
160 # this for example affects {% filter %} or {% macro %}. If a frame
161 # is buffered this variable points to the name of the list used as
162 # buffer.
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200163 self.buffer = None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200164
Armin Ronacherfed44b52008-04-13 19:42:53 +0200165 # the name of the block we're in, otherwise None.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200166 self.block = parent and parent.block or None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200167
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100168 # a set of actually assigned names
169 self.assigned_names = set()
170
Armin Ronacherfed44b52008-04-13 19:42:53 +0200171 # the parent of this frame
172 self.parent = parent
173
Armin Ronachere791c2a2008-04-07 18:39:54 +0200174 if parent is not None:
175 self.identifiers.declared.update(
176 parent.identifiers.declared |
Armin Ronacherb3a1fcf2008-05-15 11:04:14 +0200177 parent.identifiers.declared_parameter |
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100178 parent.assigned_names
Armin Ronachere791c2a2008-04-07 18:39:54 +0200179 )
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200180 self.identifiers.outer_undeclared.update(
181 parent.identifiers.undeclared -
182 self.identifiers.declared
183 )
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200184 self.buffer = parent.buffer
Armin Ronachere791c2a2008-04-07 18:39:54 +0200185
Armin Ronacher8efc5222008-04-08 14:47:40 +0200186 def copy(self):
187 """Create a copy of the current one."""
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200188 rv = object.__new__(self.__class__)
189 rv.__dict__.update(self.__dict__)
190 rv.identifiers = object.__new__(self.identifiers.__class__)
191 rv.identifiers.__dict__.update(self.identifiers.__dict__)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200192 return rv
193
Armin Ronacherc9705c22008-04-27 21:28:03 +0200194 def inspect(self, nodes, hard_scope=False):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200195 """Walk the node and check for identifiers. If the scope is hard (eg:
196 enforce on a python level) overrides from outer scopes are tracked
197 differently.
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200198 """
199 visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200200 for node in nodes:
Armin Ronacherc9705c22008-04-27 21:28:03 +0200201 visitor.visit(node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200202
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100203 def find_shadowed(self, extra=()):
204 """Find all the shadowed names. extra is an iterable of variables
205 that may be defined with `add_special` which may occour scoped.
206 """
207 i = self.identifiers
208 return (i.declared | i.outer_undeclared) & \
209 (i.declared_locally | i.declared_parameter) | \
210 set(x for x in extra if i.is_declared(x))
211
Armin Ronachere791c2a2008-04-07 18:39:54 +0200212 def inner(self):
213 """Return an inner frame."""
214 return Frame(self)
215
Armin Ronacher75cfb862008-04-11 13:47:22 +0200216 def soft(self):
217 """Return a soft frame. A soft frame may not be modified as
218 standalone thing as it shares the resources with the frame it
219 was created of, but it's not a rootlevel frame any longer.
220 """
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200221 rv = self.copy()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200222 rv.rootlevel = False
223 return rv
224
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200225 __copy__ = copy
226
Armin Ronachere791c2a2008-04-07 18:39:54 +0200227
Armin Ronacherc9705c22008-04-27 21:28:03 +0200228class VisitorExit(RuntimeError):
229 """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
230
231
232class DependencyFinderVisitor(NodeVisitor):
233 """A visitor that collects filter and test calls."""
234
235 def __init__(self):
236 self.filters = set()
237 self.tests = set()
238
239 def visit_Filter(self, node):
240 self.generic_visit(node)
241 self.filters.add(node.name)
242
243 def visit_Test(self, node):
244 self.generic_visit(node)
245 self.tests.add(node.name)
246
247 def visit_Block(self, node):
248 """Stop visiting at blocks."""
249
250
251class UndeclaredNameVisitor(NodeVisitor):
252 """A visitor that checks if a name is accessed without being
253 declared. This is different from the frame visitor as it will
254 not stop at closure frames.
255 """
256
257 def __init__(self, names):
258 self.names = set(names)
259 self.undeclared = set()
260
261 def visit_Name(self, node):
262 if node.ctx == 'load' and node.name in self.names:
263 self.undeclared.add(node.name)
264 if self.undeclared == self.names:
265 raise VisitorExit()
266 else:
267 self.names.discard(node.name)
268
269 def visit_Block(self, node):
270 """Stop visiting a blocks."""
271
272
Armin Ronachere791c2a2008-04-07 18:39:54 +0200273class FrameIdentifierVisitor(NodeVisitor):
274 """A visitor for `Frame.inspect`."""
275
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200276 def __init__(self, identifiers, hard_scope):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200277 self.identifiers = identifiers
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200278 self.hard_scope = hard_scope
Armin Ronachere791c2a2008-04-07 18:39:54 +0200279
Armin Ronacherc9705c22008-04-27 21:28:03 +0200280 def visit_Name(self, node):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200281 """All assignments to names go through this function."""
Armin Ronachere9411b42008-05-15 16:22:07 +0200282 if node.ctx == 'store':
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200283 self.identifiers.declared_locally.add(node.name)
Armin Ronachere9411b42008-05-15 16:22:07 +0200284 elif node.ctx == 'param':
285 self.identifiers.declared_parameter.add(node.name)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200286 elif node.ctx == 'load' and not \
287 self.identifiers.is_declared(node.name, self.hard_scope):
288 self.identifiers.undeclared.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200289
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200290 def visit_If(self, node):
291 self.visit(node.test)
Armin Ronacher74230e62009-10-25 12:46:31 +0100292 real_identifiers = self.identifiers
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200293
Armin Ronacher74230e62009-10-25 12:46:31 +0100294 old_names = real_identifiers.declared | \
295 real_identifiers.declared_locally | \
296 real_identifiers.declared_parameter
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200297
Armin Ronacher74230e62009-10-25 12:46:31 +0100298 def inner_visit(nodes):
Armin Ronacher1965e312009-10-25 13:03:08 +0100299 if not nodes:
300 return set()
Armin Ronacher74230e62009-10-25 12:46:31 +0100301 self.identifiers = real_identifiers.copy()
302 for subnode in nodes:
303 self.visit(subnode)
304 rv = self.identifiers.declared_locally - old_names
305 # we have to remember the undeclared variables of this branch
306 # because we will have to pull them.
307 real_identifiers.undeclared.update(self.identifiers.undeclared)
308 self.identifiers = real_identifiers
309 return rv
310
311 body = inner_visit(node.body)
312 else_ = inner_visit(node.else_ or ())
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200313
314 # the differences between the two branches are also pulled as
315 # undeclared variables
Armin Ronacher74230e62009-10-25 12:46:31 +0100316 real_identifiers.undeclared.update(body.symmetric_difference(else_))
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200317
Armin Ronacher74230e62009-10-25 12:46:31 +0100318 # remember those that are declared.
319 real_identifiers.declared_locally.update(body | else_)
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200320
Armin Ronacherc9705c22008-04-27 21:28:03 +0200321 def visit_Macro(self, node):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200322 self.identifiers.declared_locally.add(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +0200323
Armin Ronacherc9705c22008-04-27 21:28:03 +0200324 def visit_Import(self, node):
325 self.generic_visit(node)
326 self.identifiers.declared_locally.add(node.target)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200327
Armin Ronacherc9705c22008-04-27 21:28:03 +0200328 def visit_FromImport(self, node):
329 self.generic_visit(node)
330 for name in node.names:
331 if isinstance(name, tuple):
332 self.identifiers.declared_locally.add(name[1])
333 else:
334 self.identifiers.declared_locally.add(name)
335
336 def visit_Assign(self, node):
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200337 """Visit assignments in the correct order."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200338 self.visit(node.node)
339 self.visit(node.target)
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200340
Armin Ronacherc9705c22008-04-27 21:28:03 +0200341 def visit_For(self, node):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200342 """Visiting stops at for blocks. However the block sequence
343 is visited as part of the outer scope.
344 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200345 self.visit(node.iter)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200346
Armin Ronacherc9705c22008-04-27 21:28:03 +0200347 def visit_CallBlock(self, node):
Armin Ronacheref189442010-01-14 01:26:40 +0100348 self.visit(node.call)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200349
350 def visit_FilterBlock(self, node):
351 self.visit(node.filter)
352
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100353 def visit_Scope(self, node):
354 """Stop visiting at scopes."""
355
Armin Ronacherc9705c22008-04-27 21:28:03 +0200356 def visit_Block(self, node):
357 """Stop visiting at blocks."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200358
359
Armin Ronacher75cfb862008-04-11 13:47:22 +0200360class CompilerExit(Exception):
361 """Raised if the compiler encountered a situation where it just
362 doesn't make sense to further process the code. Any block that
Armin Ronacher0611e492008-04-25 23:44:14 +0200363 raises such an exception is not further processed.
364 """
Armin Ronacher75cfb862008-04-11 13:47:22 +0200365
366
Armin Ronachere791c2a2008-04-07 18:39:54 +0200367class CodeGenerator(NodeVisitor):
368
Armin Ronacher64b08a02010-03-12 03:17:41 +0100369 def __init__(self, environment, name, filename, stream=None,
370 defer_init=False):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200371 if stream is None:
372 stream = StringIO()
Christoph Hack65642a52008-04-08 14:46:56 +0200373 self.environment = environment
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200374 self.name = name
Armin Ronachere791c2a2008-04-07 18:39:54 +0200375 self.filename = filename
376 self.stream = stream
Armin Ronacher2f0d6592009-10-26 11:53:27 +0100377 self.created_block_context = False
Armin Ronacher64b08a02010-03-12 03:17:41 +0100378 self.defer_init = defer_init
Armin Ronacherfed44b52008-04-13 19:42:53 +0200379
Armin Ronacher023b5e92008-05-08 11:03:10 +0200380 # aliases for imports
381 self.import_aliases = {}
382
Armin Ronacherfed44b52008-04-13 19:42:53 +0200383 # a registry for all blocks. Because blocks are moved out
384 # into the global python scope they are registered here
Armin Ronachere791c2a2008-04-07 18:39:54 +0200385 self.blocks = {}
Armin Ronacherfed44b52008-04-13 19:42:53 +0200386
387 # the number of extends statements so far
Armin Ronacher7fb38972008-04-11 13:54:28 +0200388 self.extends_so_far = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200389
390 # some templates have a rootlevel extends. In this case we
391 # can safely assume that we're a child template and do some
392 # more optimizations.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200393 self.has_known_extends = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200394
Armin Ronacherba3757b2008-04-16 19:43:16 +0200395 # the current line number
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200396 self.code_lineno = 1
Armin Ronacherba3757b2008-04-16 19:43:16 +0200397
Armin Ronacherb9e78752008-05-10 23:36:28 +0200398 # registry of all filters and tests (global, not block local)
399 self.tests = {}
400 self.filters = {}
401
Armin Ronacherba3757b2008-04-16 19:43:16 +0200402 # the debug information
403 self.debug_info = []
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200404 self._write_debug_info = None
Armin Ronacherba3757b2008-04-16 19:43:16 +0200405
Armin Ronacherfed44b52008-04-13 19:42:53 +0200406 # the number of new lines before the next write()
407 self._new_lines = 0
408
409 # the line number of the last written statement
Armin Ronachere791c2a2008-04-07 18:39:54 +0200410 self._last_line = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200411
412 # true if nothing was written so far.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200413 self._first_write = True
414
Armin Ronacherfed44b52008-04-13 19:42:53 +0200415 # used by the `temporary_identifier` method to get new
416 # unique, temporary identifier
417 self._last_identifier = 0
418
419 # the current indentation
420 self._indentation = 0
421
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200422 # -- Various compilation helpers
423
Armin Ronachere2244882008-05-19 09:25:57 +0200424 def fail(self, msg, lineno):
425 """Fail with a `TemplateAssertionError`."""
426 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
427
Armin Ronachere791c2a2008-04-07 18:39:54 +0200428 def temporary_identifier(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200429 """Get a new unique identifier."""
430 self._last_identifier += 1
Armin Ronacher8a1d27f2008-05-19 08:37:19 +0200431 return 't_%d' % self._last_identifier
Armin Ronachere791c2a2008-04-07 18:39:54 +0200432
Armin Ronachered1e0d42008-05-18 20:25:28 +0200433 def buffer(self, frame):
434 """Enable buffering for the frame from that point onwards."""
Armin Ronachere2244882008-05-19 09:25:57 +0200435 frame.buffer = self.temporary_identifier()
436 self.writeline('%s = []' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200437
438 def return_buffer_contents(self, frame):
439 """Return the buffer contents of the frame."""
440 if self.environment.autoescape:
441 self.writeline('return Markup(concat(%s))' % frame.buffer)
442 else:
443 self.writeline('return concat(%s)' % frame.buffer)
444
Armin Ronachere791c2a2008-04-07 18:39:54 +0200445 def indent(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200446 """Indent by one."""
447 self._indentation += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +0200448
Armin Ronacher8efc5222008-04-08 14:47:40 +0200449 def outdent(self, step=1):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200450 """Outdent by step."""
451 self._indentation -= step
Armin Ronachere791c2a2008-04-07 18:39:54 +0200452
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200453 def start_write(self, frame, node=None):
454 """Yield or write into the frame buffer."""
455 if frame.buffer is None:
456 self.writeline('yield ', node)
457 else:
458 self.writeline('%s.append(' % frame.buffer, node)
459
460 def end_write(self, frame):
461 """End the writing process started by `start_write`."""
462 if frame.buffer is not None:
463 self.write(')')
464
465 def simple_write(self, s, frame, node=None):
466 """Simple shortcut for start_write + write + end_write."""
467 self.start_write(frame, node)
468 self.write(s)
469 self.end_write(frame)
470
Armin Ronacherf40c8842008-09-17 18:51:26 +0200471 def blockvisit(self, nodes, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200472 """Visit a list of nodes as block in a frame. If the current frame
473 is no buffer a dummy ``if 0: yield None`` is written automatically
474 unless the force_generator parameter is set to False.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200475 """
Armin Ronacherf40c8842008-09-17 18:51:26 +0200476 if frame.buffer is None:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200477 self.writeline('if 0: yield None')
Armin Ronacherf40c8842008-09-17 18:51:26 +0200478 else:
479 self.writeline('pass')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200480 try:
481 for node in nodes:
482 self.visit(node, frame)
483 except CompilerExit:
484 pass
Armin Ronachere791c2a2008-04-07 18:39:54 +0200485
486 def write(self, x):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200487 """Write a string into the output stream."""
488 if self._new_lines:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200489 if not self._first_write:
Armin Ronacherfed44b52008-04-13 19:42:53 +0200490 self.stream.write('\n' * self._new_lines)
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200491 self.code_lineno += self._new_lines
492 if self._write_debug_info is not None:
493 self.debug_info.append((self._write_debug_info,
494 self.code_lineno))
495 self._write_debug_info = None
Armin Ronachere791c2a2008-04-07 18:39:54 +0200496 self._first_write = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200497 self.stream.write(' ' * self._indentation)
498 self._new_lines = 0
Armin Ronachere791c2a2008-04-07 18:39:54 +0200499 self.stream.write(x)
500
501 def writeline(self, x, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200502 """Combination of newline and write."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200503 self.newline(node, extra)
504 self.write(x)
505
506 def newline(self, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200507 """Add one or more newlines before the next write."""
508 self._new_lines = max(self._new_lines, 1 + extra)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200509 if node is not None and node.lineno != self._last_line:
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200510 self._write_debug_info = node.lineno
511 self._last_line = node.lineno
Armin Ronachere791c2a2008-04-07 18:39:54 +0200512
Armin Ronacherfd310492008-05-25 00:16:51 +0200513 def signature(self, node, frame, extra_kwargs=None):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200514 """Writes a function call to the stream for the current node.
Armin Ronacherfd310492008-05-25 00:16:51 +0200515 A leading comma is added automatically. The extra keyword
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200516 arguments may not include python keywords otherwise a syntax
517 error could occour. The extra keyword arguments should be given
518 as python dict.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200519 """
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200520 # if any of the given keyword arguments is a python keyword
521 # we have to make sure that no invalid call is created.
522 kwarg_workaround = False
523 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200524 if is_python_keyword(kwarg):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200525 kwarg_workaround = True
526 break
527
Armin Ronacher8efc5222008-04-08 14:47:40 +0200528 for arg in node.args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200529 self.write(', ')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200530 self.visit(arg, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200531
532 if not kwarg_workaround:
533 for kwarg in node.kwargs:
Armin Ronacherfd310492008-05-25 00:16:51 +0200534 self.write(', ')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200535 self.visit(kwarg, frame)
536 if extra_kwargs is not None:
537 for key, value in extra_kwargs.iteritems():
Armin Ronacherfd310492008-05-25 00:16:51 +0200538 self.write(', %s=%s' % (key, value))
Armin Ronacher8efc5222008-04-08 14:47:40 +0200539 if node.dyn_args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200540 self.write(', *')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200541 self.visit(node.dyn_args, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200542
543 if kwarg_workaround:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200544 if node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200545 self.write(', **dict({')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200546 else:
Armin Ronacherfd310492008-05-25 00:16:51 +0200547 self.write(', **{')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200548 for kwarg in node.kwargs:
549 self.write('%r: ' % kwarg.key)
550 self.visit(kwarg.value, frame)
551 self.write(', ')
552 if extra_kwargs is not None:
553 for key, value in extra_kwargs.iteritems():
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200554 self.write('%r: %s, ' % (key, value))
555 if node.dyn_kwargs is not None:
556 self.write('}, **')
557 self.visit(node.dyn_kwargs, frame)
558 self.write(')')
559 else:
560 self.write('}')
561
562 elif node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200563 self.write(', **')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200564 self.visit(node.dyn_kwargs, frame)
565
Armin Ronacherc9705c22008-04-27 21:28:03 +0200566 def pull_locals(self, frame):
567 """Pull all the references identifiers into the local scope."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200568 for name in frame.identifiers.undeclared:
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200569 self.writeline('l_%s = context.resolve(%r)' % (name, name))
Armin Ronacherc9705c22008-04-27 21:28:03 +0200570
571 def pull_dependencies(self, nodes):
572 """Pull all the dependencies."""
573 visitor = DependencyFinderVisitor()
574 for node in nodes:
575 visitor.visit(node)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200576 for dependency in 'filters', 'tests':
577 mapping = getattr(self, dependency)
578 for name in getattr(visitor, dependency):
579 if name not in mapping:
580 mapping[name] = self.temporary_identifier()
581 self.writeline('%s = environment.%s[%r]' %
582 (mapping[name], dependency, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200583
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100584 def unoptimize_scope(self, frame):
585 """Disable Python optimizations for the frame."""
586 # XXX: this is not that nice but it has no real overhead. It
587 # mainly works because python finds the locals before dead code
588 # is removed. If that breaks we have to add a dummy function
589 # that just accepts the arguments and does nothing.
590 if frame.identifiers.declared:
Armin Ronacher821a4232010-02-17 07:59:38 +0100591 self.writeline('%sdummy(%s)' % (
592 unoptimize_before_dead_code and 'if 0: ' or '',
593 ', '.join('l_' + name for name in frame.identifiers.declared)
594 ))
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100595
Armin Ronacher673aa882008-10-04 18:06:57 +0200596 def push_scope(self, frame, extra_vars=()):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200597 """This function returns all the shadowed variables in a dict
598 in the form name: alias and will write the required assignments
599 into the current scope. No indentation takes place.
Armin Ronacherff53c782008-08-13 18:55:50 +0200600
Armin Ronacher673aa882008-10-04 18:06:57 +0200601 This also predefines locally declared variables from the loop
602 body because under some circumstances it may be the case that
603
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100604 `extra_vars` is passed to `Frame.find_shadowed`.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200605 """
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200606 aliases = {}
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100607 for name in frame.find_shadowed(extra_vars):
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200608 aliases[name] = ident = self.temporary_identifier()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200609 self.writeline('%s = l_%s' % (ident, name))
Armin Ronacher673aa882008-10-04 18:06:57 +0200610 to_declare = set()
611 for name in frame.identifiers.declared_locally:
612 if name not in aliases:
613 to_declare.add('l_' + name)
614 if to_declare:
615 self.writeline(' = '.join(to_declare) + ' = missing')
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200616 return aliases
617
Armin Ronacher673aa882008-10-04 18:06:57 +0200618 def pop_scope(self, aliases, frame):
619 """Restore all aliases and delete unused variables."""
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200620 for name, alias in aliases.iteritems():
621 self.writeline('l_%s = %s' % (name, alias))
Armin Ronacher673aa882008-10-04 18:06:57 +0200622 to_delete = set()
623 for name in frame.identifiers.declared_locally:
624 if name not in aliases:
625 to_delete.add('l_' + name)
626 if to_delete:
Armin Ronacher330fbc02009-02-04 19:13:58 +0100627 # we cannot use the del statement here because enclosed
628 # scopes can trigger a SyntaxError:
629 # a = 42; b = lambda: a; del a
630 self.writeline(' = '.join(to_delete) + ' = missing')
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200631
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200632 def function_scoping(self, node, frame, children=None,
633 find_special=True):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200634 """In Jinja a few statements require the help of anonymous
635 functions. Those are currently macros and call blocks and in
636 the future also recursive loops. As there is currently
637 technical limitation that doesn't allow reading and writing a
638 variable in a scope where the initial value is coming from an
639 outer scope, this function tries to fall back with a common
640 error message. Additionally the frame passed is modified so
641 that the argumetns are collected and callers are looked up.
642
643 This will return the modified frame.
644 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200645 # we have to iterate twice over it, make sure that works
646 if children is None:
647 children = node.iter_child_nodes()
648 children = list(children)
Armin Ronacher71082072008-04-12 14:19:36 +0200649 func_frame = frame.inner()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200650 func_frame.inspect(children, hard_scope=True)
Armin Ronacher71082072008-04-12 14:19:36 +0200651
652 # variables that are undeclared (accessed before declaration) and
653 # declared locally *and* part of an outside scope raise a template
654 # assertion error. Reason: we can't generate reasonable code from
Armin Ronacher02b42a82009-03-18 00:59:32 +0100655 # it without aliasing all the variables.
656 # this could be fixed in Python 3 where we have the nonlocal
657 # keyword or if we switch to bytecode generation
Armin Ronacher71082072008-04-12 14:19:36 +0200658 overriden_closure_vars = (
659 func_frame.identifiers.undeclared &
660 func_frame.identifiers.declared &
661 (func_frame.identifiers.declared_locally |
662 func_frame.identifiers.declared_parameter)
663 )
664 if overriden_closure_vars:
Armin Ronachere2244882008-05-19 09:25:57 +0200665 self.fail('It\'s not possible to set and access variables '
Armin Ronacherefcc0e52009-09-13 00:22:50 -0700666 'derived from an outer scope! (affects: %s)' %
Armin Ronachere2244882008-05-19 09:25:57 +0200667 ', '.join(sorted(overriden_closure_vars)), node.lineno)
Armin Ronacher71082072008-04-12 14:19:36 +0200668
669 # remove variables from a closure from the frame's undeclared
670 # identifiers.
671 func_frame.identifiers.undeclared -= (
672 func_frame.identifiers.undeclared &
673 func_frame.identifiers.declared
674 )
675
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200676 # no special variables for this scope, abort early
677 if not find_special:
678 return func_frame
679
Armin Ronacher963f97d2008-04-25 11:44:59 +0200680 func_frame.accesses_kwargs = False
681 func_frame.accesses_varargs = False
Armin Ronacher71082072008-04-12 14:19:36 +0200682 func_frame.accesses_caller = False
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200683 func_frame.arguments = args = ['l_' + x.name for x in node.args]
Armin Ronacher71082072008-04-12 14:19:36 +0200684
Armin Ronacherc9705c22008-04-27 21:28:03 +0200685 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
686
687 if 'caller' in undeclared:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200688 func_frame.accesses_caller = True
689 func_frame.identifiers.add_special('caller')
690 args.append('l_caller')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200691 if 'kwargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200692 func_frame.accesses_kwargs = True
693 func_frame.identifiers.add_special('kwargs')
694 args.append('l_kwargs')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200695 if 'varargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200696 func_frame.accesses_varargs = True
697 func_frame.identifiers.add_special('varargs')
698 args.append('l_varargs')
Armin Ronacher71082072008-04-12 14:19:36 +0200699 return func_frame
700
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200701 def macro_body(self, node, frame, children=None):
702 """Dump the function def of a macro or call block."""
703 frame = self.function_scoping(node, frame, children)
Armin Ronachere308bf22008-10-30 19:18:45 +0100704 # macros are delayed, they never require output checks
705 frame.require_output_check = False
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200706 args = frame.arguments
Armin Ronachereabf3dd2009-09-12 23:48:18 -0700707 # XXX: this is an ugly fix for the loop nesting bug
708 # (tests.test_old_bugs.test_loop_call_bug). This works around
709 # a identifier nesting problem we have in general. It's just more
710 # likely to happen in loops which is why we work around it. The
711 # real solution would be "nonlocal" all the identifiers that are
712 # leaking into a new python frame and might be used both unassigned
713 # and assigned.
714 if 'loop' in frame.identifiers.declared:
Armin Ronacherb4044392009-09-13 15:56:58 -0700715 args = args + ['l_loop=l_loop']
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200716 self.writeline('def macro(%s):' % ', '.join(args), node)
717 self.indent()
718 self.buffer(frame)
719 self.pull_locals(frame)
720 self.blockvisit(node.body, frame)
721 self.return_buffer_contents(frame)
722 self.outdent()
723 return frame
724
725 def macro_def(self, node, frame):
726 """Dump the macro definition for the def created by macro_body."""
727 arg_tuple = ', '.join(repr(x.name) for x in node.args)
728 name = getattr(node, 'name', None)
729 if len(node.args) == 1:
730 arg_tuple += ','
731 self.write('Macro(environment, macro, %r, (%s), (' %
732 (name, arg_tuple))
733 for arg in node.defaults:
734 self.visit(arg, frame)
735 self.write(', ')
Armin Ronacher903d1682008-05-23 00:51:58 +0200736 self.write('), %r, %r, %r)' % (
737 bool(frame.accesses_kwargs),
738 bool(frame.accesses_varargs),
739 bool(frame.accesses_caller)
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200740 ))
741
Armin Ronacher547d0b62008-07-04 16:35:10 +0200742 def position(self, node):
743 """Return a human readable position for the node."""
744 rv = 'line %d' % node.lineno
745 if self.name is not None:
Armin Ronachercebd8382008-12-25 18:33:46 +0100746 rv += ' in ' + repr(self.name)
Armin Ronacher547d0b62008-07-04 16:35:10 +0200747 return rv
748
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200749 # -- Statement Visitors
Armin Ronachere791c2a2008-04-07 18:39:54 +0200750
751 def visit_Template(self, node, frame=None):
752 assert frame is None, 'no root frame allowed'
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200753 from jinja2.runtime import __all__ as exported
Armin Ronacher709f6e52008-04-28 18:18:16 +0200754 self.writeline('from __future__ import division')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200755 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
Armin Ronacher821a4232010-02-17 07:59:38 +0100756 if not unoptimize_before_dead_code:
757 self.writeline('dummy = lambda *x: None')
Armin Ronacher8edbe492008-04-10 20:43:43 +0200758
Armin Ronacher64b08a02010-03-12 03:17:41 +0100759 # if we want a deferred initialization we cannot move the
760 # environment into a local name
761 envenv = not self.defer_init and ', environment=environment' or ''
762
Armin Ronacher75cfb862008-04-11 13:47:22 +0200763 # do we have an extends tag at all? If not, we can save some
764 # overhead by just not processing any inheritance code.
765 have_extends = node.find(nodes.Extends) is not None
766
Armin Ronacher8edbe492008-04-10 20:43:43 +0200767 # find all blocks
768 for block in node.find_all(nodes.Block):
769 if block.name in self.blocks:
Armin Ronachere2244882008-05-19 09:25:57 +0200770 self.fail('block %r defined twice' % block.name, block.lineno)
Armin Ronacher8edbe492008-04-10 20:43:43 +0200771 self.blocks[block.name] = block
Armin Ronachere791c2a2008-04-07 18:39:54 +0200772
Armin Ronacher023b5e92008-05-08 11:03:10 +0200773 # find all imports and import them
774 for import_ in node.find_all(nodes.ImportedName):
775 if import_.importname not in self.import_aliases:
776 imp = import_.importname
777 self.import_aliases[imp] = alias = self.temporary_identifier()
778 if '.' in imp:
779 module, obj = imp.rsplit('.', 1)
780 self.writeline('from %s import %s as %s' %
781 (module, obj, alias))
782 else:
783 self.writeline('import %s as %s' % (imp, alias))
784
785 # add the load name
Armin Ronacherdc02b642008-05-15 22:47:27 +0200786 self.writeline('name = %r' % self.name)
Armin Ronacher023b5e92008-05-08 11:03:10 +0200787
Armin Ronacher8efc5222008-04-08 14:47:40 +0200788 # generate the root render function.
Armin Ronacher64b08a02010-03-12 03:17:41 +0100789 self.writeline('def root(context%s):' % envenv, extra=1)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200790
791 # process the root
Armin Ronachere791c2a2008-04-07 18:39:54 +0200792 frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200793 frame.inspect(node.body)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200794 frame.toplevel = frame.rootlevel = True
Armin Ronacher79668952008-09-23 22:52:46 +0200795 frame.require_output_check = have_extends and not self.has_known_extends
Armin Ronacherf059ec12008-04-11 22:21:00 +0200796 self.indent()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200797 if have_extends:
798 self.writeline('parent_template = None')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200799 if 'self' in find_undeclared(node.body, ('self',)):
800 frame.identifiers.add_special('self')
801 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher6df604e2008-05-23 22:18:38 +0200802 self.pull_locals(frame)
803 self.pull_dependencies(node.body)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200804 self.blockvisit(node.body, frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200805 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200806
Armin Ronacher8efc5222008-04-08 14:47:40 +0200807 # make sure that the parent root is called.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200808 if have_extends:
809 if not self.has_known_extends:
810 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200811 self.writeline('if parent_template is not None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200812 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200813 self.writeline('for event in parent_template.'
Armin Ronacher5411ce72008-05-25 11:36:22 +0200814 'root_render_func(context):')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200815 self.indent()
816 self.writeline('yield event')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200817 self.outdent(2 + (not self.has_known_extends))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200818
819 # at this point we now have the blocks collected and can visit them too.
820 for name, block in self.blocks.iteritems():
821 block_frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200822 block_frame.inspect(block.body)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200823 block_frame.block = name
Armin Ronacher64b08a02010-03-12 03:17:41 +0100824 self.writeline('def block_%s(context%s):' % (name, envenv),
825 block, 1)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200826 self.indent()
827 undeclared = find_undeclared(block.body, ('self', 'super'))
828 if 'self' in undeclared:
829 block_frame.identifiers.add_special('self')
830 self.writeline('l_self = TemplateReference(context)')
831 if 'super' in undeclared:
832 block_frame.identifiers.add_special('super')
833 self.writeline('l_super = context.super(%r, '
834 'block_%s)' % (name, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200835 self.pull_locals(block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200836 self.pull_dependencies(block.body)
Armin Ronacher625215e2008-04-13 16:31:08 +0200837 self.blockvisit(block.body, block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200838 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200839
Armin Ronacher75cfb862008-04-11 13:47:22 +0200840 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
Armin Ronacherba3757b2008-04-16 19:43:16 +0200841 for x in self.blocks),
842 extra=1)
843
844 # add a function that returns the debug info
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200845 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
846 in self.debug_info))
Armin Ronacher75cfb862008-04-11 13:47:22 +0200847
Armin Ronachere791c2a2008-04-07 18:39:54 +0200848 def visit_Block(self, node, frame):
849 """Call a block and register it for the template."""
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200850 level = 1
Armin Ronacher75cfb862008-04-11 13:47:22 +0200851 if frame.toplevel:
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200852 # if we know that we are a child template, there is no need to
853 # check if we are one
854 if self.has_known_extends:
855 return
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200856 if self.extends_so_far > 0:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200857 self.writeline('if parent_template is None:')
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200858 self.indent()
859 level += 1
Armin Ronacher2f0d6592009-10-26 11:53:27 +0100860 context = node.scoped and 'context.derived(locals())' or 'context'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100861 self.writeline('for event in context.blocks[%r][0](%s):' % (
862 node.name, context), node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200863 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200864 self.simple_write('event', frame)
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200865 self.outdent(level)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200866
867 def visit_Extends(self, node, frame):
868 """Calls the extender."""
Armin Ronacher8efc5222008-04-08 14:47:40 +0200869 if not frame.toplevel:
Armin Ronachere2244882008-05-19 09:25:57 +0200870 self.fail('cannot use extend from a non top-level scope',
871 node.lineno)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200872
Armin Ronacher7fb38972008-04-11 13:54:28 +0200873 # if the number of extends statements in general is zero so
874 # far, we don't have to add a check if something extended
875 # the template before this one.
876 if self.extends_so_far > 0:
Armin Ronacher75cfb862008-04-11 13:47:22 +0200877
Armin Ronacher7fb38972008-04-11 13:54:28 +0200878 # if we have a known extends we just add a template runtime
879 # error into the generated code. We could catch that at compile
880 # time too, but i welcome it not to confuse users by throwing the
881 # same error at different times just "because we can".
882 if not self.has_known_extends:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200883 self.writeline('if parent_template is not None:')
Armin Ronacher7fb38972008-04-11 13:54:28 +0200884 self.indent()
885 self.writeline('raise TemplateRuntimeError(%r)' %
886 'extended multiple times')
Armin Ronacher79668952008-09-23 22:52:46 +0200887 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200888
Armin Ronacher7fb38972008-04-11 13:54:28 +0200889 # if we have a known extends already we don't need that code here
890 # as we know that the template execution will end here.
891 if self.has_known_extends:
892 raise CompilerExit()
Armin Ronacher7fb38972008-04-11 13:54:28 +0200893
Armin Ronacher9d42abf2008-05-14 18:10:41 +0200894 self.writeline('parent_template = environment.get_template(', node)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200895 self.visit(node.template, frame)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200896 self.write(', %r)' % self.name)
897 self.writeline('for name, parent_block in parent_template.'
Armin Ronacher0d242be2010-02-10 01:35:13 +0100898 'blocks.%s():' % dict_item_iter)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200899 self.indent()
900 self.writeline('context.blocks.setdefault(name, []).'
Armin Ronacher83fbc0f2008-05-15 12:22:28 +0200901 'append(parent_block)')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200902 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200903
904 # if this extends statement was in the root level we can take
905 # advantage of that information and simplify the generated code
906 # in the top level from this point onwards
Armin Ronacher27069d72008-05-11 19:48:12 +0200907 if frame.rootlevel:
908 self.has_known_extends = True
Armin Ronachere791c2a2008-04-07 18:39:54 +0200909
Armin Ronacher7fb38972008-04-11 13:54:28 +0200910 # and now we have one more
911 self.extends_so_far += 1
912
Armin Ronacherf059ec12008-04-11 22:21:00 +0200913 def visit_Include(self, node, frame):
914 """Handles includes."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100915 if node.with_context:
916 self.unoptimize_scope(frame)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100917 if node.ignore_missing:
918 self.writeline('try:')
919 self.indent()
Armin Ronacher31bbd9e2010-01-14 00:41:30 +0100920
921 func_name = 'get_or_select_template'
922 if isinstance(node.template, nodes.Const):
923 if isinstance(node.template.value, basestring):
924 func_name = 'get_template'
925 elif isinstance(node.template.value, (tuple, list)):
926 func_name = 'select_template'
927 elif isinstance(node.template, (nodes.Tuple, nodes.List)):
928 func_name = 'select_template'
929
930 self.writeline('template = environment.%s(' % func_name, node)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100931 self.visit(node.template, frame)
932 self.write(', %r)' % self.name)
933 if node.ignore_missing:
934 self.outdent()
935 self.writeline('except TemplateNotFound:')
936 self.indent()
937 self.writeline('pass')
938 self.outdent()
939 self.writeline('else:')
940 self.indent()
941
Armin Ronacherea847c52008-05-02 20:04:32 +0200942 if node.with_context:
Armin Ronacher5411ce72008-05-25 11:36:22 +0200943 self.writeline('for event in template.root_render_func('
Armin Ronacher673aa882008-10-04 18:06:57 +0200944 'template.new_context(context.parent, True, '
945 'locals())):')
Armin Ronacherea847c52008-05-02 20:04:32 +0200946 else:
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100947 self.writeline('for event in template.module._body_stream:')
948
Armin Ronacherf059ec12008-04-11 22:21:00 +0200949 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200950 self.simple_write('event', frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200951 self.outdent()
952
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100953 if node.ignore_missing:
954 self.outdent()
955
Armin Ronacher0611e492008-04-25 23:44:14 +0200956 def visit_Import(self, node, frame):
957 """Visit regular imports."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100958 if node.with_context:
959 self.unoptimize_scope(frame)
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200960 self.writeline('l_%s = ' % node.target, node)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200961 if frame.toplevel:
Armin Ronacher53042292008-04-26 18:30:19 +0200962 self.write('context.vars[%r] = ' % node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200963 self.write('environment.get_template(')
964 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200965 self.write(', %r).' % self.name)
966 if node.with_context:
Armin Ronacher673aa882008-10-04 18:06:57 +0200967 self.write('make_module(context.parent, True, locals())')
Armin Ronacherea847c52008-05-02 20:04:32 +0200968 else:
969 self.write('module')
Armin Ronacher903d1682008-05-23 00:51:58 +0200970 if frame.toplevel and not node.target.startswith('_'):
Armin Ronacher53042292008-04-26 18:30:19 +0200971 self.writeline('context.exported_vars.discard(%r)' % node.target)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100972 frame.assigned_names.add(node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200973
974 def visit_FromImport(self, node, frame):
975 """Visit named imports."""
976 self.newline(node)
977 self.write('included_template = environment.get_template(')
978 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200979 self.write(', %r).' % self.name)
980 if node.with_context:
981 self.write('make_module(context.parent, True)')
982 else:
983 self.write('module')
Armin Ronachera78d2762008-05-15 23:18:07 +0200984
985 var_names = []
986 discarded_names = []
Armin Ronacher0611e492008-04-25 23:44:14 +0200987 for name in node.names:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200988 if isinstance(name, tuple):
989 name, alias = name
990 else:
991 alias = name
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200992 self.writeline('l_%s = getattr(included_template, '
993 '%r, missing)' % (alias, name))
994 self.writeline('if l_%s is missing:' % alias)
Armin Ronacher0611e492008-04-25 23:44:14 +0200995 self.indent()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200996 self.writeline('l_%s = environment.undefined(%r %% '
Armin Ronacherdc02b642008-05-15 22:47:27 +0200997 'included_template.__name__, '
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200998 'name=%r)' %
Armin Ronacher547d0b62008-07-04 16:35:10 +0200999 (alias, 'the template %%r (imported on %s) does '
1000 'not export the requested name %s' % (
1001 self.position(node),
1002 repr(name)
1003 ), name))
Armin Ronacher0611e492008-04-25 23:44:14 +02001004 self.outdent()
1005 if frame.toplevel:
Armin Ronachera78d2762008-05-15 23:18:07 +02001006 var_names.append(alias)
Armin Ronacher903d1682008-05-23 00:51:58 +02001007 if not alias.startswith('_'):
Armin Ronachera78d2762008-05-15 23:18:07 +02001008 discarded_names.append(alias)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001009 frame.assigned_names.add(alias)
Armin Ronachera78d2762008-05-15 23:18:07 +02001010
1011 if var_names:
1012 if len(var_names) == 1:
1013 name = var_names[0]
1014 self.writeline('context.vars[%r] = l_%s' % (name, name))
1015 else:
1016 self.writeline('context.vars.update({%s})' % ', '.join(
1017 '%r: l_%s' % (name, name) for name in var_names
1018 ))
1019 if discarded_names:
1020 if len(discarded_names) == 1:
1021 self.writeline('context.exported_vars.discard(%r)' %
1022 discarded_names[0])
1023 else:
1024 self.writeline('context.exported_vars.difference_'
1025 'update((%s))' % ', '.join(map(repr, discarded_names)))
Armin Ronacherf059ec12008-04-11 22:21:00 +02001026
Armin Ronachere791c2a2008-04-07 18:39:54 +02001027 def visit_For(self, node, frame):
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001028 # when calculating the nodes for the inner frame we have to exclude
1029 # the iterator contents from it
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001030 children = node.iter_child_nodes(exclude=('iter',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001031 if node.recursive:
1032 loop_frame = self.function_scoping(node, frame, children,
1033 find_special=False)
1034 else:
1035 loop_frame = frame.inner()
1036 loop_frame.inspect(children)
1037
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001038 # try to figure out if we have an extended loop. An extended loop
1039 # is necessary if the loop is in recursive mode if the special loop
1040 # variable is accessed in the body.
1041 extended_loop = node.recursive or 'loop' in \
1042 find_undeclared(node.iter_child_nodes(
1043 only=('body',)), ('loop',))
1044
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001045 # if we don't have an recursive loop we have to find the shadowed
Armin Ronacherff53c782008-08-13 18:55:50 +02001046 # variables at that point. Because loops can be nested but the loop
1047 # variable is a special one we have to enforce aliasing for it.
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001048 if not node.recursive:
Armin Ronacher673aa882008-10-04 18:06:57 +02001049 aliases = self.push_scope(loop_frame, ('loop',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001050
1051 # otherwise we set up a buffer and add a function def
1052 else:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001053 self.writeline('def loop(reciter, loop_render_func):', node)
1054 self.indent()
Armin Ronachered1e0d42008-05-18 20:25:28 +02001055 self.buffer(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001056 aliases = {}
1057
Armin Ronacherff53c782008-08-13 18:55:50 +02001058 # make sure the loop variable is a special one and raise a template
1059 # assertion error if a loop tries to write to loop
Armin Ronacher833a3b52008-08-14 12:31:12 +02001060 if extended_loop:
1061 loop_frame.identifiers.add_special('loop')
Armin Ronacherff53c782008-08-13 18:55:50 +02001062 for name in node.find_all(nodes.Name):
1063 if name.ctx == 'store' and name.name == 'loop':
1064 self.fail('Can\'t assign to special loop variable '
1065 'in for-loop target', name.lineno)
1066
Armin Ronacherc9705c22008-04-27 21:28:03 +02001067 self.pull_locals(loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001068 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001069 iteration_indicator = self.temporary_identifier()
1070 self.writeline('%s = 1' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001071
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001072 # Create a fake parent loop if the else or test section of a
1073 # loop is accessing the special loop variable and no parent loop
1074 # exists.
1075 if 'loop' not in aliases and 'loop' in find_undeclared(
1076 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1077 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
Armin Ronacher547d0b62008-07-04 16:35:10 +02001078 ("'loop' is undefined. the filter section of a loop as well "
1079 "as the else block doesn't have access to the special 'loop'"
1080 " variable of the current loop. Because there is no parent "
1081 "loop it's undefined. Happened in loop on %s" %
1082 self.position(node)))
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001083
1084 self.writeline('for ', node)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001085 self.visit(node.target, loop_frame)
Armin Ronacher180a1bd2008-04-09 12:14:24 +02001086 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001087
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001088 # if we have an extened loop and a node test, we filter in the
1089 # "outer frame".
1090 if extended_loop and node.test is not None:
1091 self.write('(')
1092 self.visit(node.target, loop_frame)
1093 self.write(' for ')
1094 self.visit(node.target, loop_frame)
1095 self.write(' in ')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001096 if node.recursive:
1097 self.write('reciter')
1098 else:
1099 self.visit(node.iter, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001100 self.write(' if (')
1101 test_frame = loop_frame.copy()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001102 self.visit(node.test, test_frame)
1103 self.write('))')
1104
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001105 elif node.recursive:
1106 self.write('reciter')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001107 else:
1108 self.visit(node.iter, loop_frame)
1109
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001110 if node.recursive:
1111 self.write(', recurse=loop_render_func):')
1112 else:
1113 self.write(extended_loop and '):' or ':')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001114
1115 # tests in not extended loops become a continue
1116 if not extended_loop and node.test is not None:
1117 self.indent()
Armin Ronacher47a506f2008-05-06 12:17:23 +02001118 self.writeline('if not ')
Armin Ronacher32a910f2008-04-26 23:21:03 +02001119 self.visit(node.test, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001120 self.write(':')
1121 self.indent()
1122 self.writeline('continue')
1123 self.outdent(2)
1124
Armin Ronacherc9705c22008-04-27 21:28:03 +02001125 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001126 self.blockvisit(node.body, loop_frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001127 if node.else_:
1128 self.writeline('%s = 0' % iteration_indicator)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001129 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001130
1131 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001132 self.writeline('if %s:' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001133 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001134 self.blockvisit(node.else_, loop_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001135 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001136
Armin Ronacherd4c64f72008-04-11 17:15:29 +02001137 # reset the aliases if there are any.
Armin Ronachercebd8382008-12-25 18:33:46 +01001138 if not node.recursive:
1139 self.pop_scope(aliases, loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001140
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001141 # if the node was recursive we have to return the buffer contents
1142 # and start the iteration code
1143 if node.recursive:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001144 self.return_buffer_contents(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001145 self.outdent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001146 self.start_write(frame, node)
1147 self.write('loop(')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001148 self.visit(node.iter, frame)
1149 self.write(', loop)')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001150 self.end_write(frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001151
Armin Ronachere791c2a2008-04-07 18:39:54 +02001152 def visit_If(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001153 if_frame = frame.soft()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001154 self.writeline('if ', node)
Armin Ronacher75cfb862008-04-11 13:47:22 +02001155 self.visit(node.test, if_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001156 self.write(':')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001157 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001158 self.blockvisit(node.body, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001159 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001160 if node.else_:
1161 self.writeline('else:')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001162 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001163 self.blockvisit(node.else_, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001164 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001165
Armin Ronacher8efc5222008-04-08 14:47:40 +02001166 def visit_Macro(self, node, frame):
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001167 macro_frame = self.macro_body(node, frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001168 self.newline()
1169 if frame.toplevel:
Armin Ronacher903d1682008-05-23 00:51:58 +02001170 if not node.name.startswith('_'):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001171 self.write('context.exported_vars.add(%r)' % node.name)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001172 self.writeline('context.vars[%r] = ' % node.name)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001173 self.write('l_%s = ' % node.name)
1174 self.macro_def(node, macro_frame)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001175 frame.assigned_names.add(node.name)
Armin Ronacher71082072008-04-12 14:19:36 +02001176
1177 def visit_CallBlock(self, node, frame):
Armin Ronacher3da90312008-05-23 16:37:28 +02001178 children = node.iter_child_nodes(exclude=('call',))
1179 call_frame = self.macro_body(node, frame, children)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001180 self.writeline('caller = ')
1181 self.macro_def(node, call_frame)
1182 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001183 self.visit_Call(node.call, call_frame, forward_caller=True)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001184 self.end_write(frame)
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001185
1186 def visit_FilterBlock(self, node, frame):
1187 filter_frame = frame.inner()
1188 filter_frame.inspect(node.iter_child_nodes())
Armin Ronacher673aa882008-10-04 18:06:57 +02001189 aliases = self.push_scope(filter_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001190 self.pull_locals(filter_frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001191 self.buffer(filter_frame)
Armin Ronacherf40c8842008-09-17 18:51:26 +02001192 self.blockvisit(node.body, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001193 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001194 self.visit_Filter(node.filter, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001195 self.end_write(frame)
Armin Ronacher673aa882008-10-04 18:06:57 +02001196 self.pop_scope(aliases, filter_frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001197
Armin Ronachere791c2a2008-04-07 18:39:54 +02001198 def visit_ExprStmt(self, node, frame):
1199 self.newline(node)
Armin Ronacher6ce170c2008-04-25 12:32:36 +02001200 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001201
1202 def visit_Output(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001203 # if we have a known extends statement, we don't output anything
Armin Ronacher79668952008-09-23 22:52:46 +02001204 # if we are in a require_output_check section
1205 if self.has_known_extends and frame.require_output_check:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001206 return
Armin Ronachere791c2a2008-04-07 18:39:54 +02001207
Armin Ronacher665bfb82008-07-14 13:41:46 +02001208 if self.environment.finalize:
1209 finalize = lambda x: unicode(self.environment.finalize(x))
1210 else:
1211 finalize = unicode
1212
Armin Ronacher75cfb862008-04-11 13:47:22 +02001213 self.newline(node)
Armin Ronacher8edbe492008-04-10 20:43:43 +02001214
Armin Ronacher79668952008-09-23 22:52:46 +02001215 # if we are inside a frame that requires output checking, we do so
Armin Ronacher7fb38972008-04-11 13:54:28 +02001216 outdent_later = False
Armin Ronacher79668952008-09-23 22:52:46 +02001217 if frame.require_output_check:
Armin Ronacher203bfcb2008-04-24 21:54:44 +02001218 self.writeline('if parent_template is None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +02001219 self.indent()
Armin Ronacher7fb38972008-04-11 13:54:28 +02001220 outdent_later = True
Armin Ronacher75cfb862008-04-11 13:47:22 +02001221
Armin Ronachere791c2a2008-04-07 18:39:54 +02001222 # try to evaluate as many chunks as possible into a static
1223 # string at compile time.
1224 body = []
1225 for child in node.nodes:
1226 try:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001227 const = child.as_const()
1228 except nodes.Impossible:
1229 body.append(child)
1230 continue
1231 try:
1232 if self.environment.autoescape:
1233 if hasattr(const, '__html__'):
1234 const = const.__html__()
1235 else:
1236 const = escape(const)
Armin Ronacher665bfb82008-07-14 13:41:46 +02001237 const = finalize(const)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001238 except:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001239 # if something goes wrong here we evaluate the node
1240 # at runtime for easier debugging
Armin Ronachere791c2a2008-04-07 18:39:54 +02001241 body.append(child)
1242 continue
1243 if body and isinstance(body[-1], list):
1244 body[-1].append(const)
1245 else:
1246 body.append([const])
1247
Armin Ronachered1e0d42008-05-18 20:25:28 +02001248 # if we have less than 3 nodes or a buffer we yield or extend/append
1249 if len(body) < 3 or frame.buffer is not None:
Armin Ronacher32a910f2008-04-26 23:21:03 +02001250 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001251 # for one item we append, for more we extend
1252 if len(body) == 1:
1253 self.writeline('%s.append(' % frame.buffer)
1254 else:
1255 self.writeline('%s.extend((' % frame.buffer)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001256 self.indent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001257 for item in body:
1258 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001259 val = repr(concat(item))
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001260 if frame.buffer is None:
1261 self.writeline('yield ' + val)
1262 else:
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001263 self.writeline(val + ', ')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001264 else:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001265 if frame.buffer is None:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001266 self.writeline('yield ', item)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001267 else:
1268 self.newline(item)
Armin Ronacherd1342312008-04-28 12:20:12 +02001269 close = 1
1270 if self.environment.autoescape:
1271 self.write('escape(')
1272 else:
Armin Ronacherbd357722009-08-05 20:25:06 +02001273 self.write('to_string(')
Armin Ronacherd1342312008-04-28 12:20:12 +02001274 if self.environment.finalize is not None:
1275 self.write('environment.finalize(')
1276 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001277 self.visit(item, frame)
Armin Ronacherd1342312008-04-28 12:20:12 +02001278 self.write(')' * close)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001279 if frame.buffer is not None:
1280 self.write(', ')
1281 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001282 # close the open parentheses
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001283 self.outdent()
1284 self.writeline(len(body) == 1 and ')' or '))')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001285
1286 # otherwise we create a format string as this is faster in that case
1287 else:
1288 format = []
1289 arguments = []
1290 for item in body:
1291 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001292 format.append(concat(item).replace('%', '%%'))
Armin Ronachere791c2a2008-04-07 18:39:54 +02001293 else:
1294 format.append('%s')
1295 arguments.append(item)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001296 self.writeline('yield ')
Armin Ronacherde6bf712008-04-26 01:44:14 +02001297 self.write(repr(concat(format)) + ' % (')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001298 idx = -1
Armin Ronachera7f016d2008-05-16 00:22:40 +02001299 self.indent()
Armin Ronacher8e8d0712008-04-16 23:10:49 +02001300 for argument in arguments:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001301 self.newline(argument)
Armin Ronacherd1342312008-04-28 12:20:12 +02001302 close = 0
1303 if self.environment.autoescape:
1304 self.write('escape(')
1305 close += 1
1306 if self.environment.finalize is not None:
1307 self.write('environment.finalize(')
1308 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001309 self.visit(argument, frame)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001310 self.write(')' * close + ', ')
Armin Ronachera7f016d2008-05-16 00:22:40 +02001311 self.outdent()
1312 self.writeline(')')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001313
Armin Ronacher7fb38972008-04-11 13:54:28 +02001314 if outdent_later:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001315 self.outdent()
1316
Armin Ronacher8efc5222008-04-08 14:47:40 +02001317 def visit_Assign(self, node, frame):
1318 self.newline(node)
1319 # toplevel assignments however go into the local namespace and
1320 # the current template's context. We create a copy of the frame
1321 # here and add a set so that the Name visitor can add the assigned
1322 # names here.
1323 if frame.toplevel:
1324 assignment_frame = frame.copy()
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001325 assignment_frame.toplevel_assignments = set()
Armin Ronacher8efc5222008-04-08 14:47:40 +02001326 else:
1327 assignment_frame = frame
1328 self.visit(node.target, assignment_frame)
1329 self.write(' = ')
1330 self.visit(node.node, frame)
Armin Ronacher9706fab2008-04-08 18:49:56 +02001331
1332 # make sure toplevel assignments are added to the context.
Armin Ronacher8efc5222008-04-08 14:47:40 +02001333 if frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001334 public_names = [x for x in assignment_frame.toplevel_assignments
Armin Ronacher903d1682008-05-23 00:51:58 +02001335 if not x.startswith('_')]
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001336 if len(assignment_frame.toplevel_assignments) == 1:
Armin Ronacherbd357722009-08-05 20:25:06 +02001337 name = next(iter(assignment_frame.toplevel_assignments))
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001338 self.writeline('context.vars[%r] = l_%s' % (name, name))
Armin Ronacher69e12db2008-05-12 09:00:03 +02001339 else:
1340 self.writeline('context.vars.update({')
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001341 for idx, name in enumerate(assignment_frame.toplevel_assignments):
Armin Ronacher69e12db2008-05-12 09:00:03 +02001342 if idx:
1343 self.write(', ')
1344 self.write('%r: l_%s' % (name, name))
1345 self.write('})')
1346 if public_names:
1347 if len(public_names) == 1:
1348 self.writeline('context.exported_vars.add(%r)' %
1349 public_names[0])
1350 else:
1351 self.writeline('context.exported_vars.update((%s))' %
1352 ', '.join(map(repr, public_names)))
Armin Ronacher8efc5222008-04-08 14:47:40 +02001353
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001354 # -- Expression Visitors
1355
Armin Ronachere791c2a2008-04-07 18:39:54 +02001356 def visit_Name(self, node, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001357 if node.ctx == 'store' and frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001358 frame.toplevel_assignments.add(node.name)
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001359 self.write('l_' + node.name)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001360 frame.assigned_names.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001361
1362 def visit_Const(self, node, frame):
1363 val = node.value
1364 if isinstance(val, float):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001365 self.write(str(val))
1366 else:
1367 self.write(repr(val))
1368
Armin Ronacher5411ce72008-05-25 11:36:22 +02001369 def visit_TemplateData(self, node, frame):
1370 self.write(repr(node.as_const()))
1371
Armin Ronacher8efc5222008-04-08 14:47:40 +02001372 def visit_Tuple(self, node, frame):
1373 self.write('(')
1374 idx = -1
1375 for idx, item in enumerate(node.items):
1376 if idx:
1377 self.write(', ')
1378 self.visit(item, frame)
1379 self.write(idx == 0 and ',)' or ')')
1380
Armin Ronacher8edbe492008-04-10 20:43:43 +02001381 def visit_List(self, node, frame):
1382 self.write('[')
1383 for idx, item in enumerate(node.items):
1384 if idx:
1385 self.write(', ')
1386 self.visit(item, frame)
1387 self.write(']')
1388
1389 def visit_Dict(self, node, frame):
1390 self.write('{')
1391 for idx, item in enumerate(node.items):
1392 if idx:
1393 self.write(', ')
1394 self.visit(item.key, frame)
1395 self.write(': ')
1396 self.visit(item.value, frame)
1397 self.write('}')
1398
Armin Ronachere791c2a2008-04-07 18:39:54 +02001399 def binop(operator):
1400 def visitor(self, node, frame):
1401 self.write('(')
1402 self.visit(node.left, frame)
1403 self.write(' %s ' % operator)
1404 self.visit(node.right, frame)
1405 self.write(')')
1406 return visitor
1407
1408 def uaop(operator):
1409 def visitor(self, node, frame):
1410 self.write('(' + operator)
Armin Ronacher9a822052008-04-17 18:44:07 +02001411 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001412 self.write(')')
1413 return visitor
1414
1415 visit_Add = binop('+')
1416 visit_Sub = binop('-')
1417 visit_Mul = binop('*')
1418 visit_Div = binop('/')
1419 visit_FloorDiv = binop('//')
1420 visit_Pow = binop('**')
1421 visit_Mod = binop('%')
1422 visit_And = binop('and')
1423 visit_Or = binop('or')
1424 visit_Pos = uaop('+')
1425 visit_Neg = uaop('-')
1426 visit_Not = uaop('not ')
1427 del binop, uaop
1428
Armin Ronacherd1342312008-04-28 12:20:12 +02001429 def visit_Concat(self, node, frame):
Armin Ronacherfdf95302008-05-11 22:20:51 +02001430 self.write('%s((' % (self.environment.autoescape and
1431 'markup_join' or 'unicode_join'))
Armin Ronacherd1342312008-04-28 12:20:12 +02001432 for arg in node.nodes:
1433 self.visit(arg, frame)
1434 self.write(', ')
1435 self.write('))')
1436
Armin Ronachere791c2a2008-04-07 18:39:54 +02001437 def visit_Compare(self, node, frame):
1438 self.visit(node.expr, frame)
1439 for op in node.ops:
1440 self.visit(op, frame)
1441
1442 def visit_Operand(self, node, frame):
1443 self.write(' %s ' % operators[node.op])
1444 self.visit(node.expr, frame)
1445
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001446 def visit_Getattr(self, node, frame):
1447 self.write('environment.getattr(')
1448 self.visit(node.node, frame)
1449 self.write(', %r)' % node.attr)
1450
1451 def visit_Getitem(self, node, frame):
Armin Ronacher5c3c4702008-09-12 23:12:49 +02001452 # slices bypass the environment getitem method.
1453 if isinstance(node.arg, nodes.Slice):
Armin Ronacher8efc5222008-04-08 14:47:40 +02001454 self.visit(node.node, frame)
1455 self.write('[')
1456 self.visit(node.arg, frame)
1457 self.write(']')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001458 else:
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001459 self.write('environment.getitem(')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001460 self.visit(node.node, frame)
1461 self.write(', ')
1462 self.visit(node.arg, frame)
1463 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001464
1465 def visit_Slice(self, node, frame):
1466 if node.start is not None:
1467 self.visit(node.start, frame)
1468 self.write(':')
1469 if node.stop is not None:
1470 self.visit(node.stop, frame)
1471 if node.step is not None:
1472 self.write(':')
1473 self.visit(node.step, frame)
1474
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001475 def visit_Filter(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001476 self.write(self.filters[node.name] + '(')
Christoph Hack80909862008-04-14 01:35:10 +02001477 func = self.environment.filters.get(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +02001478 if func is None:
Armin Ronachere2244882008-05-19 09:25:57 +02001479 self.fail('no filter named %r' % node.name, node.lineno)
Christoph Hack80909862008-04-14 01:35:10 +02001480 if getattr(func, 'contextfilter', False):
1481 self.write('context, ')
Armin Ronacher9a027f42008-04-17 11:13:40 +02001482 elif getattr(func, 'environmentfilter', False):
1483 self.write('environment, ')
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001484
1485 # if the filter node is None we are inside a filter block
1486 # and want to write to the current buffer
Armin Ronacher3da90312008-05-23 16:37:28 +02001487 if node.node is not None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001488 self.visit(node.node, frame)
Armin Ronacher3da90312008-05-23 16:37:28 +02001489 elif self.environment.autoescape:
1490 self.write('Markup(concat(%s))' % frame.buffer)
1491 else:
1492 self.write('concat(%s)' % frame.buffer)
Armin Ronacherd55ab532008-04-09 16:13:39 +02001493 self.signature(node, frame)
1494 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001495
1496 def visit_Test(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001497 self.write(self.tests[node.name] + '(')
Armin Ronacher0611e492008-04-25 23:44:14 +02001498 if node.name not in self.environment.tests:
Armin Ronachere2244882008-05-19 09:25:57 +02001499 self.fail('no test named %r' % node.name, node.lineno)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001500 self.visit(node.node, frame)
1501 self.signature(node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001502 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001503
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001504 def visit_CondExpr(self, node, frame):
Armin Ronacher547d0b62008-07-04 16:35:10 +02001505 def write_expr2():
1506 if node.expr2 is not None:
1507 return self.visit(node.expr2, frame)
1508 self.write('environment.undefined(%r)' % ('the inline if-'
1509 'expression on %s evaluated to false and '
1510 'no else section was defined.' % self.position(node)))
1511
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001512 if not have_condexpr:
1513 self.write('((')
1514 self.visit(node.test, frame)
1515 self.write(') and (')
1516 self.visit(node.expr1, frame)
1517 self.write(',) or (')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001518 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001519 self.write(',))[0]')
1520 else:
1521 self.write('(')
1522 self.visit(node.expr1, frame)
1523 self.write(' if ')
1524 self.visit(node.test, frame)
1525 self.write(' else ')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001526 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001527 self.write(')')
1528
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001529 def visit_Call(self, node, frame, forward_caller=False):
Armin Ronacherc63243e2008-04-14 22:53:58 +02001530 if self.environment.sandboxed:
Armin Ronacherfd310492008-05-25 00:16:51 +02001531 self.write('environment.call(context, ')
1532 else:
1533 self.write('context.call(')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001534 self.visit(node.node, frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001535 extra_kwargs = forward_caller and {'caller': 'caller'} or None
Armin Ronacherfd310492008-05-25 00:16:51 +02001536 self.signature(node, frame, extra_kwargs)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001537 self.write(')')
1538
1539 def visit_Keyword(self, node, frame):
Armin Ronacher2e9396b2008-04-16 14:21:57 +02001540 self.write(node.key + '=')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001541 self.visit(node.value, frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001542
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001543 # -- Unused nodes for extensions
Armin Ronachered1e0d42008-05-18 20:25:28 +02001544
1545 def visit_MarkSafe(self, node, frame):
1546 self.write('Markup(')
1547 self.visit(node.expr, frame)
1548 self.write(')')
1549
1550 def visit_EnvironmentAttribute(self, node, frame):
1551 self.write('environment.' + node.name)
1552
1553 def visit_ExtensionAttribute(self, node, frame):
Armin Ronacher6df604e2008-05-23 22:18:38 +02001554 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
Armin Ronachered1e0d42008-05-18 20:25:28 +02001555
1556 def visit_ImportedName(self, node, frame):
1557 self.write(self.import_aliases[node.importname])
1558
1559 def visit_InternalName(self, node, frame):
1560 self.write(node.name)
1561
Armin Ronacher6df604e2008-05-23 22:18:38 +02001562 def visit_ContextReference(self, node, frame):
1563 self.write('context')
1564
Armin Ronachered1e0d42008-05-18 20:25:28 +02001565 def visit_Continue(self, node, frame):
1566 self.writeline('continue', node)
1567
1568 def visit_Break(self, node, frame):
1569 self.writeline('break', node)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001570
1571 def visit_Scope(self, node, frame):
1572 scope_frame = frame.inner()
1573 scope_frame.inspect(node.iter_child_nodes())
1574 aliases = self.push_scope(scope_frame)
1575 self.pull_locals(scope_frame)
1576 self.blockvisit(node.body, scope_frame)
1577 self.pop_scope(aliases, scope_frame)