blob: 2dd68cdda1e2d2f69f17c8f4d6ae3ed3b9573eae [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):
281 self.identifiers = real_identifiers.copy()
282 for subnode in nodes:
283 self.visit(subnode)
284 rv = self.identifiers.declared_locally - old_names
285 # we have to remember the undeclared variables of this branch
286 # because we will have to pull them.
287 real_identifiers.undeclared.update(self.identifiers.undeclared)
288 self.identifiers = real_identifiers
289 return rv
290
291 body = inner_visit(node.body)
292 else_ = inner_visit(node.else_ or ())
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200293
294 # the differences between the two branches are also pulled as
295 # undeclared variables
Armin Ronacher74230e62009-10-25 12:46:31 +0100296 real_identifiers.undeclared.update(body.symmetric_difference(else_))
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200297
Armin Ronacher74230e62009-10-25 12:46:31 +0100298 # remember those that are declared.
299 real_identifiers.declared_locally.update(body | else_)
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200300
Armin Ronacherc9705c22008-04-27 21:28:03 +0200301 def visit_Macro(self, node):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200302 self.identifiers.declared_locally.add(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +0200303
Armin Ronacherc9705c22008-04-27 21:28:03 +0200304 def visit_Import(self, node):
305 self.generic_visit(node)
306 self.identifiers.declared_locally.add(node.target)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200307
Armin Ronacherc9705c22008-04-27 21:28:03 +0200308 def visit_FromImport(self, node):
309 self.generic_visit(node)
310 for name in node.names:
311 if isinstance(name, tuple):
312 self.identifiers.declared_locally.add(name[1])
313 else:
314 self.identifiers.declared_locally.add(name)
315
316 def visit_Assign(self, node):
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200317 """Visit assignments in the correct order."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200318 self.visit(node.node)
319 self.visit(node.target)
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200320
Armin Ronacherc9705c22008-04-27 21:28:03 +0200321 def visit_For(self, node):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200322 """Visiting stops at for blocks. However the block sequence
323 is visited as part of the outer scope.
324 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200325 self.visit(node.iter)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200326
Armin Ronacherc9705c22008-04-27 21:28:03 +0200327 def visit_CallBlock(self, node):
328 for child in node.iter_child_nodes(exclude=('body',)):
329 self.visit(child)
330
331 def visit_FilterBlock(self, node):
332 self.visit(node.filter)
333
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100334 def visit_Scope(self, node):
335 """Stop visiting at scopes."""
336
Armin Ronacherc9705c22008-04-27 21:28:03 +0200337 def visit_Block(self, node):
338 """Stop visiting at blocks."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200339
340
Armin Ronacher75cfb862008-04-11 13:47:22 +0200341class CompilerExit(Exception):
342 """Raised if the compiler encountered a situation where it just
343 doesn't make sense to further process the code. Any block that
Armin Ronacher0611e492008-04-25 23:44:14 +0200344 raises such an exception is not further processed.
345 """
Armin Ronacher75cfb862008-04-11 13:47:22 +0200346
347
Armin Ronachere791c2a2008-04-07 18:39:54 +0200348class CodeGenerator(NodeVisitor):
349
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200350 def __init__(self, environment, name, filename, stream=None):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200351 if stream is None:
352 stream = StringIO()
Christoph Hack65642a52008-04-08 14:46:56 +0200353 self.environment = environment
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200354 self.name = name
Armin Ronachere791c2a2008-04-07 18:39:54 +0200355 self.filename = filename
356 self.stream = stream
Armin Ronacherfed44b52008-04-13 19:42:53 +0200357
Armin Ronacher023b5e92008-05-08 11:03:10 +0200358 # aliases for imports
359 self.import_aliases = {}
360
Armin Ronacherfed44b52008-04-13 19:42:53 +0200361 # a registry for all blocks. Because blocks are moved out
362 # into the global python scope they are registered here
Armin Ronachere791c2a2008-04-07 18:39:54 +0200363 self.blocks = {}
Armin Ronacherfed44b52008-04-13 19:42:53 +0200364
365 # the number of extends statements so far
Armin Ronacher7fb38972008-04-11 13:54:28 +0200366 self.extends_so_far = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200367
368 # some templates have a rootlevel extends. In this case we
369 # can safely assume that we're a child template and do some
370 # more optimizations.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200371 self.has_known_extends = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200372
Armin Ronacherba3757b2008-04-16 19:43:16 +0200373 # the current line number
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200374 self.code_lineno = 1
Armin Ronacherba3757b2008-04-16 19:43:16 +0200375
Armin Ronacherb9e78752008-05-10 23:36:28 +0200376 # registry of all filters and tests (global, not block local)
377 self.tests = {}
378 self.filters = {}
379
Armin Ronacherba3757b2008-04-16 19:43:16 +0200380 # the debug information
381 self.debug_info = []
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200382 self._write_debug_info = None
Armin Ronacherba3757b2008-04-16 19:43:16 +0200383
Armin Ronacherfed44b52008-04-13 19:42:53 +0200384 # the number of new lines before the next write()
385 self._new_lines = 0
386
387 # the line number of the last written statement
Armin Ronachere791c2a2008-04-07 18:39:54 +0200388 self._last_line = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200389
390 # true if nothing was written so far.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200391 self._first_write = True
392
Armin Ronacherfed44b52008-04-13 19:42:53 +0200393 # used by the `temporary_identifier` method to get new
394 # unique, temporary identifier
395 self._last_identifier = 0
396
397 # the current indentation
398 self._indentation = 0
399
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200400 # -- Various compilation helpers
401
Armin Ronachere2244882008-05-19 09:25:57 +0200402 def fail(self, msg, lineno):
403 """Fail with a `TemplateAssertionError`."""
404 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
405
Armin Ronachere791c2a2008-04-07 18:39:54 +0200406 def temporary_identifier(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200407 """Get a new unique identifier."""
408 self._last_identifier += 1
Armin Ronacher8a1d27f2008-05-19 08:37:19 +0200409 return 't_%d' % self._last_identifier
Armin Ronachere791c2a2008-04-07 18:39:54 +0200410
Armin Ronachered1e0d42008-05-18 20:25:28 +0200411 def buffer(self, frame):
412 """Enable buffering for the frame from that point onwards."""
Armin Ronachere2244882008-05-19 09:25:57 +0200413 frame.buffer = self.temporary_identifier()
414 self.writeline('%s = []' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200415
416 def return_buffer_contents(self, frame):
417 """Return the buffer contents of the frame."""
418 if self.environment.autoescape:
419 self.writeline('return Markup(concat(%s))' % frame.buffer)
420 else:
421 self.writeline('return concat(%s)' % frame.buffer)
422
Armin Ronachere791c2a2008-04-07 18:39:54 +0200423 def indent(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200424 """Indent by one."""
425 self._indentation += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +0200426
Armin Ronacher8efc5222008-04-08 14:47:40 +0200427 def outdent(self, step=1):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200428 """Outdent by step."""
429 self._indentation -= step
Armin Ronachere791c2a2008-04-07 18:39:54 +0200430
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200431 def start_write(self, frame, node=None):
432 """Yield or write into the frame buffer."""
433 if frame.buffer is None:
434 self.writeline('yield ', node)
435 else:
436 self.writeline('%s.append(' % frame.buffer, node)
437
438 def end_write(self, frame):
439 """End the writing process started by `start_write`."""
440 if frame.buffer is not None:
441 self.write(')')
442
443 def simple_write(self, s, frame, node=None):
444 """Simple shortcut for start_write + write + end_write."""
445 self.start_write(frame, node)
446 self.write(s)
447 self.end_write(frame)
448
Armin Ronacherf40c8842008-09-17 18:51:26 +0200449 def blockvisit(self, nodes, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200450 """Visit a list of nodes as block in a frame. If the current frame
451 is no buffer a dummy ``if 0: yield None`` is written automatically
452 unless the force_generator parameter is set to False.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200453 """
Armin Ronacherf40c8842008-09-17 18:51:26 +0200454 if frame.buffer is None:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200455 self.writeline('if 0: yield None')
Armin Ronacherf40c8842008-09-17 18:51:26 +0200456 else:
457 self.writeline('pass')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200458 try:
459 for node in nodes:
460 self.visit(node, frame)
461 except CompilerExit:
462 pass
Armin Ronachere791c2a2008-04-07 18:39:54 +0200463
464 def write(self, x):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200465 """Write a string into the output stream."""
466 if self._new_lines:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200467 if not self._first_write:
Armin Ronacherfed44b52008-04-13 19:42:53 +0200468 self.stream.write('\n' * self._new_lines)
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200469 self.code_lineno += self._new_lines
470 if self._write_debug_info is not None:
471 self.debug_info.append((self._write_debug_info,
472 self.code_lineno))
473 self._write_debug_info = None
Armin Ronachere791c2a2008-04-07 18:39:54 +0200474 self._first_write = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200475 self.stream.write(' ' * self._indentation)
476 self._new_lines = 0
Armin Ronachere791c2a2008-04-07 18:39:54 +0200477 self.stream.write(x)
478
479 def writeline(self, x, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200480 """Combination of newline and write."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200481 self.newline(node, extra)
482 self.write(x)
483
484 def newline(self, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200485 """Add one or more newlines before the next write."""
486 self._new_lines = max(self._new_lines, 1 + extra)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200487 if node is not None and node.lineno != self._last_line:
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200488 self._write_debug_info = node.lineno
489 self._last_line = node.lineno
Armin Ronachere791c2a2008-04-07 18:39:54 +0200490
Armin Ronacherfd310492008-05-25 00:16:51 +0200491 def signature(self, node, frame, extra_kwargs=None):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200492 """Writes a function call to the stream for the current node.
Armin Ronacherfd310492008-05-25 00:16:51 +0200493 A leading comma is added automatically. The extra keyword
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200494 arguments may not include python keywords otherwise a syntax
495 error could occour. The extra keyword arguments should be given
496 as python dict.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200497 """
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200498 # if any of the given keyword arguments is a python keyword
499 # we have to make sure that no invalid call is created.
500 kwarg_workaround = False
501 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200502 if is_python_keyword(kwarg):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200503 kwarg_workaround = True
504 break
505
Armin Ronacher8efc5222008-04-08 14:47:40 +0200506 for arg in node.args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200507 self.write(', ')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200508 self.visit(arg, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200509
510 if not kwarg_workaround:
511 for kwarg in node.kwargs:
Armin Ronacherfd310492008-05-25 00:16:51 +0200512 self.write(', ')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200513 self.visit(kwarg, frame)
514 if extra_kwargs is not None:
515 for key, value in extra_kwargs.iteritems():
Armin Ronacherfd310492008-05-25 00:16:51 +0200516 self.write(', %s=%s' % (key, value))
Armin Ronacher8efc5222008-04-08 14:47:40 +0200517 if node.dyn_args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200518 self.write(', *')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200519 self.visit(node.dyn_args, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200520
521 if kwarg_workaround:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200522 if node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200523 self.write(', **dict({')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200524 else:
Armin Ronacherfd310492008-05-25 00:16:51 +0200525 self.write(', **{')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200526 for kwarg in node.kwargs:
527 self.write('%r: ' % kwarg.key)
528 self.visit(kwarg.value, frame)
529 self.write(', ')
530 if extra_kwargs is not None:
531 for key, value in extra_kwargs.iteritems():
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200532 self.write('%r: %s, ' % (key, value))
533 if node.dyn_kwargs is not None:
534 self.write('}, **')
535 self.visit(node.dyn_kwargs, frame)
536 self.write(')')
537 else:
538 self.write('}')
539
540 elif node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200541 self.write(', **')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200542 self.visit(node.dyn_kwargs, frame)
543
Armin Ronacherc9705c22008-04-27 21:28:03 +0200544 def pull_locals(self, frame):
545 """Pull all the references identifiers into the local scope."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200546 for name in frame.identifiers.undeclared:
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200547 self.writeline('l_%s = context.resolve(%r)' % (name, name))
Armin Ronacherc9705c22008-04-27 21:28:03 +0200548
549 def pull_dependencies(self, nodes):
550 """Pull all the dependencies."""
551 visitor = DependencyFinderVisitor()
552 for node in nodes:
553 visitor.visit(node)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200554 for dependency in 'filters', 'tests':
555 mapping = getattr(self, dependency)
556 for name in getattr(visitor, dependency):
557 if name not in mapping:
558 mapping[name] = self.temporary_identifier()
559 self.writeline('%s = environment.%s[%r]' %
560 (mapping[name], dependency, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200561
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100562 def unoptimize_scope(self, frame):
563 """Disable Python optimizations for the frame."""
564 # XXX: this is not that nice but it has no real overhead. It
565 # mainly works because python finds the locals before dead code
566 # is removed. If that breaks we have to add a dummy function
567 # that just accepts the arguments and does nothing.
568 if frame.identifiers.declared:
569 self.writeline('if 0: dummy(%s)' % ', '.join(
570 'l_' + name for name in frame.identifiers.declared))
571
Armin Ronacher673aa882008-10-04 18:06:57 +0200572 def push_scope(self, frame, extra_vars=()):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200573 """This function returns all the shadowed variables in a dict
574 in the form name: alias and will write the required assignments
575 into the current scope. No indentation takes place.
Armin Ronacherff53c782008-08-13 18:55:50 +0200576
Armin Ronacher673aa882008-10-04 18:06:57 +0200577 This also predefines locally declared variables from the loop
578 body because under some circumstances it may be the case that
579
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100580 `extra_vars` is passed to `Frame.find_shadowed`.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200581 """
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200582 aliases = {}
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100583 for name in frame.find_shadowed(extra_vars):
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200584 aliases[name] = ident = self.temporary_identifier()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200585 self.writeline('%s = l_%s' % (ident, name))
Armin Ronacher673aa882008-10-04 18:06:57 +0200586 to_declare = set()
587 for name in frame.identifiers.declared_locally:
588 if name not in aliases:
589 to_declare.add('l_' + name)
590 if to_declare:
591 self.writeline(' = '.join(to_declare) + ' = missing')
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200592 return aliases
593
Armin Ronacher673aa882008-10-04 18:06:57 +0200594 def pop_scope(self, aliases, frame):
595 """Restore all aliases and delete unused variables."""
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200596 for name, alias in aliases.iteritems():
597 self.writeline('l_%s = %s' % (name, alias))
Armin Ronacher673aa882008-10-04 18:06:57 +0200598 to_delete = set()
599 for name in frame.identifiers.declared_locally:
600 if name not in aliases:
601 to_delete.add('l_' + name)
602 if to_delete:
Armin Ronacher330fbc02009-02-04 19:13:58 +0100603 # we cannot use the del statement here because enclosed
604 # scopes can trigger a SyntaxError:
605 # a = 42; b = lambda: a; del a
606 self.writeline(' = '.join(to_delete) + ' = missing')
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200607
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200608 def function_scoping(self, node, frame, children=None,
609 find_special=True):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200610 """In Jinja a few statements require the help of anonymous
611 functions. Those are currently macros and call blocks and in
612 the future also recursive loops. As there is currently
613 technical limitation that doesn't allow reading and writing a
614 variable in a scope where the initial value is coming from an
615 outer scope, this function tries to fall back with a common
616 error message. Additionally the frame passed is modified so
617 that the argumetns are collected and callers are looked up.
618
619 This will return the modified frame.
620 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200621 # we have to iterate twice over it, make sure that works
622 if children is None:
623 children = node.iter_child_nodes()
624 children = list(children)
Armin Ronacher71082072008-04-12 14:19:36 +0200625 func_frame = frame.inner()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200626 func_frame.inspect(children, hard_scope=True)
Armin Ronacher71082072008-04-12 14:19:36 +0200627
628 # variables that are undeclared (accessed before declaration) and
629 # declared locally *and* part of an outside scope raise a template
630 # assertion error. Reason: we can't generate reasonable code from
Armin Ronacher02b42a82009-03-18 00:59:32 +0100631 # it without aliasing all the variables.
632 # this could be fixed in Python 3 where we have the nonlocal
633 # keyword or if we switch to bytecode generation
Armin Ronacher71082072008-04-12 14:19:36 +0200634 overriden_closure_vars = (
635 func_frame.identifiers.undeclared &
636 func_frame.identifiers.declared &
637 (func_frame.identifiers.declared_locally |
638 func_frame.identifiers.declared_parameter)
639 )
640 if overriden_closure_vars:
Armin Ronachere2244882008-05-19 09:25:57 +0200641 self.fail('It\'s not possible to set and access variables '
Armin Ronacherefcc0e52009-09-13 00:22:50 -0700642 'derived from an outer scope! (affects: %s)' %
Armin Ronachere2244882008-05-19 09:25:57 +0200643 ', '.join(sorted(overriden_closure_vars)), node.lineno)
Armin Ronacher71082072008-04-12 14:19:36 +0200644
645 # remove variables from a closure from the frame's undeclared
646 # identifiers.
647 func_frame.identifiers.undeclared -= (
648 func_frame.identifiers.undeclared &
649 func_frame.identifiers.declared
650 )
651
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200652 # no special variables for this scope, abort early
653 if not find_special:
654 return func_frame
655
Armin Ronacher963f97d2008-04-25 11:44:59 +0200656 func_frame.accesses_kwargs = False
657 func_frame.accesses_varargs = False
Armin Ronacher71082072008-04-12 14:19:36 +0200658 func_frame.accesses_caller = False
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200659 func_frame.arguments = args = ['l_' + x.name for x in node.args]
Armin Ronacher71082072008-04-12 14:19:36 +0200660
Armin Ronacherc9705c22008-04-27 21:28:03 +0200661 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
662
663 if 'caller' in undeclared:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200664 func_frame.accesses_caller = True
665 func_frame.identifiers.add_special('caller')
666 args.append('l_caller')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200667 if 'kwargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200668 func_frame.accesses_kwargs = True
669 func_frame.identifiers.add_special('kwargs')
670 args.append('l_kwargs')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200671 if 'varargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200672 func_frame.accesses_varargs = True
673 func_frame.identifiers.add_special('varargs')
674 args.append('l_varargs')
Armin Ronacher71082072008-04-12 14:19:36 +0200675 return func_frame
676
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200677 def macro_body(self, node, frame, children=None):
678 """Dump the function def of a macro or call block."""
679 frame = self.function_scoping(node, frame, children)
Armin Ronachere308bf22008-10-30 19:18:45 +0100680 # macros are delayed, they never require output checks
681 frame.require_output_check = False
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200682 args = frame.arguments
Armin Ronachereabf3dd2009-09-12 23:48:18 -0700683 # XXX: this is an ugly fix for the loop nesting bug
684 # (tests.test_old_bugs.test_loop_call_bug). This works around
685 # a identifier nesting problem we have in general. It's just more
686 # likely to happen in loops which is why we work around it. The
687 # real solution would be "nonlocal" all the identifiers that are
688 # leaking into a new python frame and might be used both unassigned
689 # and assigned.
690 if 'loop' in frame.identifiers.declared:
Armin Ronacherb4044392009-09-13 15:56:58 -0700691 args = args + ['l_loop=l_loop']
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200692 self.writeline('def macro(%s):' % ', '.join(args), node)
693 self.indent()
694 self.buffer(frame)
695 self.pull_locals(frame)
696 self.blockvisit(node.body, frame)
697 self.return_buffer_contents(frame)
698 self.outdent()
699 return frame
700
701 def macro_def(self, node, frame):
702 """Dump the macro definition for the def created by macro_body."""
703 arg_tuple = ', '.join(repr(x.name) for x in node.args)
704 name = getattr(node, 'name', None)
705 if len(node.args) == 1:
706 arg_tuple += ','
707 self.write('Macro(environment, macro, %r, (%s), (' %
708 (name, arg_tuple))
709 for arg in node.defaults:
710 self.visit(arg, frame)
711 self.write(', ')
Armin Ronacher903d1682008-05-23 00:51:58 +0200712 self.write('), %r, %r, %r)' % (
713 bool(frame.accesses_kwargs),
714 bool(frame.accesses_varargs),
715 bool(frame.accesses_caller)
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200716 ))
717
Armin Ronacher547d0b62008-07-04 16:35:10 +0200718 def position(self, node):
719 """Return a human readable position for the node."""
720 rv = 'line %d' % node.lineno
721 if self.name is not None:
Armin Ronachercebd8382008-12-25 18:33:46 +0100722 rv += ' in ' + repr(self.name)
Armin Ronacher547d0b62008-07-04 16:35:10 +0200723 return rv
724
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200725 # -- Statement Visitors
Armin Ronachere791c2a2008-04-07 18:39:54 +0200726
727 def visit_Template(self, node, frame=None):
728 assert frame is None, 'no root frame allowed'
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200729 from jinja2.runtime import __all__ as exported
Armin Ronacher709f6e52008-04-28 18:18:16 +0200730 self.writeline('from __future__ import division')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200731 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
Armin Ronacher8edbe492008-04-10 20:43:43 +0200732
Armin Ronacher75cfb862008-04-11 13:47:22 +0200733 # do we have an extends tag at all? If not, we can save some
734 # overhead by just not processing any inheritance code.
735 have_extends = node.find(nodes.Extends) is not None
736
Armin Ronacher2b488392009-09-18 19:32:46 +0200737 # are there any block tags? If yes, we need a copy of the scope.
738 have_blocks = node.find(nodes.Block) is not None
739
Armin Ronacher8edbe492008-04-10 20:43:43 +0200740 # find all blocks
741 for block in node.find_all(nodes.Block):
742 if block.name in self.blocks:
Armin Ronachere2244882008-05-19 09:25:57 +0200743 self.fail('block %r defined twice' % block.name, block.lineno)
Armin Ronacher8edbe492008-04-10 20:43:43 +0200744 self.blocks[block.name] = block
Armin Ronachere791c2a2008-04-07 18:39:54 +0200745
Armin Ronacher023b5e92008-05-08 11:03:10 +0200746 # find all imports and import them
747 for import_ in node.find_all(nodes.ImportedName):
748 if import_.importname not in self.import_aliases:
749 imp = import_.importname
750 self.import_aliases[imp] = alias = self.temporary_identifier()
751 if '.' in imp:
752 module, obj = imp.rsplit('.', 1)
753 self.writeline('from %s import %s as %s' %
754 (module, obj, alias))
755 else:
756 self.writeline('import %s as %s' % (imp, alias))
757
758 # add the load name
Armin Ronacherdc02b642008-05-15 22:47:27 +0200759 self.writeline('name = %r' % self.name)
Armin Ronacher023b5e92008-05-08 11:03:10 +0200760
Armin Ronacher8efc5222008-04-08 14:47:40 +0200761 # generate the root render function.
Armin Ronacher32a910f2008-04-26 23:21:03 +0200762 self.writeline('def root(context, environment=environment):', extra=1)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200763
764 # process the root
Armin Ronachere791c2a2008-04-07 18:39:54 +0200765 frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200766 frame.inspect(node.body)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200767 frame.toplevel = frame.rootlevel = True
Armin Ronacher79668952008-09-23 22:52:46 +0200768 frame.require_output_check = have_extends and not self.has_known_extends
Armin Ronacherf059ec12008-04-11 22:21:00 +0200769 self.indent()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200770 if have_extends:
771 self.writeline('parent_template = None')
Armin Ronacher2b488392009-09-18 19:32:46 +0200772 if have_blocks:
773 self.writeline('block_context = context._block()')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200774 if 'self' in find_undeclared(node.body, ('self',)):
775 frame.identifiers.add_special('self')
776 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher6df604e2008-05-23 22:18:38 +0200777 self.pull_locals(frame)
778 self.pull_dependencies(node.body)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200779 self.blockvisit(node.body, frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200780 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200781
Armin Ronacher8efc5222008-04-08 14:47:40 +0200782 # make sure that the parent root is called.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200783 if have_extends:
784 if not self.has_known_extends:
785 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200786 self.writeline('if parent_template is not None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200787 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200788 self.writeline('for event in parent_template.'
Armin Ronacher5411ce72008-05-25 11:36:22 +0200789 'root_render_func(context):')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200790 self.indent()
791 self.writeline('yield event')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200792 self.outdent(2 + (not self.has_known_extends))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200793
794 # at this point we now have the blocks collected and can visit them too.
795 for name, block in self.blocks.iteritems():
796 block_frame = Frame()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200797 block_frame.inspect(block.body)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200798 block_frame.block = name
Armin Ronacherd4c64f72008-04-11 17:15:29 +0200799 self.writeline('def block_%s(context, environment=environment):'
800 % name, block, 1)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200801 self.indent()
802 undeclared = find_undeclared(block.body, ('self', 'super'))
803 if 'self' in undeclared:
804 block_frame.identifiers.add_special('self')
805 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher2b488392009-09-18 19:32:46 +0200806 if block.find(nodes.Block) is not None:
807 self.writeline('block_context = context._block(%r)' % name)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200808 if 'super' in undeclared:
809 block_frame.identifiers.add_special('super')
810 self.writeline('l_super = context.super(%r, '
811 'block_%s)' % (name, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200812 self.pull_locals(block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200813 self.pull_dependencies(block.body)
Armin Ronacher625215e2008-04-13 16:31:08 +0200814 self.blockvisit(block.body, block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200815 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200816
Armin Ronacher75cfb862008-04-11 13:47:22 +0200817 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
Armin Ronacherba3757b2008-04-16 19:43:16 +0200818 for x in self.blocks),
819 extra=1)
820
821 # add a function that returns the debug info
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200822 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
823 in self.debug_info))
Armin Ronacher75cfb862008-04-11 13:47:22 +0200824
Armin Ronachere791c2a2008-04-07 18:39:54 +0200825 def visit_Block(self, node, frame):
826 """Call a block and register it for the template."""
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200827 level = 1
Armin Ronacher75cfb862008-04-11 13:47:22 +0200828 if frame.toplevel:
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200829 # if we know that we are a child template, there is no need to
830 # check if we are one
831 if self.has_known_extends:
832 return
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200833 if self.extends_so_far > 0:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200834 self.writeline('if parent_template is None:')
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200835 self.indent()
836 level += 1
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100837 if node.scoped:
Armin Ronacher2b488392009-09-18 19:32:46 +0200838 context = 'block_context.derived(locals())'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100839 else:
Armin Ronacher2b488392009-09-18 19:32:46 +0200840 context = 'block_context'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100841 self.writeline('for event in context.blocks[%r][0](%s):' % (
842 node.name, context), node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200843 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200844 self.simple_write('event', frame)
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200845 self.outdent(level)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200846
847 def visit_Extends(self, node, frame):
848 """Calls the extender."""
Armin Ronacher8efc5222008-04-08 14:47:40 +0200849 if not frame.toplevel:
Armin Ronachere2244882008-05-19 09:25:57 +0200850 self.fail('cannot use extend from a non top-level scope',
851 node.lineno)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200852
Armin Ronacher7fb38972008-04-11 13:54:28 +0200853 # if the number of extends statements in general is zero so
854 # far, we don't have to add a check if something extended
855 # the template before this one.
856 if self.extends_so_far > 0:
Armin Ronacher75cfb862008-04-11 13:47:22 +0200857
Armin Ronacher7fb38972008-04-11 13:54:28 +0200858 # if we have a known extends we just add a template runtime
859 # error into the generated code. We could catch that at compile
860 # time too, but i welcome it not to confuse users by throwing the
861 # same error at different times just "because we can".
862 if not self.has_known_extends:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200863 self.writeline('if parent_template is not None:')
Armin Ronacher7fb38972008-04-11 13:54:28 +0200864 self.indent()
865 self.writeline('raise TemplateRuntimeError(%r)' %
866 'extended multiple times')
Armin Ronacher79668952008-09-23 22:52:46 +0200867 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200868
Armin Ronacher7fb38972008-04-11 13:54:28 +0200869 # if we have a known extends already we don't need that code here
870 # as we know that the template execution will end here.
871 if self.has_known_extends:
872 raise CompilerExit()
Armin Ronacher7fb38972008-04-11 13:54:28 +0200873
Armin Ronacher9d42abf2008-05-14 18:10:41 +0200874 self.writeline('parent_template = environment.get_template(', node)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200875 self.visit(node.template, frame)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200876 self.write(', %r)' % self.name)
877 self.writeline('for name, parent_block in parent_template.'
878 'blocks.iteritems():')
879 self.indent()
880 self.writeline('context.blocks.setdefault(name, []).'
Armin Ronacher83fbc0f2008-05-15 12:22:28 +0200881 'append(parent_block)')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200882 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200883
884 # if this extends statement was in the root level we can take
885 # advantage of that information and simplify the generated code
886 # in the top level from this point onwards
Armin Ronacher27069d72008-05-11 19:48:12 +0200887 if frame.rootlevel:
888 self.has_known_extends = True
Armin Ronachere791c2a2008-04-07 18:39:54 +0200889
Armin Ronacher7fb38972008-04-11 13:54:28 +0200890 # and now we have one more
891 self.extends_so_far += 1
892
Armin Ronacherf059ec12008-04-11 22:21:00 +0200893 def visit_Include(self, node, frame):
894 """Handles includes."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100895 if node.with_context:
896 self.unoptimize_scope(frame)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100897 if node.ignore_missing:
898 self.writeline('try:')
899 self.indent()
900 self.writeline('template = environment.get_template(', node)
901 self.visit(node.template, frame)
902 self.write(', %r)' % self.name)
903 if node.ignore_missing:
904 self.outdent()
905 self.writeline('except TemplateNotFound:')
906 self.indent()
907 self.writeline('pass')
908 self.outdent()
909 self.writeline('else:')
910 self.indent()
911
Armin Ronacherea847c52008-05-02 20:04:32 +0200912 if node.with_context:
Armin Ronacher5411ce72008-05-25 11:36:22 +0200913 self.writeline('for event in template.root_render_func('
Armin Ronacher673aa882008-10-04 18:06:57 +0200914 'template.new_context(context.parent, True, '
915 'locals())):')
Armin Ronacherea847c52008-05-02 20:04:32 +0200916 else:
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100917 self.writeline('for event in template.module._body_stream:')
918
Armin Ronacherf059ec12008-04-11 22:21:00 +0200919 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200920 self.simple_write('event', frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200921 self.outdent()
922
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100923 if node.ignore_missing:
924 self.outdent()
925
Armin Ronacher0611e492008-04-25 23:44:14 +0200926 def visit_Import(self, node, frame):
927 """Visit regular imports."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100928 if node.with_context:
929 self.unoptimize_scope(frame)
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200930 self.writeline('l_%s = ' % node.target, node)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200931 if frame.toplevel:
Armin Ronacher53042292008-04-26 18:30:19 +0200932 self.write('context.vars[%r] = ' % node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200933 self.write('environment.get_template(')
934 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200935 self.write(', %r).' % self.name)
936 if node.with_context:
Armin Ronacher673aa882008-10-04 18:06:57 +0200937 self.write('make_module(context.parent, True, locals())')
Armin Ronacherea847c52008-05-02 20:04:32 +0200938 else:
939 self.write('module')
Armin Ronacher903d1682008-05-23 00:51:58 +0200940 if frame.toplevel and not node.target.startswith('_'):
Armin Ronacher53042292008-04-26 18:30:19 +0200941 self.writeline('context.exported_vars.discard(%r)' % node.target)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100942 frame.assigned_names.add(node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200943
944 def visit_FromImport(self, node, frame):
945 """Visit named imports."""
946 self.newline(node)
947 self.write('included_template = environment.get_template(')
948 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200949 self.write(', %r).' % self.name)
950 if node.with_context:
951 self.write('make_module(context.parent, True)')
952 else:
953 self.write('module')
Armin Ronachera78d2762008-05-15 23:18:07 +0200954
955 var_names = []
956 discarded_names = []
Armin Ronacher0611e492008-04-25 23:44:14 +0200957 for name in node.names:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200958 if isinstance(name, tuple):
959 name, alias = name
960 else:
961 alias = name
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200962 self.writeline('l_%s = getattr(included_template, '
963 '%r, missing)' % (alias, name))
964 self.writeline('if l_%s is missing:' % alias)
Armin Ronacher0611e492008-04-25 23:44:14 +0200965 self.indent()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200966 self.writeline('l_%s = environment.undefined(%r %% '
Armin Ronacherdc02b642008-05-15 22:47:27 +0200967 'included_template.__name__, '
Armin Ronacher0a2ac692008-05-13 01:03:08 +0200968 'name=%r)' %
Armin Ronacher547d0b62008-07-04 16:35:10 +0200969 (alias, 'the template %%r (imported on %s) does '
970 'not export the requested name %s' % (
971 self.position(node),
972 repr(name)
973 ), name))
Armin Ronacher0611e492008-04-25 23:44:14 +0200974 self.outdent()
975 if frame.toplevel:
Armin Ronachera78d2762008-05-15 23:18:07 +0200976 var_names.append(alias)
Armin Ronacher903d1682008-05-23 00:51:58 +0200977 if not alias.startswith('_'):
Armin Ronachera78d2762008-05-15 23:18:07 +0200978 discarded_names.append(alias)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100979 frame.assigned_names.add(alias)
Armin Ronachera78d2762008-05-15 23:18:07 +0200980
981 if var_names:
982 if len(var_names) == 1:
983 name = var_names[0]
984 self.writeline('context.vars[%r] = l_%s' % (name, name))
985 else:
986 self.writeline('context.vars.update({%s})' % ', '.join(
987 '%r: l_%s' % (name, name) for name in var_names
988 ))
989 if discarded_names:
990 if len(discarded_names) == 1:
991 self.writeline('context.exported_vars.discard(%r)' %
992 discarded_names[0])
993 else:
994 self.writeline('context.exported_vars.difference_'
995 'update((%s))' % ', '.join(map(repr, discarded_names)))
Armin Ronacherf059ec12008-04-11 22:21:00 +0200996
Armin Ronachere791c2a2008-04-07 18:39:54 +0200997 def visit_For(self, node, frame):
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200998 # when calculating the nodes for the inner frame we have to exclude
999 # the iterator contents from it
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001000 children = node.iter_child_nodes(exclude=('iter',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001001 if node.recursive:
1002 loop_frame = self.function_scoping(node, frame, children,
1003 find_special=False)
1004 else:
1005 loop_frame = frame.inner()
1006 loop_frame.inspect(children)
1007
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001008 # try to figure out if we have an extended loop. An extended loop
1009 # is necessary if the loop is in recursive mode if the special loop
1010 # variable is accessed in the body.
1011 extended_loop = node.recursive or 'loop' in \
1012 find_undeclared(node.iter_child_nodes(
1013 only=('body',)), ('loop',))
1014
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001015 # if we don't have an recursive loop we have to find the shadowed
Armin Ronacherff53c782008-08-13 18:55:50 +02001016 # variables at that point. Because loops can be nested but the loop
1017 # variable is a special one we have to enforce aliasing for it.
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001018 if not node.recursive:
Armin Ronacher673aa882008-10-04 18:06:57 +02001019 aliases = self.push_scope(loop_frame, ('loop',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001020
1021 # otherwise we set up a buffer and add a function def
1022 else:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001023 self.writeline('def loop(reciter, loop_render_func):', node)
1024 self.indent()
Armin Ronachered1e0d42008-05-18 20:25:28 +02001025 self.buffer(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001026 aliases = {}
1027
Armin Ronacherff53c782008-08-13 18:55:50 +02001028 # make sure the loop variable is a special one and raise a template
1029 # assertion error if a loop tries to write to loop
Armin Ronacher833a3b52008-08-14 12:31:12 +02001030 if extended_loop:
1031 loop_frame.identifiers.add_special('loop')
Armin Ronacherff53c782008-08-13 18:55:50 +02001032 for name in node.find_all(nodes.Name):
1033 if name.ctx == 'store' and name.name == 'loop':
1034 self.fail('Can\'t assign to special loop variable '
1035 'in for-loop target', name.lineno)
1036
Armin Ronacherc9705c22008-04-27 21:28:03 +02001037 self.pull_locals(loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001038 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001039 iteration_indicator = self.temporary_identifier()
1040 self.writeline('%s = 1' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001041
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001042 # Create a fake parent loop if the else or test section of a
1043 # loop is accessing the special loop variable and no parent loop
1044 # exists.
1045 if 'loop' not in aliases and 'loop' in find_undeclared(
1046 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1047 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
Armin Ronacher547d0b62008-07-04 16:35:10 +02001048 ("'loop' is undefined. the filter section of a loop as well "
1049 "as the else block doesn't have access to the special 'loop'"
1050 " variable of the current loop. Because there is no parent "
1051 "loop it's undefined. Happened in loop on %s" %
1052 self.position(node)))
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001053
1054 self.writeline('for ', node)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001055 self.visit(node.target, loop_frame)
Armin Ronacher180a1bd2008-04-09 12:14:24 +02001056 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001057
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001058 # if we have an extened loop and a node test, we filter in the
1059 # "outer frame".
1060 if extended_loop and node.test is not None:
1061 self.write('(')
1062 self.visit(node.target, loop_frame)
1063 self.write(' for ')
1064 self.visit(node.target, loop_frame)
1065 self.write(' in ')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001066 if node.recursive:
1067 self.write('reciter')
1068 else:
1069 self.visit(node.iter, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001070 self.write(' if (')
1071 test_frame = loop_frame.copy()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001072 self.visit(node.test, test_frame)
1073 self.write('))')
1074
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001075 elif node.recursive:
1076 self.write('reciter')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001077 else:
1078 self.visit(node.iter, loop_frame)
1079
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001080 if node.recursive:
1081 self.write(', recurse=loop_render_func):')
1082 else:
1083 self.write(extended_loop and '):' or ':')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001084
1085 # tests in not extended loops become a continue
1086 if not extended_loop and node.test is not None:
1087 self.indent()
Armin Ronacher47a506f2008-05-06 12:17:23 +02001088 self.writeline('if not ')
Armin Ronacher32a910f2008-04-26 23:21:03 +02001089 self.visit(node.test, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001090 self.write(':')
1091 self.indent()
1092 self.writeline('continue')
1093 self.outdent(2)
1094
Armin Ronacherc9705c22008-04-27 21:28:03 +02001095 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001096 self.blockvisit(node.body, loop_frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001097 if node.else_:
1098 self.writeline('%s = 0' % iteration_indicator)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001099 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001100
1101 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001102 self.writeline('if %s:' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001103 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001104 self.blockvisit(node.else_, loop_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001105 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001106
Armin Ronacherd4c64f72008-04-11 17:15:29 +02001107 # reset the aliases if there are any.
Armin Ronachercebd8382008-12-25 18:33:46 +01001108 if not node.recursive:
1109 self.pop_scope(aliases, loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001110
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001111 # if the node was recursive we have to return the buffer contents
1112 # and start the iteration code
1113 if node.recursive:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001114 self.return_buffer_contents(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001115 self.outdent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001116 self.start_write(frame, node)
1117 self.write('loop(')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001118 self.visit(node.iter, frame)
1119 self.write(', loop)')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001120 self.end_write(frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001121
Armin Ronachere791c2a2008-04-07 18:39:54 +02001122 def visit_If(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001123 if_frame = frame.soft()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001124 self.writeline('if ', node)
Armin Ronacher75cfb862008-04-11 13:47:22 +02001125 self.visit(node.test, if_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001126 self.write(':')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001127 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001128 self.blockvisit(node.body, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001129 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001130 if node.else_:
1131 self.writeline('else:')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001132 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001133 self.blockvisit(node.else_, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001134 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001135
Armin Ronacher8efc5222008-04-08 14:47:40 +02001136 def visit_Macro(self, node, frame):
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001137 macro_frame = self.macro_body(node, frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001138 self.newline()
1139 if frame.toplevel:
Armin Ronacher903d1682008-05-23 00:51:58 +02001140 if not node.name.startswith('_'):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001141 self.write('context.exported_vars.add(%r)' % node.name)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001142 self.writeline('context.vars[%r] = ' % node.name)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001143 self.write('l_%s = ' % node.name)
1144 self.macro_def(node, macro_frame)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001145 frame.assigned_names.add(node.name)
Armin Ronacher71082072008-04-12 14:19:36 +02001146
1147 def visit_CallBlock(self, node, frame):
Armin Ronacher3da90312008-05-23 16:37:28 +02001148 children = node.iter_child_nodes(exclude=('call',))
1149 call_frame = self.macro_body(node, frame, children)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001150 self.writeline('caller = ')
1151 self.macro_def(node, call_frame)
1152 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001153 self.visit_Call(node.call, call_frame, forward_caller=True)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001154 self.end_write(frame)
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001155
1156 def visit_FilterBlock(self, node, frame):
1157 filter_frame = frame.inner()
1158 filter_frame.inspect(node.iter_child_nodes())
Armin Ronacher673aa882008-10-04 18:06:57 +02001159 aliases = self.push_scope(filter_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001160 self.pull_locals(filter_frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001161 self.buffer(filter_frame)
Armin Ronacherf40c8842008-09-17 18:51:26 +02001162 self.blockvisit(node.body, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001163 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001164 self.visit_Filter(node.filter, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001165 self.end_write(frame)
Armin Ronacher673aa882008-10-04 18:06:57 +02001166 self.pop_scope(aliases, filter_frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001167
Armin Ronachere791c2a2008-04-07 18:39:54 +02001168 def visit_ExprStmt(self, node, frame):
1169 self.newline(node)
Armin Ronacher6ce170c2008-04-25 12:32:36 +02001170 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001171
1172 def visit_Output(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001173 # if we have a known extends statement, we don't output anything
Armin Ronacher79668952008-09-23 22:52:46 +02001174 # if we are in a require_output_check section
1175 if self.has_known_extends and frame.require_output_check:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001176 return
Armin Ronachere791c2a2008-04-07 18:39:54 +02001177
Armin Ronacher665bfb82008-07-14 13:41:46 +02001178 if self.environment.finalize:
1179 finalize = lambda x: unicode(self.environment.finalize(x))
1180 else:
1181 finalize = unicode
1182
Armin Ronacher75cfb862008-04-11 13:47:22 +02001183 self.newline(node)
Armin Ronacher8edbe492008-04-10 20:43:43 +02001184
Armin Ronacher79668952008-09-23 22:52:46 +02001185 # if we are inside a frame that requires output checking, we do so
Armin Ronacher7fb38972008-04-11 13:54:28 +02001186 outdent_later = False
Armin Ronacher79668952008-09-23 22:52:46 +02001187 if frame.require_output_check:
Armin Ronacher203bfcb2008-04-24 21:54:44 +02001188 self.writeline('if parent_template is None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +02001189 self.indent()
Armin Ronacher7fb38972008-04-11 13:54:28 +02001190 outdent_later = True
Armin Ronacher75cfb862008-04-11 13:47:22 +02001191
Armin Ronachere791c2a2008-04-07 18:39:54 +02001192 # try to evaluate as many chunks as possible into a static
1193 # string at compile time.
1194 body = []
1195 for child in node.nodes:
1196 try:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001197 const = child.as_const()
1198 except nodes.Impossible:
1199 body.append(child)
1200 continue
1201 try:
1202 if self.environment.autoescape:
1203 if hasattr(const, '__html__'):
1204 const = const.__html__()
1205 else:
1206 const = escape(const)
Armin Ronacher665bfb82008-07-14 13:41:46 +02001207 const = finalize(const)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001208 except:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001209 # if something goes wrong here we evaluate the node
1210 # at runtime for easier debugging
Armin Ronachere791c2a2008-04-07 18:39:54 +02001211 body.append(child)
1212 continue
1213 if body and isinstance(body[-1], list):
1214 body[-1].append(const)
1215 else:
1216 body.append([const])
1217
Armin Ronachered1e0d42008-05-18 20:25:28 +02001218 # if we have less than 3 nodes or a buffer we yield or extend/append
1219 if len(body) < 3 or frame.buffer is not None:
Armin Ronacher32a910f2008-04-26 23:21:03 +02001220 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001221 # for one item we append, for more we extend
1222 if len(body) == 1:
1223 self.writeline('%s.append(' % frame.buffer)
1224 else:
1225 self.writeline('%s.extend((' % frame.buffer)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001226 self.indent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001227 for item in body:
1228 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001229 val = repr(concat(item))
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001230 if frame.buffer is None:
1231 self.writeline('yield ' + val)
1232 else:
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001233 self.writeline(val + ', ')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001234 else:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001235 if frame.buffer is None:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001236 self.writeline('yield ', item)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001237 else:
1238 self.newline(item)
Armin Ronacherd1342312008-04-28 12:20:12 +02001239 close = 1
1240 if self.environment.autoescape:
1241 self.write('escape(')
1242 else:
Armin Ronacherbd357722009-08-05 20:25:06 +02001243 self.write('to_string(')
Armin Ronacherd1342312008-04-28 12:20:12 +02001244 if self.environment.finalize is not None:
1245 self.write('environment.finalize(')
1246 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001247 self.visit(item, frame)
Armin Ronacherd1342312008-04-28 12:20:12 +02001248 self.write(')' * close)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001249 if frame.buffer is not None:
1250 self.write(', ')
1251 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001252 # close the open parentheses
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001253 self.outdent()
1254 self.writeline(len(body) == 1 and ')' or '))')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001255
1256 # otherwise we create a format string as this is faster in that case
1257 else:
1258 format = []
1259 arguments = []
1260 for item in body:
1261 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001262 format.append(concat(item).replace('%', '%%'))
Armin Ronachere791c2a2008-04-07 18:39:54 +02001263 else:
1264 format.append('%s')
1265 arguments.append(item)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001266 self.writeline('yield ')
Armin Ronacherde6bf712008-04-26 01:44:14 +02001267 self.write(repr(concat(format)) + ' % (')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001268 idx = -1
Armin Ronachera7f016d2008-05-16 00:22:40 +02001269 self.indent()
Armin Ronacher8e8d0712008-04-16 23:10:49 +02001270 for argument in arguments:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001271 self.newline(argument)
Armin Ronacherd1342312008-04-28 12:20:12 +02001272 close = 0
1273 if self.environment.autoescape:
1274 self.write('escape(')
1275 close += 1
1276 if self.environment.finalize is not None:
1277 self.write('environment.finalize(')
1278 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001279 self.visit(argument, frame)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001280 self.write(')' * close + ', ')
Armin Ronachera7f016d2008-05-16 00:22:40 +02001281 self.outdent()
1282 self.writeline(')')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001283
Armin Ronacher7fb38972008-04-11 13:54:28 +02001284 if outdent_later:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001285 self.outdent()
1286
Armin Ronacher8efc5222008-04-08 14:47:40 +02001287 def visit_Assign(self, node, frame):
1288 self.newline(node)
1289 # toplevel assignments however go into the local namespace and
1290 # the current template's context. We create a copy of the frame
1291 # here and add a set so that the Name visitor can add the assigned
1292 # names here.
1293 if frame.toplevel:
1294 assignment_frame = frame.copy()
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001295 assignment_frame.toplevel_assignments = set()
Armin Ronacher8efc5222008-04-08 14:47:40 +02001296 else:
1297 assignment_frame = frame
1298 self.visit(node.target, assignment_frame)
1299 self.write(' = ')
1300 self.visit(node.node, frame)
Armin Ronacher9706fab2008-04-08 18:49:56 +02001301
1302 # make sure toplevel assignments are added to the context.
Armin Ronacher8efc5222008-04-08 14:47:40 +02001303 if frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001304 public_names = [x for x in assignment_frame.toplevel_assignments
Armin Ronacher903d1682008-05-23 00:51:58 +02001305 if not x.startswith('_')]
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001306 if len(assignment_frame.toplevel_assignments) == 1:
Armin Ronacherbd357722009-08-05 20:25:06 +02001307 name = next(iter(assignment_frame.toplevel_assignments))
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001308 self.writeline('context.vars[%r] = l_%s' % (name, name))
Armin Ronacher69e12db2008-05-12 09:00:03 +02001309 else:
1310 self.writeline('context.vars.update({')
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001311 for idx, name in enumerate(assignment_frame.toplevel_assignments):
Armin Ronacher69e12db2008-05-12 09:00:03 +02001312 if idx:
1313 self.write(', ')
1314 self.write('%r: l_%s' % (name, name))
1315 self.write('})')
1316 if public_names:
1317 if len(public_names) == 1:
1318 self.writeline('context.exported_vars.add(%r)' %
1319 public_names[0])
1320 else:
1321 self.writeline('context.exported_vars.update((%s))' %
1322 ', '.join(map(repr, public_names)))
Armin Ronacher8efc5222008-04-08 14:47:40 +02001323
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001324 # -- Expression Visitors
1325
Armin Ronachere791c2a2008-04-07 18:39:54 +02001326 def visit_Name(self, node, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001327 if node.ctx == 'store' and frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001328 frame.toplevel_assignments.add(node.name)
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001329 self.write('l_' + node.name)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001330 frame.assigned_names.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001331
1332 def visit_Const(self, node, frame):
1333 val = node.value
1334 if isinstance(val, float):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001335 self.write(str(val))
1336 else:
1337 self.write(repr(val))
1338
Armin Ronacher5411ce72008-05-25 11:36:22 +02001339 def visit_TemplateData(self, node, frame):
1340 self.write(repr(node.as_const()))
1341
Armin Ronacher8efc5222008-04-08 14:47:40 +02001342 def visit_Tuple(self, node, frame):
1343 self.write('(')
1344 idx = -1
1345 for idx, item in enumerate(node.items):
1346 if idx:
1347 self.write(', ')
1348 self.visit(item, frame)
1349 self.write(idx == 0 and ',)' or ')')
1350
Armin Ronacher8edbe492008-04-10 20:43:43 +02001351 def visit_List(self, node, frame):
1352 self.write('[')
1353 for idx, item in enumerate(node.items):
1354 if idx:
1355 self.write(', ')
1356 self.visit(item, frame)
1357 self.write(']')
1358
1359 def visit_Dict(self, node, frame):
1360 self.write('{')
1361 for idx, item in enumerate(node.items):
1362 if idx:
1363 self.write(', ')
1364 self.visit(item.key, frame)
1365 self.write(': ')
1366 self.visit(item.value, frame)
1367 self.write('}')
1368
Armin Ronachere791c2a2008-04-07 18:39:54 +02001369 def binop(operator):
1370 def visitor(self, node, frame):
1371 self.write('(')
1372 self.visit(node.left, frame)
1373 self.write(' %s ' % operator)
1374 self.visit(node.right, frame)
1375 self.write(')')
1376 return visitor
1377
1378 def uaop(operator):
1379 def visitor(self, node, frame):
1380 self.write('(' + operator)
Armin Ronacher9a822052008-04-17 18:44:07 +02001381 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001382 self.write(')')
1383 return visitor
1384
1385 visit_Add = binop('+')
1386 visit_Sub = binop('-')
1387 visit_Mul = binop('*')
1388 visit_Div = binop('/')
1389 visit_FloorDiv = binop('//')
1390 visit_Pow = binop('**')
1391 visit_Mod = binop('%')
1392 visit_And = binop('and')
1393 visit_Or = binop('or')
1394 visit_Pos = uaop('+')
1395 visit_Neg = uaop('-')
1396 visit_Not = uaop('not ')
1397 del binop, uaop
1398
Armin Ronacherd1342312008-04-28 12:20:12 +02001399 def visit_Concat(self, node, frame):
Armin Ronacherfdf95302008-05-11 22:20:51 +02001400 self.write('%s((' % (self.environment.autoescape and
1401 'markup_join' or 'unicode_join'))
Armin Ronacherd1342312008-04-28 12:20:12 +02001402 for arg in node.nodes:
1403 self.visit(arg, frame)
1404 self.write(', ')
1405 self.write('))')
1406
Armin Ronachere791c2a2008-04-07 18:39:54 +02001407 def visit_Compare(self, node, frame):
1408 self.visit(node.expr, frame)
1409 for op in node.ops:
1410 self.visit(op, frame)
1411
1412 def visit_Operand(self, node, frame):
1413 self.write(' %s ' % operators[node.op])
1414 self.visit(node.expr, frame)
1415
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001416 def visit_Getattr(self, node, frame):
1417 self.write('environment.getattr(')
1418 self.visit(node.node, frame)
1419 self.write(', %r)' % node.attr)
1420
1421 def visit_Getitem(self, node, frame):
Armin Ronacher5c3c4702008-09-12 23:12:49 +02001422 # slices bypass the environment getitem method.
1423 if isinstance(node.arg, nodes.Slice):
Armin Ronacher8efc5222008-04-08 14:47:40 +02001424 self.visit(node.node, frame)
1425 self.write('[')
1426 self.visit(node.arg, frame)
1427 self.write(']')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001428 else:
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001429 self.write('environment.getitem(')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001430 self.visit(node.node, frame)
1431 self.write(', ')
1432 self.visit(node.arg, frame)
1433 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001434
1435 def visit_Slice(self, node, frame):
1436 if node.start is not None:
1437 self.visit(node.start, frame)
1438 self.write(':')
1439 if node.stop is not None:
1440 self.visit(node.stop, frame)
1441 if node.step is not None:
1442 self.write(':')
1443 self.visit(node.step, frame)
1444
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001445 def visit_Filter(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001446 self.write(self.filters[node.name] + '(')
Christoph Hack80909862008-04-14 01:35:10 +02001447 func = self.environment.filters.get(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +02001448 if func is None:
Armin Ronachere2244882008-05-19 09:25:57 +02001449 self.fail('no filter named %r' % node.name, node.lineno)
Christoph Hack80909862008-04-14 01:35:10 +02001450 if getattr(func, 'contextfilter', False):
1451 self.write('context, ')
Armin Ronacher9a027f42008-04-17 11:13:40 +02001452 elif getattr(func, 'environmentfilter', False):
1453 self.write('environment, ')
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001454
1455 # if the filter node is None we are inside a filter block
1456 # and want to write to the current buffer
Armin Ronacher3da90312008-05-23 16:37:28 +02001457 if node.node is not None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001458 self.visit(node.node, frame)
Armin Ronacher3da90312008-05-23 16:37:28 +02001459 elif self.environment.autoescape:
1460 self.write('Markup(concat(%s))' % frame.buffer)
1461 else:
1462 self.write('concat(%s)' % frame.buffer)
Armin Ronacherd55ab532008-04-09 16:13:39 +02001463 self.signature(node, frame)
1464 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001465
1466 def visit_Test(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001467 self.write(self.tests[node.name] + '(')
Armin Ronacher0611e492008-04-25 23:44:14 +02001468 if node.name not in self.environment.tests:
Armin Ronachere2244882008-05-19 09:25:57 +02001469 self.fail('no test named %r' % node.name, node.lineno)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001470 self.visit(node.node, frame)
1471 self.signature(node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001472 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001473
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001474 def visit_CondExpr(self, node, frame):
Armin Ronacher547d0b62008-07-04 16:35:10 +02001475 def write_expr2():
1476 if node.expr2 is not None:
1477 return self.visit(node.expr2, frame)
1478 self.write('environment.undefined(%r)' % ('the inline if-'
1479 'expression on %s evaluated to false and '
1480 'no else section was defined.' % self.position(node)))
1481
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001482 if not have_condexpr:
1483 self.write('((')
1484 self.visit(node.test, frame)
1485 self.write(') and (')
1486 self.visit(node.expr1, frame)
1487 self.write(',) or (')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001488 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001489 self.write(',))[0]')
1490 else:
1491 self.write('(')
1492 self.visit(node.expr1, frame)
1493 self.write(' if ')
1494 self.visit(node.test, frame)
1495 self.write(' else ')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001496 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001497 self.write(')')
1498
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001499 def visit_Call(self, node, frame, forward_caller=False):
Armin Ronacherc63243e2008-04-14 22:53:58 +02001500 if self.environment.sandboxed:
Armin Ronacherfd310492008-05-25 00:16:51 +02001501 self.write('environment.call(context, ')
1502 else:
1503 self.write('context.call(')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001504 self.visit(node.node, frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001505 extra_kwargs = forward_caller and {'caller': 'caller'} or None
Armin Ronacherfd310492008-05-25 00:16:51 +02001506 self.signature(node, frame, extra_kwargs)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001507 self.write(')')
1508
1509 def visit_Keyword(self, node, frame):
Armin Ronacher2e9396b2008-04-16 14:21:57 +02001510 self.write(node.key + '=')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001511 self.visit(node.value, frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001512
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001513 # -- Unused nodes for extensions
Armin Ronachered1e0d42008-05-18 20:25:28 +02001514
1515 def visit_MarkSafe(self, node, frame):
1516 self.write('Markup(')
1517 self.visit(node.expr, frame)
1518 self.write(')')
1519
1520 def visit_EnvironmentAttribute(self, node, frame):
1521 self.write('environment.' + node.name)
1522
1523 def visit_ExtensionAttribute(self, node, frame):
Armin Ronacher6df604e2008-05-23 22:18:38 +02001524 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
Armin Ronachered1e0d42008-05-18 20:25:28 +02001525
1526 def visit_ImportedName(self, node, frame):
1527 self.write(self.import_aliases[node.importname])
1528
1529 def visit_InternalName(self, node, frame):
1530 self.write(node.name)
1531
Armin Ronacher6df604e2008-05-23 22:18:38 +02001532 def visit_ContextReference(self, node, frame):
1533 self.write('context')
1534
Armin Ronachered1e0d42008-05-18 20:25:28 +02001535 def visit_Continue(self, node, frame):
1536 self.writeline('continue', node)
1537
1538 def visit_Break(self, node, frame):
1539 self.writeline('break', node)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001540
1541 def visit_Scope(self, node, frame):
1542 scope_frame = frame.inner()
1543 scope_frame.inspect(node.iter_child_nodes())
1544 aliases = self.push_scope(scope_frame)
1545 self.pull_locals(scope_frame)
1546 self.blockvisit(node.body, scope_frame)
1547 self.pop_scope(aliases, scope_frame)