1 # -*- coding: utf-8 -*-
6 Compiles nodes into python code.
8 :copyright: (c) 2009 by the Jinja Team.
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
32 exec '(0 if 0 else 0)'
39 def generate(node, environment, name, filename, stream=None):
40 """Generate the python source for a node tree."""
41 if not isinstance(node, nodes.Template):
42 raise TypeError('Can\'t compile non template nodes')
43 generator = CodeGenerator(environment, name, filename, stream)
46 return generator.stream.getvalue()
49 def has_safe_repr(value):
50 """Does the node have a safe representation?"""
51 if value is None or value is NotImplemented or value is Ellipsis:
53 if isinstance(value, (bool, int, long, float, complex, basestring,
56 if isinstance(value, (tuple, list, set, frozenset)):
58 if not has_safe_repr(item):
61 elif isinstance(value, dict):
62 for key, value in value.iteritems():
63 if not has_safe_repr(key):
65 if not has_safe_repr(value):
71 def find_undeclared(nodes, names):
72 """Check if the names passed are accessed undeclared. The return value
73 is a set of all the undeclared names from the sequence of names found.
75 visitor = UndeclaredNameVisitor(names)
81 return visitor.undeclared
84 class Identifiers(object):
85 """Tracks the status of identifiers in frames."""
88 # variables that are known to be declared (probably from outer
89 # frames or because they are special for the frame)
92 # undeclared variables from outer scopes
93 self.outer_undeclared = set()
95 # names that are accessed without being explicitly declared by
96 # this one or any of the outer scopes. Names can appear both in
97 # declared and undeclared.
98 self.undeclared = set()
100 # names that are declared locally
101 self.declared_locally = set()
103 # names that are declared by parameters
104 self.declared_parameter = set()
106 def add_special(self, name):
107 """Register a special name like `loop`."""
108 self.undeclared.discard(name)
109 self.declared.add(name)
111 def is_declared(self, name, local_only=False):
112 """Check if a name is declared in this or an outer scope."""
113 if name in self.declared_locally or name in self.declared_parameter:
117 return name in self.declared
120 return deepcopy(self)
124 """Holds compile time information for us."""
126 def __init__(self, parent=None):
127 self.identifiers = Identifiers()
129 # a toplevel frame is the root + soft frames such as if conditions.
130 self.toplevel = False
132 # the root frame is basically just the outermost frame, so no if
133 # conditions. This information is used to optimize inheritance
135 self.rootlevel = False
137 # in some dynamic inheritance situations the compiler needs to add
138 # write tests around output statements.
139 self.require_output_check = parent and parent.require_output_check
141 # inside some tags we are using a buffer rather than yield statements.
142 # this for example affects {% filter %} or {% macro %}. If a frame
143 # is buffered this variable points to the name of the list used as
147 # the name of the block we're in, otherwise None.
148 self.block = parent and parent.block or None
150 # a set of actually assigned names
151 self.assigned_names = set()
153 # the parent of this frame
156 if parent is not None:
157 self.identifiers.declared.update(
158 parent.identifiers.declared |
159 parent.identifiers.declared_parameter |
160 parent.assigned_names
162 self.identifiers.outer_undeclared.update(
163 parent.identifiers.undeclared -
164 self.identifiers.declared
166 self.buffer = parent.buffer
169 """Create a copy of the current one."""
170 rv = object.__new__(self.__class__)
171 rv.__dict__.update(self.__dict__)
172 rv.identifiers = object.__new__(self.identifiers.__class__)
173 rv.identifiers.__dict__.update(self.identifiers.__dict__)
176 def inspect(self, nodes, hard_scope=False):
177 """Walk the node and check for identifiers. If the scope is hard (eg:
178 enforce on a python level) overrides from outer scopes are tracked
181 visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
185 def find_shadowed(self, extra=()):
186 """Find all the shadowed names. extra is an iterable of variables
187 that may be defined with `add_special` which may occour scoped.
190 return (i.declared | i.outer_undeclared) & \
191 (i.declared_locally | i.declared_parameter) | \
192 set(x for x in extra if i.is_declared(x))
195 """Return an inner frame."""
199 """Return a soft frame. A soft frame may not be modified as
200 standalone thing as it shares the resources with the frame it
201 was created of, but it's not a rootlevel frame any longer.
210 class VisitorExit(RuntimeError):
211 """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
214 class DependencyFinderVisitor(NodeVisitor):
215 """A visitor that collects filter and test calls."""
221 def visit_Filter(self, node):
222 self.generic_visit(node)
223 self.filters.add(node.name)
225 def visit_Test(self, node):
226 self.generic_visit(node)
227 self.tests.add(node.name)
229 def visit_Block(self, node):
230 """Stop visiting at blocks."""
233 class UndeclaredNameVisitor(NodeVisitor):
234 """A visitor that checks if a name is accessed without being
235 declared. This is different from the frame visitor as it will
236 not stop at closure frames.
239 def __init__(self, names):
240 self.names = set(names)
241 self.undeclared = set()
243 def visit_Name(self, node):
244 if node.ctx == 'load' and node.name in self.names:
245 self.undeclared.add(node.name)
246 if self.undeclared == self.names:
249 self.names.discard(node.name)
251 def visit_Block(self, node):
252 """Stop visiting a blocks."""
255 class FrameIdentifierVisitor(NodeVisitor):
256 """A visitor for `Frame.inspect`."""
258 def __init__(self, identifiers, hard_scope):
259 self.identifiers = identifiers
260 self.hard_scope = hard_scope
262 def visit_Name(self, node):
263 """All assignments to names go through this function."""
264 if node.ctx == 'store':
265 self.identifiers.declared_locally.add(node.name)
266 elif node.ctx == 'param':
267 self.identifiers.declared_parameter.add(node.name)
268 elif node.ctx == 'load' and not \
269 self.identifiers.is_declared(node.name, self.hard_scope):
270 self.identifiers.undeclared.add(node.name)
272 def visit_If(self, node):
273 self.visit(node.test)
274 real_identifiers = self.identifiers
276 old_names = real_identifiers.declared | \
277 real_identifiers.declared_locally | \
278 real_identifiers.declared_parameter
280 def inner_visit(nodes):
283 self.identifiers = real_identifiers.copy()
284 for subnode in nodes:
286 rv = self.identifiers.declared_locally - old_names
287 # we have to remember the undeclared variables of this branch
288 # because we will have to pull them.
289 real_identifiers.undeclared.update(self.identifiers.undeclared)
290 self.identifiers = real_identifiers
293 body = inner_visit(node.body)
294 else_ = inner_visit(node.else_ or ())
296 # the differences between the two branches are also pulled as
297 # undeclared variables
298 real_identifiers.undeclared.update(body.symmetric_difference(else_))
300 # remember those that are declared.
301 real_identifiers.declared_locally.update(body | else_)
303 def visit_Macro(self, node):
304 self.identifiers.declared_locally.add(node.name)
306 def visit_Import(self, node):
307 self.generic_visit(node)
308 self.identifiers.declared_locally.add(node.target)
310 def visit_FromImport(self, node):
311 self.generic_visit(node)
312 for name in node.names:
313 if isinstance(name, tuple):
314 self.identifiers.declared_locally.add(name[1])
316 self.identifiers.declared_locally.add(name)
318 def visit_Assign(self, node):
319 """Visit assignments in the correct order."""
320 self.visit(node.node)
321 self.visit(node.target)
323 def visit_For(self, node):
324 """Visiting stops at for blocks. However the block sequence
325 is visited as part of the outer scope.
327 self.visit(node.iter)
329 def visit_CallBlock(self, node):
330 for child in node.iter_child_nodes(exclude=('body',)):
333 def visit_FilterBlock(self, node):
334 self.visit(node.filter)
336 def visit_Scope(self, node):
337 """Stop visiting at scopes."""
339 def visit_Block(self, node):
340 """Stop visiting at blocks."""
343 class CompilerExit(Exception):
344 """Raised if the compiler encountered a situation where it just
345 doesn't make sense to further process the code. Any block that
346 raises such an exception is not further processed.
350 class CodeGenerator(NodeVisitor):
352 def __init__(self, environment, name, filename, stream=None):
355 self.environment = environment
357 self.filename = filename
360 # aliases for imports
361 self.import_aliases = {}
363 # a registry for all blocks. Because blocks are moved out
364 # into the global python scope they are registered here
367 # the number of extends statements so far
368 self.extends_so_far = 0
370 # some templates have a rootlevel extends. In this case we
371 # can safely assume that we're a child template and do some
372 # more optimizations.
373 self.has_known_extends = False
375 # the current line number
378 # registry of all filters and tests (global, not block local)
382 # the debug information
384 self._write_debug_info = None
386 # the number of new lines before the next write()
389 # the line number of the last written statement
392 # true if nothing was written so far.
393 self._first_write = True
395 # used by the `temporary_identifier` method to get new
396 # unique, temporary identifier
397 self._last_identifier = 0
399 # the current indentation
400 self._indentation = 0
402 # -- Various compilation helpers
404 def fail(self, msg, lineno):
405 """Fail with a `TemplateAssertionError`."""
406 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
408 def temporary_identifier(self):
409 """Get a new unique identifier."""
410 self._last_identifier += 1
411 return 't_%d' % self._last_identifier
413 def buffer(self, frame):
414 """Enable buffering for the frame from that point onwards."""
415 frame.buffer = self.temporary_identifier()
416 self.writeline('%s = []' % frame.buffer)
418 def return_buffer_contents(self, frame):
419 """Return the buffer contents of the frame."""
420 if self.environment.autoescape:
421 self.writeline('return Markup(concat(%s))' % frame.buffer)
423 self.writeline('return concat(%s)' % frame.buffer)
427 self._indentation += 1
429 def outdent(self, step=1):
430 """Outdent by step."""
431 self._indentation -= step
433 def start_write(self, frame, node=None):
434 """Yield or write into the frame buffer."""
435 if frame.buffer is None:
436 self.writeline('yield ', node)
438 self.writeline('%s.append(' % frame.buffer, node)
440 def end_write(self, frame):
441 """End the writing process started by `start_write`."""
442 if frame.buffer is not None:
445 def simple_write(self, s, frame, node=None):
446 """Simple shortcut for start_write + write + end_write."""
447 self.start_write(frame, node)
449 self.end_write(frame)
451 def blockvisit(self, nodes, frame):
452 """Visit a list of nodes as block in a frame. If the current frame
453 is no buffer a dummy ``if 0: yield None`` is written automatically
454 unless the force_generator parameter is set to False.
456 if frame.buffer is None:
457 self.writeline('if 0: yield None')
459 self.writeline('pass')
462 self.visit(node, frame)
467 """Write a string into the output stream."""
469 if not self._first_write:
470 self.stream.write('\n' * self._new_lines)
471 self.code_lineno += self._new_lines
472 if self._write_debug_info is not None:
473 self.debug_info.append((self._write_debug_info,
475 self._write_debug_info = None
476 self._first_write = False
477 self.stream.write(' ' * self._indentation)
481 def writeline(self, x, node=None, extra=0):
482 """Combination of newline and write."""
483 self.newline(node, extra)
486 def newline(self, node=None, extra=0):
487 """Add one or more newlines before the next write."""
488 self._new_lines = max(self._new_lines, 1 + extra)
489 if node is not None and node.lineno != self._last_line:
490 self._write_debug_info = node.lineno
491 self._last_line = node.lineno
493 def signature(self, node, frame, extra_kwargs=None):
494 """Writes a function call to the stream for the current node.
495 A leading comma is added automatically. The extra keyword
496 arguments may not include python keywords otherwise a syntax
497 error could occour. The extra keyword arguments should be given
500 # if any of the given keyword arguments is a python keyword
501 # we have to make sure that no invalid call is created.
502 kwarg_workaround = False
503 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
504 if is_python_keyword(kwarg):
505 kwarg_workaround = True
508 for arg in node.args:
510 self.visit(arg, frame)
512 if not kwarg_workaround:
513 for kwarg in node.kwargs:
515 self.visit(kwarg, frame)
516 if extra_kwargs is not None:
517 for key, value in extra_kwargs.iteritems():
518 self.write(', %s=%s' % (key, value))
521 self.visit(node.dyn_args, frame)
524 if node.dyn_kwargs is not None:
525 self.write(', **dict({')
528 for kwarg in node.kwargs:
529 self.write('%r: ' % kwarg.key)
530 self.visit(kwarg.value, frame)
532 if extra_kwargs is not None:
533 for key, value in extra_kwargs.iteritems():
534 self.write('%r: %s, ' % (key, value))
535 if node.dyn_kwargs is not None:
537 self.visit(node.dyn_kwargs, frame)
542 elif node.dyn_kwargs is not None:
544 self.visit(node.dyn_kwargs, frame)
546 def pull_locals(self, frame):
547 """Pull all the references identifiers into the local scope."""
548 for name in frame.identifiers.undeclared:
549 self.writeline('l_%s = context.resolve(%r)' % (name, name))
551 def pull_dependencies(self, nodes):
552 """Pull all the dependencies."""
553 visitor = DependencyFinderVisitor()
556 for dependency in 'filters', 'tests':
557 mapping = getattr(self, dependency)
558 for name in getattr(visitor, dependency):
559 if name not in mapping:
560 mapping[name] = self.temporary_identifier()
561 self.writeline('%s = environment.%s[%r]' %
562 (mapping[name], dependency, name))
564 def unoptimize_scope(self, frame):
565 """Disable Python optimizations for the frame."""
566 # XXX: this is not that nice but it has no real overhead. It
567 # mainly works because python finds the locals before dead code
568 # is removed. If that breaks we have to add a dummy function
569 # that just accepts the arguments and does nothing.
570 if frame.identifiers.declared:
571 self.writeline('if 0: dummy(%s)' % ', '.join(
572 'l_' + name for name in frame.identifiers.declared))
574 def push_scope(self, frame, extra_vars=()):
575 """This function returns all the shadowed variables in a dict
576 in the form name: alias and will write the required assignments
577 into the current scope. No indentation takes place.
579 This also predefines locally declared variables from the loop
580 body because under some circumstances it may be the case that
582 `extra_vars` is passed to `Frame.find_shadowed`.
585 for name in frame.find_shadowed(extra_vars):
586 aliases[name] = ident = self.temporary_identifier()
587 self.writeline('%s = l_%s' % (ident, name))
589 for name in frame.identifiers.declared_locally:
590 if name not in aliases:
591 to_declare.add('l_' + name)
593 self.writeline(' = '.join(to_declare) + ' = missing')
596 def pop_scope(self, aliases, frame):
597 """Restore all aliases and delete unused variables."""
598 for name, alias in aliases.iteritems():
599 self.writeline('l_%s = %s' % (name, alias))
601 for name in frame.identifiers.declared_locally:
602 if name not in aliases:
603 to_delete.add('l_' + name)
605 # we cannot use the del statement here because enclosed
606 # scopes can trigger a SyntaxError:
607 # a = 42; b = lambda: a; del a
608 self.writeline(' = '.join(to_delete) + ' = missing')
610 def function_scoping(self, node, frame, children=None,
612 """In Jinja a few statements require the help of anonymous
613 functions. Those are currently macros and call blocks and in
614 the future also recursive loops. As there is currently
615 technical limitation that doesn't allow reading and writing a
616 variable in a scope where the initial value is coming from an
617 outer scope, this function tries to fall back with a common
618 error message. Additionally the frame passed is modified so
619 that the argumetns are collected and callers are looked up.
621 This will return the modified frame.
623 # we have to iterate twice over it, make sure that works
625 children = node.iter_child_nodes()
626 children = list(children)
627 func_frame = frame.inner()
628 func_frame.inspect(children, hard_scope=True)
630 # variables that are undeclared (accessed before declaration) and
631 # declared locally *and* part of an outside scope raise a template
632 # assertion error. Reason: we can't generate reasonable code from
633 # it without aliasing all the variables.
634 # this could be fixed in Python 3 where we have the nonlocal
635 # keyword or if we switch to bytecode generation
636 overriden_closure_vars = (
637 func_frame.identifiers.undeclared &
638 func_frame.identifiers.declared &
639 (func_frame.identifiers.declared_locally |
640 func_frame.identifiers.declared_parameter)
642 if overriden_closure_vars:
643 self.fail('It\'s not possible to set and access variables '
644 'derived from an outer scope! (affects: %s)' %
645 ', '.join(sorted(overriden_closure_vars)), node.lineno)
647 # remove variables from a closure from the frame's undeclared
649 func_frame.identifiers.undeclared -= (
650 func_frame.identifiers.undeclared &
651 func_frame.identifiers.declared
654 # no special variables for this scope, abort early
658 func_frame.accesses_kwargs = False
659 func_frame.accesses_varargs = False
660 func_frame.accesses_caller = False
661 func_frame.arguments = args = ['l_' + x.name for x in node.args]
663 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
665 if 'caller' in undeclared:
666 func_frame.accesses_caller = True
667 func_frame.identifiers.add_special('caller')
668 args.append('l_caller')
669 if 'kwargs' in undeclared:
670 func_frame.accesses_kwargs = True
671 func_frame.identifiers.add_special('kwargs')
672 args.append('l_kwargs')
673 if 'varargs' in undeclared:
674 func_frame.accesses_varargs = True
675 func_frame.identifiers.add_special('varargs')
676 args.append('l_varargs')
679 def macro_body(self, node, frame, children=None):
680 """Dump the function def of a macro or call block."""
681 frame = self.function_scoping(node, frame, children)
682 # macros are delayed, they never require output checks
683 frame.require_output_check = False
684 args = frame.arguments
685 # XXX: this is an ugly fix for the loop nesting bug
686 # (tests.test_old_bugs.test_loop_call_bug). This works around
687 # a identifier nesting problem we have in general. It's just more
688 # likely to happen in loops which is why we work around it. The
689 # real solution would be "nonlocal" all the identifiers that are
690 # leaking into a new python frame and might be used both unassigned
692 if 'loop' in frame.identifiers.declared:
693 args = args + ['l_loop=l_loop']
694 self.writeline('def macro(%s):' % ', '.join(args), node)
697 self.pull_locals(frame)
698 self.blockvisit(node.body, frame)
699 self.return_buffer_contents(frame)
703 def macro_def(self, node, frame):
704 """Dump the macro definition for the def created by macro_body."""
705 arg_tuple = ', '.join(repr(x.name) for x in node.args)
706 name = getattr(node, 'name', None)
707 if len(node.args) == 1:
709 self.write('Macro(environment, macro, %r, (%s), (' %
711 for arg in node.defaults:
712 self.visit(arg, frame)
714 self.write('), %r, %r, %r)' % (
715 bool(frame.accesses_kwargs),
716 bool(frame.accesses_varargs),
717 bool(frame.accesses_caller)
720 def position(self, node):
721 """Return a human readable position for the node."""
722 rv = 'line %d' % node.lineno
723 if self.name is not None:
724 rv += ' in ' + repr(self.name)
727 # -- Statement Visitors
729 def visit_Template(self, node, frame=None):
730 assert frame is None, 'no root frame allowed'
731 from jinja2.runtime import __all__ as exported
732 self.writeline('from __future__ import division')
733 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
735 # do we have an extends tag at all? If not, we can save some
736 # overhead by just not processing any inheritance code.
737 have_extends = node.find(nodes.Extends) is not None
739 # are there any block tags? If yes, we need a copy of the scope.
740 have_blocks = node.find(nodes.Block) is not None
743 for block in node.find_all(nodes.Block):
744 if block.name in self.blocks:
745 self.fail('block %r defined twice' % block.name, block.lineno)
746 self.blocks[block.name] = block
748 # find all imports and import them
749 for import_ in node.find_all(nodes.ImportedName):
750 if import_.importname not in self.import_aliases:
751 imp = import_.importname
752 self.import_aliases[imp] = alias = self.temporary_identifier()
754 module, obj = imp.rsplit('.', 1)
755 self.writeline('from %s import %s as %s' %
756 (module, obj, alias))
758 self.writeline('import %s as %s' % (imp, alias))
761 self.writeline('name = %r' % self.name)
763 # generate the root render function.
764 self.writeline('def root(context, environment=environment):', extra=1)
768 frame.inspect(node.body)
769 frame.toplevel = frame.rootlevel = True
770 frame.require_output_check = have_extends and not self.has_known_extends
773 self.writeline('parent_template = None')
775 self.writeline('block_context = context._block()')
776 if 'self' in find_undeclared(node.body, ('self',)):
777 frame.identifiers.add_special('self')
778 self.writeline('l_self = TemplateReference(context)')
779 self.pull_locals(frame)
780 self.pull_dependencies(node.body)
781 self.blockvisit(node.body, frame)
784 # make sure that the parent root is called.
786 if not self.has_known_extends:
788 self.writeline('if parent_template is not None:')
790 self.writeline('for event in parent_template.'
791 'root_render_func(context):')
793 self.writeline('yield event')
794 self.outdent(2 + (not self.has_known_extends))
796 # at this point we now have the blocks collected and can visit them too.
797 for name, block in self.blocks.iteritems():
798 block_frame = Frame()
799 block_frame.inspect(block.body)
800 block_frame.block = name
801 self.writeline('def block_%s(context, environment=environment):'
804 undeclared = find_undeclared(block.body, ('self', 'super'))
805 if 'self' in undeclared:
806 block_frame.identifiers.add_special('self')
807 self.writeline('l_self = TemplateReference(context)')
808 if block.find(nodes.Block) is not None:
809 self.writeline('block_context = context._block(%r)' % name)
810 if 'super' in undeclared:
811 block_frame.identifiers.add_special('super')
812 self.writeline('l_super = context.super(%r, '
813 'block_%s)' % (name, name))
814 self.pull_locals(block_frame)
815 self.pull_dependencies(block.body)
816 self.blockvisit(block.body, block_frame)
819 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
820 for x in self.blocks),
823 # add a function that returns the debug info
824 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
827 def visit_Block(self, node, frame):
828 """Call a block and register it for the template."""
831 # if we know that we are a child template, there is no need to
832 # check if we are one
833 if self.has_known_extends:
835 if self.extends_so_far > 0:
836 self.writeline('if parent_template is None:')
840 context = 'block_context.derived(locals())'
842 context = 'block_context'
843 self.writeline('for event in context.blocks[%r][0](%s):' % (
844 node.name, context), node)
846 self.simple_write('event', frame)
849 def visit_Extends(self, node, frame):
850 """Calls the extender."""
851 if not frame.toplevel:
852 self.fail('cannot use extend from a non top-level scope',
855 # if the number of extends statements in general is zero so
856 # far, we don't have to add a check if something extended
857 # the template before this one.
858 if self.extends_so_far > 0:
860 # if we have a known extends we just add a template runtime
861 # error into the generated code. We could catch that at compile
862 # time too, but i welcome it not to confuse users by throwing the
863 # same error at different times just "because we can".
864 if not self.has_known_extends:
865 self.writeline('if parent_template is not None:')
867 self.writeline('raise TemplateRuntimeError(%r)' %
868 'extended multiple times')
871 # if we have a known extends already we don't need that code here
872 # as we know that the template execution will end here.
873 if self.has_known_extends:
876 self.writeline('parent_template = environment.get_template(', node)
877 self.visit(node.template, frame)
878 self.write(', %r)' % self.name)
879 self.writeline('for name, parent_block in parent_template.'
880 'blocks.iteritems():')
882 self.writeline('context.blocks.setdefault(name, []).'
883 'append(parent_block)')
886 # if this extends statement was in the root level we can take
887 # advantage of that information and simplify the generated code
888 # in the top level from this point onwards
890 self.has_known_extends = True
892 # and now we have one more
893 self.extends_so_far += 1
895 def visit_Include(self, node, frame):
896 """Handles includes."""
897 if node.with_context:
898 self.unoptimize_scope(frame)
899 if node.ignore_missing:
900 self.writeline('try:')
902 self.writeline('template = environment.get_template(', node)
903 self.visit(node.template, frame)
904 self.write(', %r)' % self.name)
905 if node.ignore_missing:
907 self.writeline('except TemplateNotFound:')
909 self.writeline('pass')
911 self.writeline('else:')
914 if node.with_context:
915 self.writeline('for event in template.root_render_func('
916 'template.new_context(context.parent, True, '
919 self.writeline('for event in template.module._body_stream:')
922 self.simple_write('event', frame)
925 if node.ignore_missing:
928 def visit_Import(self, node, frame):
929 """Visit regular imports."""
930 if node.with_context:
931 self.unoptimize_scope(frame)
932 self.writeline('l_%s = ' % node.target, node)
934 self.write('context.vars[%r] = ' % node.target)
935 self.write('environment.get_template(')
936 self.visit(node.template, frame)
937 self.write(', %r).' % self.name)
938 if node.with_context:
939 self.write('make_module(context.parent, True, locals())')
942 if frame.toplevel and not node.target.startswith('_'):
943 self.writeline('context.exported_vars.discard(%r)' % node.target)
944 frame.assigned_names.add(node.target)
946 def visit_FromImport(self, node, frame):
947 """Visit named imports."""
949 self.write('included_template = environment.get_template(')
950 self.visit(node.template, frame)
951 self.write(', %r).' % self.name)
952 if node.with_context:
953 self.write('make_module(context.parent, True)')
959 for name in node.names:
960 if isinstance(name, tuple):
964 self.writeline('l_%s = getattr(included_template, '
965 '%r, missing)' % (alias, name))
966 self.writeline('if l_%s is missing:' % alias)
968 self.writeline('l_%s = environment.undefined(%r %% '
969 'included_template.__name__, '
971 (alias, 'the template %%r (imported on %s) does '
972 'not export the requested name %s' % (
978 var_names.append(alias)
979 if not alias.startswith('_'):
980 discarded_names.append(alias)
981 frame.assigned_names.add(alias)
984 if len(var_names) == 1:
986 self.writeline('context.vars[%r] = l_%s' % (name, name))
988 self.writeline('context.vars.update({%s})' % ', '.join(
989 '%r: l_%s' % (name, name) for name in var_names
992 if len(discarded_names) == 1:
993 self.writeline('context.exported_vars.discard(%r)' %
996 self.writeline('context.exported_vars.difference_'
997 'update((%s))' % ', '.join(map(repr, discarded_names)))
999 def visit_For(self, node, frame):
1000 # when calculating the nodes for the inner frame we have to exclude
1001 # the iterator contents from it
1002 children = node.iter_child_nodes(exclude=('iter',))
1004 loop_frame = self.function_scoping(node, frame, children,
1007 loop_frame = frame.inner()
1008 loop_frame.inspect(children)
1010 # try to figure out if we have an extended loop. An extended loop
1011 # is necessary if the loop is in recursive mode if the special loop
1012 # variable is accessed in the body.
1013 extended_loop = node.recursive or 'loop' in \
1014 find_undeclared(node.iter_child_nodes(
1015 only=('body',)), ('loop',))
1017 # if we don't have an recursive loop we have to find the shadowed
1018 # variables at that point. Because loops can be nested but the loop
1019 # variable is a special one we have to enforce aliasing for it.
1020 if not node.recursive:
1021 aliases = self.push_scope(loop_frame, ('loop',))
1023 # otherwise we set up a buffer and add a function def
1025 self.writeline('def loop(reciter, loop_render_func):', node)
1027 self.buffer(loop_frame)
1030 # make sure the loop variable is a special one and raise a template
1031 # assertion error if a loop tries to write to loop
1033 loop_frame.identifiers.add_special('loop')
1034 for name in node.find_all(nodes.Name):
1035 if name.ctx == 'store' and name.name == 'loop':
1036 self.fail('Can\'t assign to special loop variable '
1037 'in for-loop target', name.lineno)
1039 self.pull_locals(loop_frame)
1041 iteration_indicator = self.temporary_identifier()
1042 self.writeline('%s = 1' % iteration_indicator)
1044 # Create a fake parent loop if the else or test section of a
1045 # loop is accessing the special loop variable and no parent loop
1047 if 'loop' not in aliases and 'loop' in find_undeclared(
1048 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1049 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
1050 ("'loop' is undefined. the filter section of a loop as well "
1051 "as the else block doesn't have access to the special 'loop'"
1052 " variable of the current loop. Because there is no parent "
1053 "loop it's undefined. Happened in loop on %s" %
1054 self.position(node)))
1056 self.writeline('for ', node)
1057 self.visit(node.target, loop_frame)
1058 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
1060 # if we have an extened loop and a node test, we filter in the
1062 if extended_loop and node.test is not None:
1064 self.visit(node.target, loop_frame)
1066 self.visit(node.target, loop_frame)
1069 self.write('reciter')
1071 self.visit(node.iter, loop_frame)
1073 test_frame = loop_frame.copy()
1074 self.visit(node.test, test_frame)
1077 elif node.recursive:
1078 self.write('reciter')
1080 self.visit(node.iter, loop_frame)
1083 self.write(', recurse=loop_render_func):')
1085 self.write(extended_loop and '):' or ':')
1087 # tests in not extended loops become a continue
1088 if not extended_loop and node.test is not None:
1090 self.writeline('if not ')
1091 self.visit(node.test, loop_frame)
1094 self.writeline('continue')
1098 self.blockvisit(node.body, loop_frame)
1100 self.writeline('%s = 0' % iteration_indicator)
1104 self.writeline('if %s:' % iteration_indicator)
1106 self.blockvisit(node.else_, loop_frame)
1109 # reset the aliases if there are any.
1110 if not node.recursive:
1111 self.pop_scope(aliases, loop_frame)
1113 # if the node was recursive we have to return the buffer contents
1114 # and start the iteration code
1116 self.return_buffer_contents(loop_frame)
1118 self.start_write(frame, node)
1120 self.visit(node.iter, frame)
1121 self.write(', loop)')
1122 self.end_write(frame)
1124 def visit_If(self, node, frame):
1125 if_frame = frame.soft()
1126 self.writeline('if ', node)
1127 self.visit(node.test, if_frame)
1130 self.blockvisit(node.body, if_frame)
1133 self.writeline('else:')
1135 self.blockvisit(node.else_, if_frame)
1138 def visit_Macro(self, node, frame):
1139 macro_frame = self.macro_body(node, frame)
1142 if not node.name.startswith('_'):
1143 self.write('context.exported_vars.add(%r)' % node.name)
1144 self.writeline('context.vars[%r] = ' % node.name)
1145 self.write('l_%s = ' % node.name)
1146 self.macro_def(node, macro_frame)
1147 frame.assigned_names.add(node.name)
1149 def visit_CallBlock(self, node, frame):
1150 children = node.iter_child_nodes(exclude=('call',))
1151 call_frame = self.macro_body(node, frame, children)
1152 self.writeline('caller = ')
1153 self.macro_def(node, call_frame)
1154 self.start_write(frame, node)
1155 self.visit_Call(node.call, call_frame, forward_caller=True)
1156 self.end_write(frame)
1158 def visit_FilterBlock(self, node, frame):
1159 filter_frame = frame.inner()
1160 filter_frame.inspect(node.iter_child_nodes())
1161 aliases = self.push_scope(filter_frame)
1162 self.pull_locals(filter_frame)
1163 self.buffer(filter_frame)
1164 self.blockvisit(node.body, filter_frame)
1165 self.start_write(frame, node)
1166 self.visit_Filter(node.filter, filter_frame)
1167 self.end_write(frame)
1168 self.pop_scope(aliases, filter_frame)
1170 def visit_ExprStmt(self, node, frame):
1172 self.visit(node.node, frame)
1174 def visit_Output(self, node, frame):
1175 # if we have a known extends statement, we don't output anything
1176 # if we are in a require_output_check section
1177 if self.has_known_extends and frame.require_output_check:
1180 if self.environment.finalize:
1181 finalize = lambda x: unicode(self.environment.finalize(x))
1187 # if we are inside a frame that requires output checking, we do so
1188 outdent_later = False
1189 if frame.require_output_check:
1190 self.writeline('if parent_template is None:')
1192 outdent_later = True
1194 # try to evaluate as many chunks as possible into a static
1195 # string at compile time.
1197 for child in node.nodes:
1199 const = child.as_const()
1200 except nodes.Impossible:
1204 if self.environment.autoescape:
1205 if hasattr(const, '__html__'):
1206 const = const.__html__()
1208 const = escape(const)
1209 const = finalize(const)
1211 # if something goes wrong here we evaluate the node
1212 # at runtime for easier debugging
1215 if body and isinstance(body[-1], list):
1216 body[-1].append(const)
1218 body.append([const])
1220 # if we have less than 3 nodes or a buffer we yield or extend/append
1221 if len(body) < 3 or frame.buffer is not None:
1222 if frame.buffer is not None:
1223 # for one item we append, for more we extend
1225 self.writeline('%s.append(' % frame.buffer)
1227 self.writeline('%s.extend((' % frame.buffer)
1230 if isinstance(item, list):
1231 val = repr(concat(item))
1232 if frame.buffer is None:
1233 self.writeline('yield ' + val)
1235 self.writeline(val + ', ')
1237 if frame.buffer is None:
1238 self.writeline('yield ', item)
1242 if self.environment.autoescape:
1243 self.write('escape(')
1245 self.write('to_string(')
1246 if self.environment.finalize is not None:
1247 self.write('environment.finalize(')
1249 self.visit(item, frame)
1250 self.write(')' * close)
1251 if frame.buffer is not None:
1253 if frame.buffer is not None:
1254 # close the open parentheses
1256 self.writeline(len(body) == 1 and ')' or '))')
1258 # otherwise we create a format string as this is faster in that case
1263 if isinstance(item, list):
1264 format.append(concat(item).replace('%', '%%'))
1267 arguments.append(item)
1268 self.writeline('yield ')
1269 self.write(repr(concat(format)) + ' % (')
1272 for argument in arguments:
1273 self.newline(argument)
1275 if self.environment.autoescape:
1276 self.write('escape(')
1278 if self.environment.finalize is not None:
1279 self.write('environment.finalize(')
1281 self.visit(argument, frame)
1282 self.write(')' * close + ', ')
1289 def visit_Assign(self, node, frame):
1291 # toplevel assignments however go into the local namespace and
1292 # the current template's context. We create a copy of the frame
1293 # here and add a set so that the Name visitor can add the assigned
1296 assignment_frame = frame.copy()
1297 assignment_frame.toplevel_assignments = set()
1299 assignment_frame = frame
1300 self.visit(node.target, assignment_frame)
1302 self.visit(node.node, frame)
1304 # make sure toplevel assignments are added to the context.
1306 public_names = [x for x in assignment_frame.toplevel_assignments
1307 if not x.startswith('_')]
1308 if len(assignment_frame.toplevel_assignments) == 1:
1309 name = next(iter(assignment_frame.toplevel_assignments))
1310 self.writeline('context.vars[%r] = l_%s' % (name, name))
1312 self.writeline('context.vars.update({')
1313 for idx, name in enumerate(assignment_frame.toplevel_assignments):
1316 self.write('%r: l_%s' % (name, name))
1319 if len(public_names) == 1:
1320 self.writeline('context.exported_vars.add(%r)' %
1323 self.writeline('context.exported_vars.update((%s))' %
1324 ', '.join(map(repr, public_names)))
1326 # -- Expression Visitors
1328 def visit_Name(self, node, frame):
1329 if node.ctx == 'store' and frame.toplevel:
1330 frame.toplevel_assignments.add(node.name)
1331 self.write('l_' + node.name)
1332 frame.assigned_names.add(node.name)
1334 def visit_Const(self, node, frame):
1336 if isinstance(val, float):
1337 self.write(str(val))
1339 self.write(repr(val))
1341 def visit_TemplateData(self, node, frame):
1342 self.write(repr(node.as_const()))
1344 def visit_Tuple(self, node, frame):
1347 for idx, item in enumerate(node.items):
1350 self.visit(item, frame)
1351 self.write(idx == 0 and ',)' or ')')
1353 def visit_List(self, node, frame):
1355 for idx, item in enumerate(node.items):
1358 self.visit(item, frame)
1361 def visit_Dict(self, node, frame):
1363 for idx, item in enumerate(node.items):
1366 self.visit(item.key, frame)
1368 self.visit(item.value, frame)
1371 def binop(operator):
1372 def visitor(self, node, frame):
1374 self.visit(node.left, frame)
1375 self.write(' %s ' % operator)
1376 self.visit(node.right, frame)
1381 def visitor(self, node, frame):
1382 self.write('(' + operator)
1383 self.visit(node.node, frame)
1387 visit_Add = binop('+')
1388 visit_Sub = binop('-')
1389 visit_Mul = binop('*')
1390 visit_Div = binop('/')
1391 visit_FloorDiv = binop('//')
1392 visit_Pow = binop('**')
1393 visit_Mod = binop('%')
1394 visit_And = binop('and')
1395 visit_Or = binop('or')
1396 visit_Pos = uaop('+')
1397 visit_Neg = uaop('-')
1398 visit_Not = uaop('not ')
1401 def visit_Concat(self, node, frame):
1402 self.write('%s((' % (self.environment.autoescape and
1403 'markup_join' or 'unicode_join'))
1404 for arg in node.nodes:
1405 self.visit(arg, frame)
1409 def visit_Compare(self, node, frame):
1410 self.visit(node.expr, frame)
1412 self.visit(op, frame)
1414 def visit_Operand(self, node, frame):
1415 self.write(' %s ' % operators[node.op])
1416 self.visit(node.expr, frame)
1418 def visit_Getattr(self, node, frame):
1419 self.write('environment.getattr(')
1420 self.visit(node.node, frame)
1421 self.write(', %r)' % node.attr)
1423 def visit_Getitem(self, node, frame):
1424 # slices bypass the environment getitem method.
1425 if isinstance(node.arg, nodes.Slice):
1426 self.visit(node.node, frame)
1428 self.visit(node.arg, frame)
1431 self.write('environment.getitem(')
1432 self.visit(node.node, frame)
1434 self.visit(node.arg, frame)
1437 def visit_Slice(self, node, frame):
1438 if node.start is not None:
1439 self.visit(node.start, frame)
1441 if node.stop is not None:
1442 self.visit(node.stop, frame)
1443 if node.step is not None:
1445 self.visit(node.step, frame)
1447 def visit_Filter(self, node, frame):
1448 self.write(self.filters[node.name] + '(')
1449 func = self.environment.filters.get(node.name)
1451 self.fail('no filter named %r' % node.name, node.lineno)
1452 if getattr(func, 'contextfilter', False):
1453 self.write('context, ')
1454 elif getattr(func, 'environmentfilter', False):
1455 self.write('environment, ')
1457 # if the filter node is None we are inside a filter block
1458 # and want to write to the current buffer
1459 if node.node is not None:
1460 self.visit(node.node, frame)
1461 elif self.environment.autoescape:
1462 self.write('Markup(concat(%s))' % frame.buffer)
1464 self.write('concat(%s)' % frame.buffer)
1465 self.signature(node, frame)
1468 def visit_Test(self, node, frame):
1469 self.write(self.tests[node.name] + '(')
1470 if node.name not in self.environment.tests:
1471 self.fail('no test named %r' % node.name, node.lineno)
1472 self.visit(node.node, frame)
1473 self.signature(node, frame)
1476 def visit_CondExpr(self, node, frame):
1478 if node.expr2 is not None:
1479 return self.visit(node.expr2, frame)
1480 self.write('environment.undefined(%r)' % ('the inline if-'
1481 'expression on %s evaluated to false and '
1482 'no else section was defined.' % self.position(node)))
1484 if not have_condexpr:
1486 self.visit(node.test, frame)
1487 self.write(') and (')
1488 self.visit(node.expr1, frame)
1489 self.write(',) or (')
1491 self.write(',))[0]')
1494 self.visit(node.expr1, frame)
1496 self.visit(node.test, frame)
1497 self.write(' else ')
1501 def visit_Call(self, node, frame, forward_caller=False):
1502 if self.environment.sandboxed:
1503 self.write('environment.call(context, ')
1505 self.write('context.call(')
1506 self.visit(node.node, frame)
1507 extra_kwargs = forward_caller and {'caller': 'caller'} or None
1508 self.signature(node, frame, extra_kwargs)
1511 def visit_Keyword(self, node, frame):
1512 self.write(node.key + '=')
1513 self.visit(node.value, frame)
1515 # -- Unused nodes for extensions
1517 def visit_MarkSafe(self, node, frame):
1518 self.write('Markup(')
1519 self.visit(node.expr, frame)
1522 def visit_EnvironmentAttribute(self, node, frame):
1523 self.write('environment.' + node.name)
1525 def visit_ExtensionAttribute(self, node, frame):
1526 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1528 def visit_ImportedName(self, node, frame):
1529 self.write(self.import_aliases[node.importname])
1531 def visit_InternalName(self, node, frame):
1532 self.write(node.name)
1534 def visit_ContextReference(self, node, frame):
1535 self.write('context')
1537 def visit_Continue(self, node, frame):
1538 self.writeline('continue', node)
1540 def visit_Break(self, node, frame):
1541 self.writeline('break', node)
1543 def visit_Scope(self, node, frame):
1544 scope_frame = frame.inner()
1545 scope_frame.inspect(node.iter_child_nodes())
1546 aliases = self.push_scope(scope_frame)
1547 self.pull_locals(scope_frame)
1548 self.blockvisit(node.body, scope_frame)
1549 self.pop_scope(aliases, scope_frame)