diff --git a/CHANGES b/CHANGES index 47836997cb6ce8ad074199ec38e522f0296b7399..2d3dabe8eadf7df413f5c75f9de73b5e4e80670d 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,10 @@ to filehandles being implicitly closed. [ticket:182] +- [bug] Fixed endless recursion bug when + nesting multiple def-calls with content. + Thanks to Jeff Dairiki. [ticket:186] + 0.6.2 - [bug] The ${{"foo":"bar"}} parsing issue is fixed!! The legendary Eevee has slain the dragon! diff --git a/mako/codegen.py b/mako/codegen.py index 2e15124fd4fe64a10718616c211aee904c1a55ef..704330c8c140917fbca99ebdf2eaa5d65ef612f8 100644 --- a/mako/codegen.py +++ b/mako/codegen.py @@ -231,7 +231,8 @@ class _GenerateRenderMethod(object): self.printer.writelines( "def %s(%s):" % (name, ','.join(args)), - "context.caller_stack._push_frame()", + # push new frame, assign current frame to __M_caller + "__M_caller = context.caller_stack._push_frame()", "try:" ) if buffered or filtered or cached: @@ -516,7 +517,8 @@ class _GenerateRenderMethod(object): buffered = eval(node.attributes.get('buffered', 'False')) cached = eval(node.attributes.get('cached', 'False')) self.printer.writelines( - "context.caller_stack._push_frame()", + # push new frame, assign current frame to __M_caller + "__M_caller = context.caller_stack._push_frame()", "try:" ) if buffered or filtered or cached: @@ -848,8 +850,6 @@ class _GenerateRenderMethod(object): ) self.printer.writelines( - # get local reference to current caller, if any - "__M_caller = context.caller_stack._get_caller()", # push on caller for nested call "context.caller_stack.nextcaller = " "runtime.Namespace('caller', context, callables=ccall(__M_caller))", diff --git a/mako/runtime.py b/mako/runtime.py index 65c03e17c77bc71ff11ff81b0697f4aeecd1556c..b56fa67ec22b65c6d1a8a8563b6d3e603b3f5052 100644 --- a/mako/runtime.py +++ b/mako/runtime.py @@ -158,12 +158,16 @@ class CallerStack(list): def __nonzero__(self): return self._get_caller() and True or False def _get_caller(self): + # this method can be removed once + # codegen MAGIC_NUMBER moves past 7 return self[-1] def __getattr__(self, key): return getattr(self._get_caller(), key) def _push_frame(self): - self.append(self.nextcaller or None) + frame = self.nextcaller or None + self.append(frame) self.nextcaller = None + return frame def _pop_frame(self): self.nextcaller = self.pop() diff --git a/test/test_call.py b/test/test_call.py index 5f13e958876314ee4d38477fd541d475bd454021..0bb6079bfa4980b4ae5c4ec3edcf295b218364a1 100644 --- a/test/test_call.py +++ b/test/test_call.py @@ -385,6 +385,17 @@ class CallTest(TemplateTest): """) 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(""" <%!