def test_invalidate(self): t = Template(""" <%%def name="foo()" cached="True"> foo: ${x} </%%def> <%%def name="bar()" cached="True" cache_type='dbm' cache_dir='%s'> bar: ${x} </%%def> ${foo()} ${bar()} """ % module_base) self._install_mock_cache(t) assert result_lines(t.render(x=1)) == ["foo: 1", "bar: 1"] assert result_lines(t.render(x=2)) == ["foo: 1", "bar: 1"] t.cache.invalidate_def('foo') assert result_lines(t.render(x=3)) == ["foo: 3", "bar: 1"] t.cache.invalidate_def('bar') assert result_lines(t.render(x=4)) == ["foo: 3", "bar: 4"] t = Template(""" <%%page cached="True" cache_type="dbm" cache_dir="%s"/> page: ${x} """ % module_base) self._install_mock_cache(t) assert result_lines(t.render(x=1)) == ["page: 1"] assert result_lines(t.render(x=2)) == ["page: 1"] t.cache.invalidate_body() assert result_lines(t.render(x=3)) == ["page: 3"] assert result_lines(t.render(x=4)) == ["page: 3"]
def test_module_roundtrip(self): lookup = TemplateLookup() template = Template(""" <%inherit file="base.html"/> % for x in range(5): ${x} % endfor """, lookup=lookup) base = Template(""" This is base. ${self.body()} """, lookup=lookup) lookup.put_template("base.html", base) lookup.put_template("template.html", template) assert result_lines(template.render()) == [ "This is base.", "0", "1", "2", "3", "4" ] lookup = TemplateLookup() template = ModuleTemplate(template.module, lookup=lookup) base = ModuleTemplate(base.module, lookup=lookup) lookup.put_template("base.html", base) lookup.put_template("template.html", template) assert result_lines(template.render()) == [ "This is base.", "0", "1", "2", "3", "4" ]
def test_strict(self): t = Template(""" % if x is UNDEFINED: undefined % else: x: ${x} % endif """, strict_undefined=True) assert result_lines(t.render(x=12)) == ['x: 12'] assert_raises(NameError, t.render, y=12) l = TemplateLookup(strict_undefined=True) l.put_string("a", "some template") l.put_string( "b", """ <%namespace name='a' file='a' import='*'/> % if x is UNDEFINED: undefined % else: x: ${x} % endif """) assert result_lines(t.render(x=12)) == ['x: 12'] assert_raises(NameError, t.render, y=12)
def test_strict(self): t = Template(""" % if x is UNDEFINED: undefined % else: x: ${x} % endif """, strict_undefined=True) assert result_lines(t.render(x=12)) == ['x: 12'] assert_raises( NameError, t.render, y=12 ) l = TemplateLookup(strict_undefined=True) l.put_string("a", "some template") l.put_string("b", """ <%namespace name='a' file='a' import='*'/> % if x is UNDEFINED: undefined % else: x: ${x} % endif """) assert result_lines(t.render(x=12)) == ['x: 12'] assert_raises( NameError, t.render, y=12 )
def test_module_roundtrip(self): lookup = TemplateLookup() template = Template(""" <%inherit file="base.html"/> % for x in range(5): ${x} % endfor """, lookup=lookup) base = Template(""" This is base. ${self.body()} """, lookup=lookup) lookup.put_template("base.html", base) lookup.put_template("template.html", template) assert result_lines( template.render()) == ["This is base.", "0", "1", "2", "3", "4"] lookup = TemplateLookup() template = ModuleTemplate(template.module, lookup=lookup) base = ModuleTemplate(base.module, lookup=lookup) lookup.put_template("base.html", base) lookup.put_template("template.html", template) assert result_lines( template.render()) == ["This is base.", "0", "1", "2", "3", "4"]
def test_interpret_expression_from_arg_two(self): """test that cache_key=${foo} gets its value from the 'foo' argument regardless of it being passed from the context. This is here testing that there's no change to existing behavior before and after #191. """ t = Template(""" <%def name="layout(foo)" cached="True" cache_key="${foo}"> foo: ${value} </%def> ${layout(3)} """, cache_impl="plain") eq_( result_lines(t.render(foo='foo', value=1)), ["foo: 1"] ) eq_( result_lines(t.render(foo='bar', value=2)), ["foo: 1"] )
def test_invalidate(self): t = Template(""" <%%def name="foo()" cached="True"> foo: ${x} </%%def> <%%def name="bar()" cached="True" cache_type='dbm' cache_dir='%s'> bar: ${x} </%%def> ${foo()} ${bar()} """ % module_base) self._install_mock_cache(t) assert result_lines(t.render(x=1)) == ["foo: 1", "bar: 1"] assert result_lines(t.render(x=2)) == ["foo: 1", "bar: 1"] t.cache.invalidate_def('foo') assert result_lines(t.render(x=3)) == ["foo: 3", "bar: 1"] t.cache.invalidate_def('bar') assert result_lines(t.render(x=4)) == ["foo: 3", "bar: 4"] t = Template(""" <%%page cached="True" cache_type="dbm" cache_dir="%s"/> page: ${x} """ % module_base) self._install_mock_cache(t) assert result_lines(t.render(x=1)) == ["page: 1"] assert result_lines(t.render(x=2)) == ["page: 1"] t.cache.invalidate_body() assert result_lines(t.render(x=3)) == ["page: 3"] assert result_lines(t.render(x=4)) == ["page: 3"]
def test_custom_args_page(self): t = Template(""" <%page cached="True" cache_region="myregion" cache_timeout="50" cache_foo="foob"/> """) m = self._install_mock_cache(t, "simple") t.render() eq_(m.kwargs, {'region': 'myregion', 'timeout': 50, 'foo': 'foob'})
def test_nested_call_4(self): base = """ <%def name="A()"> A_def ${caller.body()} </%def> <%def name="B()"> B_def ${caller.body()} </%def> """ template = Template(base + """ <%def name="C()"> C_def <%self:B> <%self:A> A_body </%self:A> B_body ${caller.body()} </%self:B> </%def> <%self:C> C_body </%self:C> """) eq_( flatten_result(template.render()), "C_def B_def A_def A_body B_body C_body" ) template = Template(base + """ <%def name="C()"> C_def <%self:B> B_body ${caller.body()} <%self:A> A_body </%self:A> </%self:B> </%def> <%self:C> C_body </%self:C> """) eq_( flatten_result(template.render()), "C_def B_def B_body C_body A_def A_body" )
def test_builtins(self): t = Template(""" ${"this is <text>" | h} """) assert flatten_result(t.render()) == "this is <text>" t = Template(""" http://foo.com/arg1=${"hi! this is a string." | u} """) assert flatten_result(t.render()) == "http://foo.com/arg1=hi%21+this+is+a+string."
def test_custom_args_def(self): t = Template(""" <%def name="foo()" cached="True" cache_region="myregion" cache_timeout="50" cache_foo="foob"> </%def> ${foo()} """) m = self._install_mock_cache(t, 'simple') t.render() eq_(m.kwargs, {'region': 'myregion', 'timeout': 50, 'foo': 'foob'})
def test_builtins(self): t = Template(""" ${"this is <text>" | h} """) assert flatten_result(t.render()) == "this is <text>" t = Template(""" http://foo.com/arg1=${"hi! this is a string." | u} """) assert flatten_result(t.render()) == "http://foo.com/arg1=hi%21+this+is+a+string."
def test_basic(self): template = Template(""" <%page args="x, y, z=7"/> this is page, ${x}, ${y}, ${z} """) assert flatten_result(template.render(x=5, y=10)) == "this is page, 5, 10, 7" assert flatten_result(template.render(x=5, y=10, z=32)) == "this is page, 5, 10, 32" assert_raises(TypeError, template.render, y=10)
def test_dynamic_key_with_funcargs(self): t = Template(""" <%def name="foo(num=5)" cached="True" cache_key="foo_${str(num)}"> hi </%def> ${foo()} """) m = self._install_mock_cache(t) t.render() t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_5" t = Template(""" <%def name="foo(*args, **kwargs)" cached="True" cache_key="foo_${kwargs['bar']}"> hi </%def> ${foo(1, 2, bar='lala')} """) m = self._install_mock_cache(t) t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_lala" t = Template(''' <%page args="bar='hi'" cache_key="foo_${bar}" cached="True"/> hi ''') m = self._install_mock_cache(t) t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_hi"
def test_expression_declared(self): t = Template(""" ${",".join([t for t in ("a", "b", "c")])} """, strict_undefined=True) eq_(result_lines(t.render()), ['a,b,c']) t = Template(""" <%self:foo value="${[(val, n) for val, n in [(1, 2)]]}"/> <%def name="foo(value)"> ${value} </%def> """, strict_undefined=True) eq_(result_lines(t.render()), ['[(1, 2)]']) t = Template(""" <%call expr="foo(value=[(val, n) for val, n in [(1, 2)]])" /> <%def name="foo(value)"> ${value} </%def> """, strict_undefined=True) eq_(result_lines(t.render()), ['[(1, 2)]']) l = TemplateLookup(strict_undefined=True) l.put_string("i", "hi, ${pageargs['y']}") l.put_string( "t", """ <%include file="i" args="y=[x for x in range(3)]" /> """) eq_(result_lines(l.get_template("t").render()), ['hi, [0, 1, 2]']) l.put_string( 'q', """ <%namespace name="i" file="${(str([x for x in range(3)][2]) + 'i')[-1]}" /> ${i.body(y='x')} """) eq_(result_lines(l.get_template("q").render()), ['hi, x']) t = Template(""" <% y = lambda q: str(q) %> ${y('hi')} """, strict_undefined=True) eq_(result_lines(t.render()), ["hi"])
def test_dynamic_key_with_funcargs(self): t = Template(""" <%def name="foo(num=5)" cached="True" cache_key="foo_${str(num)}"> hi </%def> ${foo()} """) m = self._install_mock_cache(t) t.render() t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_5" t = Template(""" <%def name="foo(*args, **kwargs)" cached="True" cache_key="foo_${kwargs['bar']}"> hi </%def> ${foo(1, 2, bar='lala')} """) m = self._install_mock_cache(t) t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_lala" t = Template(''' <%page args="bar='hi'" cache_key="foo_${bar}" cached="True"/> hi ''') m = self._install_mock_cache(t) t.render() assert result_lines(t.render()) == ['hi'] assert m.key == "foo_hi"
def test_expression_declared(self): t = Template(""" ${",".join([t for t in ("a", "b", "c")])} """, strict_undefined=True) eq_(result_lines(t.render()), ['a,b,c']) t = Template(""" <%self:foo value="${[(val, n) for val, n in [(1, 2)]]}"/> <%def name="foo(value)"> ${value} </%def> """, strict_undefined=True) eq_(result_lines(t.render()), ['[(1, 2)]']) t = Template(""" <%call expr="foo(value=[(val, n) for val, n in [(1, 2)]])" /> <%def name="foo(value)"> ${value} </%def> """, strict_undefined=True) eq_(result_lines(t.render()), ['[(1, 2)]']) l = TemplateLookup(strict_undefined=True) l.put_string("i", "hi, ${pageargs['y']}") l.put_string("t", """ <%include file="i" args="y=[x for x in range(3)]" /> """) eq_( result_lines(l.get_template("t").render()), ['hi, [0, 1, 2]'] ) l.put_string('q', """ <%namespace name="i" file="${(str([x for x in range(3)][2]) + 'i')[-1]}" /> ${i.body(y='x')} """) eq_( result_lines(l.get_template("q").render()), ['hi, x'] ) t = Template(""" <% y = lambda q: str(q) %> ${y('hi')} """, strict_undefined=True) eq_( result_lines(t.render()), ["hi"] )
def test_no_lookup(self): t = Template("hi <%include file='foo.html'/>") try: t.render() assert False except errors.TemplateLookupException: eq_( str(compat.exception_as()), "Template 'memory:%s' has no TemplateLookup associated" % \ hex(id(t)) )
def test_custom_args_page(self): t = Template(""" <%page cached="True" cache_region="myregion" cache_timeout="50" cache_foo="foob"/> """) m = self._install_mock_cache(t, "simple") t.render() eq_( m.kwargs, {'region': 'myregion', 'timeout': 50, 'foo': 'foob'})
def test_pass_context(self): t = Template(""" <%page cached="True"/> """) m = self._install_mock_cache(t) t.render() assert 'context' not in m.kwargs m.pass_context = True t.render(x="bar") assert 'context' in m.kwargs assert m.kwargs['context'].get('x') == 'bar'
def test_pass_context(self): t = Template(""" <%page cached="True"/> """) m = self._install_mock_cache(t) t.render() assert 'context' not in m.kwargs m.pass_context = True t.render(x="bar") assert 'context' in m.kwargs assert m.kwargs['context'].get('x') == 'bar'
def test_basic(self): template = Template(""" <%page args="x, y, z=7"/> this is page, ${x}, ${y}, ${z} """) assert flatten_result(template.render( x=5, y=10)) == "this is page, 5, 10, 7" assert flatten_result(template.render( x=5, y=10, z=32)) == "this is page, 5, 10, 32" assert_raises(TypeError, template.render, y=10)
def test_custom_args_def(self): t = Template(""" <%def name="foo()" cached="True" cache_region="myregion" cache_timeout="50" cache_foo="foob"> </%def> ${foo()} """) m = self._install_mock_cache(t, 'simple') t.render() eq_( m.kwargs, {'region': 'myregion', 'timeout': 50, 'foo': 'foob'})
def test_cache_uses_current_context(self): t = Template(""" ${foo()} <%def name="foo()" cached="True" cache_timeout="1"> foo: ${x} </%def> """) self._install_mock_cache(t) x1 = t.render(x=1) time.sleep(1.2) x2 = t.render(x=2) eq_(x1.strip(), "foo: 1") eq_(x2.strip(), "foo: 2")
def test_cache_uses_current_context(self): t = Template(""" ${foo()} <%def name="foo()" cached="True" cache_timeout="1"> foo: ${x} </%def> """) self._install_mock_cache(t) x1 = t.render(x=1) time.sleep(1.2) x2 = t.render(x=2) eq_(x1.strip(), "foo: 1") eq_(x2.strip(), "foo: 2")
def test_scope_two(self): t = Template(""" y is ${y} <% y = 7 %> y is ${y} """) try: t.render(y=None) assert False except UnboundLocalError: assert True
def test_scope_two(self): t = Template(""" y is ${y} <% y = 7 %> y is ${y} """) try: t.render(y=None) assert False except UnboundLocalError: assert True
def test_basic(self): t = Template(""" <%! cached = None %> <%def name="foo()"> <% global cached if cached: return "cached: " + cached __M_writer = context._push_writer() %> this is foo <% buf, __M_writer = context._pop_buffer_and_writer() cached = buf.getvalue() return cached %> </%def> ${foo()} ${foo()} """) assert result_lines(t.render()) == [ "this is foo", "cached:", "this is foo" ]
def test_new_syntax(self): """test foo:bar syntax, including multiline args and expression eval.""" # note the trailing whitespace in the bottom ${} expr, need to strip # that off < python 2.7 t = Template(""" <%def name="foo(x, y, q, z)"> ${x} ${y} ${q} ${",".join("%s->%s" % (a, b) for a, b in z)} </%def> <%self:foo x="this is x" y="${'some ' + 'y'}" q=" this is q" z="${[ (1, 2), (3, 4), (5, 6) ] }"/> """) eq_( result_lines(t.render()), ['this is x', 'some y', 'this', 'is', 'q', '1->2,3->4,5->6'] )
def test_call_in_nested_2(self): t = Template(""" <%def name="a()"> <%def name="d()"> not this d </%def> this is a ${b()} <%def name="b()"> <%def name="d()"> not this d either </%def> this is b <%call expr="c()"> <%def name="d()"> this is d </%def> this is the body in b's call </%call> </%def> <%def name="c()"> this is c: ${caller.body()} the embedded "d" is: ${caller.d()} </%def> </%def> ${a()} """) assert result_lines(t.render()) == ['this is a', 'this is b', 'this is c:', "this is the body in b's call", 'the embedded "d" is:', 'this is d']
def test_chained_call_in_nested(self): t = Template(""" <%def name="embedded()"> <%def name="a()"> this is a. <%call expr="b()"> this is a's ccall. heres my body: ${caller.body()} </%call> </%def> <%def name="b()"> this is b. heres my body: ${caller.body()} whats in the body's caller's body ? ${context.caller_stack[-2].body()} </%def> <%call expr="a()"> heres the main templ call </%call> </%def> ${embedded()} """) #print t.code #print result_lines(t.render()) assert result_lines(t.render()) == [ 'this is a.', 'this is b. heres my body:', "this is a's ccall. heres my body:", 'heres the main templ call', "whats in the body's caller's body ?", 'heres the main templ call' ]
def test_fileargs_pagetag(self): t = Template(""" <%%page cache_dir='%s' cache_type='dbm'/> <%%! callcount = [0] %%> <%%def name="foo()" cached="True"> this is foo <%% callcount[0] += 1 %%> </%%def> ${foo()} ${foo()} ${foo()} callcount: ${callcount} """ % module_base) m = self._install_mock_cache(t) assert result_lines(t.render()) == [ 'this is foo', 'this is foo', 'this is foo', 'callcount: [1]', ] eq_(m.kwargs, {'dir': module_base, 'type': 'dbm'})
def test_nested_call_2(self): t = Template(""" x is ${x} <%def name="foo()"> ${caller.foosub(x=10)} </%def> <%def name="bar()"> bar: ${caller.barsub()} </%def> <%call expr="foo()"> <%def name="foosub(x)"> this is foo body: ${x} <%call expr="bar()"> <%def name="barsub()"> this is bar body: ${x} </%def> </%call> </%def> </%call> """) assert result_lines(t.render(x=5)) == [ "x is 5", "this is foo body: 10", "bar:", "this is bar body: 10" ]
def test_scope_ten(self): t = Template(""" <%def name="a()"> <%def name="b()"> <% y = 19 %> b/c: ${c()} b/y: ${y} </%def> <%def name="c()"> c/y: ${y} </%def> <% # we assign to "y". but the 'enclosing # scope' of "b" and "c" is from # the "y" on the outside y = 10 %> a/y: ${y} a/b: ${b()} </%def> <% y = 7 %> main/a: ${a()} main/y: ${y} """) eq_( flatten_result(t.render()), "main/a: a/y: 10 a/b: b/c: c/y: 10 b/y: 19 main/y: 7" )
def test_inter_def(self): """test defs calling each other""" template = Template(""" ${b()} <%def name="a()">\ im a </%def> <%def name="b()"> im b and heres a: ${a()} </%def> <%def name="c()"> im c </%def> """) # check that "a" is declared in "b", but not in "c" if compat.py3k: assert "a" not in template.module.render_c.__code__.co_varnames assert "a" in template.module.render_b.__code__.co_varnames else: assert "a" not in template.module.render_c.func_code.co_varnames assert "a" in template.module.render_b.func_code.co_varnames # then test output eq_( flatten_result(template.render()), "im b and heres a: im a" )
def test_scope_five(self): """test that variables are pulled from 'enclosing' scope before context.""" # same as test four, but adds a scope around it. t = Template(""" <%def name="enclosing()"> <% x = 5 %> <%def name="a()"> this is a. x is ${x}. </%def> <%def name="b()"> <% x = 9 %> this is b. x is ${x}. calling a. ${a()} </%def> ${b()} </%def> ${enclosing()} """) eq_( flatten_result(t.render()), "this is b. x is 9. calling a. this is a. x is 5." )
def test_inter_def(self): """test defs calling each other""" template = Template(""" ${b()} <%def name="a()">\ im a </%def> <%def name="b()"> im b and heres a: ${a()} </%def> <%def name="c()"> im c </%def> """) # check that "a" is declared in "b", but not in "c" if compat.py3k: assert "a" not in template.module.render_c.__code__.co_varnames assert "a" in template.module.render_b.__code__.co_varnames else: assert "a" not in template.module.render_c.__code__.co_varnames assert "a" in template.module.render_b.__code__.co_varnames # then test output eq_(flatten_result(template.render()), "im b and heres a: im a")
def test_scope_ten(self): t = Template(""" <%def name="a()"> <%def name="b()"> <% y = 19 %> b/c: ${c()} b/y: ${y} </%def> <%def name="c()"> c/y: ${y} </%def> <% # we assign to "y". but the 'enclosing # scope' of "b" and "c" is from # the "y" on the outside y = 10 %> a/y: ${y} a/b: ${b()} </%def> <% y = 7 %> main/a: ${a()} main/y: ${y} """) eq_(flatten_result(t.render()), "main/a: a/y: 10 a/b: b/c: c/y: 10 b/y: 19 main/y: 7")
def test_scope_five(self): """test that variables are pulled from 'enclosing' scope before context.""" # same as test four, but adds a scope around it. t = Template(""" <%def name="enclosing()"> <% x = 5 %> <%def name="a()"> this is a. x is ${x}. </%def> <%def name="b()"> <% x = 9 %> this is b. x is ${x}. calling a. ${a()} </%def> ${b()} </%def> ${enclosing()} """) eq_(flatten_result(t.render()), "this is b. x is 9. calling a. this is a. x is 5.")
def test_ccall_caller(self): t = Template(""" <%def name="outer_func()"> OUTER BEGIN <%call expr="caller.inner_func()"> INNER CALL </%call> OUTER END </%def> <%call expr="outer_func()"> <%def name="inner_func()"> INNER BEGIN ${caller.body()} INNER END </%def> </%call> """) #print t.code assert result_lines(t.render()) == [ "OUTER BEGIN", "INNER BEGIN", "INNER CALL", "INNER END", "OUTER END", ]
def test_def(self): t = Template(""" <%! callcount = [0] %> <%def name="foo()" cached="True"> this is foo <% callcount[0] += 1 %> </%def> ${foo()} ${foo()} ${foo()} callcount: ${callcount} """) m = self._install_mock_cache(t) assert result_lines(t.render()) == [ 'this is foo', 'this is foo', 'this is foo', 'callcount: [1]', ] assert m.kwargs == {}
def test_compound_call(self): t = Template(""" <%def name="bar()"> this is bar </%def> <%def name="comp1()"> this comp1 should not be called </%def> <%def name="foo()"> foo calling comp1: ${caller.comp1(x=5)} foo calling body: ${caller.body()} </%def> <%call expr="foo()"> <%def name="comp1(x)"> this is comp1, ${x} </%def> this is the body, ${comp1(6)} </%call> ${bar()} """) assert result_lines(t.render()) == ['foo calling comp1:', 'this is comp1, 5', 'foo calling body:', 'this is the body,', 'this is comp1, 6', 'this is bar']
def test_quoting(self): t = Template(""" foo ${bar | h} """) eq_(flatten_result(t.render(bar="<'some bar'>")), "foo <'some bar'>")
def test_scope_eight(self): """test that the initial context counts as 'enclosing' scope, for nested defs""" t = Template(""" <%def name="enclosing()"> <%def name="a()"> a: x is ${x} </%def> <%def name="b()"> <% x = 10 %> b. x is ${x}. ${a()} </%def> ${b()} </%def> ${enclosing()} """) eq_( flatten_result(t.render(x=5)), "b. x is 10. a: x is 5" )
def test_nested_call(self): """test %calls that are nested inside each other""" t = Template(""" <%def name="foo()"> ${caller.body(x=10)} </%def> x is ${x} <%def name="bar()"> bar: ${caller.body()} </%def> <%call expr="foo()" args="x"> this is foo body: ${x} <%call expr="bar()"> this is bar body: ${x} </%call> </%call> """) assert result_lines(t.render(x=5)) == [ "x is 5", "this is foo body: 10", "bar:", "this is bar body: 10" ]
def test_stack_pop(self): t = Template(""" <%def name="links()" buffered="True"> Some links </%def> <%def name="wrapper(links)"> <h1>${caller.body()}</h1> ${links} </%def> ## links() pushes a stack frame on. when complete, ## 'nextcaller' must be restored <%call expr="wrapper(links())"> Some title </%call> """) assert result_lines(t.render()) == [ "<h1>", "Some title", "</h1>", "Some links" ]
def test_url_escaping(self): t = Template(""" http://example.com/?bar=${bar | u}&v=1 """) eq_(flatten_result(t.render(bar=u"酒吧bar")), "http://example.com/?bar=%E9%85%92%E5%90%A7bar&v=1")
def test_outer_scope(self): t = Template(""" <%def name="a()"> a: x is ${x} </%def> <%def name="b()"> <%def name="c()"> <% x = 10 %> c. x is ${x}. ${a()} </%def> b. ${c()} </%def> ${b()} x is ${x} """) eq_( flatten_result(t.render(x=5)), "b. c. x is 10. a: x is 5 x is 5" )
def test_chained_call(self): """test %calls that are chained through their targets""" t = Template(""" <%def name="a()"> this is a. <%call expr="b()"> this is a's ccall. heres my body: ${caller.body()} </%call> </%def> <%def name="b()"> this is b. heres my body: ${caller.body()} whats in the body's caller's body ? ${context.caller_stack[-2].body()} </%def> <%call expr="a()"> heres the main templ call </%call> """) assert result_lines(t.render()) == [ 'this is a.', 'this is b. heres my body:', "this is a's ccall. heres my body:", 'heres the main templ call', "whats in the body's caller's body ?", 'heres the main templ call' ]