Victor Stinner avatar Victor Stinner committed 66191d2

Remove empty try/except: "try: pass except: pass"

Comments (0)

Files changed (5)

    Example: ``[x*10 for x in range(1, 4)]`` => ``[10, 20, 30]``.
  * Remove useless instructions. Example:
    "x=1; 'abc'; print(x)" => "x=1; print(x)"
+ * Remove empty try/except: "try: pass except: pass"
 
 Version 0.4 (2012-12-10)
 ------------------------
 Misc
 ====
 
- * remove useless code: "try: pass except: pass"
  * replace '(a and b) and c' (2 op) with 'a and b and c' (1 op), same for "or" operator
  * unroll: support break/continue
 

astoptimizer/ast_tools.py

 def clone_node_list(node_list):
     # FIXME: use something faster? or more specialized?
     return copy.deepcopy(node_list)
+
+def is_empty_body(node_list):
+    if len(node_list) == 0:
+        return True
+    if len(node_list) != 1:
+        return False
+    node = node_list[0]
+    return isinstance(node, ast.Pass)
+

astoptimizer/optimizer.py

     sort_set_elts, new_tuple, new_tuple_elts, new_list, new_list_elts,
     new_dict_elts,
     ast_contains, check_func_args,
-    clone_node_list)
+    clone_node_list, is_empty_body)
 from astoptimizer.config import optimize_unicode
 from astoptimizer.compatibility import (
     u,
         def fullvisit_Try(self, node):
             # try/except/else/finally
             node.body = self.visit_list(node.body, True)
-            node.handlers = self.visit_list(node.handlers, True)
             node.orelse = self.visit_list(node.orelse, True)
             node.finalbody = self.visit_list(node.finalbody, True)
+
+            if (self.config.remove_dead_code
+            and is_empty_body(node.body)):
+                if is_empty_body(node.orelse):
+                    # try: pass finally: code
+                    # => code
+                    return self.if_block(node, node.finalbody)
+                elif is_empty_body(node.finalbody):
+                    # try: pass except: ... else: code
+                    # => code
+                    return self.if_block(node, node.orelse)
+                else:
+                    # try: pass except: ... else: code1 finally: code2
+                    # => try: code1 finally: code2
+                    node.body = node.orelse
+                    del node.handlers[:]
+                    node.orelse = []
+                    return
+
+            node.handlers = self.visit_list(node.handlers, True)
     else:
         # Python 3.2 and older
         def fullvisit_With(self, node):
             # try/finally
             node.body = self.visit_list(node.body, True)
             node.finalbody = self.visit_list(node.finalbody, True)
+            if (self.config.remove_dead_code
+            and is_empty_body(node.body)):
+                # try: pass finally: code
+                # => code
+                return self.if_block(node, node.finalbody)
 
         def fullvisit_TryExcept(self, node):
             # try/except/else
             node.body = self.visit_list(node.body, True)
+            node.orelse = self.visit_list(node.orelse, True)
+            if (self.config.remove_dead_code
+            and is_empty_body(node.body)):
+                # try: pass except: ... else: code
+                # => code
+                return self.if_block(node, node.orelse)
             node.handlers = self.visit_list(node.handlers, True)
-            node.orelse = self.visit_list(node.orelse, True)
 
     def fullvisit_Assign(self, node):
         supported = self.config.use_experimental_vars and not self.is_conditional

astoptimizer/tests.py

 
         code = '\n'.join((
             'try:',
-            '    pass; pass',
+            '    pass; func(); pass',
             'except:',
-            '    pass; pass',
+            '    pass; func(); pass',
             'else:',
-            '    pass; pass',
+            '    pass; func(); pass',
             'finally:',
-            '    pass; pass',
+            '    pass; func(); pass',
         ))
-        self.check_pass(code)
+        code2 = '\n'.join((
+            'try:',
+            '    func()',
+            'except:',
+            '    func()',
+            'else:',
+            '    func()',
+            'finally:',
+            '    func()',
+        ))
+        self.check(code, self.text_ast(code2))
 
     def test_If(self):
         self.check('if 0: print("log")', self.TEXT_PASS)
         """.strip()
         self.check_not_optimized(code, catch_syntaxerror=True)
 
+        # empty try/except
+        self.check('try: pass\nexcept: func1()',
+                   self.text_ast('pass'))
+        self.check('try: pass\nexcept: func1()\nelse: func2()',
+                   self.text_ast('func2()'))
+        self.check('try: pass\nfinally: func1()',
+                   self.text_ast('func1()'))
+        self.check('try: pass\nexcept: func()\nfinally: func2()',
+                   self.text_ast('func2()'))
+        code = 'try: pass\nexcept: func1()\nelse: func2()\nfinally: func3()'
+        self.check(code,
+                   self.text_ast('try: func2()\nfinally: func3()'))
+
     def test_remove_docstring(self):
         keep_docstring = self.create_config()
         keep_docstring.remove_docstring = False
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.