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