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 jinja2 import nodes
14 from jinja2.visitor import NodeVisitor, NodeTransformer
15 from jinja2.exceptions import TemplateAssertionError
16 from jinja2.utils import Markup, concat, escape, is_python_keyword, next
31 exec '(0 if 0 else 0)'
38 def generate(node, environment, name, filename, stream=None):
39 """Generate the python source for a node tree."""
40 if not isinstance(node, nodes.Template):
41 raise TypeError('Can\'t compile non template nodes')
42 generator = CodeGenerator(environment, name, filename, stream)
45 return generator.stream.getvalue()
48 def has_safe_repr(value):
49 """Does the node have a safe representation?"""
50 if value is None or value is NotImplemented or value is Ellipsis:
52 if isinstance(value, (bool, int, long, float, complex, basestring,
55 if isinstance(value, (tuple, list, set, frozenset)):
57 if not has_safe_repr(item):
60 elif isinstance(value, dict):
61 for key, value in value.iteritems():
62 if not has_safe_repr(key):
64 if not has_safe_repr(value):
70 def find_undeclared(nodes, names):
71 """Check if the names passed are accessed undeclared. The return value
72 is a set of all the undeclared names from the sequence of names found.
74 visitor = UndeclaredNameVisitor(names)
80 return visitor.undeclared
83 class Identifiers(object):
84 """Tracks the status of identifiers in frames."""
87 # variables that are known to be declared (probably from outer
88 # frames or because they are special for the frame)
91 # undeclared variables from outer scopes
92 self.outer_undeclared = set()
94 # names that are accessed without being explicitly declared by
95 # this one or any of the outer scopes. Names can appear both in
96 # declared and undeclared.
97 self.undeclared = set()
99 # names that are declared locally
100 self.declared_locally = set()
102 # names that are declared by parameters
103 self.declared_parameter = set()
105 def add_special(self, name):
106 """Register a special name like `loop`."""
107 self.undeclared.discard(name)
108 self.declared.add(name)
110 def is_declared(self, name, local_only=False):
111 """Check if a name is declared in this or an outer scope."""
112 if name in self.declared_locally or name in self.declared_parameter:
116 return name in self.declared
120 """Holds compile time information for us."""
122 def __init__(self, parent=None):
123 self.identifiers = Identifiers()
125 # a toplevel frame is the root + soft frames such as if conditions.
126 self.toplevel = False
128 # the root frame is basically just the outermost frame, so no if
129 # conditions. This information is used to optimize inheritance
131 self.rootlevel = False
133 # in some dynamic inheritance situations the compiler needs to add
134 # write tests around output statements.
135 self.require_output_check = parent and parent.require_output_check
137 # inside some tags we are using a buffer rather than yield statements.
138 # this for example affects {% filter %} or {% macro %}. If a frame
139 # is buffered this variable points to the name of the list used as
143 # the name of the block we're in, otherwise None.
144 self.block = parent and parent.block or None
146 # a set of actually assigned names
147 self.assigned_names = set()
149 # the parent of this frame
152 if parent is not None:
153 self.identifiers.declared.update(
154 parent.identifiers.declared |
155 parent.identifiers.declared_parameter |
156 parent.assigned_names
158 self.identifiers.outer_undeclared.update(
159 parent.identifiers.undeclared -
160 self.identifiers.declared
162 self.buffer = parent.buffer
165 """Create a copy of the current one."""
166 rv = object.__new__(self.__class__)
167 rv.__dict__.update(self.__dict__)
168 rv.identifiers = object.__new__(self.identifiers.__class__)
169 rv.identifiers.__dict__.update(self.identifiers.__dict__)
172 def inspect(self, nodes, hard_scope=False):
173 """Walk the node and check for identifiers. If the scope is hard (eg:
174 enforce on a python level) overrides from outer scopes are tracked
177 visitor = FrameIdentifierVisitor(self.identifiers, hard_scope)
181 def find_shadowed(self, extra=()):
182 """Find all the shadowed names. extra is an iterable of variables
183 that may be defined with `add_special` which may occour scoped.
186 return (i.declared | i.outer_undeclared) & \
187 (i.declared_locally | i.declared_parameter) | \
188 set(x for x in extra if i.is_declared(x))
191 """Return an inner frame."""
195 """Return a soft frame. A soft frame may not be modified as
196 standalone thing as it shares the resources with the frame it
197 was created of, but it's not a rootlevel frame any longer.
206 class VisitorExit(RuntimeError):
207 """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
210 class DependencyFinderVisitor(NodeVisitor):
211 """A visitor that collects filter and test calls."""
217 def visit_Filter(self, node):
218 self.generic_visit(node)
219 self.filters.add(node.name)
221 def visit_Test(self, node):
222 self.generic_visit(node)
223 self.tests.add(node.name)
225 def visit_Block(self, node):
226 """Stop visiting at blocks."""
229 class UndeclaredNameVisitor(NodeVisitor):
230 """A visitor that checks if a name is accessed without being
231 declared. This is different from the frame visitor as it will
232 not stop at closure frames.
235 def __init__(self, names):
236 self.names = set(names)
237 self.undeclared = set()
239 def visit_Name(self, node):
240 if node.ctx == 'load' and node.name in self.names:
241 self.undeclared.add(node.name)
242 if self.undeclared == self.names:
245 self.names.discard(node.name)
247 def visit_Block(self, node):
248 """Stop visiting a blocks."""
251 class FrameIdentifierVisitor(NodeVisitor):
252 """A visitor for `Frame.inspect`."""
254 def __init__(self, identifiers, hard_scope):
255 self.identifiers = identifiers
256 self.hard_scope = hard_scope
258 def visit_Name(self, node):
259 """All assignments to names go through this function."""
260 if node.ctx == 'store':
261 self.identifiers.declared_locally.add(node.name)
262 elif node.ctx == 'param':
263 self.identifiers.declared_parameter.add(node.name)
264 elif node.ctx == 'load' and not \
265 self.identifiers.is_declared(node.name, self.hard_scope):
266 self.identifiers.undeclared.add(node.name)
268 def visit_Macro(self, node):
269 self.identifiers.declared_locally.add(node.name)
271 def visit_Import(self, node):
272 self.generic_visit(node)
273 self.identifiers.declared_locally.add(node.target)
275 def visit_FromImport(self, node):
276 self.generic_visit(node)
277 for name in node.names:
278 if isinstance(name, tuple):
279 self.identifiers.declared_locally.add(name[1])
281 self.identifiers.declared_locally.add(name)
283 def visit_Assign(self, node):
284 """Visit assignments in the correct order."""
285 self.visit(node.node)
286 self.visit(node.target)
288 def visit_For(self, node):
289 """Visiting stops at for blocks. However the block sequence
290 is visited as part of the outer scope.
292 self.visit(node.iter)
294 def visit_CallBlock(self, node):
295 for child in node.iter_child_nodes(exclude=('body',)):
298 def visit_FilterBlock(self, node):
299 self.visit(node.filter)
301 def visit_Scope(self, node):
302 """Stop visiting at scopes."""
304 def visit_Block(self, node):
305 """Stop visiting at blocks."""
308 class CompilerExit(Exception):
309 """Raised if the compiler encountered a situation where it just
310 doesn't make sense to further process the code. Any block that
311 raises such an exception is not further processed.
315 class CodeGenerator(NodeVisitor):
317 def __init__(self, environment, name, filename, stream=None):
320 self.environment = environment
322 self.filename = filename
325 # aliases for imports
326 self.import_aliases = {}
328 # a registry for all blocks. Because blocks are moved out
329 # into the global python scope they are registered here
332 # the number of extends statements so far
333 self.extends_so_far = 0
335 # some templates have a rootlevel extends. In this case we
336 # can safely assume that we're a child template and do some
337 # more optimizations.
338 self.has_known_extends = False
340 # the current line number
343 # registry of all filters and tests (global, not block local)
347 # the debug information
349 self._write_debug_info = None
351 # the number of new lines before the next write()
354 # the line number of the last written statement
357 # true if nothing was written so far.
358 self._first_write = True
360 # used by the `temporary_identifier` method to get new
361 # unique, temporary identifier
362 self._last_identifier = 0
364 # the current indentation
365 self._indentation = 0
367 # -- Various compilation helpers
369 def fail(self, msg, lineno):
370 """Fail with a `TemplateAssertionError`."""
371 raise TemplateAssertionError(msg, lineno, self.name, self.filename)
373 def temporary_identifier(self):
374 """Get a new unique identifier."""
375 self._last_identifier += 1
376 return 't_%d' % self._last_identifier
378 def buffer(self, frame):
379 """Enable buffering for the frame from that point onwards."""
380 frame.buffer = self.temporary_identifier()
381 self.writeline('%s = []' % frame.buffer)
383 def return_buffer_contents(self, frame):
384 """Return the buffer contents of the frame."""
385 if self.environment.autoescape:
386 self.writeline('return Markup(concat(%s))' % frame.buffer)
388 self.writeline('return concat(%s)' % frame.buffer)
392 self._indentation += 1
394 def outdent(self, step=1):
395 """Outdent by step."""
396 self._indentation -= step
398 def start_write(self, frame, node=None):
399 """Yield or write into the frame buffer."""
400 if frame.buffer is None:
401 self.writeline('yield ', node)
403 self.writeline('%s.append(' % frame.buffer, node)
405 def end_write(self, frame):
406 """End the writing process started by `start_write`."""
407 if frame.buffer is not None:
410 def simple_write(self, s, frame, node=None):
411 """Simple shortcut for start_write + write + end_write."""
412 self.start_write(frame, node)
414 self.end_write(frame)
416 def blockvisit(self, nodes, frame):
417 """Visit a list of nodes as block in a frame. If the current frame
418 is no buffer a dummy ``if 0: yield None`` is written automatically
419 unless the force_generator parameter is set to False.
421 if frame.buffer is None:
422 self.writeline('if 0: yield None')
424 self.writeline('pass')
427 self.visit(node, frame)
432 """Write a string into the output stream."""
434 if not self._first_write:
435 self.stream.write('\n' * self._new_lines)
436 self.code_lineno += self._new_lines
437 if self._write_debug_info is not None:
438 self.debug_info.append((self._write_debug_info,
440 self._write_debug_info = None
441 self._first_write = False
442 self.stream.write(' ' * self._indentation)
446 def writeline(self, x, node=None, extra=0):
447 """Combination of newline and write."""
448 self.newline(node, extra)
451 def newline(self, node=None, extra=0):
452 """Add one or more newlines before the next write."""
453 self._new_lines = max(self._new_lines, 1 + extra)
454 if node is not None and node.lineno != self._last_line:
455 self._write_debug_info = node.lineno
456 self._last_line = node.lineno
458 def signature(self, node, frame, extra_kwargs=None):
459 """Writes a function call to the stream for the current node.
460 A leading comma is added automatically. The extra keyword
461 arguments may not include python keywords otherwise a syntax
462 error could occour. The extra keyword arguments should be given
465 # if any of the given keyword arguments is a python keyword
466 # we have to make sure that no invalid call is created.
467 kwarg_workaround = False
468 for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
469 if is_python_keyword(kwarg):
470 kwarg_workaround = True
473 for arg in node.args:
475 self.visit(arg, frame)
477 if not kwarg_workaround:
478 for kwarg in node.kwargs:
480 self.visit(kwarg, frame)
481 if extra_kwargs is not None:
482 for key, value in extra_kwargs.iteritems():
483 self.write(', %s=%s' % (key, value))
486 self.visit(node.dyn_args, frame)
489 if node.dyn_kwargs is not None:
490 self.write(', **dict({')
493 for kwarg in node.kwargs:
494 self.write('%r: ' % kwarg.key)
495 self.visit(kwarg.value, frame)
497 if extra_kwargs is not None:
498 for key, value in extra_kwargs.iteritems():
499 self.write('%r: %s, ' % (key, value))
500 if node.dyn_kwargs is not None:
502 self.visit(node.dyn_kwargs, frame)
507 elif node.dyn_kwargs is not None:
509 self.visit(node.dyn_kwargs, frame)
511 def pull_locals(self, frame):
512 """Pull all the references identifiers into the local scope."""
513 for name in frame.identifiers.undeclared:
514 self.writeline('l_%s = context.resolve(%r)' % (name, name))
516 def pull_dependencies(self, nodes):
517 """Pull all the dependencies."""
518 visitor = DependencyFinderVisitor()
521 for dependency in 'filters', 'tests':
522 mapping = getattr(self, dependency)
523 for name in getattr(visitor, dependency):
524 if name not in mapping:
525 mapping[name] = self.temporary_identifier()
526 self.writeline('%s = environment.%s[%r]' %
527 (mapping[name], dependency, name))
529 def unoptimize_scope(self, frame):
530 """Disable Python optimizations for the frame."""
531 # XXX: this is not that nice but it has no real overhead. It
532 # mainly works because python finds the locals before dead code
533 # is removed. If that breaks we have to add a dummy function
534 # that just accepts the arguments and does nothing.
535 if frame.identifiers.declared:
536 self.writeline('if 0: dummy(%s)' % ', '.join(
537 'l_' + name for name in frame.identifiers.declared))
539 def push_scope(self, frame, extra_vars=()):
540 """This function returns all the shadowed variables in a dict
541 in the form name: alias and will write the required assignments
542 into the current scope. No indentation takes place.
544 This also predefines locally declared variables from the loop
545 body because under some circumstances it may be the case that
547 `extra_vars` is passed to `Frame.find_shadowed`.
550 for name in frame.find_shadowed(extra_vars):
551 aliases[name] = ident = self.temporary_identifier()
552 self.writeline('%s = l_%s' % (ident, name))
554 for name in frame.identifiers.declared_locally:
555 if name not in aliases:
556 to_declare.add('l_' + name)
558 self.writeline(' = '.join(to_declare) + ' = missing')
561 def pop_scope(self, aliases, frame):
562 """Restore all aliases and delete unused variables."""
563 for name, alias in aliases.iteritems():
564 self.writeline('l_%s = %s' % (name, alias))
566 for name in frame.identifiers.declared_locally:
567 if name not in aliases:
568 to_delete.add('l_' + name)
570 # we cannot use the del statement here because enclosed
571 # scopes can trigger a SyntaxError:
572 # a = 42; b = lambda: a; del a
573 self.writeline(' = '.join(to_delete) + ' = missing')
575 def function_scoping(self, node, frame, children=None,
577 """In Jinja a few statements require the help of anonymous
578 functions. Those are currently macros and call blocks and in
579 the future also recursive loops. As there is currently
580 technical limitation that doesn't allow reading and writing a
581 variable in a scope where the initial value is coming from an
582 outer scope, this function tries to fall back with a common
583 error message. Additionally the frame passed is modified so
584 that the argumetns are collected and callers are looked up.
586 This will return the modified frame.
588 # we have to iterate twice over it, make sure that works
590 children = node.iter_child_nodes()
591 children = list(children)
592 func_frame = frame.inner()
593 func_frame.inspect(children, hard_scope=True)
595 # variables that are undeclared (accessed before declaration) and
596 # declared locally *and* part of an outside scope raise a template
597 # assertion error. Reason: we can't generate reasonable code from
598 # it without aliasing all the variables.
599 # this could be fixed in Python 3 where we have the nonlocal
600 # keyword or if we switch to bytecode generation
601 overriden_closure_vars = (
602 func_frame.identifiers.undeclared &
603 func_frame.identifiers.declared &
604 (func_frame.identifiers.declared_locally |
605 func_frame.identifiers.declared_parameter)
607 if overriden_closure_vars:
608 self.fail('It\'s not possible to set and access variables '
609 'derived from an outer scope! (affects: %s)' %
610 ', '.join(sorted(overriden_closure_vars)), node.lineno)
612 # remove variables from a closure from the frame's undeclared
614 func_frame.identifiers.undeclared -= (
615 func_frame.identifiers.undeclared &
616 func_frame.identifiers.declared
619 # no special variables for this scope, abort early
623 func_frame.accesses_kwargs = False
624 func_frame.accesses_varargs = False
625 func_frame.accesses_caller = False
626 func_frame.arguments = args = ['l_' + x.name for x in node.args]
628 undeclared = find_undeclared(children, ('caller', 'kwargs', 'varargs'))
630 if 'caller' in undeclared:
631 func_frame.accesses_caller = True
632 func_frame.identifiers.add_special('caller')
633 args.append('l_caller')
634 if 'kwargs' in undeclared:
635 func_frame.accesses_kwargs = True
636 func_frame.identifiers.add_special('kwargs')
637 args.append('l_kwargs')
638 if 'varargs' in undeclared:
639 func_frame.accesses_varargs = True
640 func_frame.identifiers.add_special('varargs')
641 args.append('l_varargs')
644 def macro_body(self, node, frame, children=None):
645 """Dump the function def of a macro or call block."""
646 frame = self.function_scoping(node, frame, children)
647 # macros are delayed, they never require output checks
648 frame.require_output_check = False
649 args = frame.arguments
650 # XXX: this is an ugly fix for the loop nesting bug
651 # (tests.test_old_bugs.test_loop_call_bug). This works around
652 # a identifier nesting problem we have in general. It's just more
653 # likely to happen in loops which is why we work around it. The
654 # real solution would be "nonlocal" all the identifiers that are
655 # leaking into a new python frame and might be used both unassigned
657 if 'loop' in frame.identifiers.declared:
658 args.append('l_loop=l_loop')
659 self.writeline('def macro(%s):' % ', '.join(args), node)
662 self.pull_locals(frame)
663 self.blockvisit(node.body, frame)
664 self.return_buffer_contents(frame)
668 def macro_def(self, node, frame):
669 """Dump the macro definition for the def created by macro_body."""
670 arg_tuple = ', '.join(repr(x.name) for x in node.args)
671 name = getattr(node, 'name', None)
672 if len(node.args) == 1:
674 self.write('Macro(environment, macro, %r, (%s), (' %
676 for arg in node.defaults:
677 self.visit(arg, frame)
679 self.write('), %r, %r, %r)' % (
680 bool(frame.accesses_kwargs),
681 bool(frame.accesses_varargs),
682 bool(frame.accesses_caller)
685 def position(self, node):
686 """Return a human readable position for the node."""
687 rv = 'line %d' % node.lineno
688 if self.name is not None:
689 rv += ' in ' + repr(self.name)
692 # -- Statement Visitors
694 def visit_Template(self, node, frame=None):
695 assert frame is None, 'no root frame allowed'
696 from jinja2.runtime import __all__ as exported
697 self.writeline('from __future__ import division')
698 self.writeline('from jinja2.runtime import ' + ', '.join(exported))
700 # do we have an extends tag at all? If not, we can save some
701 # overhead by just not processing any inheritance code.
702 have_extends = node.find(nodes.Extends) is not None
705 for block in node.find_all(nodes.Block):
706 if block.name in self.blocks:
707 self.fail('block %r defined twice' % block.name, block.lineno)
708 self.blocks[block.name] = block
710 # find all imports and import them
711 for import_ in node.find_all(nodes.ImportedName):
712 if import_.importname not in self.import_aliases:
713 imp = import_.importname
714 self.import_aliases[imp] = alias = self.temporary_identifier()
716 module, obj = imp.rsplit('.', 1)
717 self.writeline('from %s import %s as %s' %
718 (module, obj, alias))
720 self.writeline('import %s as %s' % (imp, alias))
723 self.writeline('name = %r' % self.name)
725 # generate the root render function.
726 self.writeline('def root(context, environment=environment):', extra=1)
730 frame.inspect(node.body)
731 frame.toplevel = frame.rootlevel = True
732 frame.require_output_check = have_extends and not self.has_known_extends
735 self.writeline('parent_template = None')
736 if 'self' in find_undeclared(node.body, ('self',)):
737 frame.identifiers.add_special('self')
738 self.writeline('l_self = TemplateReference(context)')
739 self.pull_locals(frame)
740 self.pull_dependencies(node.body)
741 self.blockvisit(node.body, frame)
744 # make sure that the parent root is called.
746 if not self.has_known_extends:
748 self.writeline('if parent_template is not None:')
750 self.writeline('for event in parent_template.'
751 'root_render_func(context):')
753 self.writeline('yield event')
754 self.outdent(2 + (not self.has_known_extends))
756 # at this point we now have the blocks collected and can visit them too.
757 for name, block in self.blocks.iteritems():
758 block_frame = Frame()
759 block_frame.inspect(block.body)
760 block_frame.block = name
761 self.writeline('def block_%s(context, environment=environment):'
764 undeclared = find_undeclared(block.body, ('self', 'super'))
765 if 'self' in undeclared:
766 block_frame.identifiers.add_special('self')
767 self.writeline('l_self = TemplateReference(context)')
768 if 'super' in undeclared:
769 block_frame.identifiers.add_special('super')
770 self.writeline('l_super = context.super(%r, '
771 'block_%s)' % (name, name))
772 self.pull_locals(block_frame)
773 self.pull_dependencies(block.body)
774 self.blockvisit(block.body, block_frame)
777 self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
778 for x in self.blocks),
781 # add a function that returns the debug info
782 self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
785 def visit_Block(self, node, frame):
786 """Call a block and register it for the template."""
789 # if we know that we are a child template, there is no need to
790 # check if we are one
791 if self.has_known_extends:
793 if self.extends_so_far > 0:
794 self.writeline('if parent_template is None:')
798 context = 'context.derived(locals())'
801 self.writeline('for event in context.blocks[%r][0](%s):' % (
802 node.name, context), node)
804 self.simple_write('event', frame)
807 def visit_Extends(self, node, frame):
808 """Calls the extender."""
809 if not frame.toplevel:
810 self.fail('cannot use extend from a non top-level scope',
813 # if the number of extends statements in general is zero so
814 # far, we don't have to add a check if something extended
815 # the template before this one.
816 if self.extends_so_far > 0:
818 # if we have a known extends we just add a template runtime
819 # error into the generated code. We could catch that at compile
820 # time too, but i welcome it not to confuse users by throwing the
821 # same error at different times just "because we can".
822 if not self.has_known_extends:
823 self.writeline('if parent_template is not None:')
825 self.writeline('raise TemplateRuntimeError(%r)' %
826 'extended multiple times')
829 # if we have a known extends already we don't need that code here
830 # as we know that the template execution will end here.
831 if self.has_known_extends:
834 self.writeline('parent_template = environment.get_template(', node)
835 self.visit(node.template, frame)
836 self.write(', %r)' % self.name)
837 self.writeline('for name, parent_block in parent_template.'
838 'blocks.iteritems():')
840 self.writeline('context.blocks.setdefault(name, []).'
841 'append(parent_block)')
844 # if this extends statement was in the root level we can take
845 # advantage of that information and simplify the generated code
846 # in the top level from this point onwards
848 self.has_known_extends = True
850 # and now we have one more
851 self.extends_so_far += 1
853 def visit_Include(self, node, frame):
854 """Handles includes."""
855 if node.with_context:
856 self.unoptimize_scope(frame)
857 if node.ignore_missing:
858 self.writeline('try:')
860 self.writeline('template = environment.get_template(', node)
861 self.visit(node.template, frame)
862 self.write(', %r)' % self.name)
863 if node.ignore_missing:
865 self.writeline('except TemplateNotFound:')
867 self.writeline('pass')
869 self.writeline('else:')
872 if node.with_context:
873 self.writeline('for event in template.root_render_func('
874 'template.new_context(context.parent, True, '
877 self.writeline('for event in template.module._body_stream:')
880 self.simple_write('event', frame)
883 if node.ignore_missing:
886 def visit_Import(self, node, frame):
887 """Visit regular imports."""
888 if node.with_context:
889 self.unoptimize_scope(frame)
890 self.writeline('l_%s = ' % node.target, node)
892 self.write('context.vars[%r] = ' % node.target)
893 self.write('environment.get_template(')
894 self.visit(node.template, frame)
895 self.write(', %r).' % self.name)
896 if node.with_context:
897 self.write('make_module(context.parent, True, locals())')
900 if frame.toplevel and not node.target.startswith('_'):
901 self.writeline('context.exported_vars.discard(%r)' % node.target)
902 frame.assigned_names.add(node.target)
904 def visit_FromImport(self, node, frame):
905 """Visit named imports."""
907 self.write('included_template = environment.get_template(')
908 self.visit(node.template, frame)
909 self.write(', %r).' % self.name)
910 if node.with_context:
911 self.write('make_module(context.parent, True)')
917 for name in node.names:
918 if isinstance(name, tuple):
922 self.writeline('l_%s = getattr(included_template, '
923 '%r, missing)' % (alias, name))
924 self.writeline('if l_%s is missing:' % alias)
926 self.writeline('l_%s = environment.undefined(%r %% '
927 'included_template.__name__, '
929 (alias, 'the template %%r (imported on %s) does '
930 'not export the requested name %s' % (
936 var_names.append(alias)
937 if not alias.startswith('_'):
938 discarded_names.append(alias)
939 frame.assigned_names.add(alias)
942 if len(var_names) == 1:
944 self.writeline('context.vars[%r] = l_%s' % (name, name))
946 self.writeline('context.vars.update({%s})' % ', '.join(
947 '%r: l_%s' % (name, name) for name in var_names
950 if len(discarded_names) == 1:
951 self.writeline('context.exported_vars.discard(%r)' %
954 self.writeline('context.exported_vars.difference_'
955 'update((%s))' % ', '.join(map(repr, discarded_names)))
957 def visit_For(self, node, frame):
958 # when calculating the nodes for the inner frame we have to exclude
959 # the iterator contents from it
960 children = node.iter_child_nodes(exclude=('iter',))
962 loop_frame = self.function_scoping(node, frame, children,
965 loop_frame = frame.inner()
966 loop_frame.inspect(children)
968 # try to figure out if we have an extended loop. An extended loop
969 # is necessary if the loop is in recursive mode if the special loop
970 # variable is accessed in the body.
971 extended_loop = node.recursive or 'loop' in \
972 find_undeclared(node.iter_child_nodes(
973 only=('body',)), ('loop',))
975 # if we don't have an recursive loop we have to find the shadowed
976 # variables at that point. Because loops can be nested but the loop
977 # variable is a special one we have to enforce aliasing for it.
978 if not node.recursive:
979 aliases = self.push_scope(loop_frame, ('loop',))
981 # otherwise we set up a buffer and add a function def
983 self.writeline('def loop(reciter, loop_render_func):', node)
985 self.buffer(loop_frame)
988 # make sure the loop variable is a special one and raise a template
989 # assertion error if a loop tries to write to loop
991 loop_frame.identifiers.add_special('loop')
992 for name in node.find_all(nodes.Name):
993 if name.ctx == 'store' and name.name == 'loop':
994 self.fail('Can\'t assign to special loop variable '
995 'in for-loop target', name.lineno)
997 self.pull_locals(loop_frame)
999 iteration_indicator = self.temporary_identifier()
1000 self.writeline('%s = 1' % iteration_indicator)
1002 # Create a fake parent loop if the else or test section of a
1003 # loop is accessing the special loop variable and no parent loop
1005 if 'loop' not in aliases and 'loop' in find_undeclared(
1006 node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
1007 self.writeline("l_loop = environment.undefined(%r, name='loop')" %
1008 ("'loop' is undefined. the filter section of a loop as well "
1009 "as the else block doesn't have access to the special 'loop'"
1010 " variable of the current loop. Because there is no parent "
1011 "loop it's undefined. Happened in loop on %s" %
1012 self.position(node)))
1014 self.writeline('for ', node)
1015 self.visit(node.target, loop_frame)
1016 self.write(extended_loop and ', l_loop in LoopContext(' or ' in ')
1018 # if we have an extened loop and a node test, we filter in the
1020 if extended_loop and node.test is not None:
1022 self.visit(node.target, loop_frame)
1024 self.visit(node.target, loop_frame)
1027 self.write('reciter')
1029 self.visit(node.iter, loop_frame)
1031 test_frame = loop_frame.copy()
1032 self.visit(node.test, test_frame)
1035 elif node.recursive:
1036 self.write('reciter')
1038 self.visit(node.iter, loop_frame)
1041 self.write(', recurse=loop_render_func):')
1043 self.write(extended_loop and '):' or ':')
1045 # tests in not extended loops become a continue
1046 if not extended_loop and node.test is not None:
1048 self.writeline('if not ')
1049 self.visit(node.test, loop_frame)
1052 self.writeline('continue')
1056 self.blockvisit(node.body, loop_frame)
1058 self.writeline('%s = 0' % iteration_indicator)
1062 self.writeline('if %s:' % iteration_indicator)
1064 self.blockvisit(node.else_, loop_frame)
1067 # reset the aliases if there are any.
1068 if not node.recursive:
1069 self.pop_scope(aliases, loop_frame)
1071 # if the node was recursive we have to return the buffer contents
1072 # and start the iteration code
1074 self.return_buffer_contents(loop_frame)
1076 self.start_write(frame, node)
1078 self.visit(node.iter, frame)
1079 self.write(', loop)')
1080 self.end_write(frame)
1082 def visit_If(self, node, frame):
1083 if_frame = frame.soft()
1084 self.writeline('if ', node)
1085 self.visit(node.test, if_frame)
1088 self.blockvisit(node.body, if_frame)
1091 self.writeline('else:')
1093 self.blockvisit(node.else_, if_frame)
1096 def visit_Macro(self, node, frame):
1097 macro_frame = self.macro_body(node, frame)
1100 if not node.name.startswith('_'):
1101 self.write('context.exported_vars.add(%r)' % node.name)
1102 self.writeline('context.vars[%r] = ' % node.name)
1103 self.write('l_%s = ' % node.name)
1104 self.macro_def(node, macro_frame)
1105 frame.assigned_names.add(node.name)
1107 def visit_CallBlock(self, node, frame):
1108 children = node.iter_child_nodes(exclude=('call',))
1109 call_frame = self.macro_body(node, frame, children)
1110 self.writeline('caller = ')
1111 self.macro_def(node, call_frame)
1112 self.start_write(frame, node)
1113 self.visit_Call(node.call, call_frame, forward_caller=True)
1114 self.end_write(frame)
1116 def visit_FilterBlock(self, node, frame):
1117 filter_frame = frame.inner()
1118 filter_frame.inspect(node.iter_child_nodes())
1119 aliases = self.push_scope(filter_frame)
1120 self.pull_locals(filter_frame)
1121 self.buffer(filter_frame)
1122 self.blockvisit(node.body, filter_frame)
1123 self.start_write(frame, node)
1124 self.visit_Filter(node.filter, filter_frame)
1125 self.end_write(frame)
1126 self.pop_scope(aliases, filter_frame)
1128 def visit_ExprStmt(self, node, frame):
1130 self.visit(node.node, frame)
1132 def visit_Output(self, node, frame):
1133 # if we have a known extends statement, we don't output anything
1134 # if we are in a require_output_check section
1135 if self.has_known_extends and frame.require_output_check:
1138 if self.environment.finalize:
1139 finalize = lambda x: unicode(self.environment.finalize(x))
1145 # if we are inside a frame that requires output checking, we do so
1146 outdent_later = False
1147 if frame.require_output_check:
1148 self.writeline('if parent_template is None:')
1150 outdent_later = True
1152 # try to evaluate as many chunks as possible into a static
1153 # string at compile time.
1155 for child in node.nodes:
1157 const = child.as_const()
1158 except nodes.Impossible:
1162 if self.environment.autoescape:
1163 if hasattr(const, '__html__'):
1164 const = const.__html__()
1166 const = escape(const)
1167 const = finalize(const)
1169 # if something goes wrong here we evaluate the node
1170 # at runtime for easier debugging
1173 if body and isinstance(body[-1], list):
1174 body[-1].append(const)
1176 body.append([const])
1178 # if we have less than 3 nodes or a buffer we yield or extend/append
1179 if len(body) < 3 or frame.buffer is not None:
1180 if frame.buffer is not None:
1181 # for one item we append, for more we extend
1183 self.writeline('%s.append(' % frame.buffer)
1185 self.writeline('%s.extend((' % frame.buffer)
1188 if isinstance(item, list):
1189 val = repr(concat(item))
1190 if frame.buffer is None:
1191 self.writeline('yield ' + val)
1193 self.writeline(val + ', ')
1195 if frame.buffer is None:
1196 self.writeline('yield ', item)
1200 if self.environment.autoescape:
1201 self.write('escape(')
1203 self.write('to_string(')
1204 if self.environment.finalize is not None:
1205 self.write('environment.finalize(')
1207 self.visit(item, frame)
1208 self.write(')' * close)
1209 if frame.buffer is not None:
1211 if frame.buffer is not None:
1212 # close the open parentheses
1214 self.writeline(len(body) == 1 and ')' or '))')
1216 # otherwise we create a format string as this is faster in that case
1221 if isinstance(item, list):
1222 format.append(concat(item).replace('%', '%%'))
1225 arguments.append(item)
1226 self.writeline('yield ')
1227 self.write(repr(concat(format)) + ' % (')
1230 for argument in arguments:
1231 self.newline(argument)
1233 if self.environment.autoescape:
1234 self.write('escape(')
1236 if self.environment.finalize is not None:
1237 self.write('environment.finalize(')
1239 self.visit(argument, frame)
1240 self.write(')' * close + ', ')
1247 def visit_Assign(self, node, frame):
1249 # toplevel assignments however go into the local namespace and
1250 # the current template's context. We create a copy of the frame
1251 # here and add a set so that the Name visitor can add the assigned
1254 assignment_frame = frame.copy()
1255 assignment_frame.toplevel_assignments = set()
1257 assignment_frame = frame
1258 self.visit(node.target, assignment_frame)
1260 self.visit(node.node, frame)
1262 # make sure toplevel assignments are added to the context.
1264 public_names = [x for x in assignment_frame.toplevel_assignments
1265 if not x.startswith('_')]
1266 if len(assignment_frame.toplevel_assignments) == 1:
1267 name = next(iter(assignment_frame.toplevel_assignments))
1268 self.writeline('context.vars[%r] = l_%s' % (name, name))
1270 self.writeline('context.vars.update({')
1271 for idx, name in enumerate(assignment_frame.toplevel_assignments):
1274 self.write('%r: l_%s' % (name, name))
1277 if len(public_names) == 1:
1278 self.writeline('context.exported_vars.add(%r)' %
1281 self.writeline('context.exported_vars.update((%s))' %
1282 ', '.join(map(repr, public_names)))
1284 # -- Expression Visitors
1286 def visit_Name(self, node, frame):
1287 if node.ctx == 'store' and frame.toplevel:
1288 frame.toplevel_assignments.add(node.name)
1289 self.write('l_' + node.name)
1290 frame.assigned_names.add(node.name)
1292 def visit_Const(self, node, frame):
1294 if isinstance(val, float):
1295 self.write(str(val))
1297 self.write(repr(val))
1299 def visit_TemplateData(self, node, frame):
1300 self.write(repr(node.as_const()))
1302 def visit_Tuple(self, node, frame):
1305 for idx, item in enumerate(node.items):
1308 self.visit(item, frame)
1309 self.write(idx == 0 and ',)' or ')')
1311 def visit_List(self, node, frame):
1313 for idx, item in enumerate(node.items):
1316 self.visit(item, frame)
1319 def visit_Dict(self, node, frame):
1321 for idx, item in enumerate(node.items):
1324 self.visit(item.key, frame)
1326 self.visit(item.value, frame)
1329 def binop(operator):
1330 def visitor(self, node, frame):
1332 self.visit(node.left, frame)
1333 self.write(' %s ' % operator)
1334 self.visit(node.right, frame)
1339 def visitor(self, node, frame):
1340 self.write('(' + operator)
1341 self.visit(node.node, frame)
1345 visit_Add = binop('+')
1346 visit_Sub = binop('-')
1347 visit_Mul = binop('*')
1348 visit_Div = binop('/')
1349 visit_FloorDiv = binop('//')
1350 visit_Pow = binop('**')
1351 visit_Mod = binop('%')
1352 visit_And = binop('and')
1353 visit_Or = binop('or')
1354 visit_Pos = uaop('+')
1355 visit_Neg = uaop('-')
1356 visit_Not = uaop('not ')
1359 def visit_Concat(self, node, frame):
1360 self.write('%s((' % (self.environment.autoescape and
1361 'markup_join' or 'unicode_join'))
1362 for arg in node.nodes:
1363 self.visit(arg, frame)
1367 def visit_Compare(self, node, frame):
1368 self.visit(node.expr, frame)
1370 self.visit(op, frame)
1372 def visit_Operand(self, node, frame):
1373 self.write(' %s ' % operators[node.op])
1374 self.visit(node.expr, frame)
1376 def visit_Getattr(self, node, frame):
1377 self.write('environment.getattr(')
1378 self.visit(node.node, frame)
1379 self.write(', %r)' % node.attr)
1381 def visit_Getitem(self, node, frame):
1382 # slices bypass the environment getitem method.
1383 if isinstance(node.arg, nodes.Slice):
1384 self.visit(node.node, frame)
1386 self.visit(node.arg, frame)
1389 self.write('environment.getitem(')
1390 self.visit(node.node, frame)
1392 self.visit(node.arg, frame)
1395 def visit_Slice(self, node, frame):
1396 if node.start is not None:
1397 self.visit(node.start, frame)
1399 if node.stop is not None:
1400 self.visit(node.stop, frame)
1401 if node.step is not None:
1403 self.visit(node.step, frame)
1405 def visit_Filter(self, node, frame):
1406 self.write(self.filters[node.name] + '(')
1407 func = self.environment.filters.get(node.name)
1409 self.fail('no filter named %r' % node.name, node.lineno)
1410 if getattr(func, 'contextfilter', False):
1411 self.write('context, ')
1412 elif getattr(func, 'environmentfilter', False):
1413 self.write('environment, ')
1415 # if the filter node is None we are inside a filter block
1416 # and want to write to the current buffer
1417 if node.node is not None:
1418 self.visit(node.node, frame)
1419 elif self.environment.autoescape:
1420 self.write('Markup(concat(%s))' % frame.buffer)
1422 self.write('concat(%s)' % frame.buffer)
1423 self.signature(node, frame)
1426 def visit_Test(self, node, frame):
1427 self.write(self.tests[node.name] + '(')
1428 if node.name not in self.environment.tests:
1429 self.fail('no test named %r' % node.name, node.lineno)
1430 self.visit(node.node, frame)
1431 self.signature(node, frame)
1434 def visit_CondExpr(self, node, frame):
1436 if node.expr2 is not None:
1437 return self.visit(node.expr2, frame)
1438 self.write('environment.undefined(%r)' % ('the inline if-'
1439 'expression on %s evaluated to false and '
1440 'no else section was defined.' % self.position(node)))
1442 if not have_condexpr:
1444 self.visit(node.test, frame)
1445 self.write(') and (')
1446 self.visit(node.expr1, frame)
1447 self.write(',) or (')
1449 self.write(',))[0]')
1452 self.visit(node.expr1, frame)
1454 self.visit(node.test, frame)
1455 self.write(' else ')
1459 def visit_Call(self, node, frame, forward_caller=False):
1460 if self.environment.sandboxed:
1461 self.write('environment.call(context, ')
1463 self.write('context.call(')
1464 self.visit(node.node, frame)
1465 extra_kwargs = forward_caller and {'caller': 'caller'} or None
1466 self.signature(node, frame, extra_kwargs)
1469 def visit_Keyword(self, node, frame):
1470 self.write(node.key + '=')
1471 self.visit(node.value, frame)
1473 # -- Unused nodes for extensions
1475 def visit_MarkSafe(self, node, frame):
1476 self.write('Markup(')
1477 self.visit(node.expr, frame)
1480 def visit_EnvironmentAttribute(self, node, frame):
1481 self.write('environment.' + node.name)
1483 def visit_ExtensionAttribute(self, node, frame):
1484 self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
1486 def visit_ImportedName(self, node, frame):
1487 self.write(self.import_aliases[node.importname])
1489 def visit_InternalName(self, node, frame):
1490 self.write(node.name)
1492 def visit_ContextReference(self, node, frame):
1493 self.write('context')
1495 def visit_Continue(self, node, frame):
1496 self.writeline('continue', node)
1498 def visit_Break(self, node, frame):
1499 self.writeline('break', node)
1501 def visit_Scope(self, node, frame):
1502 scope_frame = frame.inner()
1503 scope_frame.inspect(node.iter_child_nodes())
1504 aliases = self.push_scope(scope_frame)
1505 self.pull_locals(scope_frame)
1506 self.blockvisit(node.body, scope_frame)
1507 self.pop_scope(aliases, scope_frame)