@@ -186,44 +186,62 @@ def changes_semantics(self, namespace, candidate_suite):
186186 else :
187187 return properties != candidate_properties
188188
189+ def constant_test (self , node ):
190+ """
191+ The constant truth value of an if statement's test, or None
192+
193+ RemoveDebug marks if statements whose __debug__ test it has resolved
194+ with a resolved_test attribute. Otherwise only the True and False
195+ constants are recognised - before python 3.4 they are reassignable
196+ names, so nothing is recognised.
197+
198+ :param node: The statement to examine
199+ :type node: ast.AST
200+ :rtype: bool or None
201+ """
202+ if not isinstance (node , ast .If ):
203+ return None
204+
205+ if hasattr (node , 'resolved_test' ):
206+ if node .resolved_test is True or node .resolved_test is False :
207+ return node .resolved_test
208+ return None
209+
210+ if is_constant_node (node .test , ast .NameConstant ) and isinstance (node .test .value , bool ):
211+ return node .test .value
212+
213+ return None
214+
189215 def remove_false_branches (self , node_list ):
190216 suite = []
191217
192218 for node in node_list :
193- if not isinstance (node , ast .If ):
194- suite .append (self .visit (node ))
195- continue
219+ condition = self .constant_test (node )
196220
197- # This is an If statement
221+ # A branch of a constant test can be removed, if that doesn't change
222+ # the semantics of the program
198223
199- if hasattr (node , 'resolved_test' ):
200- condition = node .resolved_test
201- elif is_constant_node (node .test , ast .NameConstant ) and isinstance (node .test .value , bool ):
202- condition = node .test .value
203- else :
204- # The test is not a constant, so we can't remove this branch
205- suite .append (self .visit (node ))
224+ if condition is True and not self .changes_semantics (node .namespace , node .orelse ):
225+ # The else branch is dead, keep only the body
226+ self ._removed_suites .append (node .orelse )
227+ suite .extend (self .remove_false_branches (node .body ))
206228 continue
207229
208- # We can possibly remove one of the branches, but we need to check if it changes the semantics of the program
209-
210- if condition is True :
211- if self .changes_semantics (node .namespace , node .orelse ):
212- # Removing the else branch changes the semantics of the program, so we can't remove it
213- suite .append (self .visit (node ))
214- else :
215- # The else branch is dead, keep only the body
216- self ._removed_suites .append (node .orelse )
217- suite .extend (self .remove_false_branches (node .body ))
218-
219- elif condition is False :
220- if self .changes_semantics (node .namespace , node .body ):
221- # Removing the body branch changes the semantics of the program, so we can't remove it
222- suite .append (self .visit (node ))
223- else :
224- # The body is dead, keep only the else branch
225- self ._removed_suites .append (node .body )
226- suite .extend (self .remove_false_branches (node .orelse ))
230+ if condition is False and not self .changes_semantics (node .namespace , node .body ):
231+ # The body is dead, keep only the else branch
232+ self ._removed_suites .append (node .body )
233+ suite .extend (self .remove_false_branches (node .orelse ))
234+ continue
235+
236+ node = self .visit (node )
237+
238+ # An else suite that dead branch removal (or another transform) emptied
239+ # or reduced to the 0 padding can be omitted.
240+ orelse = getattr (node , 'orelse' , None )
241+ if orelse and self ._is_empty_suite (orelse ):
242+ node .orelse = []
243+
244+ suite .append (node )
227245
228246 return suite
229247
@@ -253,39 +271,3 @@ def _is_empty_suite(self, suite):
253271 if len (suite ) == 0 :
254272 return True
255273 return len (suite ) == 1 and isinstance (suite [0 ], ast .Expr ) and is_constant_node (suite [0 ].value , ast .Num ) and suite [0 ].value .n == 0
256-
257- def visit_If (self , node ):
258- node = super (RemoveDeadBranches , self ).visit_If (node )
259-
260- # Empty orelse suite can be omitted
261- if self ._is_empty_suite (node .orelse ):
262- node .orelse = []
263-
264- return node
265-
266- def visit_While (self , node ):
267- node = super (RemoveDeadBranches , self ).visit_While (node )
268-
269- # Empty orelse suite can be omitted
270- if self ._is_empty_suite (node .orelse ):
271- node .orelse = []
272-
273- return node
274-
275- def visit_For (self , node ):
276- node = super (RemoveDeadBranches , self ).visit_For (node )
277-
278- # Empty orelse suite can be omitted
279- if self ._is_empty_suite (node .orelse ):
280- node .orelse = []
281-
282- return node
283-
284- def visit_Try (self , node ):
285- node = super (RemoveDeadBranches , self ).visit_Try (node )
286-
287- # Empty orelse suite can be omitted
288- if self ._is_empty_suite (node .orelse ):
289- node .orelse = []
290-
291- return node
0 commit comments