Commits

Mike Bayer  committed a17da8b

- [feature] Control lines with no bodies will
now succeed, as "pass" is added for these
when no statements are otherwise present.
Courtesy Ben Trofatter [ticket:146]

  • Participants
  • Parent commits 6b158a5

Comments (0)

Files changed (6)

+0.7.1
+- [feature] Control lines with no bodies will
+  now succeed, as "pass" is added for these
+  when no statements are otherwise present.
+  Courtesy Ben Trofatter [ticket:146]
+
 0.7.0
 - [feature] Added new "loop" variable to templates,
   is provided within a % for block to provide

File mako/__init__.py

 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
 
-__version__ = '0.7.0'
+__version__ = '0.7.1'
 

File mako/codegen.py

  
     def visitControlLine(self, node):
         if node.isend:
-            if not node.get_children():
-                self.printer.writeline("pass")
             self.printer.writeline(None)
             if node.has_loop_context:
                 self.printer.writeline('finally:')
             else:
                 text = node.text
             self.printer.writeline(text)
+            children = node.get_children()
+            # this covers the two situations where we want to insert a pass:
+            #    1) a ternary control line with no children and
+            #    2) a primary control line with nothing but its own ternary
+            #          and end control lines
+            if (not node.get_children or
+                util.all(isinstance(c, parsetree.ControlLine)
+                         for c in children) and
+                util.all((node.is_ternary(c.keyword) or c.isend)
+                         for c in children)):
+                self.printer.writeline("pass")
  
     def visitText(self, node):
         self.write_source_comment(node)

File mako/lexer.py

         self.match_position = 0
         self.tag = []
         self.control_line = []
+        self.ternary_stack = []
         self.disable_unicode = disable_unicode
         self.encoding = input_encoding
  
             self.template.nodes.append(node)
         # build a set of child nodes for the control line
         # (used for loop variable detection)
+        # also build a set of child nodes on ternary control lines
+        # (used for determining if a pass needs to be auto-inserted
         if self.control_line:
-            self.control_line[-1].nodes.append(node)
+            control_frame = self.control_line[-1]
+            control_frame.nodes.append(node)
+            if not (isinstance(node, parsetree.ControlLine) and
+                    control_frame.is_ternary(node.keyword)):
+                if self.ternary_stack and self.ternary_stack[-1]:
+                    self.ternary_stack[-1][-1].nodes.append(node)
         if isinstance(node, parsetree.Tag):
             if len(self.tag):
                 node.parent = self.tag[-1]
         elif isinstance(node, parsetree.ControlLine):
             if node.isend:
                 self.control_line.pop()
+                self.ternary_stack.pop()
             elif node.is_primary:
                 self.control_line.append(node)
-            elif len(self.control_line) and \
+                self.ternary_stack.append([])
+            elif self.control_line and \
+                    self.control_line[-1].is_ternary(node.keyword):
+                self.ternary_stack[-1].append(node)
+            elif self.control_line and \
                     not self.control_line[-1].is_ternary(node.keyword):
                 raise exceptions.SyntaxException(
                           "Keyword '%s' not a legal ternary for keyword '%s'" %

File mako/util.py

     time_func = time.clock
 else:
     time_func = time.time 
- 
+
 def function_named(fn, name):
     """Return a function with a given __name__.
 
         return newfunc
 
 if py24:
+    def all(iterable):
+        for i in iterable:
+            if not i:
+                return False
+        return True
+
     def exception_name(exc):
         try:
             return exc.__class__.__name__
         except AttributeError:
             return exc.__name__
 else:
+    all = all
+
     def exception_name(exc):
         return exc.__class__.__name__
 
+
 class PluginLoader(object):
     def __init__(self, group):
         self.group = group

File test/test_template.py

             "yes x has test"
         ]
  
-    def test_blank_control(self):
+    def test_blank_control_1(self):
         self._do_memory_test(
             """
             % if True:
             filters=lambda s:s.strip()
         )
  
+    def test_blank_control_2(self):
+        self._do_memory_test(
+            """
+            % if True:
+            % elif True:
+            % endif
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_3(self):
+        self._do_memory_test(
+            """
+            % if True:
+            % else:
+            % endif
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_4(self):
+        self._do_memory_test(
+            """
+            % if True:
+            % elif True:
+            % else:
+            % endif
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_5(self):
+        self._do_memory_test(
+            """
+            % for x in range(10):
+            % endfor
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_6(self):
+        self._do_memory_test(
+            """
+            % while False:
+            % endwhile
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_7(self):
+        self._do_memory_test(
+            """
+            % try:
+            % except:
+            % endtry
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
+    def test_blank_control_8(self):
+        self._do_memory_test(
+            """
+            % with open('x', 'w') as fp:
+            % endwith
+            """,
+            "",
+            filters=lambda s:s.strip()
+        )
+ 
     def test_multiline_control(self):
         t = Template("""
     % for x in \\