blob: 5c7f1a61952c1715c5137271069c05bac05a9dbe [file] [log] [blame]
Armin Ronachere791c2a2008-04-07 18:39:54 +02001# -*- coding: utf-8 -*-
2"""
3 jinja2.compiler
4 ~~~~~~~~~~~~~~~
5
6 Compiles nodes into python code.
7
Armin Ronacher55494e42010-01-22 09:41:48 +01008 :copyright: (c) 2010 by the Jinja Team.
Armin Ronacher7af781c2010-02-09 16:05:08 +01009 :license: BSD, see LICENSE for more details.
Armin Ronachere791c2a2008-04-07 18:39:54 +020010"""
Armin Ronacherd1ff8582008-05-11 00:30:43 +020011from itertools import chain
Armin Ronacher74230e62009-10-25 12:46:31 +010012from copy import deepcopy
Armin Ronachere791c2a2008-04-07 18:39:54 +020013from jinja2 import nodes
Armin Ronacher8346bd72010-03-14 19:43:47 +010014from jinja2.nodes import EvalContext
Armin Ronacher9573b662010-12-21 00:44:34 +010015from jinja2.visitor import NodeVisitor
Armin Ronachere791c2a2008-04-07 18:39:54 +020016from jinja2.exceptions import TemplateAssertionError
Thomas Waldmann7d295622013-05-18 00:06:22 +020017from jinja2.utils import Markup, concat, escape, is_python_keyword
Thomas Waldmanne0003552013-05-17 23:52:14 +020018import six
Armin Ronacherd7d663f2013-05-18 11:38:34 +010019from six.moves import cStringIO as StringIO, map
Armin Ronachere791c2a2008-04-07 18:39:54 +020020
Cory Benfieldd5a0edf2013-05-18 11:41:24 +010021# TODO: Move this to the compat module.
22try:
23 range_type = xrange
24except NameError:
25 range_type = range
26
Armin Ronachere791c2a2008-04-07 18:39:54 +020027
28operators = {
29 'eq': '==',
30 'ne': '!=',
31 'gt': '>',
32 'gteq': '>=',
33 'lt': '<',
34 'lteq': '<=',
35 'in': 'in',
36 'notin': 'not in'
37}
38
Armin Ronacher3d8b7842008-04-13 13:16:50 +020039try:
Thomas Waldmanne0003552013-05-17 23:52:14 +020040 exec('(0 if 0 else 0)')
Armin Ronacher3d8b7842008-04-13 13:16:50 +020041except SyntaxError:
42 have_condexpr = False
43else:
44 have_condexpr = True
45
46
Armin Ronacher0d242be2010-02-10 01:35:13 +010047# what method to iterate over items do we want to use for dict iteration
48# in generated code? on 2.x let's go with iteritems, on 3.x with items
49if hasattr(dict, 'iteritems'):
50 dict_item_iter = 'iteritems'
51else:
52 dict_item_iter = 'items'
53
54
Armin Ronacher821a4232010-02-17 07:59:38 +010055# does if 0: dummy(x) get us x into the scope?
56def unoptimize_before_dead_code():
57 x = 42
58 def f():
59 if 0: dummy(x)
60 return f
Armin Ronacher9dd7fad2013-05-18 11:36:32 +010061
62# The getattr is necessary for pypy which does not set this attribute if
63# no closure is on the function
64unoptimize_before_dead_code = bool(
65 getattr(unoptimize_before_dead_code(), '__closure__', None))
Armin Ronacher821a4232010-02-17 07:59:38 +010066
67
Armin Ronacher64b08a02010-03-12 03:17:41 +010068def generate(node, environment, name, filename, stream=None,
69 defer_init=False):
Armin Ronacherbcb7c532008-04-11 16:30:34 +020070 """Generate the python source for a node tree."""
Armin Ronacher023b5e92008-05-08 11:03:10 +020071 if not isinstance(node, nodes.Template):
72 raise TypeError('Can\'t compile non template nodes')
Armin Ronacher64b08a02010-03-12 03:17:41 +010073 generator = CodeGenerator(environment, name, filename, stream, defer_init)
Armin Ronachere791c2a2008-04-07 18:39:54 +020074 generator.visit(node)
75 if stream is None:
76 return generator.stream.getvalue()
77
78
Armin Ronacher4dfc9752008-04-09 15:03:29 +020079def has_safe_repr(value):
80 """Does the node have a safe representation?"""
Armin Ronacherd55ab532008-04-09 16:13:39 +020081 if value is None or value is NotImplemented or value is Ellipsis:
Armin Ronacher4dfc9752008-04-09 15:03:29 +020082 return True
Thomas Waldmann7d295622013-05-18 00:06:22 +020083 if isinstance(value, (bool, int, float, complex, range_type, Markup) + six.string_types):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020084 return True
Armin Ronacherd55ab532008-04-09 16:13:39 +020085 if isinstance(value, (tuple, list, set, frozenset)):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020086 for item in value:
87 if not has_safe_repr(item):
88 return False
89 return True
90 elif isinstance(value, dict):
Thomas Waldmanne0003552013-05-17 23:52:14 +020091 for key, value in six.iteritems(value):
Armin Ronacher4dfc9752008-04-09 15:03:29 +020092 if not has_safe_repr(key):
93 return False
94 if not has_safe_repr(value):
95 return False
96 return True
97 return False
98
99
Armin Ronacherc9705c22008-04-27 21:28:03 +0200100def find_undeclared(nodes, names):
101 """Check if the names passed are accessed undeclared. The return value
102 is a set of all the undeclared names from the sequence of names found.
103 """
104 visitor = UndeclaredNameVisitor(names)
105 try:
106 for node in nodes:
107 visitor.visit(node)
108 except VisitorExit:
109 pass
110 return visitor.undeclared
111
112
Armin Ronachere791c2a2008-04-07 18:39:54 +0200113class Identifiers(object):
114 """Tracks the status of identifiers in frames."""
115
116 def __init__(self):
117 # variables that are known to be declared (probably from outer
118 # frames or because they are special for the frame)
119 self.declared = set()
120
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200121 # undeclared variables from outer scopes
122 self.outer_undeclared = set()
123
Armin Ronachere791c2a2008-04-07 18:39:54 +0200124 # names that are accessed without being explicitly declared by
125 # this one or any of the outer scopes. Names can appear both in
126 # declared and undeclared.
127 self.undeclared = set()
128
129 # names that are declared locally
130 self.declared_locally = set()
131
132 # names that are declared by parameters
133 self.declared_parameter = set()
134
135 def add_special(self, name):
136 """Register a special name like `loop`."""
137 self.undeclared.discard(name)
138 self.declared.add(name)
139
Armin Ronacherda632622011-03-13 14:33:27 -0400140 def is_declared(self, name):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200141 """Check if a name is declared in this or an outer scope."""
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200142 if name in self.declared_locally or name in self.declared_parameter:
143 return True
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200144 return name in self.declared
Armin Ronachere791c2a2008-04-07 18:39:54 +0200145
Armin Ronacher74230e62009-10-25 12:46:31 +0100146 def copy(self):
147 return deepcopy(self)
148
Armin Ronachere791c2a2008-04-07 18:39:54 +0200149
150class Frame(object):
Armin Ronacher75cfb862008-04-11 13:47:22 +0200151 """Holds compile time information for us."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200152
Armin Ronacher8346bd72010-03-14 19:43:47 +0100153 def __init__(self, eval_ctx, parent=None):
154 self.eval_ctx = eval_ctx
Armin Ronachere791c2a2008-04-07 18:39:54 +0200155 self.identifiers = Identifiers()
Armin Ronacherfed44b52008-04-13 19:42:53 +0200156
Armin Ronacher75cfb862008-04-11 13:47:22 +0200157 # a toplevel frame is the root + soft frames such as if conditions.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200158 self.toplevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200159
Armin Ronacher75cfb862008-04-11 13:47:22 +0200160 # the root frame is basically just the outermost frame, so no if
161 # conditions. This information is used to optimize inheritance
162 # situations.
163 self.rootlevel = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200164
Armin Ronacher79668952008-09-23 22:52:46 +0200165 # in some dynamic inheritance situations the compiler needs to add
166 # write tests around output statements.
167 self.require_output_check = parent and parent.require_output_check
Armin Ronacherf40c8842008-09-17 18:51:26 +0200168
Armin Ronacherfed44b52008-04-13 19:42:53 +0200169 # inside some tags we are using a buffer rather than yield statements.
170 # this for example affects {% filter %} or {% macro %}. If a frame
171 # is buffered this variable points to the name of the list used as
172 # buffer.
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200173 self.buffer = None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200174
Armin Ronacherfed44b52008-04-13 19:42:53 +0200175 # the name of the block we're in, otherwise None.
Armin Ronacher8efc5222008-04-08 14:47:40 +0200176 self.block = parent and parent.block or None
Armin Ronacherfed44b52008-04-13 19:42:53 +0200177
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100178 # a set of actually assigned names
179 self.assigned_names = set()
180
Armin Ronacherfed44b52008-04-13 19:42:53 +0200181 # the parent of this frame
182 self.parent = parent
183
Armin Ronachere791c2a2008-04-07 18:39:54 +0200184 if parent is not None:
185 self.identifiers.declared.update(
186 parent.identifiers.declared |
Armin Ronacherb3a1fcf2008-05-15 11:04:14 +0200187 parent.identifiers.declared_parameter |
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100188 parent.assigned_names
Armin Ronachere791c2a2008-04-07 18:39:54 +0200189 )
Armin Ronacher10f3ba22008-04-18 11:30:37 +0200190 self.identifiers.outer_undeclared.update(
191 parent.identifiers.undeclared -
192 self.identifiers.declared
193 )
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200194 self.buffer = parent.buffer
Armin Ronachere791c2a2008-04-07 18:39:54 +0200195
Armin Ronacher8efc5222008-04-08 14:47:40 +0200196 def copy(self):
197 """Create a copy of the current one."""
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200198 rv = object.__new__(self.__class__)
199 rv.__dict__.update(self.__dict__)
200 rv.identifiers = object.__new__(self.identifiers.__class__)
201 rv.identifiers.__dict__.update(self.identifiers.__dict__)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200202 return rv
203
Armin Ronacherda632622011-03-13 14:33:27 -0400204 def inspect(self, nodes):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200205 """Walk the node and check for identifiers. If the scope is hard (eg:
206 enforce on a python level) overrides from outer scopes are tracked
207 differently.
Armin Ronacher4f62a9f2008-04-08 18:09:13 +0200208 """
Armin Ronacherda632622011-03-13 14:33:27 -0400209 visitor = FrameIdentifierVisitor(self.identifiers)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200210 for node in nodes:
Armin Ronacherc9705c22008-04-27 21:28:03 +0200211 visitor.visit(node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200212
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100213 def find_shadowed(self, extra=()):
214 """Find all the shadowed names. extra is an iterable of variables
215 that may be defined with `add_special` which may occour scoped.
216 """
217 i = self.identifiers
218 return (i.declared | i.outer_undeclared) & \
219 (i.declared_locally | i.declared_parameter) | \
220 set(x for x in extra if i.is_declared(x))
221
Armin Ronachere791c2a2008-04-07 18:39:54 +0200222 def inner(self):
223 """Return an inner frame."""
Armin Ronacher8346bd72010-03-14 19:43:47 +0100224 return Frame(self.eval_ctx, self)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200225
Armin Ronacher75cfb862008-04-11 13:47:22 +0200226 def soft(self):
227 """Return a soft frame. A soft frame may not be modified as
228 standalone thing as it shares the resources with the frame it
229 was created of, but it's not a rootlevel frame any longer.
230 """
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200231 rv = self.copy()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200232 rv.rootlevel = False
233 return rv
234
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200235 __copy__ = copy
236
Armin Ronachere791c2a2008-04-07 18:39:54 +0200237
Armin Ronacherc9705c22008-04-27 21:28:03 +0200238class VisitorExit(RuntimeError):
239 """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
240
241
242class DependencyFinderVisitor(NodeVisitor):
243 """A visitor that collects filter and test calls."""
244
245 def __init__(self):
246 self.filters = set()
247 self.tests = set()
248
249 def visit_Filter(self, node):
250 self.generic_visit(node)
251 self.filters.add(node.name)
252
253 def visit_Test(self, node):
254 self.generic_visit(node)
255 self.tests.add(node.name)
256
257 def visit_Block(self, node):
258 """Stop visiting at blocks."""
259
260
261class UndeclaredNameVisitor(NodeVisitor):
262 """A visitor that checks if a name is accessed without being
263 declared. This is different from the frame visitor as it will
264 not stop at closure frames.
265 """
266
267 def __init__(self, names):
268 self.names = set(names)
269 self.undeclared = set()
270
271 def visit_Name(self, node):
272 if node.ctx == 'load' and node.name in self.names:
273 self.undeclared.add(node.name)
274 if self.undeclared == self.names:
275 raise VisitorExit()
276 else:
277 self.names.discard(node.name)
278
279 def visit_Block(self, node):
280 """Stop visiting a blocks."""
281
282
Armin Ronachere791c2a2008-04-07 18:39:54 +0200283class FrameIdentifierVisitor(NodeVisitor):
284 """A visitor for `Frame.inspect`."""
285
Armin Ronacherda632622011-03-13 14:33:27 -0400286 def __init__(self, identifiers):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200287 self.identifiers = identifiers
288
Armin Ronacherc9705c22008-04-27 21:28:03 +0200289 def visit_Name(self, node):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200290 """All assignments to names go through this function."""
Armin Ronachere9411b42008-05-15 16:22:07 +0200291 if node.ctx == 'store':
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200292 self.identifiers.declared_locally.add(node.name)
Armin Ronachere9411b42008-05-15 16:22:07 +0200293 elif node.ctx == 'param':
294 self.identifiers.declared_parameter.add(node.name)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200295 elif node.ctx == 'load' and not \
Armin Ronacherda632622011-03-13 14:33:27 -0400296 self.identifiers.is_declared(node.name):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200297 self.identifiers.undeclared.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200298
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200299 def visit_If(self, node):
300 self.visit(node.test)
Armin Ronacher74230e62009-10-25 12:46:31 +0100301 real_identifiers = self.identifiers
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200302
Armin Ronacher8a672512010-04-05 18:43:07 +0200303 old_names = real_identifiers.declared_locally | \
Armin Ronacher74230e62009-10-25 12:46:31 +0100304 real_identifiers.declared_parameter
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200305
Armin Ronacher74230e62009-10-25 12:46:31 +0100306 def inner_visit(nodes):
Armin Ronacher1965e312009-10-25 13:03:08 +0100307 if not nodes:
308 return set()
Armin Ronacher74230e62009-10-25 12:46:31 +0100309 self.identifiers = real_identifiers.copy()
310 for subnode in nodes:
311 self.visit(subnode)
312 rv = self.identifiers.declared_locally - old_names
313 # we have to remember the undeclared variables of this branch
314 # because we will have to pull them.
315 real_identifiers.undeclared.update(self.identifiers.undeclared)
316 self.identifiers = real_identifiers
317 return rv
318
319 body = inner_visit(node.body)
320 else_ = inner_visit(node.else_ or ())
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200321
322 # the differences between the two branches are also pulled as
323 # undeclared variables
Armin Ronacher8a672512010-04-05 18:43:07 +0200324 real_identifiers.undeclared.update(body.symmetric_difference(else_) -
325 real_identifiers.declared)
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200326
Armin Ronacher74230e62009-10-25 12:46:31 +0100327 # remember those that are declared.
328 real_identifiers.declared_locally.update(body | else_)
Armin Ronacherf1c421d2009-09-17 00:48:41 +0200329
Armin Ronacherc9705c22008-04-27 21:28:03 +0200330 def visit_Macro(self, node):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200331 self.identifiers.declared_locally.add(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +0200332
Armin Ronacherc9705c22008-04-27 21:28:03 +0200333 def visit_Import(self, node):
334 self.generic_visit(node)
335 self.identifiers.declared_locally.add(node.target)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200336
Armin Ronacherc9705c22008-04-27 21:28:03 +0200337 def visit_FromImport(self, node):
338 self.generic_visit(node)
339 for name in node.names:
340 if isinstance(name, tuple):
341 self.identifiers.declared_locally.add(name[1])
342 else:
343 self.identifiers.declared_locally.add(name)
344
345 def visit_Assign(self, node):
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200346 """Visit assignments in the correct order."""
Armin Ronacherc9705c22008-04-27 21:28:03 +0200347 self.visit(node.node)
348 self.visit(node.target)
Armin Ronacherebe55aa2008-04-10 20:51:23 +0200349
Armin Ronacherc9705c22008-04-27 21:28:03 +0200350 def visit_For(self, node):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200351 """Visiting stops at for blocks. However the block sequence
352 is visited as part of the outer scope.
353 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200354 self.visit(node.iter)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200355
Armin Ronacherc9705c22008-04-27 21:28:03 +0200356 def visit_CallBlock(self, node):
Armin Ronacheref189442010-01-14 01:26:40 +0100357 self.visit(node.call)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200358
359 def visit_FilterBlock(self, node):
360 self.visit(node.filter)
361
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100362 def visit_Scope(self, node):
363 """Stop visiting at scopes."""
364
Armin Ronacherc9705c22008-04-27 21:28:03 +0200365 def visit_Block(self, node):
366 """Stop visiting at blocks."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200367
368
Armin Ronacher75cfb862008-04-11 13:47:22 +0200369class CompilerExit(Exception):
370 """Raised if the compiler encountered a situation where it just
371 doesn't make sense to further process the code. Any block that
Armin Ronacher0611e492008-04-25 23:44:14 +0200372 raises such an exception is not further processed.
373 """
Armin Ronacher75cfb862008-04-11 13:47:22 +0200374
375
Armin Ronachere791c2a2008-04-07 18:39:54 +0200376class CodeGenerator(NodeVisitor):
377
Armin Ronacher64b08a02010-03-12 03:17:41 +0100378 def __init__(self, environment, name, filename, stream=None,
379 defer_init=False):
Armin Ronachere791c2a2008-04-07 18:39:54 +0200380 if stream is None:
381 stream = StringIO()
Christoph Hack65642a52008-04-08 14:46:56 +0200382 self.environment = environment
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200383 self.name = name
Armin Ronachere791c2a2008-04-07 18:39:54 +0200384 self.filename = filename
385 self.stream = stream
Armin Ronacher2f0d6592009-10-26 11:53:27 +0100386 self.created_block_context = False
Armin Ronacher64b08a02010-03-12 03:17:41 +0100387 self.defer_init = defer_init
Armin Ronacherfed44b52008-04-13 19:42:53 +0200388
Armin Ronacher023b5e92008-05-08 11:03:10 +0200389 # aliases for imports
390 self.import_aliases = {}
391
Armin Ronacherfed44b52008-04-13 19:42:53 +0200392 # a registry for all blocks. Because blocks are moved out
393 # into the global python scope they are registered here
Armin Ronachere791c2a2008-04-07 18:39:54 +0200394 self.blocks = {}
Armin Ronacherfed44b52008-04-13 19:42:53 +0200395
396 # the number of extends statements so far
Armin Ronacher7fb38972008-04-11 13:54:28 +0200397 self.extends_so_far = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200398
399 # some templates have a rootlevel extends. In this case we
400 # can safely assume that we're a child template and do some
401 # more optimizations.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200402 self.has_known_extends = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200403
Armin Ronacherba3757b2008-04-16 19:43:16 +0200404 # the current line number
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200405 self.code_lineno = 1
Armin Ronacherba3757b2008-04-16 19:43:16 +0200406
Armin Ronacherb9e78752008-05-10 23:36:28 +0200407 # registry of all filters and tests (global, not block local)
408 self.tests = {}
409 self.filters = {}
410
Armin Ronacherba3757b2008-04-16 19:43:16 +0200411 # the debug information
412 self.debug_info = []
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200413 self._write_debug_info = None
Armin Ronacherba3757b2008-04-16 19:43:16 +0200414
Armin Ronacherfed44b52008-04-13 19:42:53 +0200415 # the number of new lines before the next write()
416 self._new_lines = 0
417
418 # the line number of the last written statement
Armin Ronachere791c2a2008-04-07 18:39:54 +0200419 self._last_line = 0
Armin Ronacherfed44b52008-04-13 19:42:53 +0200420
421 # true if nothing was written so far.
Armin Ronachere791c2a2008-04-07 18:39:54 +0200422 self._first_write = True
423
Armin Ronacherfed44b52008-04-13 19:42:53 +0200424 # used by the `temporary_identifier` method to get new
425 # unique, temporary identifier
426 self._last_identifier = 0
427
428 # the current indentation
429 self._indentation = 0
430
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200431 # -- Various compilation helpers
432
Armin Ronachere2244882008-05-19 09:25:57 +0200433 def fail(self, msg, lineno):
Armin Ronacher8346bd72010-03-14 19:43:47 +0100434 """Fail with a :exc:`TemplateAssertionError`."""
Armin Ronachere2244882008-05-19 09:25:57 +0200435 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
436
Armin Ronachere791c2a2008-04-07 18:39:54 +0200437 def temporary_identifier(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200438 """Get a new unique identifier."""
439 self._last_identifier += 1
Armin Ronacher8a1d27f2008-05-19 08:37:19 +0200440 return 't_%d' % self._last_identifier
Armin Ronachere791c2a2008-04-07 18:39:54 +0200441
Armin Ronachered1e0d42008-05-18 20:25:28 +0200442 def buffer(self, frame):
443 """Enable buffering for the frame from that point onwards."""
Armin Ronachere2244882008-05-19 09:25:57 +0200444 frame.buffer = self.temporary_identifier()
445 self.writeline('%s = []' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200446
447 def return_buffer_contents(self, frame):
448 """Return the buffer contents of the frame."""
Armin Ronacher8346bd72010-03-14 19:43:47 +0100449 if frame.eval_ctx.volatile:
Armin Ronacherf3c66d92010-03-15 00:48:46 +0100450 self.writeline('if context.eval_ctx.autoescape:')
451 self.indent()
452 self.writeline('return Markup(concat(%s))' % frame.buffer)
453 self.outdent()
454 self.writeline('else:')
455 self.indent()
456 self.writeline('return concat(%s)' % frame.buffer)
457 self.outdent()
Armin Ronacher8346bd72010-03-14 19:43:47 +0100458 elif frame.eval_ctx.autoescape:
Armin Ronacherf3c66d92010-03-15 00:48:46 +0100459 self.writeline('return Markup(concat(%s))' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200460 else:
Armin Ronacherf3c66d92010-03-15 00:48:46 +0100461 self.writeline('return concat(%s)' % frame.buffer)
Armin Ronachered1e0d42008-05-18 20:25:28 +0200462
Armin Ronachere791c2a2008-04-07 18:39:54 +0200463 def indent(self):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200464 """Indent by one."""
465 self._indentation += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +0200466
Armin Ronacher8efc5222008-04-08 14:47:40 +0200467 def outdent(self, step=1):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200468 """Outdent by step."""
469 self._indentation -= step
Armin Ronachere791c2a2008-04-07 18:39:54 +0200470
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200471 def start_write(self, frame, node=None):
472 """Yield or write into the frame buffer."""
473 if frame.buffer is None:
474 self.writeline('yield ', node)
475 else:
476 self.writeline('%s.append(' % frame.buffer, node)
477
478 def end_write(self, frame):
479 """End the writing process started by `start_write`."""
480 if frame.buffer is not None:
481 self.write(')')
482
483 def simple_write(self, s, frame, node=None):
484 """Simple shortcut for start_write + write + end_write."""
485 self.start_write(frame, node)
486 self.write(s)
487 self.end_write(frame)
488
Armin Ronacherf40c8842008-09-17 18:51:26 +0200489 def blockvisit(self, nodes, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +0200490 """Visit a list of nodes as block in a frame. If the current frame
491 is no buffer a dummy ``if 0: yield None`` is written automatically
492 unless the force_generator parameter is set to False.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200493 """
Armin Ronacherf40c8842008-09-17 18:51:26 +0200494 if frame.buffer is None:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200495 self.writeline('if 0: yield None')
Armin Ronacherf40c8842008-09-17 18:51:26 +0200496 else:
497 self.writeline('pass')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200498 try:
499 for node in nodes:
500 self.visit(node, frame)
501 except CompilerExit:
502 pass
Armin Ronachere791c2a2008-04-07 18:39:54 +0200503
504 def write(self, x):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200505 """Write a string into the output stream."""
506 if self._new_lines:
Armin Ronachere791c2a2008-04-07 18:39:54 +0200507 if not self._first_write:
Armin Ronacherfed44b52008-04-13 19:42:53 +0200508 self.stream.write('\n' * self._new_lines)
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200509 self.code_lineno += self._new_lines
510 if self._write_debug_info is not None:
511 self.debug_info.append((self._write_debug_info,
512 self.code_lineno))
513 self._write_debug_info = None
Armin Ronachere791c2a2008-04-07 18:39:54 +0200514 self._first_write = False
Armin Ronacherfed44b52008-04-13 19:42:53 +0200515 self.stream.write(' ' * self._indentation)
516 self._new_lines = 0
Armin Ronachere791c2a2008-04-07 18:39:54 +0200517 self.stream.write(x)
518
519 def writeline(self, x, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200520 """Combination of newline and write."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200521 self.newline(node, extra)
522 self.write(x)
523
524 def newline(self, node=None, extra=0):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200525 """Add one or more newlines before the next write."""
526 self._new_lines = max(self._new_lines, 1 + extra)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200527 if node is not None and node.lineno != self._last_line:
Armin Ronacher8e8d0712008-04-16 23:10:49 +0200528 self._write_debug_info = node.lineno
529 self._last_line = node.lineno
Armin Ronachere791c2a2008-04-07 18:39:54 +0200530
Armin Ronacherfd310492008-05-25 00:16:51 +0200531 def signature(self, node, frame, extra_kwargs=None):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200532 """Writes a function call to the stream for the current node.
Armin Ronacherfd310492008-05-25 00:16:51 +0200533 A leading comma is added automatically. The extra keyword
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200534 arguments may not include python keywords otherwise a syntax
535 error could occour. The extra keyword arguments should be given
536 as python dict.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200537 """
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200538 # if any of the given keyword arguments is a python keyword
539 # we have to make sure that no invalid call is created.
540 kwarg_workaround = False
541 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
Armin Ronacher9a0078d2008-08-13 18:24:17 +0200542 if is_python_keyword(kwarg):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200543 kwarg_workaround = True
544 break
545
Armin Ronacher8efc5222008-04-08 14:47:40 +0200546 for arg in node.args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200547 self.write(', ')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200548 self.visit(arg, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200549
550 if not kwarg_workaround:
551 for kwarg in node.kwargs:
Armin Ronacherfd310492008-05-25 00:16:51 +0200552 self.write(', ')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200553 self.visit(kwarg, frame)
554 if extra_kwargs is not None:
Thomas Waldmanne0003552013-05-17 23:52:14 +0200555 for key, value in six.iteritems(extra_kwargs):
Armin Ronacherfd310492008-05-25 00:16:51 +0200556 self.write(', %s=%s' % (key, value))
Armin Ronacher8efc5222008-04-08 14:47:40 +0200557 if node.dyn_args:
Armin Ronacherfd310492008-05-25 00:16:51 +0200558 self.write(', *')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200559 self.visit(node.dyn_args, frame)
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200560
561 if kwarg_workaround:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200562 if node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200563 self.write(', **dict({')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200564 else:
Armin Ronacherfd310492008-05-25 00:16:51 +0200565 self.write(', **{')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200566 for kwarg in node.kwargs:
567 self.write('%r: ' % kwarg.key)
568 self.visit(kwarg.value, frame)
569 self.write(', ')
570 if extra_kwargs is not None:
Thomas Waldmanne0003552013-05-17 23:52:14 +0200571 for key, value in six.iteritems(extra_kwargs):
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200572 self.write('%r: %s, ' % (key, value))
573 if node.dyn_kwargs is not None:
574 self.write('}, **')
575 self.visit(node.dyn_kwargs, frame)
576 self.write(')')
577 else:
578 self.write('}')
579
580 elif node.dyn_kwargs is not None:
Armin Ronacherfd310492008-05-25 00:16:51 +0200581 self.write(', **')
Armin Ronacher8efc5222008-04-08 14:47:40 +0200582 self.visit(node.dyn_kwargs, frame)
583
Armin Ronacherc9705c22008-04-27 21:28:03 +0200584 def pull_locals(self, frame):
585 """Pull all the references identifiers into the local scope."""
Armin Ronachere791c2a2008-04-07 18:39:54 +0200586 for name in frame.identifiers.undeclared:
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200587 self.writeline('l_%s = context.resolve(%r)' % (name, name))
Armin Ronacherc9705c22008-04-27 21:28:03 +0200588
589 def pull_dependencies(self, nodes):
590 """Pull all the dependencies."""
591 visitor = DependencyFinderVisitor()
592 for node in nodes:
593 visitor.visit(node)
Armin Ronacherb9e78752008-05-10 23:36:28 +0200594 for dependency in 'filters', 'tests':
595 mapping = getattr(self, dependency)
596 for name in getattr(visitor, dependency):
597 if name not in mapping:
598 mapping[name] = self.temporary_identifier()
599 self.writeline('%s = environment.%s[%r]' %
600 (mapping[name], dependency, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200601
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100602 def unoptimize_scope(self, frame):
603 """Disable Python optimizations for the frame."""
604 # XXX: this is not that nice but it has no real overhead. It
605 # mainly works because python finds the locals before dead code
606 # is removed. If that breaks we have to add a dummy function
607 # that just accepts the arguments and does nothing.
608 if frame.identifiers.declared:
Armin Ronacher821a4232010-02-17 07:59:38 +0100609 self.writeline('%sdummy(%s)' % (
610 unoptimize_before_dead_code and 'if 0: ' or '',
611 ', '.join('l_' + name for name in frame.identifiers.declared)
612 ))
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100613
Armin Ronacher673aa882008-10-04 18:06:57 +0200614 def push_scope(self, frame, extra_vars=()):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200615 """This function returns all the shadowed variables in a dict
616 in the form name: alias and will write the required assignments
617 into the current scope. No indentation takes place.
Armin Ronacherff53c782008-08-13 18:55:50 +0200618
Armin Ronacher673aa882008-10-04 18:06:57 +0200619 This also predefines locally declared variables from the loop
620 body because under some circumstances it may be the case that
621
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100622 `extra_vars` is passed to `Frame.find_shadowed`.
Armin Ronacherfed44b52008-04-13 19:42:53 +0200623 """
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200624 aliases = {}
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100625 for name in frame.find_shadowed(extra_vars):
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200626 aliases[name] = ident = self.temporary_identifier()
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200627 self.writeline('%s = l_%s' % (ident, name))
Armin Ronacher673aa882008-10-04 18:06:57 +0200628 to_declare = set()
629 for name in frame.identifiers.declared_locally:
630 if name not in aliases:
631 to_declare.add('l_' + name)
632 if to_declare:
633 self.writeline(' = '.join(to_declare) + ' = missing')
Armin Ronacherfa865fb2008-04-12 22:11:53 +0200634 return aliases
635
Armin Ronacher673aa882008-10-04 18:06:57 +0200636 def pop_scope(self, aliases, frame):
637 """Restore all aliases and delete unused variables."""
Thomas Waldmanne0003552013-05-17 23:52:14 +0200638 for name, alias in six.iteritems(aliases):
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200639 self.writeline('l_%s = %s' % (name, alias))
Armin Ronacher673aa882008-10-04 18:06:57 +0200640 to_delete = set()
641 for name in frame.identifiers.declared_locally:
642 if name not in aliases:
643 to_delete.add('l_' + name)
644 if to_delete:
Armin Ronacher330fbc02009-02-04 19:13:58 +0100645 # we cannot use the del statement here because enclosed
646 # scopes can trigger a SyntaxError:
647 # a = 42; b = lambda: a; del a
648 self.writeline(' = '.join(to_delete) + ' = missing')
Armin Ronacher105f0dc2008-05-23 16:12:47 +0200649
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200650 def function_scoping(self, node, frame, children=None,
651 find_special=True):
Armin Ronacherfed44b52008-04-13 19:42:53 +0200652 """In Jinja a few statements require the help of anonymous
653 functions. Those are currently macros and call blocks and in
654 the future also recursive loops. As there is currently
655 technical limitation that doesn't allow reading and writing a
656 variable in a scope where the initial value is coming from an
657 outer scope, this function tries to fall back with a common
658 error message. Additionally the frame passed is modified so
659 that the argumetns are collected and callers are looked up.
660
661 This will return the modified frame.
662 """
Armin Ronacherc9705c22008-04-27 21:28:03 +0200663 # we have to iterate twice over it, make sure that works
664 if children is None:
665 children = node.iter_child_nodes()
666 children = list(children)
Armin Ronacher71082072008-04-12 14:19:36 +0200667 func_frame = frame.inner()
Armin Ronacherda632622011-03-13 14:33:27 -0400668 func_frame.inspect(children)
Armin Ronacher71082072008-04-12 14:19:36 +0200669
670 # variables that are undeclared (accessed before declaration) and
671 # declared locally *and* part of an outside scope raise a template
672 # assertion error. Reason: we can't generate reasonable code from
Armin Ronacher02b42a82009-03-18 00:59:32 +0100673 # it without aliasing all the variables.
674 # this could be fixed in Python 3 where we have the nonlocal
675 # keyword or if we switch to bytecode generation
Armin Ronacher71082072008-04-12 14:19:36 +0200676 overriden_closure_vars = (
677 func_frame.identifiers.undeclared &
678 func_frame.identifiers.declared &
679 (func_frame.identifiers.declared_locally |
680 func_frame.identifiers.declared_parameter)
681 )
682 if overriden_closure_vars:
Armin Ronachere2244882008-05-19 09:25:57 +0200683 self.fail('It\'s not possible to set and access variables '
Armin Ronacherefcc0e52009-09-13 00:22:50 -0700684 'derived from an outer scope! (affects: %s)' %
Armin Ronachere2244882008-05-19 09:25:57 +0200685 ', '.join(sorted(overriden_closure_vars)), node.lineno)
Armin Ronacher71082072008-04-12 14:19:36 +0200686
687 # remove variables from a closure from the frame's undeclared
688 # identifiers.
689 func_frame.identifiers.undeclared -= (
690 func_frame.identifiers.undeclared &
691 func_frame.identifiers.declared
692 )
693
Armin Ronacher1e1e8902008-05-11 23:21:16 +0200694 # no special variables for this scope, abort early
695 if not find_special:
696 return func_frame
697
Armin Ronacher963f97d2008-04-25 11:44:59 +0200698 func_frame.accesses_kwargs = False
699 func_frame.accesses_varargs = False
Armin Ronacher71082072008-04-12 14:19:36 +0200700 func_frame.accesses_caller = False
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200701 func_frame.arguments = args = ['l_' + x.name for x in node.args]
Armin Ronacher71082072008-04-12 14:19:36 +0200702
Armin Ronacherc9705c22008-04-27 21:28:03 +0200703 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
704
705 if 'caller' in undeclared:
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200706 func_frame.accesses_caller = True
707 func_frame.identifiers.add_special('caller')
708 args.append('l_caller')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200709 if 'kwargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200710 func_frame.accesses_kwargs = True
711 func_frame.identifiers.add_special('kwargs')
712 args.append('l_kwargs')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200713 if 'varargs' in undeclared:
Armin Ronacher963f97d2008-04-25 11:44:59 +0200714 func_frame.accesses_varargs = True
715 func_frame.identifiers.add_special('varargs')
716 args.append('l_varargs')
Armin Ronacher71082072008-04-12 14:19:36 +0200717 return func_frame
718
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200719 def macro_body(self, node, frame, children=None):
720 """Dump the function def of a macro or call block."""
721 frame = self.function_scoping(node, frame, children)
Armin Ronachere308bf22008-10-30 19:18:45 +0100722 # macros are delayed, they never require output checks
723 frame.require_output_check = False
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200724 args = frame.arguments
Armin Ronachereabf3dd2009-09-12 23:48:18 -0700725 # XXX: this is an ugly fix for the loop nesting bug
726 # (tests.test_old_bugs.test_loop_call_bug). This works around
727 # a identifier nesting problem we have in general. It's just more
728 # likely to happen in loops which is why we work around it. The
729 # real solution would be "nonlocal" all the identifiers that are
730 # leaking into a new python frame and might be used both unassigned
731 # and assigned.
732 if 'loop' in frame.identifiers.declared:
Armin Ronacherb4044392009-09-13 15:56:58 -0700733 args = args + ['l_loop=l_loop']
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200734 self.writeline('def macro(%s):' % ', '.join(args), node)
735 self.indent()
736 self.buffer(frame)
737 self.pull_locals(frame)
738 self.blockvisit(node.body, frame)
739 self.return_buffer_contents(frame)
740 self.outdent()
741 return frame
742
743 def macro_def(self, node, frame):
744 """Dump the macro definition for the def created by macro_body."""
745 arg_tuple = ', '.join(repr(x.name) for x in node.args)
746 name = getattr(node, 'name', None)
747 if len(node.args) == 1:
748 arg_tuple += ','
749 self.write('Macro(environment, macro, %r, (%s), (' %
750 (name, arg_tuple))
751 for arg in node.defaults:
752 self.visit(arg, frame)
753 self.write(', ')
Armin Ronacher903d1682008-05-23 00:51:58 +0200754 self.write('), %r, %r, %r)' % (
755 bool(frame.accesses_kwargs),
756 bool(frame.accesses_varargs),
757 bool(frame.accesses_caller)
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200758 ))
759
Armin Ronacher547d0b62008-07-04 16:35:10 +0200760 def position(self, node):
761 """Return a human readable position for the node."""
762 rv = 'line %d' % node.lineno
763 if self.name is not None:
Armin Ronachercebd8382008-12-25 18:33:46 +0100764 rv += ' in ' + repr(self.name)
Armin Ronacher547d0b62008-07-04 16:35:10 +0200765 return rv
766
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200767 # -- Statement Visitors
Armin Ronachere791c2a2008-04-07 18:39:54 +0200768
769 def visit_Template(self, node, frame=None):
770 assert frame is None, 'no root frame allowed'
Armin Ronacher1da23d12010-04-05 18:11:18 +0200771 eval_ctx = EvalContext(self.environment, self.name)
Armin Ronacher8346bd72010-03-14 19:43:47 +0100772
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200773 from jinja2.runtime import __all__ as exported
Armin Ronacher709f6e52008-04-28 18:18:16 +0200774 self.writeline('from __future__ import division')
Armin Ronacher2feed1d2008-04-26 16:26:52 +0200775 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
Armin Ronacher821a4232010-02-17 07:59:38 +0100776 if not unoptimize_before_dead_code:
777 self.writeline('dummy = lambda *x: None')
Armin Ronacher8edbe492008-04-10 20:43:43 +0200778
Armin Ronacher64b08a02010-03-12 03:17:41 +0100779 # if we want a deferred initialization we cannot move the
780 # environment into a local name
781 envenv = not self.defer_init and ', environment=environment' or ''
782
Armin Ronacher75cfb862008-04-11 13:47:22 +0200783 # do we have an extends tag at all? If not, we can save some
784 # overhead by just not processing any inheritance code.
785 have_extends = node.find(nodes.Extends) is not None
786
Armin Ronacher8edbe492008-04-10 20:43:43 +0200787 # find all blocks
788 for block in node.find_all(nodes.Block):
789 if block.name in self.blocks:
Armin Ronachere2244882008-05-19 09:25:57 +0200790 self.fail('block %r defined twice' % block.name, block.lineno)
Armin Ronacher8edbe492008-04-10 20:43:43 +0200791 self.blocks[block.name] = block
Armin Ronachere791c2a2008-04-07 18:39:54 +0200792
Armin Ronacher023b5e92008-05-08 11:03:10 +0200793 # find all imports and import them
794 for import_ in node.find_all(nodes.ImportedName):
795 if import_.importname not in self.import_aliases:
796 imp = import_.importname
797 self.import_aliases[imp] = alias = self.temporary_identifier()
798 if '.' in imp:
799 module, obj = imp.rsplit('.', 1)
800 self.writeline('from %s import %s as %s' %
801 (module, obj, alias))
802 else:
803 self.writeline('import %s as %s' % (imp, alias))
804
805 # add the load name
Armin Ronacherdc02b642008-05-15 22:47:27 +0200806 self.writeline('name = %r' % self.name)
Armin Ronacher023b5e92008-05-08 11:03:10 +0200807
Armin Ronacher8efc5222008-04-08 14:47:40 +0200808 # generate the root render function.
Armin Ronacher64b08a02010-03-12 03:17:41 +0100809 self.writeline('def root(context%s):' % envenv, extra=1)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200810
811 # process the root
Armin Ronacher8346bd72010-03-14 19:43:47 +0100812 frame = Frame(eval_ctx)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200813 frame.inspect(node.body)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200814 frame.toplevel = frame.rootlevel = True
Armin Ronacher79668952008-09-23 22:52:46 +0200815 frame.require_output_check = have_extends and not self.has_known_extends
Armin Ronacherf059ec12008-04-11 22:21:00 +0200816 self.indent()
Armin Ronacherc9705c22008-04-27 21:28:03 +0200817 if have_extends:
818 self.writeline('parent_template = None')
Armin Ronacherc9705c22008-04-27 21:28:03 +0200819 if 'self' in find_undeclared(node.body, ('self',)):
820 frame.identifiers.add_special('self')
821 self.writeline('l_self = TemplateReference(context)')
Armin Ronacher6df604e2008-05-23 22:18:38 +0200822 self.pull_locals(frame)
823 self.pull_dependencies(node.body)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200824 self.blockvisit(node.body, frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200825 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200826
Armin Ronacher8efc5222008-04-08 14:47:40 +0200827 # make sure that the parent root is called.
Armin Ronacher75cfb862008-04-11 13:47:22 +0200828 if have_extends:
829 if not self.has_known_extends:
830 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200831 self.writeline('if parent_template is not None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200832 self.indent()
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200833 self.writeline('for event in parent_template.'
Armin Ronacher5411ce72008-05-25 11:36:22 +0200834 'root_render_func(context):')
Armin Ronacher75cfb862008-04-11 13:47:22 +0200835 self.indent()
836 self.writeline('yield event')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200837 self.outdent(2 + (not self.has_known_extends))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200838
839 # at this point we now have the blocks collected and can visit them too.
Thomas Waldmanne0003552013-05-17 23:52:14 +0200840 for name, block in six.iteritems(self.blocks):
Armin Ronacher8346bd72010-03-14 19:43:47 +0100841 block_frame = Frame(eval_ctx)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200842 block_frame.inspect(block.body)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200843 block_frame.block = name
Armin Ronacher64b08a02010-03-12 03:17:41 +0100844 self.writeline('def block_%s(context%s):' % (name, envenv),
845 block, 1)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200846 self.indent()
847 undeclared = find_undeclared(block.body, ('self', 'super'))
848 if 'self' in undeclared:
849 block_frame.identifiers.add_special('self')
850 self.writeline('l_self = TemplateReference(context)')
851 if 'super' in undeclared:
852 block_frame.identifiers.add_special('super')
853 self.writeline('l_super = context.super(%r, '
854 'block_%s)' % (name, name))
Armin Ronachere791c2a2008-04-07 18:39:54 +0200855 self.pull_locals(block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200856 self.pull_dependencies(block.body)
Armin Ronacher625215e2008-04-13 16:31:08 +0200857 self.blockvisit(block.body, block_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +0200858 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +0200859
Armin Ronacher75cfb862008-04-11 13:47:22 +0200860 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
Armin Ronacherba3757b2008-04-16 19:43:16 +0200861 for x in self.blocks),
862 extra=1)
863
864 # add a function that returns the debug info
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200865 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
866 in self.debug_info))
Armin Ronacher75cfb862008-04-11 13:47:22 +0200867
Armin Ronachere791c2a2008-04-07 18:39:54 +0200868 def visit_Block(self, node, frame):
869 """Call a block and register it for the template."""
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200870 level = 1
Armin Ronacher75cfb862008-04-11 13:47:22 +0200871 if frame.toplevel:
Armin Ronacherbcb7c532008-04-11 16:30:34 +0200872 # if we know that we are a child template, there is no need to
873 # check if we are one
874 if self.has_known_extends:
875 return
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200876 if self.extends_so_far > 0:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200877 self.writeline('if parent_template is None:')
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200878 self.indent()
879 level += 1
Armin Ronacher2f0d6592009-10-26 11:53:27 +0100880 context = node.scoped and 'context.derived(locals())' or 'context'
Armin Ronacher74a0cd92009-02-19 15:56:53 +0100881 self.writeline('for event in context.blocks[%r][0](%s):' % (
882 node.name, context), node)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200883 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200884 self.simple_write('event', frame)
Armin Ronacher41ef36f2008-04-11 19:55:08 +0200885 self.outdent(level)
Armin Ronachere791c2a2008-04-07 18:39:54 +0200886
887 def visit_Extends(self, node, frame):
888 """Calls the extender."""
Armin Ronacher8efc5222008-04-08 14:47:40 +0200889 if not frame.toplevel:
Armin Ronachere2244882008-05-19 09:25:57 +0200890 self.fail('cannot use extend from a non top-level scope',
891 node.lineno)
Armin Ronacher75cfb862008-04-11 13:47:22 +0200892
Armin Ronacher7fb38972008-04-11 13:54:28 +0200893 # if the number of extends statements in general is zero so
894 # far, we don't have to add a check if something extended
895 # the template before this one.
896 if self.extends_so_far > 0:
Armin Ronacher75cfb862008-04-11 13:47:22 +0200897
Armin Ronacher7fb38972008-04-11 13:54:28 +0200898 # if we have a known extends we just add a template runtime
899 # error into the generated code. We could catch that at compile
900 # time too, but i welcome it not to confuse users by throwing the
901 # same error at different times just "because we can".
902 if not self.has_known_extends:
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200903 self.writeline('if parent_template is not None:')
Armin Ronacher7fb38972008-04-11 13:54:28 +0200904 self.indent()
905 self.writeline('raise TemplateRuntimeError(%r)' %
906 'extended multiple times')
Armin Ronacher79668952008-09-23 22:52:46 +0200907 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200908
Armin Ronacher7fb38972008-04-11 13:54:28 +0200909 # if we have a known extends already we don't need that code here
910 # as we know that the template execution will end here.
911 if self.has_known_extends:
912 raise CompilerExit()
Armin Ronacher7fb38972008-04-11 13:54:28 +0200913
Armin Ronacher9d42abf2008-05-14 18:10:41 +0200914 self.writeline('parent_template = environment.get_template(', node)
Armin Ronacher8efc5222008-04-08 14:47:40 +0200915 self.visit(node.template, frame)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200916 self.write(', %r)' % self.name)
917 self.writeline('for name, parent_block in parent_template.'
Armin Ronacher0d242be2010-02-10 01:35:13 +0100918 'blocks.%s():' % dict_item_iter)
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200919 self.indent()
920 self.writeline('context.blocks.setdefault(name, []).'
Armin Ronacher83fbc0f2008-05-15 12:22:28 +0200921 'append(parent_block)')
Armin Ronacher203bfcb2008-04-24 21:54:44 +0200922 self.outdent()
Armin Ronacher75cfb862008-04-11 13:47:22 +0200923
924 # if this extends statement was in the root level we can take
925 # advantage of that information and simplify the generated code
926 # in the top level from this point onwards
Armin Ronacher27069d72008-05-11 19:48:12 +0200927 if frame.rootlevel:
928 self.has_known_extends = True
Armin Ronachere791c2a2008-04-07 18:39:54 +0200929
Armin Ronacher7fb38972008-04-11 13:54:28 +0200930 # and now we have one more
931 self.extends_so_far += 1
932
Armin Ronacherf059ec12008-04-11 22:21:00 +0200933 def visit_Include(self, node, frame):
934 """Handles includes."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100935 if node.with_context:
936 self.unoptimize_scope(frame)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100937 if node.ignore_missing:
938 self.writeline('try:')
939 self.indent()
Armin Ronacher31bbd9e2010-01-14 00:41:30 +0100940
941 func_name = 'get_or_select_template'
942 if isinstance(node.template, nodes.Const):
Thomas Waldmann7d295622013-05-18 00:06:22 +0200943 if isinstance(node.template.value, six.string_types):
Armin Ronacher31bbd9e2010-01-14 00:41:30 +0100944 func_name = 'get_template'
945 elif isinstance(node.template.value, (tuple, list)):
946 func_name = 'select_template'
947 elif isinstance(node.template, (nodes.Tuple, nodes.List)):
948 func_name = 'select_template'
949
950 self.writeline('template = environment.%s(' % func_name, node)
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100951 self.visit(node.template, frame)
952 self.write(', %r)' % self.name)
953 if node.ignore_missing:
954 self.outdent()
955 self.writeline('except TemplateNotFound:')
956 self.indent()
957 self.writeline('pass')
958 self.outdent()
959 self.writeline('else:')
960 self.indent()
961
Armin Ronacherea847c52008-05-02 20:04:32 +0200962 if node.with_context:
Armin Ronacher5411ce72008-05-25 11:36:22 +0200963 self.writeline('for event in template.root_render_func('
Armin Ronacher673aa882008-10-04 18:06:57 +0200964 'template.new_context(context.parent, True, '
965 'locals())):')
Armin Ronacherea847c52008-05-02 20:04:32 +0200966 else:
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100967 self.writeline('for event in template.module._body_stream:')
968
Armin Ronacherf059ec12008-04-11 22:21:00 +0200969 self.indent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +0200970 self.simple_write('event', frame)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200971 self.outdent()
972
Armin Ronacher37f58ce2008-12-27 13:10:38 +0100973 if node.ignore_missing:
974 self.outdent()
975
Armin Ronacher0611e492008-04-25 23:44:14 +0200976 def visit_Import(self, node, frame):
977 """Visit regular imports."""
Armin Ronacher7887a8c2009-02-08 19:11:44 +0100978 if node.with_context:
979 self.unoptimize_scope(frame)
Armin Ronacherd1ff8582008-05-11 00:30:43 +0200980 self.writeline('l_%s = ' % node.target, node)
Armin Ronacherf059ec12008-04-11 22:21:00 +0200981 if frame.toplevel:
Armin Ronacher53042292008-04-26 18:30:19 +0200982 self.write('context.vars[%r] = ' % node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200983 self.write('environment.get_template(')
984 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200985 self.write(', %r).' % self.name)
986 if node.with_context:
Armin Ronacher673aa882008-10-04 18:06:57 +0200987 self.write('make_module(context.parent, True, locals())')
Armin Ronacherea847c52008-05-02 20:04:32 +0200988 else:
989 self.write('module')
Armin Ronacher903d1682008-05-23 00:51:58 +0200990 if frame.toplevel and not node.target.startswith('_'):
Armin Ronacher53042292008-04-26 18:30:19 +0200991 self.writeline('context.exported_vars.discard(%r)' % node.target)
Armin Ronacher271a0eb2009-02-11 22:49:08 +0100992 frame.assigned_names.add(node.target)
Armin Ronacher0611e492008-04-25 23:44:14 +0200993
994 def visit_FromImport(self, node, frame):
995 """Visit named imports."""
996 self.newline(node)
997 self.write('included_template = environment.get_template(')
998 self.visit(node.template, frame)
Armin Ronacherea847c52008-05-02 20:04:32 +0200999 self.write(', %r).' % self.name)
1000 if node.with_context:
1001 self.write('make_module(context.parent, True)')
1002 else:
1003 self.write('module')
Armin Ronachera78d2762008-05-15 23:18:07 +02001004
1005 var_names = []
1006 discarded_names = []
Armin Ronacher0611e492008-04-25 23:44:14 +02001007 for name in node.names:
Armin Ronacher2feed1d2008-04-26 16:26:52 +02001008 if isinstance(name, tuple):
1009 name, alias = name
1010 else:
1011 alias = name
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001012 self.writeline('l_%s = getattr(included_template, '
1013 '%r, missing)' % (alias, name))
1014 self.writeline('if l_%s is missing:' % alias)
Armin Ronacher0611e492008-04-25 23:44:14 +02001015 self.indent()
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001016 self.writeline('l_%s = environment.undefined(%r %% '
Armin Ronacherdc02b642008-05-15 22:47:27 +02001017 'included_template.__name__, '
Armin Ronacher0a2ac692008-05-13 01:03:08 +02001018 'name=%r)' %
Armin Ronacher547d0b62008-07-04 16:35:10 +02001019 (alias, 'the template %%r (imported on %s) does '
1020 'not export the requested name %s' % (
1021 self.position(node),
1022 repr(name)
1023 ), name))
Armin Ronacher0611e492008-04-25 23:44:14 +02001024 self.outdent()
1025 if frame.toplevel:
Armin Ronachera78d2762008-05-15 23:18:07 +02001026 var_names.append(alias)
Armin Ronacher903d1682008-05-23 00:51:58 +02001027 if not alias.startswith('_'):
Armin Ronachera78d2762008-05-15 23:18:07 +02001028 discarded_names.append(alias)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001029 frame.assigned_names.add(alias)
Armin Ronachera78d2762008-05-15 23:18:07 +02001030
1031 if var_names:
1032 if len(var_names) == 1:
1033 name = var_names[0]
1034 self.writeline('context.vars[%r] = l_%s' % (name, name))
1035 else:
1036 self.writeline('context.vars.update({%s})' % ', '.join(
1037 '%r: l_%s' % (name, name) for name in var_names
1038 ))
1039 if discarded_names:
1040 if len(discarded_names) == 1:
1041 self.writeline('context.exported_vars.discard(%r)' %
1042 discarded_names[0])
1043 else:
1044 self.writeline('context.exported_vars.difference_'
1045 'update((%s))' % ', '.join(map(repr, discarded_names)))
Armin Ronacherf059ec12008-04-11 22:21:00 +02001046
Armin Ronachere791c2a2008-04-07 18:39:54 +02001047 def visit_For(self, node, frame):
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001048 # when calculating the nodes for the inner frame we have to exclude
1049 # the iterator contents from it
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001050 children = node.iter_child_nodes(exclude=('iter',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001051 if node.recursive:
1052 loop_frame = self.function_scoping(node, frame, children,
1053 find_special=False)
1054 else:
1055 loop_frame = frame.inner()
1056 loop_frame.inspect(children)
1057
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001058 # try to figure out if we have an extended loop. An extended loop
1059 # is necessary if the loop is in recursive mode if the special loop
1060 # variable is accessed in the body.
1061 extended_loop = node.recursive or 'loop' in \
1062 find_undeclared(node.iter_child_nodes(
1063 only=('body',)), ('loop',))
1064
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001065 # if we don't have an recursive loop we have to find the shadowed
Armin Ronacherff53c782008-08-13 18:55:50 +02001066 # variables at that point. Because loops can be nested but the loop
1067 # variable is a special one we have to enforce aliasing for it.
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001068 if not node.recursive:
Armin Ronacher673aa882008-10-04 18:06:57 +02001069 aliases = self.push_scope(loop_frame, ('loop',))
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001070
1071 # otherwise we set up a buffer and add a function def
1072 else:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001073 self.writeline('def loop(reciter, loop_render_func):', node)
1074 self.indent()
Armin Ronachered1e0d42008-05-18 20:25:28 +02001075 self.buffer(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001076 aliases = {}
1077
Armin Ronacherff53c782008-08-13 18:55:50 +02001078 # make sure the loop variable is a special one and raise a template
1079 # assertion error if a loop tries to write to loop
Armin Ronacher833a3b52008-08-14 12:31:12 +02001080 if extended_loop:
1081 loop_frame.identifiers.add_special('loop')
Armin Ronacherff53c782008-08-13 18:55:50 +02001082 for name in node.find_all(nodes.Name):
1083 if name.ctx == 'store' and name.name == 'loop':
1084 self.fail('Can\'t assign to special loop variable '
1085 'in for-loop target', name.lineno)
1086
Armin Ronacherc9705c22008-04-27 21:28:03 +02001087 self.pull_locals(loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001088 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001089 iteration_indicator = self.temporary_identifier()
1090 self.writeline('%s = 1' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001091
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001092 # Create a fake parent loop if the else or test section of a
1093 # loop is accessing the special loop variable and no parent loop
1094 # exists.
1095 if 'loop' not in aliases and 'loop' in find_undeclared(
1096 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1097 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
Armin Ronacher547d0b62008-07-04 16:35:10 +02001098 ("'loop' is undefined. the filter section of a loop as well "
Armin Ronacherbc56cd22011-01-15 18:35:45 +01001099 "as the else block don't have access to the special 'loop'"
Armin Ronacher547d0b62008-07-04 16:35:10 +02001100 " variable of the current loop. Because there is no parent "
1101 "loop it's undefined. Happened in loop on %s" %
1102 self.position(node)))
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001103
1104 self.writeline('for ', node)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001105 self.visit(node.target, loop_frame)
Armin Ronacher180a1bd2008-04-09 12:14:24 +02001106 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001107
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001108 # if we have an extened loop and a node test, we filter in the
1109 # "outer frame".
1110 if extended_loop and node.test is not None:
1111 self.write('(')
1112 self.visit(node.target, loop_frame)
1113 self.write(' for ')
1114 self.visit(node.target, loop_frame)
1115 self.write(' in ')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001116 if node.recursive:
1117 self.write('reciter')
1118 else:
1119 self.visit(node.iter, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001120 self.write(' if (')
1121 test_frame = loop_frame.copy()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001122 self.visit(node.test, test_frame)
1123 self.write('))')
1124
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001125 elif node.recursive:
1126 self.write('reciter')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001127 else:
1128 self.visit(node.iter, loop_frame)
1129
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001130 if node.recursive:
1131 self.write(', recurse=loop_render_func):')
1132 else:
1133 self.write(extended_loop and '):' or ':')
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001134
1135 # tests in not extended loops become a continue
1136 if not extended_loop and node.test is not None:
1137 self.indent()
Armin Ronacher47a506f2008-05-06 12:17:23 +02001138 self.writeline('if not ')
Armin Ronacher32a910f2008-04-26 23:21:03 +02001139 self.visit(node.test, loop_frame)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001140 self.write(':')
1141 self.indent()
1142 self.writeline('continue')
1143 self.outdent(2)
1144
Armin Ronacherc9705c22008-04-27 21:28:03 +02001145 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001146 self.blockvisit(node.body, loop_frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001147 if node.else_:
1148 self.writeline('%s = 0' % iteration_indicator)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001149 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001150
1151 if node.else_:
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001152 self.writeline('if %s:' % iteration_indicator)
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001153 self.indent()
Armin Ronacherf40c8842008-09-17 18:51:26 +02001154 self.blockvisit(node.else_, loop_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001155 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001156
Armin Ronacherd4c64f72008-04-11 17:15:29 +02001157 # reset the aliases if there are any.
Armin Ronachercebd8382008-12-25 18:33:46 +01001158 if not node.recursive:
1159 self.pop_scope(aliases, loop_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001160
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001161 # if the node was recursive we have to return the buffer contents
1162 # and start the iteration code
1163 if node.recursive:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001164 self.return_buffer_contents(loop_frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001165 self.outdent()
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001166 self.start_write(frame, node)
1167 self.write('loop(')
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001168 self.visit(node.iter, frame)
1169 self.write(', loop)')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001170 self.end_write(frame)
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001171
Armin Ronachere791c2a2008-04-07 18:39:54 +02001172 def visit_If(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001173 if_frame = frame.soft()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001174 self.writeline('if ', node)
Armin Ronacher75cfb862008-04-11 13:47:22 +02001175 self.visit(node.test, if_frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001176 self.write(':')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001177 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001178 self.blockvisit(node.body, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001179 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001180 if node.else_:
1181 self.writeline('else:')
Armin Ronacherc9705c22008-04-27 21:28:03 +02001182 self.indent()
Armin Ronacher75cfb862008-04-11 13:47:22 +02001183 self.blockvisit(node.else_, if_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001184 self.outdent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001185
Armin Ronacher8efc5222008-04-08 14:47:40 +02001186 def visit_Macro(self, node, frame):
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001187 macro_frame = self.macro_body(node, frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001188 self.newline()
1189 if frame.toplevel:
Armin Ronacher903d1682008-05-23 00:51:58 +02001190 if not node.name.startswith('_'):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001191 self.write('context.exported_vars.add(%r)' % node.name)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001192 self.writeline('context.vars[%r] = ' % node.name)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001193 self.write('l_%s = ' % node.name)
1194 self.macro_def(node, macro_frame)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001195 frame.assigned_names.add(node.name)
Armin Ronacher71082072008-04-12 14:19:36 +02001196
1197 def visit_CallBlock(self, node, frame):
Armin Ronacher3da90312008-05-23 16:37:28 +02001198 children = node.iter_child_nodes(exclude=('call',))
1199 call_frame = self.macro_body(node, frame, children)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001200 self.writeline('caller = ')
1201 self.macro_def(node, call_frame)
1202 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001203 self.visit_Call(node.call, call_frame, forward_caller=True)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001204 self.end_write(frame)
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001205
1206 def visit_FilterBlock(self, node, frame):
1207 filter_frame = frame.inner()
1208 filter_frame.inspect(node.iter_child_nodes())
Armin Ronacher673aa882008-10-04 18:06:57 +02001209 aliases = self.push_scope(filter_frame)
Armin Ronacherc9705c22008-04-27 21:28:03 +02001210 self.pull_locals(filter_frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001211 self.buffer(filter_frame)
Armin Ronacherf40c8842008-09-17 18:51:26 +02001212 self.blockvisit(node.body, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001213 self.start_write(frame, node)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001214 self.visit_Filter(node.filter, filter_frame)
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001215 self.end_write(frame)
Armin Ronacher673aa882008-10-04 18:06:57 +02001216 self.pop_scope(aliases, filter_frame)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001217
Armin Ronachere791c2a2008-04-07 18:39:54 +02001218 def visit_ExprStmt(self, node, frame):
1219 self.newline(node)
Armin Ronacher6ce170c2008-04-25 12:32:36 +02001220 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001221
1222 def visit_Output(self, node, frame):
Armin Ronacher75cfb862008-04-11 13:47:22 +02001223 # if we have a known extends statement, we don't output anything
Armin Ronacher79668952008-09-23 22:52:46 +02001224 # if we are in a require_output_check section
1225 if self.has_known_extends and frame.require_output_check:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001226 return
Armin Ronachere791c2a2008-04-07 18:39:54 +02001227
Armin Ronacher665bfb82008-07-14 13:41:46 +02001228 if self.environment.finalize:
Thomas Waldmanne0003552013-05-17 23:52:14 +02001229 finalize = lambda x: six.text_type(self.environment.finalize(x))
Armin Ronacher665bfb82008-07-14 13:41:46 +02001230 else:
Thomas Waldmann7d295622013-05-18 00:06:22 +02001231 finalize = six.text_type
Armin Ronacher665bfb82008-07-14 13:41:46 +02001232
Armin Ronacher79668952008-09-23 22:52:46 +02001233 # if we are inside a frame that requires output checking, we do so
Armin Ronacher7fb38972008-04-11 13:54:28 +02001234 outdent_later = False
Armin Ronacher79668952008-09-23 22:52:46 +02001235 if frame.require_output_check:
Armin Ronacher203bfcb2008-04-24 21:54:44 +02001236 self.writeline('if parent_template is None:')
Armin Ronacher75cfb862008-04-11 13:47:22 +02001237 self.indent()
Armin Ronacher7fb38972008-04-11 13:54:28 +02001238 outdent_later = True
Armin Ronacher75cfb862008-04-11 13:47:22 +02001239
Armin Ronachere791c2a2008-04-07 18:39:54 +02001240 # try to evaluate as many chunks as possible into a static
1241 # string at compile time.
1242 body = []
1243 for child in node.nodes:
1244 try:
Armin Ronacher8346bd72010-03-14 19:43:47 +01001245 const = child.as_const(frame.eval_ctx)
Armin Ronacher9cf95912008-05-24 19:54:43 +02001246 except nodes.Impossible:
1247 body.append(child)
1248 continue
Armin Ronacher8346bd72010-03-14 19:43:47 +01001249 # the frame can't be volatile here, becaus otherwise the
1250 # as_const() function would raise an Impossible exception
1251 # at that point.
Armin Ronacher9cf95912008-05-24 19:54:43 +02001252 try:
Armin Ronacher8346bd72010-03-14 19:43:47 +01001253 if frame.eval_ctx.autoescape:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001254 if hasattr(const, '__html__'):
1255 const = const.__html__()
1256 else:
1257 const = escape(const)
Armin Ronacher665bfb82008-07-14 13:41:46 +02001258 const = finalize(const)
Ian Lewisab014bd2010-10-31 20:29:28 +09001259 except Exception:
Armin Ronacher9cf95912008-05-24 19:54:43 +02001260 # if something goes wrong here we evaluate the node
1261 # at runtime for easier debugging
Armin Ronachere791c2a2008-04-07 18:39:54 +02001262 body.append(child)
1263 continue
1264 if body and isinstance(body[-1], list):
1265 body[-1].append(const)
1266 else:
1267 body.append([const])
1268
Armin Ronachered1e0d42008-05-18 20:25:28 +02001269 # if we have less than 3 nodes or a buffer we yield or extend/append
1270 if len(body) < 3 or frame.buffer is not None:
Armin Ronacher32a910f2008-04-26 23:21:03 +02001271 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001272 # for one item we append, for more we extend
1273 if len(body) == 1:
1274 self.writeline('%s.append(' % frame.buffer)
1275 else:
1276 self.writeline('%s.extend((' % frame.buffer)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001277 self.indent()
Armin Ronachere791c2a2008-04-07 18:39:54 +02001278 for item in body:
1279 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001280 val = repr(concat(item))
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001281 if frame.buffer is None:
1282 self.writeline('yield ' + val)
1283 else:
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001284 self.writeline(val + ', ')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001285 else:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001286 if frame.buffer is None:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001287 self.writeline('yield ', item)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001288 else:
1289 self.newline(item)
Armin Ronacherd1342312008-04-28 12:20:12 +02001290 close = 1
Armin Ronacher8346bd72010-03-14 19:43:47 +01001291 if frame.eval_ctx.volatile:
1292 self.write('(context.eval_ctx.autoescape and'
1293 ' escape or to_string)(')
1294 elif frame.eval_ctx.autoescape:
Armin Ronacherd1342312008-04-28 12:20:12 +02001295 self.write('escape(')
1296 else:
Armin Ronacherbd357722009-08-05 20:25:06 +02001297 self.write('to_string(')
Armin Ronacherd1342312008-04-28 12:20:12 +02001298 if self.environment.finalize is not None:
1299 self.write('environment.finalize(')
1300 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001301 self.visit(item, frame)
Armin Ronacherd1342312008-04-28 12:20:12 +02001302 self.write(')' * close)
Armin Ronacher32a910f2008-04-26 23:21:03 +02001303 if frame.buffer is not None:
1304 self.write(', ')
1305 if frame.buffer is not None:
Armin Ronacher1e1e8902008-05-11 23:21:16 +02001306 # close the open parentheses
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001307 self.outdent()
1308 self.writeline(len(body) == 1 and ')' or '))')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001309
1310 # otherwise we create a format string as this is faster in that case
1311 else:
1312 format = []
1313 arguments = []
1314 for item in body:
1315 if isinstance(item, list):
Armin Ronacherde6bf712008-04-26 01:44:14 +02001316 format.append(concat(item).replace('%', '%%'))
Armin Ronachere791c2a2008-04-07 18:39:54 +02001317 else:
1318 format.append('%s')
1319 arguments.append(item)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001320 self.writeline('yield ')
Armin Ronacherde6bf712008-04-26 01:44:14 +02001321 self.write(repr(concat(format)) + ' % (')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001322 idx = -1
Armin Ronachera7f016d2008-05-16 00:22:40 +02001323 self.indent()
Armin Ronacher8e8d0712008-04-16 23:10:49 +02001324 for argument in arguments:
Armin Ronachered1e0d42008-05-18 20:25:28 +02001325 self.newline(argument)
Armin Ronacherd1342312008-04-28 12:20:12 +02001326 close = 0
Armin Ronacher8346bd72010-03-14 19:43:47 +01001327 if frame.eval_ctx.volatile:
1328 self.write('(context.eval_ctx.autoescape and'
1329 ' escape or to_string)(')
Armin Ronacher744bb0a2010-03-15 00:26:05 +01001330 close += 1
Armin Ronacher8346bd72010-03-14 19:43:47 +01001331 elif frame.eval_ctx.autoescape:
Armin Ronacherd1342312008-04-28 12:20:12 +02001332 self.write('escape(')
1333 close += 1
1334 if self.environment.finalize is not None:
1335 self.write('environment.finalize(')
1336 close += 1
Armin Ronachere791c2a2008-04-07 18:39:54 +02001337 self.visit(argument, frame)
Armin Ronacher1f627ff2008-05-15 13:23:26 +02001338 self.write(')' * close + ', ')
Armin Ronachera7f016d2008-05-16 00:22:40 +02001339 self.outdent()
1340 self.writeline(')')
Armin Ronachere791c2a2008-04-07 18:39:54 +02001341
Armin Ronacher7fb38972008-04-11 13:54:28 +02001342 if outdent_later:
Armin Ronacher75cfb862008-04-11 13:47:22 +02001343 self.outdent()
1344
Armin Ronacher8efc5222008-04-08 14:47:40 +02001345 def visit_Assign(self, node, frame):
1346 self.newline(node)
1347 # toplevel assignments however go into the local namespace and
1348 # the current template's context. We create a copy of the frame
1349 # here and add a set so that the Name visitor can add the assigned
1350 # names here.
1351 if frame.toplevel:
1352 assignment_frame = frame.copy()
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001353 assignment_frame.toplevel_assignments = set()
Armin Ronacher8efc5222008-04-08 14:47:40 +02001354 else:
1355 assignment_frame = frame
1356 self.visit(node.target, assignment_frame)
1357 self.write(' = ')
1358 self.visit(node.node, frame)
Armin Ronacher9706fab2008-04-08 18:49:56 +02001359
1360 # make sure toplevel assignments are added to the context.
Armin Ronacher8efc5222008-04-08 14:47:40 +02001361 if frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001362 public_names = [x for x in assignment_frame.toplevel_assignments
Armin Ronacher903d1682008-05-23 00:51:58 +02001363 if not x.startswith('_')]
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001364 if len(assignment_frame.toplevel_assignments) == 1:
Thomas Waldmann7d295622013-05-18 00:06:22 +02001365 name = six.advance_iterator(iter(assignment_frame.toplevel_assignments))
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001366 self.writeline('context.vars[%r] = l_%s' % (name, name))
Armin Ronacher69e12db2008-05-12 09:00:03 +02001367 else:
1368 self.writeline('context.vars.update({')
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001369 for idx, name in enumerate(assignment_frame.toplevel_assignments):
Armin Ronacher69e12db2008-05-12 09:00:03 +02001370 if idx:
1371 self.write(', ')
1372 self.write('%r: l_%s' % (name, name))
1373 self.write('})')
1374 if public_names:
1375 if len(public_names) == 1:
1376 self.writeline('context.exported_vars.add(%r)' %
1377 public_names[0])
1378 else:
1379 self.writeline('context.exported_vars.update((%s))' %
1380 ', '.join(map(repr, public_names)))
Armin Ronacher8efc5222008-04-08 14:47:40 +02001381
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001382 # -- Expression Visitors
1383
Armin Ronachere791c2a2008-04-07 18:39:54 +02001384 def visit_Name(self, node, frame):
Armin Ronacherc9705c22008-04-27 21:28:03 +02001385 if node.ctx == 'store' and frame.toplevel:
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001386 frame.toplevel_assignments.add(node.name)
Armin Ronacherd1ff8582008-05-11 00:30:43 +02001387 self.write('l_' + node.name)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001388 frame.assigned_names.add(node.name)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001389
1390 def visit_Const(self, node, frame):
1391 val = node.value
1392 if isinstance(val, float):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001393 self.write(str(val))
1394 else:
1395 self.write(repr(val))
1396
Armin Ronacher5411ce72008-05-25 11:36:22 +02001397 def visit_TemplateData(self, node, frame):
Armin Ronacherffaa2e72010-05-29 20:57:16 +02001398 try:
1399 self.write(repr(node.as_const(frame.eval_ctx)))
1400 except nodes.Impossible:
1401 self.write('(context.eval_ctx.autoescape and Markup or identity)(%r)'
1402 % node.data)
Armin Ronacher5411ce72008-05-25 11:36:22 +02001403
Armin Ronacher8efc5222008-04-08 14:47:40 +02001404 def visit_Tuple(self, node, frame):
1405 self.write('(')
1406 idx = -1
1407 for idx, item in enumerate(node.items):
1408 if idx:
1409 self.write(', ')
1410 self.visit(item, frame)
1411 self.write(idx == 0 and ',)' or ')')
1412
Armin Ronacher8edbe492008-04-10 20:43:43 +02001413 def visit_List(self, node, frame):
1414 self.write('[')
1415 for idx, item in enumerate(node.items):
1416 if idx:
1417 self.write(', ')
1418 self.visit(item, frame)
1419 self.write(']')
1420
1421 def visit_Dict(self, node, frame):
1422 self.write('{')
1423 for idx, item in enumerate(node.items):
1424 if idx:
1425 self.write(', ')
1426 self.visit(item.key, frame)
1427 self.write(': ')
1428 self.visit(item.value, frame)
1429 self.write('}')
1430
Armin Ronachera9195382010-11-29 13:21:57 +01001431 def binop(operator, interceptable=True):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001432 def visitor(self, node, frame):
Armin Ronachera9195382010-11-29 13:21:57 +01001433 if self.environment.sandboxed and \
1434 operator in self.environment.intercepted_binops:
1435 self.write('environment.call_binop(context, %r, ' % operator)
1436 self.visit(node.left, frame)
1437 self.write(', ')
1438 self.visit(node.right, frame)
1439 else:
1440 self.write('(')
1441 self.visit(node.left, frame)
1442 self.write(' %s ' % operator)
1443 self.visit(node.right, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001444 self.write(')')
1445 return visitor
1446
Armin Ronachera9195382010-11-29 13:21:57 +01001447 def uaop(operator, interceptable=True):
Armin Ronachere791c2a2008-04-07 18:39:54 +02001448 def visitor(self, node, frame):
Armin Ronachera9195382010-11-29 13:21:57 +01001449 if self.environment.sandboxed and \
1450 operator in self.environment.intercepted_unops:
1451 self.write('environment.call_unop(context, %r, ' % operator)
1452 self.visit(node.node, frame)
1453 else:
1454 self.write('(' + operator)
1455 self.visit(node.node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001456 self.write(')')
1457 return visitor
1458
1459 visit_Add = binop('+')
1460 visit_Sub = binop('-')
1461 visit_Mul = binop('*')
1462 visit_Div = binop('/')
1463 visit_FloorDiv = binop('//')
1464 visit_Pow = binop('**')
1465 visit_Mod = binop('%')
Armin Ronachera9195382010-11-29 13:21:57 +01001466 visit_And = binop('and', interceptable=False)
1467 visit_Or = binop('or', interceptable=False)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001468 visit_Pos = uaop('+')
1469 visit_Neg = uaop('-')
Armin Ronachera9195382010-11-29 13:21:57 +01001470 visit_Not = uaop('not ', interceptable=False)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001471 del binop, uaop
1472
Armin Ronacherd1342312008-04-28 12:20:12 +02001473 def visit_Concat(self, node, frame):
Armin Ronacher8346bd72010-03-14 19:43:47 +01001474 if frame.eval_ctx.volatile:
1475 func_name = '(context.eval_ctx.volatile and' \
1476 ' markup_join or unicode_join)'
1477 elif frame.eval_ctx.autoescape:
1478 func_name = 'markup_join'
1479 else:
1480 func_name = 'unicode_join'
1481 self.write('%s((' % func_name)
Armin Ronacherd1342312008-04-28 12:20:12 +02001482 for arg in node.nodes:
1483 self.visit(arg, frame)
1484 self.write(', ')
1485 self.write('))')
1486
Armin Ronachere791c2a2008-04-07 18:39:54 +02001487 def visit_Compare(self, node, frame):
1488 self.visit(node.expr, frame)
1489 for op in node.ops:
1490 self.visit(op, frame)
1491
1492 def visit_Operand(self, node, frame):
1493 self.write(' %s ' % operators[node.op])
1494 self.visit(node.expr, frame)
1495
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001496 def visit_Getattr(self, node, frame):
1497 self.write('environment.getattr(')
1498 self.visit(node.node, frame)
1499 self.write(', %r)' % node.attr)
1500
1501 def visit_Getitem(self, node, frame):
Armin Ronacher5c3c4702008-09-12 23:12:49 +02001502 # slices bypass the environment getitem method.
1503 if isinstance(node.arg, nodes.Slice):
Armin Ronacher8efc5222008-04-08 14:47:40 +02001504 self.visit(node.node, frame)
1505 self.write('[')
1506 self.visit(node.arg, frame)
1507 self.write(']')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001508 else:
Armin Ronacher6dc6f292008-06-12 08:50:07 +02001509 self.write('environment.getitem(')
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001510 self.visit(node.node, frame)
1511 self.write(', ')
1512 self.visit(node.arg, frame)
1513 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001514
1515 def visit_Slice(self, node, frame):
1516 if node.start is not None:
1517 self.visit(node.start, frame)
1518 self.write(':')
1519 if node.stop is not None:
1520 self.visit(node.stop, frame)
1521 if node.step is not None:
1522 self.write(':')
1523 self.visit(node.step, frame)
1524
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001525 def visit_Filter(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001526 self.write(self.filters[node.name] + '(')
Christoph Hack80909862008-04-14 01:35:10 +02001527 func = self.environment.filters.get(node.name)
Armin Ronacher0611e492008-04-25 23:44:14 +02001528 if func is None:
Armin Ronachere2244882008-05-19 09:25:57 +02001529 self.fail('no filter named %r' % node.name, node.lineno)
Christoph Hack80909862008-04-14 01:35:10 +02001530 if getattr(func, 'contextfilter', False):
1531 self.write('context, ')
Armin Ronacher8346bd72010-03-14 19:43:47 +01001532 elif getattr(func, 'evalcontextfilter', False):
1533 self.write('context.eval_ctx, ')
Armin Ronacher9a027f42008-04-17 11:13:40 +02001534 elif getattr(func, 'environmentfilter', False):
1535 self.write('environment, ')
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001536
1537 # if the filter node is None we are inside a filter block
1538 # and want to write to the current buffer
Armin Ronacher3da90312008-05-23 16:37:28 +02001539 if node.node is not None:
Armin Ronacherfa865fb2008-04-12 22:11:53 +02001540 self.visit(node.node, frame)
Armin Ronacher8346bd72010-03-14 19:43:47 +01001541 elif frame.eval_ctx.volatile:
1542 self.write('(context.eval_ctx.autoescape and'
1543 ' Markup(concat(%s)) or concat(%s))' %
1544 (frame.buffer, frame.buffer))
1545 elif frame.eval_ctx.autoescape:
Armin Ronacher3da90312008-05-23 16:37:28 +02001546 self.write('Markup(concat(%s))' % frame.buffer)
1547 else:
1548 self.write('concat(%s)' % frame.buffer)
Armin Ronacherd55ab532008-04-09 16:13:39 +02001549 self.signature(node, frame)
1550 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001551
1552 def visit_Test(self, node, frame):
Armin Ronacherb9e78752008-05-10 23:36:28 +02001553 self.write(self.tests[node.name] + '(')
Armin Ronacher0611e492008-04-25 23:44:14 +02001554 if node.name not in self.environment.tests:
Armin Ronachere2244882008-05-19 09:25:57 +02001555 self.fail('no test named %r' % node.name, node.lineno)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001556 self.visit(node.node, frame)
1557 self.signature(node, frame)
Armin Ronachere791c2a2008-04-07 18:39:54 +02001558 self.write(')')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001559
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001560 def visit_CondExpr(self, node, frame):
Armin Ronacher547d0b62008-07-04 16:35:10 +02001561 def write_expr2():
1562 if node.expr2 is not None:
1563 return self.visit(node.expr2, frame)
1564 self.write('environment.undefined(%r)' % ('the inline if-'
1565 'expression on %s evaluated to false and '
1566 'no else section was defined.' % self.position(node)))
1567
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001568 if not have_condexpr:
1569 self.write('((')
1570 self.visit(node.test, frame)
1571 self.write(') and (')
1572 self.visit(node.expr1, frame)
1573 self.write(',) or (')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001574 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001575 self.write(',))[0]')
1576 else:
1577 self.write('(')
1578 self.visit(node.expr1, frame)
1579 self.write(' if ')
1580 self.visit(node.test, frame)
1581 self.write(' else ')
Armin Ronacher547d0b62008-07-04 16:35:10 +02001582 write_expr2()
Armin Ronacher3d8b7842008-04-13 13:16:50 +02001583 self.write(')')
1584
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001585 def visit_Call(self, node, frame, forward_caller=False):
Armin Ronacherc63243e2008-04-14 22:53:58 +02001586 if self.environment.sandboxed:
Armin Ronacherfd310492008-05-25 00:16:51 +02001587 self.write('environment.call(context, ')
1588 else:
1589 self.write('context.call(')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001590 self.visit(node.node, frame)
Armin Ronacher105f0dc2008-05-23 16:12:47 +02001591 extra_kwargs = forward_caller and {'caller': 'caller'} or None
Armin Ronacherfd310492008-05-25 00:16:51 +02001592 self.signature(node, frame, extra_kwargs)
Armin Ronacher8efc5222008-04-08 14:47:40 +02001593 self.write(')')
1594
1595 def visit_Keyword(self, node, frame):
Armin Ronacher2e9396b2008-04-16 14:21:57 +02001596 self.write(node.key + '=')
Armin Ronacher8efc5222008-04-08 14:47:40 +02001597 self.visit(node.value, frame)
Armin Ronachered1e0d42008-05-18 20:25:28 +02001598
Armin Ronachera2eb77d2008-05-22 20:28:21 +02001599 # -- Unused nodes for extensions
Armin Ronachered1e0d42008-05-18 20:25:28 +02001600
1601 def visit_MarkSafe(self, node, frame):
1602 self.write('Markup(')
1603 self.visit(node.expr, frame)
1604 self.write(')')
1605
Armin Ronacher4da90342010-05-29 17:35:10 +02001606 def visit_MarkSafeIfAutoescape(self, node, frame):
1607 self.write('(context.eval_ctx.autoescape and Markup or identity)(')
1608 self.visit(node.expr, frame)
1609 self.write(')')
1610
Armin Ronachered1e0d42008-05-18 20:25:28 +02001611 def visit_EnvironmentAttribute(self, node, frame):
1612 self.write('environment.' + node.name)
1613
1614 def visit_ExtensionAttribute(self, node, frame):
Armin Ronacher6df604e2008-05-23 22:18:38 +02001615 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
Armin Ronachered1e0d42008-05-18 20:25:28 +02001616
1617 def visit_ImportedName(self, node, frame):
1618 self.write(self.import_aliases[node.importname])
1619
1620 def visit_InternalName(self, node, frame):
1621 self.write(node.name)
1622
Armin Ronacher6df604e2008-05-23 22:18:38 +02001623 def visit_ContextReference(self, node, frame):
1624 self.write('context')
1625
Armin Ronachered1e0d42008-05-18 20:25:28 +02001626 def visit_Continue(self, node, frame):
1627 self.writeline('continue', node)
1628
1629 def visit_Break(self, node, frame):
1630 self.writeline('break', node)
Armin Ronacher271a0eb2009-02-11 22:49:08 +01001631
1632 def visit_Scope(self, node, frame):
1633 scope_frame = frame.inner()
1634 scope_frame.inspect(node.iter_child_nodes())
1635 aliases = self.push_scope(scope_frame)
1636 self.pull_locals(scope_frame)
1637 self.blockvisit(node.body, scope_frame)
1638 self.pop_scope(aliases, scope_frame)
Armin Ronacher8346bd72010-03-14 19:43:47 +01001639
1640 def visit_EvalContextModifier(self, node, frame):
1641 for keyword in node.options:
1642 self.writeline('context.eval_ctx.%s = ' % keyword.key)
1643 self.visit(keyword.value, frame)
1644 try:
1645 val = keyword.value.as_const(frame.eval_ctx)
1646 except nodes.Impossible:
Armin Ronacher744bb0a2010-03-15 00:26:05 +01001647 frame.eval_ctx.volatile = True
Armin Ronacher8346bd72010-03-14 19:43:47 +01001648 else:
1649 setattr(frame.eval_ctx, keyword.key, val)
1650
1651 def visit_ScopedEvalContextModifier(self, node, frame):
1652 old_ctx_name = self.temporary_identifier()
1653 safed_ctx = frame.eval_ctx.save()
1654 self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
1655 self.visit_EvalContextModifier(node, frame)
1656 for child in node.body:
1657 self.visit(child, frame)
1658 frame.eval_ctx.revert(safed_ctx)
1659 self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)