diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py index 20b32b69b5e972a4c38f2d0139e6fac44081a61a..1068ae54926898155de42bf60c6814eb982495d1 100644 --- a/lib/mako/codegen.py +++ b/lib/mako/codegen.py @@ -83,7 +83,12 @@ class _GenerateRenderMethod(object): def write_variable_declares(self, identifiers): comp_idents = dict([(c.name, c) for c in identifiers.components]) print "Write variable declares, set is", identifiers.undeclared.union(util.Set([c.name for c in identifiers.closurecomponents if c.parent is self.node])) - for ident in identifiers.undeclared.union(util.Set([c.name for c in identifiers.closurecomponents if c.parent is self.node])): + + to_write = identifiers.declared.intersection(identifiers.locally_declared) + to_write = to_write.union(identifiers.undeclared) + to_write = to_write.union(util.Set([c.name for c in identifiers.closurecomponents if c.parent is self.node])) + + for ident in to_write: if ident in comp_idents: comp = comp_idents[ident] if comp.is_root(): @@ -111,20 +116,18 @@ class _GenerateRenderMethod(object): namedecls = node.function_decl.get_argument_expressions() self.printer.writeline("def %s(%s):" % (node.name, ",".join(namedecls))) - print "inline component, name", node.name, identifiers identifiers = identifiers.branch(node) print "updated", identifiers, "\n" - raise "hi" - make_closure = False #len(localdecl) > 0 +# raise "hi" + + make_closure = len(identifiers.locally_declared) > 0 -# if make_closure: -# self.printer.writeline("def %s(%s):" % (node.name, ",".join(['context'] + namedecls))) -# (compdecl, compundecl) = _find_declared_identifiers(node.nodes, declared, localundecl) -# else: -# (compdecl, compundecl) = _find_declared_identifiers(node.nodes, declared, undeclared) -# raise "hi" - self.write_variable_declares(identifiers) + if make_closure: + self.printer.writeline("def %s(%s):" % (node.name, ",".join(['context'] + namedecls))) + self.write_variable_declares(identifiers) + else: + self.write_variable_declares(identifiers) for n in node.nodes: n.accept_visitor(self) @@ -186,7 +189,7 @@ class _GenerateRenderMethod(object): class _Identifiers(object): def __init__(self, node=None, parent=None): if parent is not None: - self.declared = util.Set(parent.declared).union([c.name for c in parent.closurecomponents]) + self.declared = util.Set(parent.declared).union([c.name for c in parent.closurecomponents]).union(parent.locally_declared) self.undeclared = util.Set() self.toplevelcomponents = util.Set(parent.toplevelcomponents) self.closurecomponents = util.Set() @@ -195,6 +198,7 @@ class _Identifiers(object): self.undeclared = util.Set() self.toplevelcomponents = util.Set() self.closurecomponents = util.Set() + self.locally_declared = util.Set() self.node = node if node is not None: @@ -206,13 +210,14 @@ class _Identifiers(object): components = property(lambda s:s.toplevelcomponents.union(s.closurecomponents)) def __repr__(self): - return "Identifiers(%s, %s, %s, %s)" % (repr(list(self.declared)), repr(list(self.undeclared)), repr([c.name for c in self.toplevelcomponents]), repr([c.name for c in self.closurecomponents])) + return "Identifiers(%s, %s, %s, %s, %s)" % (repr(list(self.declared)), repr(list(self.locally_declared)), repr(list(self.undeclared)), repr([c.name for c in self.toplevelcomponents]), repr([c.name for c in self.closurecomponents])) + def check_declared(self, node): for ident in node.declared_identifiers(): - self.declared.add(ident) + self.locally_declared.add(ident) for ident in node.undeclared_identifiers(): - if ident != 'context' and ident not in self.declared: + if ident != 'context' and ident not in self.declared.union(self.locally_declared): self.undeclared.add(ident) def visitExpression(self, node): self.check_declared(node) @@ -225,7 +230,7 @@ class _Identifiers(object): #print "component tag", node.name, "our node is:", getattr(self.node, 'name', self.node.__class__.__name__), (node is self.node or node.parent is self.node) if node.is_root(): self.toplevelcomponents.add(node) - else: + elif node is not self.node: self.closurecomponents.add(node) self.check_declared(node) if node is self.node: diff --git a/test/template.py b/test/template.py index e907a98298c9a4385b5441bd0726262737dd74e9..ab429f89cd41e8a330a22532e3aa0652901f4603 100644 --- a/test/template.py +++ b/test/template.py @@ -62,6 +62,43 @@ im c # then test output assert template.render().strip() == "im b\nand heres a: im a" + def test_local_names(self): + template = """ + + <%component name="a"> + this is a, and y is ${y} + </%component> + + ${a()} + + <% + y = 7 + %> + + ${a()} + +""" + t = Template(template) + print t.code + result = t.render() + result = re.sub(r'[\s\n]+', ' ', result).strip() + assert result == "this is a, and y is None this is a, and y is 7" + + def test_local_names_2(self): + template = """ + y is ${y} + + <% + y = 7 + %> + + y is ${y} +""" + t = Template(template) + result = t.render() + result = re.sub(r'[\s\n]+', ' ', result).strip() + assert result == "y is None y is 7" + class NestedComponentTest(unittest.TestCase): def test_nested_component(self): template = """ @@ -164,42 +201,6 @@ class NestedComponentTest(unittest.TestCase): t = Template(template) print t.code - def test_local_names(self): - template = """ - - <%component name="a"> - this is a, and y is ${y} - </%component> - - ${a()} - - <% - y = 7 - %> - - ${a()} - -""" - t = Template(template) - #print t.code - result = t.render() - result = re.sub(r'[\s\n]+', ' ', result).strip() - assert result == "this is a, and y is None this is a, and y is 7" - - def test_local_names_2(self): - template = """ - y is ${y} - - <% - y = 7 - %> - - y is ${y} -""" - t = Template(template) - result = t.render() - result = re.sub(r'[\s\n]+', ' ', result).strip() - assert result == "y is None y is 7" def test_local_local_names(self): """test assignment of variables inside nested components, which requires extra scoping logic""" @@ -243,12 +244,12 @@ class NestedComponentTest(unittest.TestCase): heres y again: ${y} """ - t = Template(template) + t = Template(template, format_exceptions=False) print t.code result = t.render(y=5) - print result result = re.sub(r'[\s\n]+', ' ', result).strip() - assert result == "heres y: 5 now heres y 7 a, heres y: 7 a, now heres y: 10 a, heres b: b, heres y: 10 heres y again: 7" + print result + assert result == "heres y: 5 now heres y 7 a, heres y: 7 a, now heres y: 10 a, heres b: b, heres y: 10 b, heres c: this is c b, heres y again: 19 heres y again: 7" class NamespaceTest(unittest.TestCase): def test_inline(self):