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