summaryrefslogtreecommitdiff
path: root/test/test_call.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_call.py')
-rw-r--r--test/test_call.py573
1 files changed, 573 insertions, 0 deletions
diff --git a/test/test_call.py b/test/test_call.py
new file mode 100644
index 0000000..4dea2b3
--- /dev/null
+++ b/test/test_call.py
@@ -0,0 +1,573 @@
+from mako.template import Template
+from mako.testing.assertions import eq_
+from mako.testing.fixtures import TemplateTest
+from mako.testing.helpers import flatten_result
+from mako.testing.helpers import result_lines
+
+
+class CallTest(TemplateTest):
+ def test_call(self):
+ t = Template(
+ """
+ <%def name="foo()">
+ hi im foo ${caller.body(y=5)}
+ </%def>
+
+ <%call expr="foo()" args="y, **kwargs">
+ this is the body, y is ${y}
+ </%call>
+"""
+ )
+ assert result_lines(t.render()) == [
+ "hi im foo",
+ "this is the body, y is 5",
+ ]
+
+ 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_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_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_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_conditional_call(self):
+ """test that 'caller' is non-None only if the immediate <%def> was
+ called via <%call>"""
+
+ t = Template(
+ """
+ <%def name="a()">
+ % if caller:
+ ${ caller.body() } \\
+ % endif
+ AAA
+ ${ b() }
+ </%def>
+
+ <%def name="b()">
+ % if caller:
+ ${ caller.body() } \\
+ % endif
+ BBB
+ ${ c() }
+ </%def>
+
+ <%def name="c()">
+ % if caller:
+ ${ caller.body() } \\
+ % endif
+ CCC
+ </%def>
+
+ <%call expr="a()">
+ CALL
+ </%call>
+
+ """
+ )
+ assert result_lines(t.render()) == ["CALL", "AAA", "BBB", "CCC"]
+
+ 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",
+ ]
+
+ 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_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_nested_call_3(self):
+ template = Template(
+ """\
+ <%def name="A()">
+ ${caller.body()}
+ </%def>
+
+ <%def name="B()">
+ ${caller.foo()}
+ </%def>
+
+ <%call expr="A()">
+ <%call expr="B()">
+ <%def name="foo()">
+ foo
+ </%def>
+ </%call>
+ </%call>
+
+ """
+ )
+ assert flatten_result(template.render()) == "foo"
+
+ 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_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_call_in_nested(self):
+ t = Template(
+ """
+ <%def name="a()">
+ this is a ${b()}
+ <%def name="b()">
+ this is b
+ <%call expr="c()">
+ this is the body in b's call
+ </%call>
+ </%def>
+ <%def name="c()">
+ this is c: ${caller.body()}
+ </%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",
+ ]
+
+ def test_composed_def(self):
+ t = Template(
+ """
+ <%def name="f()"><f>${caller.body()}</f></%def>
+ <%def name="g()"><g>${caller.body()}</g></%def>
+ <%def name="fg()">
+ <%self:f><%self:g>${caller.body()}</%self:g></%self:f>
+ </%def>
+ <%self:fg>fgbody</%self:fg>
+ """
+ )
+ assert result_lines(t.render()) == ["<f><g>fgbody</g></f>"]
+
+ def test_regular_defs(self):
+ t = Template(
+ """
+ <%!
+ @runtime.supports_caller
+ def a(context):
+ context.write("this is a")
+ if context['caller']:
+ context['caller'].body()
+ context.write("a is done")
+ return ''
+ %>
+
+ <%def name="b()">
+ this is b
+ our body: ${caller.body()}
+ ${a(context)}
+ </%def>
+ test 1
+ <%call expr="a(context)">
+ this is the body
+ </%call>
+ test 2
+ <%call expr="b()">
+ this is the body
+ </%call>
+ test 3
+ <%call expr="b()">
+ this is the body
+ <%call expr="b()">
+ this is the nested body
+ </%call>
+ </%call>
+
+
+ """
+ )
+ assert result_lines(t.render()) == [
+ "test 1",
+ "this is a",
+ "this is the body",
+ "a is done",
+ "test 2",
+ "this is b",
+ "our body:",
+ "this is the body",
+ "this is aa is done",
+ "test 3",
+ "this is b",
+ "our body:",
+ "this is the body",
+ "this is b",
+ "our body:",
+ "this is the nested body",
+ "this is aa is done",
+ "this is aa is done",
+ ]
+
+ 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",
+ ]
+
+
+class SelfCacheTest(TemplateTest):
+ """this test uses a now non-public API."""
+
+ 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",
+ ]