blob: a6f26a59219558333ef140a3b8f90c6d399474ac [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 Ronacher62ccd1b2009-01-04 14:26:19 +01008 :copyright: (c) 2009 by the Jinja Team.
Armin Ronacherd7764372008-07-15 00:11:14 +02009 :license: BSD.
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 Ronacher8e8d0712008-04-16 23:10:49 +020039def generate(node, environment, name, filename, stream=None):
Armin Ronacherbcb7c532008-04-11 16:30:34 +020040 """Generate the python source for a node tree."""
Armin Ronacher023b5e92008-05-08 11:03:10 +020041 if not isinstance(node, nodes.Template):
42 raise TypeError('Can\'t compile non template nodes')
Armin Ronacher8e8d0712008-04-16 23:10:49 +020043 generator = CodeGenerator(environment, name, filename, stream)
Armin Ronachere791c2a2008-04-07 18:39:54 +020044 generator.visit(node)
45 if stream is None:
46 return generator.stream.getvalue()
47
48
Armin Ronacher4dfc9752008-04-09 15:03:29 +020049def has_safe_repr(value):
50 """Does the node have a safe representation?"""
Armin Ronacherd55ab532008-04-09 16:13:39 +020051 if value is None or value is NotImplemented or value is Ellipsis:
Armin Ronacher4dfc9752008-04-09 15:03:29 +020052 return True
Armin Ronacherd55ab532008-04-09 16:13:39 +020053 if isinstance(value, (bool, int, long, float, complex, basestring,
Armin Ronacher32a910f2008-04-26 23:21:03 +020054 xrange, Markup)):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020055 return True
Armin Ronacherd55ab532008-04-09 16:13:39 +020056 if isinstance(value, (tuple, list, set, frozenset)):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020057 for item in value:
58 if not has_safe_repr(item):
59 return False
60 return True
61 elif isinstance(value, dict):
62 for key, value in value.iteritems():
63 if not has_safe_repr(key):
64 return False
65 if not has_safe_repr(value):
66 return False
67 return True
68 return False
69
70
Armin Ronacherc9705c22008-04-27 21:28:03 +020071def find_undeclared(nodes, names):
72 """Check if the names passed are accessed undeclared. The return value
73 is a set of all the undeclared names from the sequence of names found.
74 """
75 visitor = UndeclaredNameVisitor(names)
76 try:
77 for node in nodes:
78 visitor.visit(node)
79 except VisitorExit:
80 pass
81 return visitor.undeclared
82
83
Armin Ronachere791c2a2008-04-07 18:39:54 +020084class Identifiers(object):
85 """Tracks the status of identifiers in frames."""
86
87 def __init__(self):
88 # variables that are known to be declared (probably from outer
89 # frames or because they are special for the frame)
90 self.declared = set()
91
Armin Ronacher10f3ba22008-04-18 11:30:37 +020092 # undeclared variables from outer scopes
93 self.outer_undeclared = set()
94
Armin Ronachere791c2a2008-04-07 18:39:54 +020095 # names that are accessed without being explicitly declared by
96 # this one or any of the outer scopes. Names can appear both in
97 # declared and undeclared.
98 self.undeclared = set()
99
100 # names that are declared locally
101 self.declared_locally = set()
102
103 # names that are declared by parameters
104 self.declared_parameter = set()
105
106 def add_special(self, name):
107 """Register a special name like `loop`."""
108 self.undeclared.discard(name)
109 self.declared.add(name)
110
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200111 def is_declared(self, name, local_only=False):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200112 """Check if a name is declared in this or an outer scope."""
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200113 if name in self.declared_locally or name in self.declared_parameter:
114 return True
115 if local_only:
116 return False
117 return name in self.declared
Armin Ronachere791c2a2008-04-07 18:39:54 +0200118
Armin Ronacher74230e62009-10-25 12:46:31 +0100119 def copy(self):
120 return deepcopy(self)
121
Armin Ronachere791c2a2008-04-07 18:39:54 +0200122
123class Frame(object):
Armin Ronacher75cfb862008-04-11 13:47:22 +0200124 """Holds compile time information for us."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200125
126 def __init__(self, parent=None):
127 self.identifiers = Identifiers()
Armin Ronacherfed44b52008-04-13 19:42:53 +0200128
Armin Ronacher75cfb862008-04-11 13:47:22 +0200129 # a toplevel frame is the root + soft frames such as if conditions.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200130 self.toplevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200131
Armin Ronacher75cfb862008-04-11 13:47:22 +0200132 # the root frame is basically just the outermost frame, so no if
133 # conditions. This information is used to optimize inheritance
134 # situations.
135 self.rootlevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200136
Armin Ronacher79668952008-09-23 22:52:46 +0200137 # in some dynamic inheritance situations the compiler needs to add
138 # write tests around output statements.
139 self.require_output_check = parent and parent.require_output_check
Armin Ronacherf40c8842008-09-17 18:51:26 +0200140
Armin Ronacherfed44b52008-04-13 19:42:53 +0200141 # inside some tags we are using a buffer rather than yield statements.
142 # this for example affects {% filter %} or {% macro %}. If a frame
143 # is buffered this variable points to the name of the list used as
144 # buffer.
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200145 self.buffer = None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200146
Armin Ronacherfed44b52008-04-13 19:42:53 +0200147 # the name of the block we're in, otherwise None.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200148 self.block = parent and parent.block or None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200149
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100150 # a set of actually assigned names
151 self.assigned_names = set()
152
Armin Ronacherfed44b52008-04-13 19:42:53 +0200153 # the parent of this frame
154 self.parent = parent
155
Armin Ronachere791c2a2008-04-07 18:39:54 +0200156 if parent is not None:
157 self.identifiers.declared.update(
158 parent.identifiers.declared |
Armin Ronacherb3a1fcf2008-05-15 11:04:14 +0200159 parent.identifiers.declared_parameter |
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100160 parent.assigned_names
Armin Ronachere791c2a2008-04-07 18:39:54 +0200161 )
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200162 self.identifiers.outer_undeclared.update(
163 parent.identifiers.undeclared -
164 self.identifiers.declared
165 )
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200166 self.buffer = parent.buffer
Armin Ronachere791c2a2008-04-07 18:39:54 +0200167
Armin Ronacher8efc5222008-04-08 14:47:40 +0200168 def copy(self):
169 """Create a copy of the current one."""
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200170 rv = object.__new__(self.__class__)
171 rv.__dict__.update(self.__dict__)
172 rv.identifiers = object.__new__(self.identifiers.__class__)
173 rv.identifiers.__dict__.update(self.identifiers.__dict__)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200174 return rv
175
Armin Ronacherc9705c22008-04-27 21:28:03 +0200176 def inspect(self, nodes, hard_scope=False):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200177 """Walk the node and check for identifiers. If the scope is hard (eg:
178 enforce on a python level) overrides from outer scopes are tracked
179 differently.
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200180 """
181 visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200182 for node in nodes:
Armin Ronacherc9705c22008-04-27 21:28:03 +0200183 visitor.visit(node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200184
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100185 def find_shadowed(self, extra=()):
186 """Find all the shadowed names. extra is an iterable of variables
187 that may be defined with `add_special` which may occour scoped.
188 """
189 i = self.identifiers
190 return (i.declared | i.outer_undeclared) & \
191 (i.declared_locally | i.declared_parameter) | \
192 set(x for x in extra if i.is_declared(x))
193
Armin Ronachere791c2a2008-04-07 18:39:54 +0200194 def inner(self):
195 """Return an inner frame."""
196 return Frame(self)
197
Armin Ronacher75cfb862008-04-11 13:47:22 +0200198 def soft(self):
199 """Return a soft frame. A soft frame may not be modified as
200 standalone thing as it shares the resources with the frame it
201 was created of, but it's not a rootlevel frame any longer.
202 """
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200203 rv = self.copy()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200204 rv.rootlevel = False
205 return rv
206
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200207 __copy__ = copy
208
Armin Ronachere791c2a2008-04-07 18:39:54 +0200209
Armin Ronacherc9705c22008-04-27 21:28:03 +0200210class VisitorExit(RuntimeError):
211 """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
212
213
214class DependencyFinderVisitor(NodeVisitor):
215 """A visitor that collects filter and test calls."""
216
217 def __init__(self):
218 self.filters = set()
219 self.tests = set()
220
221 def visit_Filter(self, node):
222 self.generic_visit(node)
223 self.filters.add(node.name)
224
225 def visit_Test(self, node):
226 self.generic_visit(node)
227 self.tests.add(node.name)
228
229 def visit_Block(self, node):
230 """Stop visiting at blocks."""
231
232
233class UndeclaredNameVisitor(NodeVisitor):
234 """A visitor that checks if a name is accessed without being
235 declared. This is different from the frame visitor as it will
236 not stop at closure frames.
237 """
238
239 def __init__(self, names):
240 self.names = set(names)
241 self.undeclared = set()
242
243 def visit_Name(self, node):
244 if node.ctx == 'load' and node.name in self.names:
245 self.undeclared.add(node.name)
246 if self.undeclared == self.names:
247 raise VisitorExit()
248 else:
249 self.names.discard(node.name)
250
251 def visit_Block(self, node):
252 """Stop visiting a blocks."""
253
254
Armin Ronachere791c2a2008-04-07 18:39:54 +0200255class FrameIdentifierVisitor(NodeVisitor):
256 """A visitor for `Frame.inspect`."""
257
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200258 def __init__(self, identifiers, hard_scope):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200259 self.identifiers = identifiers
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200260 self.hard_scope = hard_scope
Armin Ronachere791c2a2008-04-07 18:39:54 +0200261
Armin Ronacherc9705c22008-04-27 21:28:03 +0200262 def visit_Name(self, node):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200263 """All assignments to names go through this function."""
Armin Ronachere9411b42008-05-15 16:22:07 +0200264 if node.ctx == 'store':
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200265 self.identifiers.declared_locally.add(node.name)
Armin Ronachere9411b42008-05-15 16:22:07 +0200266 elif node.ctx == 'param':
267 self.identifiers.declared_parameter.add(node.name)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200268 elif node.ctx == 'load' and not \
269 self.identifiers.is_declared(node.name, self.hard_scope):
270 self.identifiers.undeclared.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200271
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200272 def visit_If(self, node):
273 self.visit(node.test)
Armin Ronacher74230e62009-10-25 12:46:31 +0100274 real_identifiers = self.identifiers
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200275
Armin Ronacher74230e62009-10-25 12:46:31 +0100276 old_names = real_identifiers.declared | \
277 real_identifiers.declared_locally | \
278 real_identifiers.declared_parameter
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200279
Armin Ronacher74230e62009-10-25 12:46:31 +0100280 def inner_visit(nodes):
Armin Ronacher1965e312009-10-25 13:03:08 +0100281 if not nodes:
282 return set()
Armin Ronacher74230e62009-10-25 12:46:31 +0100283 self.identifiers = real_identifiers.copy()
284 for subnode in nodes:
285 self.visit(subnode)
286 rv = self.identifiers.declared_locally - old_names
287 # we have to remember the undeclared variables of this branch
288 # because we will have to pull them.
289 real_identifiers.undeclared.update(self.identifiers.undeclared)
290 self.identifiers = real_identifiers
291 return rv
292
293 body = inner_visit(node.body)
294 else_ = inner_visit(node.else_ or ())
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200295
296 # the differences between the two branches are also pulled as
297 # undeclared variables
Armin Ronacher74230e62009-10-25 12:46:31 +0100298 real_identifiers.undeclared.update(body.symmetric_difference(else_))
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200299
Armin Ronacher74230e62009-10-25 12:46:31 +0100300 # remember those that are declared.
301 real_identifiers.declared_locally.update(body | else_)
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200302
Armin Ronacherc9705c22008-04-27 21:28:03 +0200303 def visit_Macro(self, node):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200304 self.identifiers.declared_locally.add(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +0200305
Armin Ronacherc9705c22008-04-27 21:28:03 +0200306 def visit_Import(self, node):
307 self.generic_visit(node)
308 self.identifiers.declared_locally.add(node.target)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200309
Armin Ronacherc9705c22008-04-27 21:28:03 +0200310 def visit_FromImport(self, node):
311 self.generic_visit(node)
312 for name in node.names:
313 if isinstance(name, tuple):
314 self.identifiers.declared_locally.add(name[1])
315 else:
316 self.identifiers.declared_locally.add(name)
317
318 def visit_Assign(self, node):
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200319 """Visit assignments in the correct order."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200320 self.visit(node.node)
321 self.visit(node.target)
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200322
Armin Ronacherc9705c22008-04-27 21:28:03 +0200323 def visit_For(self, node):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200324 """Visiting stops at for blocks. However the block sequence
325 is visited as part of the outer scope.
326 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200327 self.visit(node.iter)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200328
Armin Ronacherc9705c22008-04-27 21:28:03 +0200329 def visit_CallBlock(self, node):
330 for child in node.iter_child_nodes(exclude=('body',)):
331 self.visit(child)
332
333 def visit_FilterBlock(self, node):
334 self.visit(node.filter)
335
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100336 def visit_Scope(self, node):
337 """Stop visiting at scopes."""
338
Armin Ronacherc9705c22008-04-27 21:28:03 +0200339 def visit_Block(self, node):
340 """Stop visiting at blocks."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200341
342
Armin Ronacher75cfb862008-04-11 13:47:22 +0200343class CompilerExit(Exception):
344 """Raised if the compiler encountered a situation where it just
345 doesn't make sense to further process the code. Any block that
Armin Ronacher0611e492008-04-25 23:44:14 +0200346 raises such an exception is not further processed.
347 """
Armin Ronacher75cfb862008-04-11 13:47:22 +0200348
349
Armin Ronachere791c2a2008-04-07 18:39:54 +0200350class CodeGenerator(NodeVisitor):
351
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200352 def __init__(self, environment, name, filename, stream=None):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200353 if stream is None:
354 stream = StringIO()
Christoph Hack65642a52008-04-08 14:46:56 +0200355 self.environment = environment
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200356 self.name = name
Armin Ronachere791c2a2008-04-07 18:39:54 +0200357 self.filename = filename
358 self.stream = stream
Armin Ronacherfed44b52008-04-13 19:42:53 +0200359
Armin Ronacher023b5e92008-05-08 11:03:10 +0200360 # aliases for imports
361 self.import_aliases = {}
362
Armin Ronacherfed44b52008-04-13 19:42:53 +0200363 # a registry for all blocks. Because blocks are moved out
364 # into the global python scope they are registered here
Armin Ronachere791c2a2008-04-07 18:39:54 +0200365 self.blocks = {}
Armin Ronacherfed44b52008-04-13 19:42:53 +0200366
367 # the number of extends statements so far
Armin Ronacher7fb38972008-04-11 13:54:28 +0200368 self.extends_so_far = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200369
370 # some templates have a rootlevel extends. In this case we
371 # can safely assume that we're a child template and do some
372 # more optimizations.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200373 self.has_known_extends = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200374
Armin Ronacherba3757b2008-04-16 19:43:16 +0200375 # the current line number
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200376 self.code_lineno = 1
Armin Ronacherba3757b2008-04-16 19:43:16 +0200377
Armin Ronacherb9e78752008-05-10 23:36:28 +0200378 # registry of all filters and tests (global, not block local)
379 self.tests = {}
380 self.filters = {}
381
Armin Ronacherba3757b2008-04-16 19:43:16 +0200382 # the debug information
383 self.debug_info = []
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200384 self._write_debug_info = None
Armin Ronacherba3757b2008-04-16 19:43:16 +0200385
Armin Ronacherfed44b52008-04-13 19:42:53 +0200386 # the number of new lines before the next write()
387 self._new_lines = 0
388
389 # the line number of the last written statement
Armin Ronachere791c2a2008-04-07 18:39:54 +0200390 self._last_line = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200391
392 # true if nothing was written so far.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200393 self._first_write = True
394
Armin Ronacherfed44b52008-04-13 19:42:53 +0200395 # used by the `temporary_identifier` method to get new
396 # unique, temporary identifier
397 self._last_identifier = 0
398
399 # the current indentation
400 self._indentation = 0
401
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200402 # -- Various compilation helpers
403
Armin Ronachere2244882008-05-19 09:25:57 +0200404 def fail(self, msg, lineno):
405 """Fail with a `TemplateAssertionError`."""
406 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
407
Armin Ronachere791c2a2008-04-07 18:39:54 +0200408 def temporary_identifier(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200409 """Get a new unique identifier."""
410 self._last_identifier += 1
Armin Ronacher8a1d27f2008-05-19 08:37:19 +0200411 return 't_%d' % self._last_identifier
Armin Ronachere791c2a2008-04-07 18:39:54 +0200412
Armin Ronachered1e0d42008-05-18 20:25:28 +0200413 def buffer(self, frame):
414 """Enable buffering for the frame from that point onwards."""
Armin Ronachere2244882008-05-19 09:25:57 +0200415 frame.buffer = self.temporary_identifier()
416 self.writeline('%s = []' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200417
418 def return_buffer_contents(self, frame):
419 """Return the buffer contents of the frame."""
420 if self.environment.autoescape:
421 self.writeline('return Markup(concat(%s))' % frame.buffer)
422 else:
423 self.writeline('return concat(%s)' % frame.buffer)
424
Armin Ronachere791c2a2008-04-07 18:39:54 +0200425 def indent(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200426 """Indent by one."""
427 self._indentation += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +0200428
Armin Ronacher8efc5222008-04-08 14:47:40 +0200429 def outdent(self, step=1):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200430 """Outdent by step."""
431 self._indentation -= step
Armin Ronachere791c2a2008-04-07 18:39:54 +0200432
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200433 def start_write(self, frame, node=None):
434 """Yield or write into the frame buffer."""
435 if frame.buffer is None:
436 self.writeline('yield ', node)
437 else:
438 self.writeline('%s.append(' % frame.buffer, node)
439
440 def end_write(self, frame):
441 """End the writing process started by `start_write`."""
442 if frame.buffer is not None:
443 self.write(')')
444
445 def simple_write(self, s, frame, node=None):
446 """Simple shortcut for start_write + write + end_write."""
447 self.start_write(frame, node)
448 self.write(s)
449 self.end_write(frame)
450
Armin Ronacherf40c8842008-09-17 18:51:26 +0200451 def blockvisit(self, nodes, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200452 """Visit a list of nodes as block in a frame. If the current frame
453 is no buffer a dummy ``if 0: yield None`` is written automatically
454 unless the force_generator parameter is set to False.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200455 """
Armin Ronacherf40c8842008-09-17 18:51:26 +0200456 if frame.buffer is None:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200457 self.writeline('if 0: yield None')
Armin Ronacherf40c8842008-09-17 18:51:26 +0200458 else:
459 self.writeline('pass')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200460 try:
461 for node in nodes:
462 self.visit(node, frame)
463 except CompilerExit:
464 pass
Armin Ronachere791c2a2008-04-07 18:39:54 +0200465
466 def write(self, x):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200467 """Write a string into the output stream."""
468 if self._new_lines:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200469 if not self._first_write:
Armin Ronacherfed44b52008-04-13 19:42:53 +0200470 self.stream.write('\n' * self._new_lines)
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200471 self.code_lineno += self._new_lines
472 if self._write_debug_info is not None:
473 self.debug_info.append((self._write_debug_info,
474 self.code_lineno))
475 self._write_debug_info = None
Armin Ronachere791c2a2008-04-07 18:39:54 +0200476 self._first_write = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200477 self.stream.write(' ' * self._indentation)
478 self._new_lines = 0
Armin Ronachere791c2a2008-04-07 18:39:54 +0200479 self.stream.write(x)
480
481 def writeline(self, x, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200482 """Combination of newline and write."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200483 self.newline(node, extra)
484 self.write(x)
485
486 def newline(self, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200487 """Add one or more newlines before the next write."""
488 self._new_lines = max(self._new_lines, 1 + extra)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200489 if node is not None and node.lineno != self._last_line:
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200490 self._write_debug_info = node.lineno
491 self._last_line = node.lineno
Armin Ronachere791c2a2008-04-07 18:39:54 +0200492
Armin Ronacherfd310492008-05-25 00:16:51 +0200493 def signature(self, node, frame, extra_kwargs=None):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200494 """Writes a function call to the stream for the current node.
Armin Ronacherfd310492008-05-25 00:16:51 +0200495 A leading comma is added automatically. The extra keyword
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200496 arguments may not include python keywords otherwise a syntax
497 error could occour. The extra keyword arguments should be given
498 as python dict.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200499 """
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200500 # if any of the given keyword arguments is a python keyword
501 # we have to make sure that no invalid call is created.
502 kwarg_workaround = False
503 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200504 if is_python_keyword(kwarg):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200505 kwarg_workaround = True
506 break
507
Armin Ronacher8efc5222008-04-08 14:47:40 +0200508 for arg in node.args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200509 self.write(', ')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200510 self.visit(arg, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200511
512 if not kwarg_workaround:
513 for kwarg in node.kwargs:
Armin Ronacherfd310492008-05-25 00:16:51 +0200514 self.write(', ')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200515 self.visit(kwarg, frame)
516 if extra_kwargs is not None:
517 for key, value in extra_kwargs.iteritems():
Armin Ronacherfd310492008-05-25 00:16:51 +0200518 self.write(', %s=%s' % (key, value))
Armin Ronacher8efc5222008-04-08 14:47:40 +0200519 if node.dyn_args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200520 self.write(', *')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200521 self.visit(node.dyn_args, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200522
523 if kwarg_workaround:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200524 if node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200525 self.write(', **dict({')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200526 else:
Armin Ronacherfd310492008-05-25 00:16:51 +0200527 self.write(', **{')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200528 for kwarg in node.kwargs:
529 self.write('%r: ' % kwarg.key)
530 self.visit(kwarg.value, frame)
531 self.write(', ')
532 if extra_kwargs is not None:
533 for key, value in extra_kwargs.iteritems():
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200534 self.write('%r: %s, ' % (key, value))
535 if node.dyn_kwargs is not None:
536 self.write('}, **')
537 self.visit(node.dyn_kwargs, frame)
538 self.write(')')
539 else:
540 self.write('}')
541
542 elif node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200543 self.write(', **')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200544 self.visit(node.dyn_kwargs, frame)
545
Armin Ronacherc9705c22008-04-27 21:28:03 +0200546 def pull_locals(self, frame):
547 """Pull all the references identifiers into the local scope."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200548 for name in frame.identifiers.undeclared:
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200549 self.writeline('l_%s = context.resolve(%r)' % (name, name))
Armin Ronacherc9705c22008-04-27 21:28:03 +0200550
551 def pull_dependencies(self, nodes):
552 """Pull all the dependencies."""
553 visitor = DependencyFinderVisitor()
554 for node in nodes:
555 visitor.visit(node)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200556 for dependency in 'filters', 'tests':
557 mapping = getattr(self, dependency)
558 for name in getattr(visitor, dependency):
559 if name not in mapping:
560 mapping[name] = self.temporary_identifier()
561 self.writeline('%s = environment.%s[%r]' %
562 (mapping[name], dependency, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200563
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100564 def unoptimize_scope(self, frame):
565 """Disable Python optimizations for the frame."""
566 # XXX: this is not that nice but it has no real overhead. It
567 # mainly works because python finds the locals before dead code
568 # is removed. If that breaks we have to add a dummy function
569 # that just accepts the arguments and does nothing.
570 if frame.identifiers.declared:
571 self.writeline('if 0: dummy(%s)' % ', '.join(
572 'l_' + name for name in frame.identifiers.declared))
573
Armin Ronacher673aa882008-10-04 18:06:57 +0200574 def push_scope(self, frame, extra_vars=()):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200575 """This function returns all the shadowed variables in a dict
576 in the form name: alias and will write the required assignments
577 into the current scope. No indentation takes place.
Armin Ronacherff53c782008-08-13 18:55:50 +0200578
Armin Ronacher673aa882008-10-04 18:06:57 +0200579 This also predefines locally declared variables from the loop
580 body because under some circumstances it may be the case that
581
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100582 `extra_vars` is passed to `Frame.find_shadowed`.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200583 """
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200584 aliases = {}
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100585 for name in frame.find_shadowed(extra_vars):
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200586 aliases[name] = ident = self.temporary_identifier()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200587 self.writeline('%s = l_%s' % (ident, name))
Armin Ronacher673aa882008-10-04 18:06:57 +0200588 to_declare = set()
589 for name in frame.identifiers.declared_locally:
590 if name not in aliases:
591 to_declare.add('l_' + name)
592 if to_declare:
593 self.writeline(' = '.join(to_declare) + ' = missing')
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200594 return aliases
595
Armin Ronacher673aa882008-10-04 18:06:57 +0200596 def pop_scope(self, aliases, frame):
597 """Restore all aliases and delete unused variables."""
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200598 for name, alias in aliases.iteritems():
599 self.writeline('l_%s = %s' % (name, alias))
Armin Ronacher673aa882008-10-04 18:06:57 +0200600 to_delete = set()
601 for name in frame.identifiers.declared_locally:
602 if name not in aliases:
603 to_delete.add('l_' + name)
604 if to_delete:
Armin Ronacher330fbc02009-02-04 19:13:58 +0100605 # we cannot use the del statement here because enclosed
606 # scopes can trigger a SyntaxError:
607 # a = 42; b = lambda: a; del a
608 self.writeline(' = '.join(to_delete) + ' = missing')
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200609
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200610 def function_scoping(self, node, frame, children=None,
611 find_special=True):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200612 """In Jinja a few statements require the help of anonymous
613 functions. Those are currently macros and call blocks and in
614 the future also recursive loops. As there is currently
615 technical limitation that doesn't allow reading and writing a
616 variable in a scope where the initial value is coming from an
617 outer scope, this function tries to fall back with a common
618 error message. Additionally the frame passed is modified so
619 that the argumetns are collected and callers are looked up.
620
621 This will return the modified frame.
622 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200623 # we have to iterate twice over it, make sure that works
624 if children is None:
625 children = node.iter_child_nodes()
626 children = list(children)
Armin Ronacher71082072008-04-12 14:19:36 +0200627 func_frame = frame.inner()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200628 func_frame.inspect(children, hard_scope=True)
Armin Ronacher71082072008-04-12 14:19:36 +0200629
630 # variables that are undeclared (accessed before declaration) and
631 # declared locally *and* part of an outside scope raise a template
632 # assertion error. Reason: we can't generate reasonable code from
Armin Ronacher02b42a82009-03-18 00:59:32 +0100633 # it without aliasing all the variables.
634 # this could be fixed in Python 3 where we have the nonlocal
635 # keyword or if we switch to bytecode generation
Armin Ronacher71082072008-04-12 14:19:36 +0200636 overriden_closure_vars = (
637 func_frame.identifiers.undeclared &
638 func_frame.identifiers.declared &
639 (func_frame.identifiers.declared_locally |
640 func_frame.identifiers.declared_parameter)
641 )
642 if overriden_closure_vars:
Armin Ronachere2244882008-05-19 09:25:57 +0200643 self.fail('It\'s not possible to set and access variables '
Armin Ronacherefcc0e52009-09-13 00:22:50 -0700644 'derived from an outer scope! (affects: %s)' %
Armin Ronachere2244882008-05-19 09:25:57 +0200645 ', '.join(sorted(overriden_closure_vars)), node.lineno)
Armin Ronacher71082072008-04-12 14:19:36 +0200646
647 # remove variables from a closure from the frame's undeclared
648 # identifiers.
649 func_frame.identifiers.undeclared -= (
650 func_frame.identifiers.undeclared &
651 func_frame.identifiers.declared
652 )
653
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200654 # no special variables for this scope, abort early
655 if not find_special:
656 return func_frame
657
Armin Ronacher963f97d2008-04-25 11:44:59 +0200658 func_frame.accesses_kwargs = False
659 func_frame.accesses_varargs = False
Armin Ronacher71082072008-04-12 14:19:36 +0200660 func_frame.accesses_caller = False
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200661 func_frame.arguments = args = ['l_' + x.name for x in node.args]
Armin Ronacher71082072008-04-12 14:19:36 +0200662
Armin Ronacherc9705c22008-04-27 21:28:03 +0200663 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
664
665 if 'caller' in undeclared:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200666 func_frame.accesses_caller = True
667 func_frame.identifiers.add_special('caller')
668 args.append('l_caller')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200669 if 'kwargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200670 func_frame.accesses_kwargs = True
671 func_frame.identifiers.add_special('kwargs')
672 args.append('l_kwargs')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200673 if 'varargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200674 func_frame.accesses_varargs = True
675 func_frame.identifiers.add_special('varargs')
676 args.append('l_varargs')
Armin Ronacher71082072008-04-12 14:19:36 +0200677 return func_frame
678
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200679 def macro_body(self, node, frame, children=None):
680 """Dump the function def of a macro or call block."""
681 frame = self.function_scoping(node, frame, children)
Armin Ronachere308bf22008-10-30 19:18:45 +0100682 # macros are delayed, they never require output checks
683 frame.require_output_check = False
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200684 args = frame.arguments
Armin Ronachereabf3dd2009-09-12 23:48:18 -0700685 # XXX: this is an ugly fix for the loop nesting bug
686 # (tests.test_old_bugs.test_loop_call_bug). This works around
687 # a identifier nesting problem we have in general. It's just more
688 # likely to happen in loops which is why we work around it. The
689 # real solution would be "nonlocal" all the identifiers that are
690 # leaking into a new python frame and might be used both unassigned
691 # and assigned.
692 if 'loop' in frame.identifiers.declared:
Armin Ronacherb4044392009-09-13 15:56:58 -0700693 args = args + ['l_loop=l_loop']
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200694 self.writeline('def macro(%s):' % ', '.join(args), node)
695 self.indent()
696 self.buffer(frame)
697 self.pull_locals(frame)
698 self.blockvisit(node.body, frame)
699 self.return_buffer_contents(frame)
700 self.outdent()
701 return frame
702
703 def macro_def(self, node, frame):
704 """Dump the macro definition for the def created by macro_body."""
705 arg_tuple = ', '.join(repr(x.name) for x in node.args)
706 name = getattr(node, 'name', None)
707 if len(node.args) == 1:
708 arg_tuple += ','
709 self.write('Macro(environment, macro, %r, (%s), (' %
710 (name, arg_tuple))
711 for arg in node.defaults:
712 self.visit(arg, frame)
713 self.write(', ')
Armin Ronacher903d1682008-05-23 00:51:58 +0200714 self.write('), %r, %r, %r)' % (
715 bool(frame.accesses_kwargs),
716 bool(frame.accesses_varargs),
717 bool(frame.accesses_caller)
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200718 ))
719
Armin Ronacher547d0b62008-07-04 16:35:10 +0200720 def position(self, node):
721 """Return a human readable position for the node."""
722 rv = 'line %d' % node.lineno
723 if self.name is not None:
Armin Ronachercebd8382008-12-25 18:33:46 +0100724 rv += ' in ' + repr(self.name)
Armin Ronacher547d0b62008-07-04 16:35:10 +0200725 return rv
726
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200727 # -- Statement Visitors
Armin Ronachere791c2a2008-04-07 18:39:54 +0200728
729 def visit_Template(self, node, frame=None):
730 assert frame is None, 'no root frame allowed'
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200731 from jinja2.runtime import __all__ as exported
Armin Ronacher709f6e52008-04-28 18:18:16 +0200732 self.writeline('from __future__ import division')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200733 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
Armin Ronacher8edbe492008-04-10 20:43:43 +0200734
Armin Ronacher75cfb862008-04-11 13:47:22 +0200735 # do we have an extends tag at all? If not, we can save some
736 # overhead by just not processing any inheritance code.
737 have_extends = node.find(nodes.Extends) is not None
738
Armin Ronacher2b488392009-09-18 19:32:46 +0200739 # are there any block tags? If yes, we need a copy of the scope.
740 have_blocks = node.find(nodes.Block) is not None
741
Armin Ronacher8edbe492008-04-10 20:43:43 +0200742 # find all blocks
743 for block in node.find_all(nodes.Block):
744 if block.name in self.blocks:
Armin Ronachere2244882008-05-19 09:25:57 +0200745 self.fail('block %r defined twice' % block.name, block.lineno)
Armin Ronacher8edbe492008-04-10 20:43:43 +0200746 self.blocks[block.name] = block
Armin Ronachere791c2a2008-04-07 18:39:54 +0200747
Armin Ronacher023b5e92008-05-08 11:03:10 +0200748 # find all imports and import them
749 for import_ in node.find_all(nodes.ImportedName):
750 if import_.importname not in self.import_aliases:
751 imp = import_.importname
752 self.import_aliases[imp] = alias = self.temporary_identifier()
753 if '.' in imp:
754 module, obj = imp.rsplit('.', 1)
755 self.writeline('from %s import %s as %s' %
756 (module, obj, alias))
757 else:
758 self.writeline('import %s as %s' % (imp, alias))
759
760 # add the load name
Armin Ronacherdc02b642008-05-15 22:47:27 +0200761 self.writeline('name = %r' % self.name)
Armin Ronacher023b5e92008-05-08 11:03:10 +0200762
Armin Ronacher8efc5222008-04-08 14:47:40 +0200763 # generate the root render function.
Armin Ronacher32a910f2008-04-26 23:21:03 +0200764 self.writeline('def root(context, environment=environment):', extra=1)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200765
766 # process the root
Armin Ronachere791c2a2008-04-07 18:39:54 +0200767 frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200768 frame.inspect(node.body)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200769 frame.toplevel = frame.rootlevel = True
Armin Ronacher79668952008-09-23 22:52:46 +0200770 frame.require_output_check = have_extends and not self.has_known_extends
Armin Ronacherf059ec12008-04-11 22:21:00 +0200771 self.indent()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200772 if have_extends:
773 self.writeline('parent_template = None')
Armin Ronacher2b488392009-09-18 19:32:46 +0200774 if have_blocks:
775 self.writeline('block_context = context._block()')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200776 if 'self' in find_undeclared(node.body, ('self',)):
777 frame.identifiers.add_special('self')
778 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher6df604e2008-05-23 22:18:38 +0200779 self.pull_locals(frame)
780 self.pull_dependencies(node.body)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200781 self.blockvisit(node.body, frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200782 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200783
Armin Ronacher8efc5222008-04-08 14:47:40 +0200784 # make sure that the parent root is called.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200785 if have_extends:
786 if not self.has_known_extends:
787 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200788 self.writeline('if parent_template is not None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200789 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200790 self.writeline('for event in parent_template.'
Armin Ronacher5411ce72008-05-25 11:36:22 +0200791 'root_render_func(context):')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200792 self.indent()
793 self.writeline('yield event')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200794 self.outdent(2 + (not self.has_known_extends))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200795
796 # at this point we now have the blocks collected and can visit them too.
797 for name, block in self.blocks.iteritems():
798 block_frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200799 block_frame.inspect(block.body)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200800 block_frame.block = name
Armin Ronacherd4c64f72008-04-11 17:15:29 +0200801 self.writeline('def block_%s(context, environment=environment):'
802 % name, block, 1)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200803 self.indent()
804 undeclared = find_undeclared(block.body, ('self', 'super'))
805 if 'self' in undeclared:
806 block_frame.identifiers.add_special('self')
807 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher2b488392009-09-18 19:32:46 +0200808 if block.find(nodes.Block) is not None:
809 self.writeline('block_context = context._block(%r)' % name)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200810 if 'super' in undeclared:
811 block_frame.identifiers.add_special('super')
812 self.writeline('l_super = context.super(%r, '
813 'block_%s)' % (name, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200814 self.pull_locals(block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200815 self.pull_dependencies(block.body)
Armin Ronacher625215e2008-04-13 16:31:08 +0200816 self.blockvisit(block.body, block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200817 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200818
Armin Ronacher75cfb862008-04-11 13:47:22 +0200819 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
Armin Ronacherba3757b2008-04-16 19:43:16 +0200820 for x in self.blocks),
821 extra=1)
822
823 # add a function that returns the debug info
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200824 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
825 in self.debug_info))
Armin Ronacher75cfb862008-04-11 13:47:22 +0200826
Armin Ronachere791c2a2008-04-07 18:39:54 +0200827 def visit_Block(self, node, frame):
828 """Call a block and register it for the template."""
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200829 level = 1
Armin Ronacher75cfb862008-04-11 13:47:22 +0200830 if frame.toplevel:
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200831 # if we know that we are a child template, there is no need to
832 # check if we are one
833 if self.has_known_extends:
834 return
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200835 if self.extends_so_far > 0:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200836 self.writeline('if parent_template is None:')
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200837 self.indent()
838 level += 1
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100839 if node.scoped:
Armin Ronacher2b488392009-09-18 19:32:46 +0200840 context = 'block_context.derived(locals())'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100841 else:
Armin Ronacher2b488392009-09-18 19:32:46 +0200842 context = 'block_context'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100843 self.writeline('for event in context.blocks[%r][0](%s):' % (
844 node.name, context), node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200845 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200846 self.simple_write('event', frame)
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200847 self.outdent(level)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200848
849 def visit_Extends(self, node, frame):
850 """Calls the extender."""
Armin Ronacher8efc5222008-04-08 14:47:40 +0200851 if not frame.toplevel:
Armin Ronachere2244882008-05-19 09:25:57 +0200852 self.fail('cannot use extend from a non top-level scope',
853 node.lineno)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200854
Armin Ronacher7fb38972008-04-11 13:54:28 +0200855 # if the number of extends statements in general is zero so
856 # far, we don't have to add a check if something extended
857 # the template before this one.
858 if self.extends_so_far > 0:
Armin Ronacher75cfb862008-04-11 13:47:22 +0200859
Armin Ronacher7fb38972008-04-11 13:54:28 +0200860 # if we have a known extends we just add a template runtime
861 # error into the generated code. We could catch that at compile
862 # time too, but i welcome it not to confuse users by throwing the
863 # same error at different times just "because we can".
864 if not self.has_known_extends:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200865 self.writeline('if parent_template is not None:')
Armin Ronacher7fb38972008-04-11 13:54:28 +0200866 self.indent()
867 self.writeline('raise TemplateRuntimeError(%r)' %
868 'extended multiple times')
Armin Ronacher79668952008-09-23 22:52:46 +0200869 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200870
Armin Ronacher7fb38972008-04-11 13:54:28 +0200871 # if we have a known extends already we don't need that code here
872 # as we know that the template execution will end here.
873 if self.has_known_extends:
874 raise CompilerExit()
Armin Ronacher7fb38972008-04-11 13:54:28 +0200875
Armin Ronacher9d42abf2008-05-14 18:10:41 +0200876 self.writeline('parent_template = environment.get_template(', node)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200877 self.visit(node.template, frame)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200878 self.write(', %r)' % self.name)
879 self.writeline('for name, parent_block in parent_template.'
880 'blocks.iteritems():')
881 self.indent()
882 self.writeline('context.blocks.setdefault(name, []).'
Armin Ronacher83fbc0f2008-05-15 12:22:28 +0200883 'append(parent_block)')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200884 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200885
886 # if this extends statement was in the root level we can take
887 # advantage of that information and simplify the generated code
888 # in the top level from this point onwards
Armin Ronacher27069d72008-05-11 19:48:12 +0200889 if frame.rootlevel:
890 self.has_known_extends = True
Armin Ronachere791c2a2008-04-07 18:39:54 +0200891
Armin Ronacher7fb38972008-04-11 13:54:28 +0200892 # and now we have one more
893 self.extends_so_far += 1
894
Armin Ronacherf059ec12008-04-11 22:21:00 +0200895 def visit_Include(self, node, frame):
896 """Handles includes."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100897 if node.with_context:
898 self.unoptimize_scope(frame)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100899 if node.ignore_missing:
900 self.writeline('try:')
901 self.indent()
902 self.writeline('template = environment.get_template(', node)
903 self.visit(node.template, frame)
904 self.write(', %r)' % self.name)
905 if node.ignore_missing:
906 self.outdent()
907 self.writeline('except TemplateNotFound:')
908 self.indent()
909 self.writeline('pass')
910 self.outdent()
911 self.writeline('else:')
912 self.indent()
913
Armin Ronacherea847c52008-05-02 20:04:32 +0200914 if node.with_context:
Armin Ronacher5411ce72008-05-25 11:36:22 +0200915 self.writeline('for event in template.root_render_func('
Armin Ronacher673aa882008-10-04 18:06:57 +0200916 'template.new_context(context.parent, True, '
917 'locals())):')
Armin Ronacherea847c52008-05-02 20:04:32 +0200918 else:
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100919 self.writeline('for event in template.module._body_stream:')
920
Armin Ronacherf059ec12008-04-11 22:21:00 +0200921 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200922 self.simple_write('event', frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200923 self.outdent()
924
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100925 if node.ignore_missing:
926 self.outdent()
927
Armin Ronacher0611e492008-04-25 23:44:14 +0200928 def visit_Import(self, node, frame):
929 """Visit regular imports."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100930 if node.with_context:
931 self.unoptimize_scope(frame)
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200932 self.writeline('l_%s = ' % node.target, node)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200933 if frame.toplevel:
Armin Ronacher53042292008-04-26 18:30:19 +0200934 self.write('context.vars[%r] = ' % node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200935 self.write('environment.get_template(')
936 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200937 self.write(', %r).' % self.name)
938 if node.with_context:
Armin Ronacher673aa882008-10-04 18:06:57 +0200939 self.write('make_module(context.parent, True, locals())')
Armin Ronacherea847c52008-05-02 20:04:32 +0200940 else:
941 self.write('module')
Armin Ronacher903d1682008-05-23 00:51:58 +0200942 if frame.toplevel and not node.target.startswith('_'):
Armin Ronacher53042292008-04-26 18:30:19 +0200943 self.writeline('context.exported_vars.discard(%r)' % node.target)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100944 frame.assigned_names.add(node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200945
946 def visit_FromImport(self, node, frame):
947 """Visit named imports."""
948 self.newline(node)
949 self.write('included_template = environment.get_template(')
950 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200951 self.write(', %r).' % self.name)
952 if node.with_context:
953 self.write('make_module(context.parent, True)')
954 else:
955 self.write('module')
Armin Ronachera78d2762008-05-15 23:18:07 +0200956
957 var_names = []
958 discarded_names = []
Armin Ronacher0611e492008-04-25 23:44:14 +0200959 for name in node.names:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200960 if isinstance(name, tuple):
961 name, alias = name
962 else:
963 alias = name
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200964 self.writeline('l_%s = getattr(included_template, '
965 '%r, missing)' % (alias, name))
966 self.writeline('if l_%s is missing:' % alias)
Armin Ronacher0611e492008-04-25 23:44:14 +0200967 self.indent()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200968 self.writeline('l_%s = environment.undefined(%r %% '
Armin Ronacherdc02b642008-05-15 22:47:27 +0200969 'included_template.__name__, '
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200970 'name=%r)' %
Armin Ronacher547d0b62008-07-04 16:35:10 +0200971 (alias, 'the template %%r (imported on %s) does '
972 'not export the requested name %s' % (
973 self.position(node),
974 repr(name)
975 ), name))
Armin Ronacher0611e492008-04-25 23:44:14 +0200976 self.outdent()
977 if frame.toplevel:
Armin Ronachera78d2762008-05-15 23:18:07 +0200978 var_names.append(alias)
Armin Ronacher903d1682008-05-23 00:51:58 +0200979 if not alias.startswith('_'):
Armin Ronachera78d2762008-05-15 23:18:07 +0200980 discarded_names.append(alias)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100981 frame.assigned_names.add(alias)
Armin Ronachera78d2762008-05-15 23:18:07 +0200982
983 if var_names:
984 if len(var_names) == 1:
985 name = var_names[0]
986 self.writeline('context.vars[%r] = l_%s' % (name, name))
987 else:
988 self.writeline('context.vars.update({%s})' % ', '.join(
989 '%r: l_%s' % (name, name) for name in var_names
990 ))
991 if discarded_names:
992 if len(discarded_names) == 1:
993 self.writeline('context.exported_vars.discard(%r)' %
994 discarded_names[0])
995 else:
996 self.writeline('context.exported_vars.difference_'
997 'update((%s))' % ', '.join(map(repr, discarded_names)))
Armin Ronacherf059ec12008-04-11 22:21:00 +0200998
Armin Ronachere791c2a2008-04-07 18:39:54 +0200999 def visit_For(self, node, frame):
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001000 # when calculating the nodes for the inner frame we have to exclude
1001 # the iterator contents from it
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001002 children = node.iter_child_nodes(exclude=('iter',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001003 if node.recursive:
1004 loop_frame = self.function_scoping(node, frame, children,
1005 find_special=False)
1006 else:
1007 loop_frame = frame.inner()
1008 loop_frame.inspect(children)
1009
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001010 # try to figure out if we have an extended loop. An extended loop
1011 # is necessary if the loop is in recursive mode if the special loop
1012 # variable is accessed in the body.
1013 extended_loop = node.recursive or 'loop' in \
1014 find_undeclared(node.iter_child_nodes(
1015 only=('body',)), ('loop',))
1016
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001017 # if we don't have an recursive loop we have to find the shadowed
Armin Ronacherff53c782008-08-13 18:55:50 +02001018 # variables at that point. Because loops can be nested but the loop
1019 # variable is a special one we have to enforce aliasing for it.
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001020 if not node.recursive:
Armin Ronacher673aa882008-10-04 18:06:57 +02001021 aliases = self.push_scope(loop_frame, ('loop',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001022
1023 # otherwise we set up a buffer and add a function def
1024 else:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001025 self.writeline('def loop(reciter, loop_render_func):', node)
1026 self.indent()
Armin Ronachered1e0d42008-05-18 20:25:28 +02001027 self.buffer(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001028 aliases = {}
1029
Armin Ronacherff53c782008-08-13 18:55:50 +02001030 # make sure the loop variable is a special one and raise a template
1031 # assertion error if a loop tries to write to loop
Armin Ronacher833a3b52008-08-14 12:31:12 +02001032 if extended_loop:
1033 loop_frame.identifiers.add_special('loop')
Armin Ronacherff53c782008-08-13 18:55:50 +02001034 for name in node.find_all(nodes.Name):
1035 if name.ctx == 'store' and name.name == 'loop':
1036 self.fail('Can\'t assign to special loop variable '
1037 'in for-loop target', name.lineno)
1038
Armin Ronacherc9705c22008-04-27 21:28:03 +02001039 self.pull_locals(loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001040 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001041 iteration_indicator = self.temporary_identifier()
1042 self.writeline('%s = 1' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001043
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001044 # Create a fake parent loop if the else or test section of a
1045 # loop is accessing the special loop variable and no parent loop
1046 # exists.
1047 if 'loop' not in aliases and 'loop' in find_undeclared(
1048 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1049 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
Armin Ronacher547d0b62008-07-04 16:35:10 +02001050 ("'loop' is undefined. the filter section of a loop as well "
1051 "as the else block doesn't have access to the special 'loop'"
1052 " variable of the current loop. Because there is no parent "
1053 "loop it's undefined. Happened in loop on %s" %
1054 self.position(node)))
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001055
1056 self.writeline('for ', node)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001057 self.visit(node.target, loop_frame)
Armin Ronacher180a1bd2008-04-09 12:14:24 +02001058 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001059
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001060 # if we have an extened loop and a node test, we filter in the
1061 # "outer frame".
1062 if extended_loop and node.test is not None:
1063 self.write('(')
1064 self.visit(node.target, loop_frame)
1065 self.write(' for ')
1066 self.visit(node.target, loop_frame)
1067 self.write(' in ')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001068 if node.recursive:
1069 self.write('reciter')
1070 else:
1071 self.visit(node.iter, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001072 self.write(' if (')
1073 test_frame = loop_frame.copy()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001074 self.visit(node.test, test_frame)
1075 self.write('))')
1076
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001077 elif node.recursive:
1078 self.write('reciter')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001079 else:
1080 self.visit(node.iter, loop_frame)
1081
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001082 if node.recursive:
1083 self.write(', recurse=loop_render_func):')
1084 else:
1085 self.write(extended_loop and '):' or ':')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001086
1087 # tests in not extended loops become a continue
1088 if not extended_loop and node.test is not None:
1089 self.indent()
Armin Ronacher47a506f2008-05-06 12:17:23 +02001090 self.writeline('if not ')
Armin Ronacher32a910f2008-04-26 23:21:03 +02001091 self.visit(node.test, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001092 self.write(':')
1093 self.indent()
1094 self.writeline('continue')
1095 self.outdent(2)
1096
Armin Ronacherc9705c22008-04-27 21:28:03 +02001097 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001098 self.blockvisit(node.body, loop_frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001099 if node.else_:
1100 self.writeline('%s = 0' % iteration_indicator)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001101 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001102
1103 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001104 self.writeline('if %s:' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001105 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001106 self.blockvisit(node.else_, loop_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001107 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001108
Armin Ronacherd4c64f72008-04-11 17:15:29 +02001109 # reset the aliases if there are any.
Armin Ronachercebd8382008-12-25 18:33:46 +01001110 if not node.recursive:
1111 self.pop_scope(aliases, loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001112
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001113 # if the node was recursive we have to return the buffer contents
1114 # and start the iteration code
1115 if node.recursive:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001116 self.return_buffer_contents(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001117 self.outdent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001118 self.start_write(frame, node)
1119 self.write('loop(')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001120 self.visit(node.iter, frame)
1121 self.write(', loop)')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001122 self.end_write(frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001123
Armin Ronachere791c2a2008-04-07 18:39:54 +02001124 def visit_If(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001125 if_frame = frame.soft()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001126 self.writeline('if ', node)
Armin Ronacher75cfb862008-04-11 13:47:22 +02001127 self.visit(node.test, if_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001128 self.write(':')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001129 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001130 self.blockvisit(node.body, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001131 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001132 if node.else_:
1133 self.writeline('else:')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001134 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001135 self.blockvisit(node.else_, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001136 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001137
Armin Ronacher8efc5222008-04-08 14:47:40 +02001138 def visit_Macro(self, node, frame):
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001139 macro_frame = self.macro_body(node, frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001140 self.newline()
1141 if frame.toplevel:
Armin Ronacher903d1682008-05-23 00:51:58 +02001142 if not node.name.startswith('_'):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001143 self.write('context.exported_vars.add(%r)' % node.name)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001144 self.writeline('context.vars[%r] = ' % node.name)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001145 self.write('l_%s = ' % node.name)
1146 self.macro_def(node, macro_frame)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001147 frame.assigned_names.add(node.name)
Armin Ronacher71082072008-04-12 14:19:36 +02001148
1149 def visit_CallBlock(self, node, frame):
Armin Ronacher3da90312008-05-23 16:37:28 +02001150 children = node.iter_child_nodes(exclude=('call',))
1151 call_frame = self.macro_body(node, frame, children)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001152 self.writeline('caller = ')
1153 self.macro_def(node, call_frame)
1154 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001155 self.visit_Call(node.call, call_frame, forward_caller=True)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001156 self.end_write(frame)
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001157
1158 def visit_FilterBlock(self, node, frame):
1159 filter_frame = frame.inner()
1160 filter_frame.inspect(node.iter_child_nodes())
Armin Ronacher673aa882008-10-04 18:06:57 +02001161 aliases = self.push_scope(filter_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001162 self.pull_locals(filter_frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001163 self.buffer(filter_frame)
Armin Ronacherf40c8842008-09-17 18:51:26 +02001164 self.blockvisit(node.body, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001165 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001166 self.visit_Filter(node.filter, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001167 self.end_write(frame)
Armin Ronacher673aa882008-10-04 18:06:57 +02001168 self.pop_scope(aliases, filter_frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001169
Armin Ronachere791c2a2008-04-07 18:39:54 +02001170 def visit_ExprStmt(self, node, frame):
1171 self.newline(node)
Armin Ronacher6ce170c2008-04-25 12:32:36 +02001172 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001173
1174 def visit_Output(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001175 # if we have a known extends statement, we don't output anything
Armin Ronacher79668952008-09-23 22:52:46 +02001176 # if we are in a require_output_check section
1177 if self.has_known_extends and frame.require_output_check:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001178 return
Armin Ronachere791c2a2008-04-07 18:39:54 +02001179
Armin Ronacher665bfb82008-07-14 13:41:46 +02001180 if self.environment.finalize:
1181 finalize = lambda x: unicode(self.environment.finalize(x))
1182 else:
1183 finalize = unicode
1184
Armin Ronacher75cfb862008-04-11 13:47:22 +02001185 self.newline(node)
Armin Ronacher8edbe492008-04-10 20:43:43 +02001186
Armin Ronacher79668952008-09-23 22:52:46 +02001187 # if we are inside a frame that requires output checking, we do so
Armin Ronacher7fb38972008-04-11 13:54:28 +02001188 outdent_later = False
Armin Ronacher79668952008-09-23 22:52:46 +02001189 if frame.require_output_check:
Armin Ronacher203bfcb2008-04-24 21:54:44 +02001190 self.writeline('if parent_template is None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +02001191 self.indent()
Armin Ronacher7fb38972008-04-11 13:54:28 +02001192 outdent_later = True
Armin Ronacher75cfb862008-04-11 13:47:22 +02001193
Armin Ronachere791c2a2008-04-07 18:39:54 +02001194 # try to evaluate as many chunks as possible into a static
1195 # string at compile time.
1196 body = []
1197 for child in node.nodes:
1198 try:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001199 const = child.as_const()
1200 except nodes.Impossible:
1201 body.append(child)
1202 continue
1203 try:
1204 if self.environment.autoescape:
1205 if hasattr(const, '__html__'):
1206 const = const.__html__()
1207 else:
1208 const = escape(const)
Armin Ronacher665bfb82008-07-14 13:41:46 +02001209 const = finalize(const)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001210 except:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001211 # if something goes wrong here we evaluate the node
1212 # at runtime for easier debugging
Armin Ronachere791c2a2008-04-07 18:39:54 +02001213 body.append(child)
1214 continue
1215 if body and isinstance(body[-1], list):
1216 body[-1].append(const)
1217 else:
1218 body.append([const])
1219
Armin Ronachered1e0d42008-05-18 20:25:28 +02001220 # if we have less than 3 nodes or a buffer we yield or extend/append
1221 if len(body) < 3 or frame.buffer is not None:
Armin Ronacher32a910f2008-04-26 23:21:03 +02001222 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001223 # for one item we append, for more we extend
1224 if len(body) == 1:
1225 self.writeline('%s.append(' % frame.buffer)
1226 else:
1227 self.writeline('%s.extend((' % frame.buffer)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001228 self.indent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001229 for item in body:
1230 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001231 val = repr(concat(item))
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001232 if frame.buffer is None:
1233 self.writeline('yield ' + val)
1234 else:
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001235 self.writeline(val + ', ')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001236 else:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001237 if frame.buffer is None:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001238 self.writeline('yield ', item)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001239 else:
1240 self.newline(item)
Armin Ronacherd1342312008-04-28 12:20:12 +02001241 close = 1
1242 if self.environment.autoescape:
1243 self.write('escape(')
1244 else:
Armin Ronacherbd357722009-08-05 20:25:06 +02001245 self.write('to_string(')
Armin Ronacherd1342312008-04-28 12:20:12 +02001246 if self.environment.finalize is not None:
1247 self.write('environment.finalize(')
1248 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001249 self.visit(item, frame)
Armin Ronacherd1342312008-04-28 12:20:12 +02001250 self.write(')' * close)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001251 if frame.buffer is not None:
1252 self.write(', ')
1253 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001254 # close the open parentheses
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001255 self.outdent()
1256 self.writeline(len(body) == 1 and ')' or '))')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001257
1258 # otherwise we create a format string as this is faster in that case
1259 else:
1260 format = []
1261 arguments = []
1262 for item in body:
1263 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001264 format.append(concat(item).replace('%', '%%'))
Armin Ronachere791c2a2008-04-07 18:39:54 +02001265 else:
1266 format.append('%s')
1267 arguments.append(item)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001268 self.writeline('yield ')
Armin Ronacherde6bf712008-04-26 01:44:14 +02001269 self.write(repr(concat(format)) + ' % (')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001270 idx = -1
Armin Ronachera7f016d2008-05-16 00:22:40 +02001271 self.indent()
Armin Ronacher8e8d0712008-04-16 23:10:49 +02001272 for argument in arguments:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001273 self.newline(argument)
Armin Ronacherd1342312008-04-28 12:20:12 +02001274 close = 0
1275 if self.environment.autoescape:
1276 self.write('escape(')
1277 close += 1
1278 if self.environment.finalize is not None:
1279 self.write('environment.finalize(')
1280 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001281 self.visit(argument, frame)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001282 self.write(')' * close + ', ')
Armin Ronachera7f016d2008-05-16 00:22:40 +02001283 self.outdent()
1284 self.writeline(')')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001285
Armin Ronacher7fb38972008-04-11 13:54:28 +02001286 if outdent_later:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001287 self.outdent()
1288
Armin Ronacher8efc5222008-04-08 14:47:40 +02001289 def visit_Assign(self, node, frame):
1290 self.newline(node)
1291 # toplevel assignments however go into the local namespace and
1292 # the current template's context. We create a copy of the frame
1293 # here and add a set so that the Name visitor can add the assigned
1294 # names here.
1295 if frame.toplevel:
1296 assignment_frame = frame.copy()
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001297 assignment_frame.toplevel_assignments = set()
Armin Ronacher8efc5222008-04-08 14:47:40 +02001298 else:
1299 assignment_frame = frame
1300 self.visit(node.target, assignment_frame)
1301 self.write(' = ')
1302 self.visit(node.node, frame)
Armin Ronacher9706fab2008-04-08 18:49:56 +02001303
1304 # make sure toplevel assignments are added to the context.
Armin Ronacher8efc5222008-04-08 14:47:40 +02001305 if frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001306 public_names = [x for x in assignment_frame.toplevel_assignments
Armin Ronacher903d1682008-05-23 00:51:58 +02001307 if not x.startswith('_')]
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001308 if len(assignment_frame.toplevel_assignments) == 1:
Armin Ronacherbd357722009-08-05 20:25:06 +02001309 name = next(iter(assignment_frame.toplevel_assignments))
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001310 self.writeline('context.vars[%r] = l_%s' % (name, name))
Armin Ronacher69e12db2008-05-12 09:00:03 +02001311 else:
1312 self.writeline('context.vars.update({')
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001313 for idx, name in enumerate(assignment_frame.toplevel_assignments):
Armin Ronacher69e12db2008-05-12 09:00:03 +02001314 if idx:
1315 self.write(', ')
1316 self.write('%r: l_%s' % (name, name))
1317 self.write('})')
1318 if public_names:
1319 if len(public_names) == 1:
1320 self.writeline('context.exported_vars.add(%r)' %
1321 public_names[0])
1322 else:
1323 self.writeline('context.exported_vars.update((%s))' %
1324 ', '.join(map(repr, public_names)))
Armin Ronacher8efc5222008-04-08 14:47:40 +02001325
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001326 # -- Expression Visitors
1327
Armin Ronachere791c2a2008-04-07 18:39:54 +02001328 def visit_Name(self, node, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001329 if node.ctx == 'store' and frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001330 frame.toplevel_assignments.add(node.name)
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001331 self.write('l_' + node.name)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001332 frame.assigned_names.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001333
1334 def visit_Const(self, node, frame):
1335 val = node.value
1336 if isinstance(val, float):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001337 self.write(str(val))
1338 else:
1339 self.write(repr(val))
1340
Armin Ronacher5411ce72008-05-25 11:36:22 +02001341 def visit_TemplateData(self, node, frame):
1342 self.write(repr(node.as_const()))
1343
Armin Ronacher8efc5222008-04-08 14:47:40 +02001344 def visit_Tuple(self, node, frame):
1345 self.write('(')
1346 idx = -1
1347 for idx, item in enumerate(node.items):
1348 if idx:
1349 self.write(', ')
1350 self.visit(item, frame)
1351 self.write(idx == 0 and ',)' or ')')
1352
Armin Ronacher8edbe492008-04-10 20:43:43 +02001353 def visit_List(self, node, frame):
1354 self.write('[')
1355 for idx, item in enumerate(node.items):
1356 if idx:
1357 self.write(', ')
1358 self.visit(item, frame)
1359 self.write(']')
1360
1361 def visit_Dict(self, node, frame):
1362 self.write('{')
1363 for idx, item in enumerate(node.items):
1364 if idx:
1365 self.write(', ')
1366 self.visit(item.key, frame)
1367 self.write(': ')
1368 self.visit(item.value, frame)
1369 self.write('}')
1370
Armin Ronachere791c2a2008-04-07 18:39:54 +02001371 def binop(operator):
1372 def visitor(self, node, frame):
1373 self.write('(')
1374 self.visit(node.left, frame)
1375 self.write(' %s ' % operator)
1376 self.visit(node.right, frame)
1377 self.write(')')
1378 return visitor
1379
1380 def uaop(operator):
1381 def visitor(self, node, frame):
1382 self.write('(' + operator)
Armin Ronacher9a822052008-04-17 18:44:07 +02001383 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001384 self.write(')')
1385 return visitor
1386
1387 visit_Add = binop('+')
1388 visit_Sub = binop('-')
1389 visit_Mul = binop('*')
1390 visit_Div = binop('/')
1391 visit_FloorDiv = binop('//')
1392 visit_Pow = binop('**')
1393 visit_Mod = binop('%')
1394 visit_And = binop('and')
1395 visit_Or = binop('or')
1396 visit_Pos = uaop('+')
1397 visit_Neg = uaop('-')
1398 visit_Not = uaop('not ')
1399 del binop, uaop
1400
Armin Ronacherd1342312008-04-28 12:20:12 +02001401 def visit_Concat(self, node, frame):
Armin Ronacherfdf95302008-05-11 22:20:51 +02001402 self.write('%s((' % (self.environment.autoescape and
1403 'markup_join' or 'unicode_join'))
Armin Ronacherd1342312008-04-28 12:20:12 +02001404 for arg in node.nodes:
1405 self.visit(arg, frame)
1406 self.write(', ')
1407 self.write('))')
1408
Armin Ronachere791c2a2008-04-07 18:39:54 +02001409 def visit_Compare(self, node, frame):
1410 self.visit(node.expr, frame)
1411 for op in node.ops:
1412 self.visit(op, frame)
1413
1414 def visit_Operand(self, node, frame):
1415 self.write(' %s ' % operators[node.op])
1416 self.visit(node.expr, frame)
1417
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001418 def visit_Getattr(self, node, frame):
1419 self.write('environment.getattr(')
1420 self.visit(node.node, frame)
1421 self.write(', %r)' % node.attr)
1422
1423 def visit_Getitem(self, node, frame):
Armin Ronacher5c3c4702008-09-12 23:12:49 +02001424 # slices bypass the environment getitem method.
1425 if isinstance(node.arg, nodes.Slice):
Armin Ronacher8efc5222008-04-08 14:47:40 +02001426 self.visit(node.node, frame)
1427 self.write('[')
1428 self.visit(node.arg, frame)
1429 self.write(']')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001430 else:
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001431 self.write('environment.getitem(')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001432 self.visit(node.node, frame)
1433 self.write(', ')
1434 self.visit(node.arg, frame)
1435 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001436
1437 def visit_Slice(self, node, frame):
1438 if node.start is not None:
1439 self.visit(node.start, frame)
1440 self.write(':')
1441 if node.stop is not None:
1442 self.visit(node.stop, frame)
1443 if node.step is not None:
1444 self.write(':')
1445 self.visit(node.step, frame)
1446
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001447 def visit_Filter(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001448 self.write(self.filters[node.name] + '(')
Christoph Hack80909862008-04-14 01:35:10 +02001449 func = self.environment.filters.get(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +02001450 if func is None:
Armin Ronachere2244882008-05-19 09:25:57 +02001451 self.fail('no filter named %r' % node.name, node.lineno)
Christoph Hack80909862008-04-14 01:35:10 +02001452 if getattr(func, 'contextfilter', False):
1453 self.write('context, ')
Armin Ronacher9a027f42008-04-17 11:13:40 +02001454 elif getattr(func, 'environmentfilter', False):
1455 self.write('environment, ')
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001456
1457 # if the filter node is None we are inside a filter block
1458 # and want to write to the current buffer
Armin Ronacher3da90312008-05-23 16:37:28 +02001459 if node.node is not None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001460 self.visit(node.node, frame)
Armin Ronacher3da90312008-05-23 16:37:28 +02001461 elif self.environment.autoescape:
1462 self.write('Markup(concat(%s))' % frame.buffer)
1463 else:
1464 self.write('concat(%s)' % frame.buffer)
Armin Ronacherd55ab532008-04-09 16:13:39 +02001465 self.signature(node, frame)
1466 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001467
1468 def visit_Test(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001469 self.write(self.tests[node.name] + '(')
Armin Ronacher0611e492008-04-25 23:44:14 +02001470 if node.name not in self.environment.tests:
Armin Ronachere2244882008-05-19 09:25:57 +02001471 self.fail('no test named %r' % node.name, node.lineno)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001472 self.visit(node.node, frame)
1473 self.signature(node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001474 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001475
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001476 def visit_CondExpr(self, node, frame):
Armin Ronacher547d0b62008-07-04 16:35:10 +02001477 def write_expr2():
1478 if node.expr2 is not None:
1479 return self.visit(node.expr2, frame)
1480 self.write('environment.undefined(%r)' % ('the inline if-'
1481 'expression on %s evaluated to false and '
1482 'no else section was defined.' % self.position(node)))
1483
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001484 if not have_condexpr:
1485 self.write('((')
1486 self.visit(node.test, frame)
1487 self.write(') and (')
1488 self.visit(node.expr1, frame)
1489 self.write(',) or (')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001490 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001491 self.write(',))[0]')
1492 else:
1493 self.write('(')
1494 self.visit(node.expr1, frame)
1495 self.write(' if ')
1496 self.visit(node.test, frame)
1497 self.write(' else ')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001498 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001499 self.write(')')
1500
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001501 def visit_Call(self, node, frame, forward_caller=False):
Armin Ronacherc63243e2008-04-14 22:53:58 +02001502 if self.environment.sandboxed:
Armin Ronacherfd310492008-05-25 00:16:51 +02001503 self.write('environment.call(context, ')
1504 else:
1505 self.write('context.call(')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001506 self.visit(node.node, frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001507 extra_kwargs = forward_caller and {'caller': 'caller'} or None
Armin Ronacherfd310492008-05-25 00:16:51 +02001508 self.signature(node, frame, extra_kwargs)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001509 self.write(')')
1510
1511 def visit_Keyword(self, node, frame):
Armin Ronacher2e9396b2008-04-16 14:21:57 +02001512 self.write(node.key + '=')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001513 self.visit(node.value, frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001514
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001515 # -- Unused nodes for extensions
Armin Ronachered1e0d42008-05-18 20:25:28 +02001516
1517 def visit_MarkSafe(self, node, frame):
1518 self.write('Markup(')
1519 self.visit(node.expr, frame)
1520 self.write(')')
1521
1522 def visit_EnvironmentAttribute(self, node, frame):
1523 self.write('environment.' + node.name)
1524
1525 def visit_ExtensionAttribute(self, node, frame):
Armin Ronacher6df604e2008-05-23 22:18:38 +02001526 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
Armin Ronachered1e0d42008-05-18 20:25:28 +02001527
1528 def visit_ImportedName(self, node, frame):
1529 self.write(self.import_aliases[node.importname])
1530
1531 def visit_InternalName(self, node, frame):
1532 self.write(node.name)
1533
Armin Ronacher6df604e2008-05-23 22:18:38 +02001534 def visit_ContextReference(self, node, frame):
1535 self.write('context')
1536
Armin Ronachered1e0d42008-05-18 20:25:28 +02001537 def visit_Continue(self, node, frame):
1538 self.writeline('continue', node)
1539
1540 def visit_Break(self, node, frame):
1541 self.writeline('break', node)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001542
1543 def visit_Scope(self, node, frame):
1544 scope_frame = frame.inner()
1545 scope_frame.inspect(node.iter_child_nodes())
1546 aliases = self.push_scope(scope_frame)
1547 self.pull_locals(scope_frame)
1548 self.blockvisit(node.body, scope_frame)
1549 self.pop_scope(aliases, scope_frame)