added a :class:`ModuleLoader` that can load templates from
[jinja2.git] / jinja2 / compiler.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.compiler
4     ~~~~~~~~~~~~~~~
5
6     Compiles nodes into python code.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD, see LICENSE for more details.
10 """
11 from cStringIO import StringIO
12 from itertools import chain
13 from copy import deepcopy
14 from jinja2 import nodes
15 from jinja2.visitor import NodeVisitor, NodeTransformer
16 from jinja2.exceptions import TemplateAssertionError
17 from jinja2.utils import Markup, concat, escape, is_python_keyword, next
18
19
20 operators = {
21     'eq':       '==',
22     'ne':       '!=',
23     'gt':       '>',
24     'gteq':     '>=',
25     'lt':       '<',
26     'lteq':     '<=',
27     'in':       'in',
28     'notin':    'not in'
29 }
30
31 try:
32     exec '(0 if 0 else 0)'
33 except SyntaxError:
34     have_condexpr = False
35 else:
36     have_condexpr = True
37
38
39 # what method to iterate over items do we want to use for dict iteration
40 # in generated code?  on 2.x let's go with iteritems, on 3.x with items
41 if hasattr(dict, 'iteritems'):
42     dict_item_iter = 'iteritems'
43 else:
44     dict_item_iter = 'items'
45
46
47 # does if 0: dummy(x) get us x into the scope?
48 def unoptimize_before_dead_code():
49     x = 42
50     def f():
51         if 0: dummy(x)
52     return f
53 unoptimize_before_dead_code = bool(unoptimize_before_dead_code().func_closure)
54
55
56 def generate(node, environment, name, filename, stream=None,
57              defer_init=False):
58     """Generate the python source for a node tree."""
59     if not isinstance(node, nodes.Template):
60         raise TypeError('Can\'t compile non template nodes')
61     generator = CodeGenerator(environment, name, filename, stream, defer_init)
62     generator.visit(node)
63     if stream is None:
64         return generator.stream.getvalue()
65
66
67 def has_safe_repr(value):
68     """Does the node have a safe representation?"""
69     if value is None or value is NotImplemented or value is Ellipsis:
70         return True
71     if isinstance(value, (bool, int, long, float, complex, basestring,
72                           xrange, Markup)):
73         return True
74     if isinstance(value, (tuple, list, set, frozenset)):
75         for item in value:
76             if not has_safe_repr(item):
77                 return False
78         return True
79     elif isinstance(value, dict):
80         for key, value in value.iteritems():
81             if not has_safe_repr(key):
82                 return False
83             if not has_safe_repr(value):
84                 return False
85         return True
86     return False
87
88
89 def find_undeclared(nodes, names):
90     """Check if the names passed are accessed undeclared.  The return value
91     is a set of all the undeclared names from the sequence of names found.
92     """
93     visitor = UndeclaredNameVisitor(names)
94     try:
95         for node in nodes:
96             visitor.visit(node)
97     except VisitorExit:
98         pass
99     return visitor.undeclared
100
101
102 class Identifiers(object):
103     """Tracks the status of identifiers in frames."""
104
105     def __init__(self):
106         # variables that are known to be declared (probably from outer
107         # frames or because they are special for the frame)
108         self.declared = set()
109
110         # undeclared variables from outer scopes
111         self.outer_undeclared = set()
112
113         # names that are accessed without being explicitly declared by
114         # this one or any of the outer scopes.  Names can appear both in
115         # declared and undeclared.
116         self.undeclared = set()
117
118         # names that are declared locally
119         self.declared_locally = set()
120
121         # names that are declared by parameters
122         self.declared_parameter = set()
123
124     def add_special(self, name):
125         """Register a special name like `loop`."""
126         self.undeclared.discard(name)
127         self.declared.add(name)
128
129     def is_declared(self, name, local_only=False):
130         """Check if a name is declared in this or an outer scope."""
131         if name in self.declared_locally or name in self.declared_parameter:
132             return True
133         if local_only:
134             return False
135         return name in self.declared
136
137     def copy(self):
138         return deepcopy(self)
139
140
141 class Frame(object):
142     """Holds compile time information for us."""
143
144     def __init__(self, parent=None):
145         self.identifiers = Identifiers()
146
147         # a toplevel frame is the root + soft frames such as if conditions.
148         self.toplevel = False
149
150         # the root frame is basically just the outermost frame, so no if
151         # conditions.  This information is used to optimize inheritance
152         # situations.
153         self.rootlevel = False
154
155         # in some dynamic inheritance situations the compiler needs to add
156         # write tests around output statements.
157         self.require_output_check = parent and parent.require_output_check
158
159         # inside some tags we are using a buffer rather than yield statements.
160         # this for example affects {% filter %} or {% macro %}.  If a frame
161         # is buffered this variable points to the name of the list used as
162         # buffer.
163         self.buffer = None
164
165         # the name of the block we're in, otherwise None.
166         self.block = parent and parent.block or None
167
168         # a set of actually assigned names
169         self.assigned_names = set()
170
171         # the parent of this frame
172         self.parent = parent
173
174         if parent is not None:
175             self.identifiers.declared.update(
176                 parent.identifiers.declared |
177                 parent.identifiers.declared_parameter |
178                 parent.assigned_names
179             )
180             self.identifiers.outer_undeclared.update(
181                 parent.identifiers.undeclared -
182                 self.identifiers.declared
183             )
184             self.buffer = parent.buffer
185
186     def copy(self):
187         """Create a copy of the current one."""
188         rv = object.__new__(self.__class__)
189         rv.__dict__.update(self.__dict__)
190         rv.identifiers = object.__new__(self.identifiers.__class__)
191         rv.identifiers.__dict__.update(self.identifiers.__dict__)
192         return rv
193
194     def inspect(self, nodes, hard_scope=False):
195         """Walk the node and check for identifiers.  If the scope is hard (eg:
196         enforce on a python level) overrides from outer scopes are tracked
197         differently.
198         """
199         visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
200         for node in nodes:
201             visitor.visit(node)
202
203     def find_shadowed(self, extra=()):
204         """Find all the shadowed names.  extra is an iterable of variables
205         that may be defined with `add_special` which may occour scoped.
206         """
207         i = self.identifiers
208         return (i.declared | i.outer_undeclared) & \
209                (i.declared_locally | i.declared_parameter) | \
210                set(x for x in extra if i.is_declared(x))
211
212     def inner(self):
213         """Return an inner frame."""
214         return Frame(self)
215
216     def soft(self):
217         """Return a soft frame.  A soft frame may not be modified as
218         standalone thing as it shares the resources with the frame it
219         was created of, but it's not a rootlevel frame any longer.
220         """
221         rv = self.copy()
222         rv.rootlevel = False
223         return rv
224
225     __copy__ = copy
226
227
228 class VisitorExit(RuntimeError):
229     """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
230
231
232 class DependencyFinderVisitor(NodeVisitor):
233     """A visitor that collects filter and test calls."""
234
235     def __init__(self):
236         self.filters = set()
237         self.tests = set()
238
239     def visit_Filter(self, node):
240         self.generic_visit(node)
241         self.filters.add(node.name)
242
243     def visit_Test(self, node):
244         self.generic_visit(node)
245         self.tests.add(node.name)
246
247     def visit_Block(self, node):
248         """Stop visiting at blocks."""
249
250
251 class UndeclaredNameVisitor(NodeVisitor):
252     """A visitor that checks if a name is accessed without being
253     declared.  This is different from the frame visitor as it will
254     not stop at closure frames.
255     """
256
257     def __init__(self, names):
258         self.names = set(names)
259         self.undeclared = set()
260
261     def visit_Name(self, node):
262         if node.ctx == 'load' and node.name in self.names:
263             self.undeclared.add(node.name)
264             if self.undeclared == self.names:
265                 raise VisitorExit()
266         else:
267             self.names.discard(node.name)
268
269     def visit_Block(self, node):
270         """Stop visiting a blocks."""
271
272
273 class FrameIdentifierVisitor(NodeVisitor):
274     """A visitor for `Frame.inspect`."""
275
276     def __init__(self, identifiers, hard_scope):
277         self.identifiers = identifiers
278         self.hard_scope = hard_scope
279
280     def visit_Name(self, node):
281         """All assignments to names go through this function."""
282         if node.ctx == 'store':
283             self.identifiers.declared_locally.add(node.name)
284         elif node.ctx == 'param':
285             self.identifiers.declared_parameter.add(node.name)
286         elif node.ctx == 'load' and not \
287              self.identifiers.is_declared(node.name, self.hard_scope):
288             self.identifiers.undeclared.add(node.name)
289
290     def visit_If(self, node):
291         self.visit(node.test)
292         real_identifiers = self.identifiers
293
294         old_names = real_identifiers.declared | \
295                     real_identifiers.declared_locally | \
296                     real_identifiers.declared_parameter
297
298         def inner_visit(nodes):
299             if not nodes:
300                 return set()
301             self.identifiers = real_identifiers.copy()
302             for subnode in nodes:
303                 self.visit(subnode)
304             rv = self.identifiers.declared_locally - old_names
305             # we have to remember the undeclared variables of this branch
306             # because we will have to pull them.
307             real_identifiers.undeclared.update(self.identifiers.undeclared)
308             self.identifiers = real_identifiers
309             return rv
310
311         body = inner_visit(node.body)
312         else_ = inner_visit(node.else_ or ())
313
314         # the differences between the two branches are also pulled as
315         # undeclared variables
316         real_identifiers.undeclared.update(body.symmetric_difference(else_))
317
318         # remember those that are declared.
319         real_identifiers.declared_locally.update(body | else_)
320
321     def visit_Macro(self, node):
322         self.identifiers.declared_locally.add(node.name)
323
324     def visit_Import(self, node):
325         self.generic_visit(node)
326         self.identifiers.declared_locally.add(node.target)
327
328     def visit_FromImport(self, node):
329         self.generic_visit(node)
330         for name in node.names:
331             if isinstance(name, tuple):
332                 self.identifiers.declared_locally.add(name[1])
333             else:
334                 self.identifiers.declared_locally.add(name)
335
336     def visit_Assign(self, node):
337         """Visit assignments in the correct order."""
338         self.visit(node.node)
339         self.visit(node.target)
340
341     def visit_For(self, node):
342         """Visiting stops at for blocks.  However the block sequence
343         is visited as part of the outer scope.
344         """
345         self.visit(node.iter)
346
347     def visit_CallBlock(self, node):
348         self.visit(node.call)
349
350     def visit_FilterBlock(self, node):
351         self.visit(node.filter)
352
353     def visit_Scope(self, node):
354         """Stop visiting at scopes."""
355
356     def visit_Block(self, node):
357         """Stop visiting at blocks."""
358
359
360 class CompilerExit(Exception):
361     """Raised if the compiler encountered a situation where it just
362     doesn't make sense to further process the code.  Any block that
363     raises such an exception is not further processed.
364     """
365
366
367 class CodeGenerator(NodeVisitor):
368
369     def __init__(self, environment, name, filename, stream=None,
370                  defer_init=False):
371         if stream is None:
372             stream = StringIO()
373         self.environment = environment
374         self.name = name
375         self.filename = filename
376         self.stream = stream
377         self.created_block_context = False
378         self.defer_init = defer_init
379
380         # aliases for imports
381         self.import_aliases = {}
382
383         # a registry for all blocks.  Because blocks are moved out
384         # into the global python scope they are registered here
385         self.blocks = {}
386
387         # the number of extends statements so far
388         self.extends_so_far = 0
389
390         # some templates have a rootlevel extends.  In this case we
391         # can safely assume that we're a child template and do some
392         # more optimizations.
393         self.has_known_extends = False
394
395         # the current line number
396         self.code_lineno = 1
397
398         # registry of all filters and tests (global, not block local)
399         self.tests = {}
400         self.filters = {}
401
402         # the debug information
403         self.debug_info = []
404         self._write_debug_info = None
405
406         # the number of new lines before the next write()
407         self._new_lines = 0
408
409         # the line number of the last written statement
410         self._last_line = 0
411
412         # true if nothing was written so far.
413         self._first_write = True
414
415         # used by the `temporary_identifier` method to get new
416         # unique, temporary identifier
417         self._last_identifier = 0
418
419         # the current indentation
420         self._indentation = 0
421
422     # -- Various compilation helpers
423
424     def fail(self, msg, lineno):
425         """Fail with a `TemplateAssertionError`."""
426         raise TemplateAssertionError(msg, lineno, self.name, self.filename)
427
428     def temporary_identifier(self):
429         """Get a new unique identifier."""
430         self._last_identifier += 1
431         return 't_%d' % self._last_identifier
432
433     def buffer(self, frame):
434         """Enable buffering for the frame from that point onwards."""
435         frame.buffer = self.temporary_identifier()
436         self.writeline('%s = []' % frame.buffer)
437
438     def return_buffer_contents(self, frame):
439         """Return the buffer contents of the frame."""
440         if self.environment.autoescape:
441             self.writeline('return Markup(concat(%s))' % frame.buffer)
442         else:
443             self.writeline('return concat(%s)' % frame.buffer)
444
445     def indent(self):
446         """Indent by one."""
447         self._indentation += 1
448
449     def outdent(self, step=1):
450         """Outdent by step."""
451         self._indentation -= step
452
453     def start_write(self, frame, node=None):
454         """Yield or write into the frame buffer."""
455         if frame.buffer is None:
456             self.writeline('yield ', node)
457         else:
458             self.writeline('%s.append(' % frame.buffer, node)
459
460     def end_write(self, frame):
461         """End the writing process started by `start_write`."""
462         if frame.buffer is not None:
463             self.write(')')
464
465     def simple_write(self, s, frame, node=None):
466         """Simple shortcut for start_write + write + end_write."""
467         self.start_write(frame, node)
468         self.write(s)
469         self.end_write(frame)
470
471     def blockvisit(self, nodes, frame):
472         """Visit a list of nodes as block in a frame.  If the current frame
473         is no buffer a dummy ``if 0: yield None`` is written automatically
474         unless the force_generator parameter is set to False.
475         """
476         if frame.buffer is None:
477             self.writeline('if 0: yield None')
478         else:
479             self.writeline('pass')
480         try:
481             for node in nodes:
482                 self.visit(node, frame)
483         except CompilerExit:
484             pass
485
486     def write(self, x):
487         """Write a string into the output stream."""
488         if self._new_lines:
489             if not self._first_write:
490                 self.stream.write('\n' * self._new_lines)
491                 self.code_lineno += self._new_lines
492                 if self._write_debug_info is not None:
493                     self.debug_info.append((self._write_debug_info,
494                                             self.code_lineno))
495                     self._write_debug_info = None
496             self._first_write = False
497             self.stream.write('    ' * self._indentation)
498             self._new_lines = 0
499         self.stream.write(x)
500
501     def writeline(self, x, node=None, extra=0):
502         """Combination of newline and write."""
503         self.newline(node, extra)
504         self.write(x)
505
506     def newline(self, node=None, extra=0):
507         """Add one or more newlines before the next write."""
508         self._new_lines = max(self._new_lines, 1 + extra)
509         if node is not None and node.lineno != self._last_line:
510             self._write_debug_info = node.lineno
511             self._last_line = node.lineno
512
513     def signature(self, node, frame, extra_kwargs=None):
514         """Writes a function call to the stream for the current node.
515         A leading comma is added automatically.  The extra keyword
516         arguments may not include python keywords otherwise a syntax
517         error could occour.  The extra keyword arguments should be given
518         as python dict.
519         """
520         # if any of the given keyword arguments is a python keyword
521         # we have to make sure that no invalid call is created.
522         kwarg_workaround = False
523         for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
524             if is_python_keyword(kwarg):
525                 kwarg_workaround = True
526                 break
527
528         for arg in node.args:
529             self.write(', ')
530             self.visit(arg, frame)
531
532         if not kwarg_workaround:
533             for kwarg in node.kwargs:
534                 self.write(', ')
535                 self.visit(kwarg, frame)
536             if extra_kwargs is not None:
537                 for key, value in extra_kwargs.iteritems():
538                     self.write(', %s=%s' % (key, value))
539         if node.dyn_args:
540             self.write(', *')
541             self.visit(node.dyn_args, frame)
542
543         if kwarg_workaround:
544             if node.dyn_kwargs is not None:
545                 self.write(', **dict({')
546             else:
547                 self.write(', **{')
548             for kwarg in node.kwargs:
549                 self.write('%r: ' % kwarg.key)
550                 self.visit(kwarg.value, frame)
551                 self.write(', ')
552             if extra_kwargs is not None:
553                 for key, value in extra_kwargs.iteritems():
554                     self.write('%r: %s, ' % (key, value))
555             if node.dyn_kwargs is not None:
556                 self.write('}, **')
557                 self.visit(node.dyn_kwargs, frame)
558                 self.write(')')
559             else:
560                 self.write('}')
561
562         elif node.dyn_kwargs is not None:
563             self.write(', **')
564             self.visit(node.dyn_kwargs, frame)
565
566     def pull_locals(self, frame):
567         """Pull all the references identifiers into the local scope."""
568         for name in frame.identifiers.undeclared:
569             self.writeline('l_%s = context.resolve(%r)' % (name, name))
570
571     def pull_dependencies(self, nodes):
572         """Pull all the dependencies."""
573         visitor = DependencyFinderVisitor()
574         for node in nodes:
575             visitor.visit(node)
576         for dependency in 'filters', 'tests':
577             mapping = getattr(self, dependency)
578             for name in getattr(visitor, dependency):
579                 if name not in mapping:
580                     mapping[name] = self.temporary_identifier()
581                 self.writeline('%s = environment.%s[%r]' %
582                                (mapping[name], dependency, name))
583
584     def unoptimize_scope(self, frame):
585         """Disable Python optimizations for the frame."""
586         # XXX: this is not that nice but it has no real overhead.  It
587         # mainly works because python finds the locals before dead code
588         # is removed.  If that breaks we have to add a dummy function
589         # that just accepts the arguments and does nothing.
590         if frame.identifiers.declared:
591             self.writeline('%sdummy(%s)' % (
592                 unoptimize_before_dead_code and 'if 0: ' or '',
593                 ', '.join('l_' + name for name in frame.identifiers.declared)
594             ))
595
596     def push_scope(self, frame, extra_vars=()):
597         """This function returns all the shadowed variables in a dict
598         in the form name: alias and will write the required assignments
599         into the current scope.  No indentation takes place.
600
601         This also predefines locally declared variables from the loop
602         body because under some circumstances it may be the case that
603
604         `extra_vars` is passed to `Frame.find_shadowed`.
605         """
606         aliases = {}
607         for name in frame.find_shadowed(extra_vars):
608             aliases[name] = ident = self.temporary_identifier()
609             self.writeline('%s = l_%s' % (ident, name))
610         to_declare = set()
611         for name in frame.identifiers.declared_locally:
612             if name not in aliases:
613                 to_declare.add('l_' + name)
614         if to_declare:
615             self.writeline(' = '.join(to_declare) + ' = missing')
616         return aliases
617
618     def pop_scope(self, aliases, frame):
619         """Restore all aliases and delete unused variables."""
620         for name, alias in aliases.iteritems():
621             self.writeline('l_%s = %s' % (name, alias))
622         to_delete = set()
623         for name in frame.identifiers.declared_locally:
624             if name not in aliases:
625                 to_delete.add('l_' + name)
626         if to_delete:
627             # we cannot use the del statement here because enclosed
628             # scopes can trigger a SyntaxError:
629             #   a = 42; b = lambda: a; del a
630             self.writeline(' = '.join(to_delete) + ' = missing')
631
632     def function_scoping(self, node, frame, children=None,
633                          find_special=True):
634         """In Jinja a few statements require the help of anonymous
635         functions.  Those are currently macros and call blocks and in
636         the future also recursive loops.  As there is currently
637         technical limitation that doesn't allow reading and writing a
638         variable in a scope where the initial value is coming from an
639         outer scope, this function tries to fall back with a common
640         error message.  Additionally the frame passed is modified so
641         that the argumetns are collected and callers are looked up.
642
643         This will return the modified frame.
644         """
645         # we have to iterate twice over it, make sure that works
646         if children is None:
647             children = node.iter_child_nodes()
648         children = list(children)
649         func_frame = frame.inner()
650         func_frame.inspect(children, hard_scope=True)
651
652         # variables that are undeclared (accessed before declaration) and
653         # declared locally *and* part of an outside scope raise a template
654         # assertion error. Reason: we can't generate reasonable code from
655         # it without aliasing all the variables.
656         # this could be fixed in Python 3 where we have the nonlocal
657         # keyword or if we switch to bytecode generation
658         overriden_closure_vars = (
659             func_frame.identifiers.undeclared &
660             func_frame.identifiers.declared &
661             (func_frame.identifiers.declared_locally |
662              func_frame.identifiers.declared_parameter)
663         )
664         if overriden_closure_vars:
665             self.fail('It\'s not possible to set and access variables '
666                       'derived from an outer scope! (affects: %s)' %
667                       ', '.join(sorted(overriden_closure_vars)), node.lineno)
668
669         # remove variables from a closure from the frame's undeclared
670         # identifiers.
671         func_frame.identifiers.undeclared -= (
672             func_frame.identifiers.undeclared &
673             func_frame.identifiers.declared
674         )
675
676         # no special variables for this scope, abort early
677         if not find_special:
678             return func_frame
679
680         func_frame.accesses_kwargs = False
681         func_frame.accesses_varargs = False
682         func_frame.accesses_caller = False
683         func_frame.arguments = args = ['l_' + x.name for x in node.args]
684
685         undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
686
687         if 'caller' in undeclared:
688             func_frame.accesses_caller = True
689             func_frame.identifiers.add_special('caller')
690             args.append('l_caller')
691         if 'kwargs' in undeclared:
692             func_frame.accesses_kwargs = True
693             func_frame.identifiers.add_special('kwargs')
694             args.append('l_kwargs')
695         if 'varargs' in undeclared:
696             func_frame.accesses_varargs = True
697             func_frame.identifiers.add_special('varargs')
698             args.append('l_varargs')
699         return func_frame
700
701     def macro_body(self, node, frame, children=None):
702         """Dump the function def of a macro or call block."""
703         frame = self.function_scoping(node, frame, children)
704         # macros are delayed, they never require output checks
705         frame.require_output_check = False
706         args = frame.arguments
707         # XXX: this is an ugly fix for the loop nesting bug
708         # (tests.test_old_bugs.test_loop_call_bug).  This works around
709         # a identifier nesting problem we have in general.  It's just more
710         # likely to happen in loops which is why we work around it.  The
711         # real solution would be "nonlocal" all the identifiers that are
712         # leaking into a new python frame and might be used both unassigned
713         # and assigned.
714         if 'loop' in frame.identifiers.declared:
715             args = args + ['l_loop=l_loop']
716         self.writeline('def macro(%s):' % ', '.join(args), node)
717         self.indent()
718         self.buffer(frame)
719         self.pull_locals(frame)
720         self.blockvisit(node.body, frame)
721         self.return_buffer_contents(frame)
722         self.outdent()
723         return frame
724
725     def macro_def(self, node, frame):
726         """Dump the macro definition for the def created by macro_body."""
727         arg_tuple = ', '.join(repr(x.name) for x in node.args)
728         name = getattr(node, 'name', None)
729         if len(node.args) == 1:
730             arg_tuple += ','
731         self.write('Macro(environment, macro, %r, (%s), (' %
732                    (name, arg_tuple))
733         for arg in node.defaults:
734             self.visit(arg, frame)
735             self.write(', ')
736         self.write('), %r, %r, %r)' % (
737             bool(frame.accesses_kwargs),
738             bool(frame.accesses_varargs),
739             bool(frame.accesses_caller)
740         ))
741
742     def position(self, node):
743         """Return a human readable position for the node."""
744         rv = 'line %d' % node.lineno
745         if self.name is not None:
746             rv += ' in ' + repr(self.name)
747         return rv
748
749     # -- Statement Visitors
750
751     def visit_Template(self, node, frame=None):
752         assert frame is None, 'no root frame allowed'
753         from jinja2.runtime import __all__ as exported
754         self.writeline('from __future__ import division')
755         self.writeline('from jinja2.runtime import ' + ', '.join(exported))
756         if not unoptimize_before_dead_code:
757             self.writeline('dummy = lambda *x: None')
758
759         # if we want a deferred initialization we cannot move the
760         # environment into a local name
761         envenv = not self.defer_init and ', environment=environment' or ''
762
763         # do we have an extends tag at all?  If not, we can save some
764         # overhead by just not processing any inheritance code.
765         have_extends = node.find(nodes.Extends) is not None
766
767         # find all blocks
768         for block in node.find_all(nodes.Block):
769             if block.name in self.blocks:
770                 self.fail('block %r defined twice' % block.name, block.lineno)
771             self.blocks[block.name] = block
772
773         # find all imports and import them
774         for import_ in node.find_all(nodes.ImportedName):
775             if import_.importname not in self.import_aliases:
776                 imp = import_.importname
777                 self.import_aliases[imp] = alias = self.temporary_identifier()
778                 if '.' in imp:
779                     module, obj = imp.rsplit('.', 1)
780                     self.writeline('from %s import %s as %s' %
781                                    (module, obj, alias))
782                 else:
783                     self.writeline('import %s as %s' % (imp, alias))
784
785         # add the load name
786         self.writeline('name = %r' % self.name)
787
788         # generate the root render function.
789         self.writeline('def root(context%s):' % envenv, extra=1)
790
791         # process the root
792         frame = Frame()
793         frame.inspect(node.body)
794         frame.toplevel = frame.rootlevel = True
795         frame.require_output_check = have_extends and not self.has_known_extends
796         self.indent()
797         if have_extends:
798             self.writeline('parent_template = None')
799         if 'self' in find_undeclared(node.body, ('self',)):
800             frame.identifiers.add_special('self')
801             self.writeline('l_self = TemplateReference(context)')
802         self.pull_locals(frame)
803         self.pull_dependencies(node.body)
804         self.blockvisit(node.body, frame)
805         self.outdent()
806
807         # make sure that the parent root is called.
808         if have_extends:
809             if not self.has_known_extends:
810                 self.indent()
811                 self.writeline('if parent_template is not None:')
812             self.indent()
813             self.writeline('for event in parent_template.'
814                            'root_render_func(context):')
815             self.indent()
816             self.writeline('yield event')
817             self.outdent(2 + (not self.has_known_extends))
818
819         # at this point we now have the blocks collected and can visit them too.
820         for name, block in self.blocks.iteritems():
821             block_frame = Frame()
822             block_frame.inspect(block.body)
823             block_frame.block = name
824             self.writeline('def block_%s(context%s):' % (name, envenv),
825                            block, 1)
826             self.indent()
827             undeclared = find_undeclared(block.body, ('self', 'super'))
828             if 'self' in undeclared:
829                 block_frame.identifiers.add_special('self')
830                 self.writeline('l_self = TemplateReference(context)')
831             if 'super' in undeclared:
832                 block_frame.identifiers.add_special('super')
833                 self.writeline('l_super = context.super(%r, '
834                                'block_%s)' % (name, name))
835             self.pull_locals(block_frame)
836             self.pull_dependencies(block.body)
837             self.blockvisit(block.body, block_frame)
838             self.outdent()
839
840         self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
841                                                    for x in self.blocks),
842                        extra=1)
843
844         # add a function that returns the debug info
845         self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
846                                                     in self.debug_info))
847
848     def visit_Block(self, node, frame):
849         """Call a block and register it for the template."""
850         level = 1
851         if frame.toplevel:
852             # if we know that we are a child template, there is no need to
853             # check if we are one
854             if self.has_known_extends:
855                 return
856             if self.extends_so_far > 0:
857                 self.writeline('if parent_template is None:')
858                 self.indent()
859                 level += 1
860         context = node.scoped and 'context.derived(locals())' or 'context'
861         self.writeline('for event in context.blocks[%r][0](%s):' % (
862                        node.name, context), node)
863         self.indent()
864         self.simple_write('event', frame)
865         self.outdent(level)
866
867     def visit_Extends(self, node, frame):
868         """Calls the extender."""
869         if not frame.toplevel:
870             self.fail('cannot use extend from a non top-level scope',
871                       node.lineno)
872
873         # if the number of extends statements in general is zero so
874         # far, we don't have to add a check if something extended
875         # the template before this one.
876         if self.extends_so_far > 0:
877
878             # if we have a known extends we just add a template runtime
879             # error into the generated code.  We could catch that at compile
880             # time too, but i welcome it not to confuse users by throwing the
881             # same error at different times just "because we can".
882             if not self.has_known_extends:
883                 self.writeline('if parent_template is not None:')
884                 self.indent()
885             self.writeline('raise TemplateRuntimeError(%r)' %
886                            'extended multiple times')
887             self.outdent()
888
889             # if we have a known extends already we don't need that code here
890             # as we know that the template execution will end here.
891             if self.has_known_extends:
892                 raise CompilerExit()
893
894         self.writeline('parent_template = environment.get_template(', node)
895         self.visit(node.template, frame)
896         self.write(', %r)' % self.name)
897         self.writeline('for name, parent_block in parent_template.'
898                        'blocks.%s():' % dict_item_iter)
899         self.indent()
900         self.writeline('context.blocks.setdefault(name, []).'
901                        'append(parent_block)')
902         self.outdent()
903
904         # if this extends statement was in the root level we can take
905         # advantage of that information and simplify the generated code
906         # in the top level from this point onwards
907         if frame.rootlevel:
908             self.has_known_extends = True
909
910         # and now we have one more
911         self.extends_so_far += 1
912
913     def visit_Include(self, node, frame):
914         """Handles includes."""
915         if node.with_context:
916             self.unoptimize_scope(frame)
917         if node.ignore_missing:
918             self.writeline('try:')
919             self.indent()
920
921         func_name = 'get_or_select_template'
922         if isinstance(node.template, nodes.Const):
923             if isinstance(node.template.value, basestring):
924                 func_name = 'get_template'
925             elif isinstance(node.template.value, (tuple, list)):
926                 func_name = 'select_template'
927         elif isinstance(node.template, (nodes.Tuple, nodes.List)):
928             func_name = 'select_template'
929
930         self.writeline('template = environment.%s(' % func_name, node)
931         self.visit(node.template, frame)
932         self.write(', %r)' % self.name)
933         if node.ignore_missing:
934             self.outdent()
935             self.writeline('except TemplateNotFound:')
936             self.indent()
937             self.writeline('pass')
938             self.outdent()
939             self.writeline('else:')
940             self.indent()
941
942         if node.with_context:
943             self.writeline('for event in template.root_render_func('
944                            'template.new_context(context.parent, True, '
945                            'locals())):')
946         else:
947             self.writeline('for event in template.module._body_stream:')
948
949         self.indent()
950         self.simple_write('event', frame)
951         self.outdent()
952
953         if node.ignore_missing:
954             self.outdent()
955
956     def visit_Import(self, node, frame):
957         """Visit regular imports."""
958         if node.with_context:
959             self.unoptimize_scope(frame)
960         self.writeline('l_%s = ' % node.target, node)
961         if frame.toplevel:
962             self.write('context.vars[%r] = ' % node.target)
963         self.write('environment.get_template(')
964         self.visit(node.template, frame)
965         self.write(', %r).' % self.name)
966         if node.with_context:
967             self.write('make_module(context.parent, True, locals())')
968         else:
969             self.write('module')
970         if frame.toplevel and not node.target.startswith('_'):
971             self.writeline('context.exported_vars.discard(%r)' % node.target)
972         frame.assigned_names.add(node.target)
973
974     def visit_FromImport(self, node, frame):
975         """Visit named imports."""
976         self.newline(node)
977         self.write('included_template = environment.get_template(')
978         self.visit(node.template, frame)
979         self.write(', %r).' % self.name)
980         if node.with_context:
981             self.write('make_module(context.parent, True)')
982         else:
983             self.write('module')
984
985         var_names = []
986         discarded_names = []
987         for name in node.names:
988             if isinstance(name, tuple):
989                 name, alias = name
990             else:
991                 alias = name
992             self.writeline('l_%s = getattr(included_template, '
993                            '%r, missing)' % (alias, name))
994             self.writeline('if l_%s is missing:' % alias)
995             self.indent()
996             self.writeline('l_%s = environment.undefined(%r %% '
997                            'included_template.__name__, '
998                            'name=%r)' %
999                            (alias, 'the template %%r (imported on %s) does '
1000                            'not export the requested name %s' % (
1001                                 self.position(node),
1002                                 repr(name)
1003                            ), name))
1004             self.outdent()
1005             if frame.toplevel:
1006                 var_names.append(alias)
1007                 if not alias.startswith('_'):
1008                     discarded_names.append(alias)
1009             frame.assigned_names.add(alias)
1010
1011         if var_names:
1012             if len(var_names) == 1:
1013                 name = var_names[0]
1014                 self.writeline('context.vars[%r] = l_%s' % (name, name))
1015             else:
1016                 self.writeline('context.vars.update({%s})' % ', '.join(
1017                     '%r: l_%s' % (name, name) for name in var_names
1018                 ))
1019         if discarded_names:
1020             if len(discarded_names) == 1:
1021                 self.writeline('context.exported_vars.discard(%r)' %
1022                                discarded_names[0])
1023             else:
1024                 self.writeline('context.exported_vars.difference_'
1025                                'update((%s))' % ', '.join(map(repr, discarded_names)))
1026
1027     def visit_For(self, node, frame):
1028         # when calculating the nodes for the inner frame we have to exclude
1029         # the iterator contents from it
1030         children = node.iter_child_nodes(exclude=('iter',))
1031         if node.recursive:
1032             loop_frame = self.function_scoping(node, frame, children,
1033                                                find_special=False)
1034         else:
1035             loop_frame = frame.inner()
1036             loop_frame.inspect(children)
1037
1038         # try to figure out if we have an extended loop.  An extended loop
1039         # is necessary if the loop is in recursive mode if the special loop
1040         # variable is accessed in the body.
1041         extended_loop = node.recursive or 'loop' in \
1042                         find_undeclared(node.iter_child_nodes(
1043                             only=('body',)), ('loop',))
1044
1045         # if we don't have an recursive loop we have to find the shadowed
1046         # variables at that point.  Because loops can be nested but the loop
1047         # variable is a special one we have to enforce aliasing for it.
1048         if not node.recursive:
1049             aliases = self.push_scope(loop_frame, ('loop',))
1050
1051         # otherwise we set up a buffer and add a function def
1052         else:
1053             self.writeline('def loop(reciter, loop_render_func):', node)
1054             self.indent()
1055             self.buffer(loop_frame)
1056             aliases = {}
1057
1058         # make sure the loop variable is a special one and raise a template
1059         # assertion error if a loop tries to write to loop
1060         if extended_loop:
1061             loop_frame.identifiers.add_special('loop')
1062         for name in node.find_all(nodes.Name):
1063             if name.ctx == 'store' and name.name == 'loop':
1064                 self.fail('Can\'t assign to special loop variable '
1065                           'in for-loop target', name.lineno)
1066
1067         self.pull_locals(loop_frame)
1068         if node.else_:
1069             iteration_indicator = self.temporary_identifier()
1070             self.writeline('%s = 1' % iteration_indicator)
1071
1072         # Create a fake parent loop if the else or test section of a
1073         # loop is accessing the special loop variable and no parent loop
1074         # exists.
1075         if 'loop' not in aliases and 'loop' in find_undeclared(
1076            node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1077             self.writeline("l_loop = environment.undefined(%r, name='loop')" %
1078                 ("'loop' is undefined. the filter section of a loop as well "
1079                  "as the else block doesn't have access to the special 'loop'"
1080                  " variable of the current loop.  Because there is no parent "
1081                  "loop it's undefined.  Happened in loop on %s" %
1082                  self.position(node)))
1083
1084         self.writeline('for ', node)
1085         self.visit(node.target, loop_frame)
1086         self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
1087
1088         # if we have an extened loop and a node test, we filter in the
1089         # "outer frame".
1090         if extended_loop and node.test is not None:
1091             self.write('(')
1092             self.visit(node.target, loop_frame)
1093             self.write(' for ')
1094             self.visit(node.target, loop_frame)
1095             self.write(' in ')
1096             if node.recursive:
1097                 self.write('reciter')
1098             else:
1099                 self.visit(node.iter, loop_frame)
1100             self.write(' if (')
1101             test_frame = loop_frame.copy()
1102             self.visit(node.test, test_frame)
1103             self.write('))')
1104
1105         elif node.recursive:
1106             self.write('reciter')
1107         else:
1108             self.visit(node.iter, loop_frame)
1109
1110         if node.recursive:
1111             self.write(', recurse=loop_render_func):')
1112         else:
1113             self.write(extended_loop and '):' or ':')
1114
1115         # tests in not extended loops become a continue
1116         if not extended_loop and node.test is not None:
1117             self.indent()
1118             self.writeline('if not ')
1119             self.visit(node.test, loop_frame)
1120             self.write(':')
1121             self.indent()
1122             self.writeline('continue')
1123             self.outdent(2)
1124
1125         self.indent()
1126         self.blockvisit(node.body, loop_frame)
1127         if node.else_:
1128             self.writeline('%s = 0' % iteration_indicator)
1129         self.outdent()
1130
1131         if node.else_:
1132             self.writeline('if %s:' % iteration_indicator)
1133             self.indent()
1134             self.blockvisit(node.else_, loop_frame)
1135             self.outdent()
1136
1137         # reset the aliases if there are any.
1138         if not node.recursive:
1139             self.pop_scope(aliases, loop_frame)
1140
1141         # if the node was recursive we have to return the buffer contents
1142         # and start the iteration code
1143         if node.recursive:
1144             self.return_buffer_contents(loop_frame)
1145             self.outdent()
1146             self.start_write(frame, node)
1147             self.write('loop(')
1148             self.visit(node.iter, frame)
1149             self.write(', loop)')
1150             self.end_write(frame)
1151
1152     def visit_If(self, node, frame):
1153         if_frame = frame.soft()
1154         self.writeline('if ', node)
1155         self.visit(node.test, if_frame)
1156         self.write(':')
1157         self.indent()
1158         self.blockvisit(node.body, if_frame)
1159         self.outdent()
1160         if node.else_:
1161             self.writeline('else:')
1162             self.indent()
1163             self.blockvisit(node.else_, if_frame)
1164             self.outdent()
1165
1166     def visit_Macro(self, node, frame):
1167         macro_frame = self.macro_body(node, frame)
1168         self.newline()
1169         if frame.toplevel:
1170             if not node.name.startswith('_'):
1171                 self.write('context.exported_vars.add(%r)' % node.name)
1172             self.writeline('context.vars[%r] = ' % node.name)
1173         self.write('l_%s = ' % node.name)
1174         self.macro_def(node, macro_frame)
1175         frame.assigned_names.add(node.name)
1176
1177     def visit_CallBlock(self, node, frame):
1178         children = node.iter_child_nodes(exclude=('call',))
1179         call_frame = self.macro_body(node, frame, children)
1180         self.writeline('caller = ')
1181         self.macro_def(node, call_frame)
1182         self.start_write(frame, node)
1183         self.visit_Call(node.call, call_frame, forward_caller=True)
1184         self.end_write(frame)
1185
1186     def visit_FilterBlock(self, node, frame):
1187         filter_frame = frame.inner()
1188         filter_frame.inspect(node.iter_child_nodes())
1189         aliases = self.push_scope(filter_frame)
1190         self.pull_locals(filter_frame)
1191         self.buffer(filter_frame)
1192         self.blockvisit(node.body, filter_frame)
1193         self.start_write(frame, node)
1194         self.visit_Filter(node.filter, filter_frame)
1195         self.end_write(frame)
1196         self.pop_scope(aliases, filter_frame)
1197
1198     def visit_ExprStmt(self, node, frame):
1199         self.newline(node)
1200         self.visit(node.node, frame)
1201
1202     def visit_Output(self, node, frame):
1203         # if we have a known extends statement, we don't output anything
1204         # if we are in a require_output_check section
1205         if self.has_known_extends and frame.require_output_check:
1206             return
1207
1208         if self.environment.finalize:
1209             finalize = lambda x: unicode(self.environment.finalize(x))
1210         else:
1211             finalize = unicode
1212
1213         self.newline(node)
1214
1215         # if we are inside a frame that requires output checking, we do so
1216         outdent_later = False
1217         if frame.require_output_check:
1218             self.writeline('if parent_template is None:')
1219             self.indent()
1220             outdent_later = True
1221
1222         # try to evaluate as many chunks as possible into a static
1223         # string at compile time.
1224         body = []
1225         for child in node.nodes:
1226             try:
1227                 const = child.as_const()
1228             except nodes.Impossible:
1229                 body.append(child)
1230                 continue
1231             try:
1232                 if self.environment.autoescape:
1233                     if hasattr(const, '__html__'):
1234                         const = const.__html__()
1235                     else:
1236                         const = escape(const)
1237                 const = finalize(const)
1238             except:
1239                 # if something goes wrong here we evaluate the node
1240                 # at runtime for easier debugging
1241                 body.append(child)
1242                 continue
1243             if body and isinstance(body[-1], list):
1244                 body[-1].append(const)
1245             else:
1246                 body.append([const])
1247
1248         # if we have less than 3 nodes or a buffer we yield or extend/append
1249         if len(body) < 3 or frame.buffer is not None:
1250             if frame.buffer is not None:
1251                 # for one item we append, for more we extend
1252                 if len(body) == 1:
1253                     self.writeline('%s.append(' % frame.buffer)
1254                 else:
1255                     self.writeline('%s.extend((' % frame.buffer)
1256                 self.indent()
1257             for item in body:
1258                 if isinstance(item, list):
1259                     val = repr(concat(item))
1260                     if frame.buffer is None:
1261                         self.writeline('yield ' + val)
1262                     else:
1263                         self.writeline(val + ', ')
1264                 else:
1265                     if frame.buffer is None:
1266                         self.writeline('yield ', item)
1267                     else:
1268                         self.newline(item)
1269                     close = 1
1270                     if self.environment.autoescape:
1271                         self.write('escape(')
1272                     else:
1273                         self.write('to_string(')
1274                     if self.environment.finalize is not None:
1275                         self.write('environment.finalize(')
1276                         close += 1
1277                     self.visit(item, frame)
1278                     self.write(')' * close)
1279                     if frame.buffer is not None:
1280                         self.write(', ')
1281             if frame.buffer is not None:
1282                 # close the open parentheses
1283                 self.outdent()
1284                 self.writeline(len(body) == 1 and ')' or '))')
1285
1286         # otherwise we create a format string as this is faster in that case
1287         else:
1288             format = []
1289             arguments = []
1290             for item in body:
1291                 if isinstance(item, list):
1292                     format.append(concat(item).replace('%', '%%'))
1293                 else:
1294                     format.append('%s')
1295                     arguments.append(item)
1296             self.writeline('yield ')
1297             self.write(repr(concat(format)) + ' % (')
1298             idx = -1
1299             self.indent()
1300             for argument in arguments:
1301                 self.newline(argument)
1302                 close = 0
1303                 if self.environment.autoescape:
1304                     self.write('escape(')
1305                     close += 1
1306                 if self.environment.finalize is not None:
1307                     self.write('environment.finalize(')
1308                     close += 1
1309                 self.visit(argument, frame)
1310                 self.write(')' * close + ', ')
1311             self.outdent()
1312             self.writeline(')')
1313
1314         if outdent_later:
1315             self.outdent()
1316
1317     def visit_Assign(self, node, frame):
1318         self.newline(node)
1319         # toplevel assignments however go into the local namespace and
1320         # the current template's context.  We create a copy of the frame
1321         # here and add a set so that the Name visitor can add the assigned
1322         # names here.
1323         if frame.toplevel:
1324             assignment_frame = frame.copy()
1325             assignment_frame.toplevel_assignments = set()
1326         else:
1327             assignment_frame = frame
1328         self.visit(node.target, assignment_frame)
1329         self.write(' = ')
1330         self.visit(node.node, frame)
1331
1332         # make sure toplevel assignments are added to the context.
1333         if frame.toplevel:
1334             public_names = [x for x in assignment_frame.toplevel_assignments
1335                             if not x.startswith('_')]
1336             if len(assignment_frame.toplevel_assignments) == 1:
1337                 name = next(iter(assignment_frame.toplevel_assignments))
1338                 self.writeline('context.vars[%r] = l_%s' % (name, name))
1339             else:
1340                 self.writeline('context.vars.update({')
1341                 for idx, name in enumerate(assignment_frame.toplevel_assignments):
1342                     if idx:
1343                         self.write(', ')
1344                     self.write('%r: l_%s' % (name, name))
1345                 self.write('})')
1346             if public_names:
1347                 if len(public_names) == 1:
1348                     self.writeline('context.exported_vars.add(%r)' %
1349                                    public_names[0])
1350                 else:
1351                     self.writeline('context.exported_vars.update((%s))' %
1352                                    ', '.join(map(repr, public_names)))
1353
1354     # -- Expression Visitors
1355
1356     def visit_Name(self, node, frame):
1357         if node.ctx == 'store' and frame.toplevel:
1358             frame.toplevel_assignments.add(node.name)
1359         self.write('l_' + node.name)
1360         frame.assigned_names.add(node.name)
1361
1362     def visit_Const(self, node, frame):
1363         val = node.value
1364         if isinstance(val, float):
1365             self.write(str(val))
1366         else:
1367             self.write(repr(val))
1368
1369     def visit_TemplateData(self, node, frame):
1370         self.write(repr(node.as_const()))
1371
1372     def visit_Tuple(self, node, frame):
1373         self.write('(')
1374         idx = -1
1375         for idx, item in enumerate(node.items):
1376             if idx:
1377                 self.write(', ')
1378             self.visit(item, frame)
1379         self.write(idx == 0 and ',)' or ')')
1380
1381     def visit_List(self, node, frame):
1382         self.write('[')
1383         for idx, item in enumerate(node.items):
1384             if idx:
1385                 self.write(', ')
1386             self.visit(item, frame)
1387         self.write(']')
1388
1389     def visit_Dict(self, node, frame):
1390         self.write('{')
1391         for idx, item in enumerate(node.items):
1392             if idx:
1393                 self.write(', ')
1394             self.visit(item.key, frame)
1395             self.write(': ')
1396             self.visit(item.value, frame)
1397         self.write('}')
1398
1399     def binop(operator):
1400         def visitor(self, node, frame):
1401             self.write('(')
1402             self.visit(node.left, frame)
1403             self.write(' %s ' % operator)
1404             self.visit(node.right, frame)
1405             self.write(')')
1406         return visitor
1407
1408     def uaop(operator):
1409         def visitor(self, node, frame):
1410             self.write('(' + operator)
1411             self.visit(node.node, frame)
1412             self.write(')')
1413         return visitor
1414
1415     visit_Add = binop('+')
1416     visit_Sub = binop('-')
1417     visit_Mul = binop('*')
1418     visit_Div = binop('/')
1419     visit_FloorDiv = binop('//')
1420     visit_Pow = binop('**')
1421     visit_Mod = binop('%')
1422     visit_And = binop('and')
1423     visit_Or = binop('or')
1424     visit_Pos = uaop('+')
1425     visit_Neg = uaop('-')
1426     visit_Not = uaop('not ')
1427     del binop, uaop
1428
1429     def visit_Concat(self, node, frame):
1430         self.write('%s((' % (self.environment.autoescape and
1431                              'markup_join' or 'unicode_join'))
1432         for arg in node.nodes:
1433             self.visit(arg, frame)
1434             self.write(', ')
1435         self.write('))')
1436
1437     def visit_Compare(self, node, frame):
1438         self.visit(node.expr, frame)
1439         for op in node.ops:
1440             self.visit(op, frame)
1441
1442     def visit_Operand(self, node, frame):
1443         self.write(' %s ' % operators[node.op])
1444         self.visit(node.expr, frame)
1445
1446     def visit_Getattr(self, node, frame):
1447         self.write('environment.getattr(')
1448         self.visit(node.node, frame)
1449         self.write(', %r)' % node.attr)
1450
1451     def visit_Getitem(self, node, frame):
1452         # slices bypass the environment getitem method.
1453         if isinstance(node.arg, nodes.Slice):
1454             self.visit(node.node, frame)
1455             self.write('[')
1456             self.visit(node.arg, frame)
1457             self.write(']')
1458         else:
1459             self.write('environment.getitem(')
1460             self.visit(node.node, frame)
1461             self.write(', ')
1462             self.visit(node.arg, frame)
1463             self.write(')')
1464
1465     def visit_Slice(self, node, frame):
1466         if node.start is not None:
1467             self.visit(node.start, frame)
1468         self.write(':')
1469         if node.stop is not None:
1470             self.visit(node.stop, frame)
1471         if node.step is not None:
1472             self.write(':')
1473             self.visit(node.step, frame)
1474
1475     def visit_Filter(self, node, frame):
1476         self.write(self.filters[node.name] + '(')
1477         func = self.environment.filters.get(node.name)
1478         if func is None:
1479             self.fail('no filter named %r' % node.name, node.lineno)
1480         if getattr(func, 'contextfilter', False):
1481             self.write('context, ')
1482         elif getattr(func, 'environmentfilter', False):
1483             self.write('environment, ')
1484
1485         # if the filter node is None we are inside a filter block
1486         # and want to write to the current buffer
1487         if node.node is not None:
1488             self.visit(node.node, frame)
1489         elif self.environment.autoescape:
1490             self.write('Markup(concat(%s))' % frame.buffer)
1491         else:
1492             self.write('concat(%s)' % frame.buffer)
1493         self.signature(node, frame)
1494         self.write(')')
1495
1496     def visit_Test(self, node, frame):
1497         self.write(self.tests[node.name] + '(')
1498         if node.name not in self.environment.tests:
1499             self.fail('no test named %r' % node.name, node.lineno)
1500         self.visit(node.node, frame)
1501         self.signature(node, frame)
1502         self.write(')')
1503
1504     def visit_CondExpr(self, node, frame):
1505         def write_expr2():
1506             if node.expr2 is not None:
1507                 return self.visit(node.expr2, frame)
1508             self.write('environment.undefined(%r)' % ('the inline if-'
1509                        'expression on %s evaluated to false and '
1510                        'no else section was defined.' % self.position(node)))
1511
1512         if not have_condexpr:
1513             self.write('((')
1514             self.visit(node.test, frame)
1515             self.write(') and (')
1516             self.visit(node.expr1, frame)
1517             self.write(',) or (')
1518             write_expr2()
1519             self.write(',))[0]')
1520         else:
1521             self.write('(')
1522             self.visit(node.expr1, frame)
1523             self.write(' if ')
1524             self.visit(node.test, frame)
1525             self.write(' else ')
1526             write_expr2()
1527             self.write(')')
1528
1529     def visit_Call(self, node, frame, forward_caller=False):
1530         if self.environment.sandboxed:
1531             self.write('environment.call(context, ')
1532         else:
1533             self.write('context.call(')
1534         self.visit(node.node, frame)
1535         extra_kwargs = forward_caller and {'caller': 'caller'} or None
1536         self.signature(node, frame, extra_kwargs)
1537         self.write(')')
1538
1539     def visit_Keyword(self, node, frame):
1540         self.write(node.key + '=')
1541         self.visit(node.value, frame)
1542
1543     # -- Unused nodes for extensions
1544
1545     def visit_MarkSafe(self, node, frame):
1546         self.write('Markup(')
1547         self.visit(node.expr, frame)
1548         self.write(')')
1549
1550     def visit_EnvironmentAttribute(self, node, frame):
1551         self.write('environment.' + node.name)
1552
1553     def visit_ExtensionAttribute(self, node, frame):
1554         self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1555
1556     def visit_ImportedName(self, node, frame):
1557         self.write(self.import_aliases[node.importname])
1558
1559     def visit_InternalName(self, node, frame):
1560         self.write(node.name)
1561
1562     def visit_ContextReference(self, node, frame):
1563         self.write('context')
1564
1565     def visit_Continue(self, node, frame):
1566         self.writeline('continue', node)
1567
1568     def visit_Break(self, node, frame):
1569         self.writeline('break', node)
1570
1571     def visit_Scope(self, node, frame):
1572         scope_frame = frame.inner()
1573         scope_frame.inspect(node.iter_child_nodes())
1574         aliases = self.push_scope(scope_frame)
1575         self.pull_locals(scope_frame)
1576         self.blockvisit(node.body, scope_frame)
1577         self.pop_scope(aliases, scope_frame)