def _check_useless_loop_else(self, node: AnyLoop) -> None: if not node.orelse: return body_returning = any( walk.is_contained(sub, self._returning_nodes) for sub in node.body) else_returning = any( walk.is_contained(sub, self._returning_nodes) for sub in node.orelse) if body_returning and else_returning: self.add_violation(UselessReturningElseViolation(node))
def _find_returing_nodes( node: ast.Try, bad_returning_nodes: AnyNodes, ) -> Tuple[bool, bool, bool, bool]: try_has = any( # TODO: also check ast.Break is_contained(line, bad_returning_nodes) for line in node.body) except_has = any( is_contained(except_handler, bad_returning_nodes) for except_handler in node.handlers) else_has = any( is_contained(line, bad_returning_nodes) for line in node.orelse) finally_has = any( is_contained(line, bad_returning_nodes) for line in node.finalbody) return try_has, except_has, else_has, finally_has
def _check_useless_loop_else(self, node: AnyLoop) -> None: if not node.orelse: return # An else statement makes sense if we # want to execute something after breaking # out of the loop without writing more code body_returning = any( walk.is_contained(sub, self._returning_nodes[1:]) for sub in node.body) else_returning = any( walk.is_contained(sub, self._returning_nodes) for sub in node.orelse) if body_returning and else_returning: self.add_violation(UselessReturningElseViolation(node))
def find_returning_nodes( node: ast.Try, bad_returning_nodes: AnyNodes, ) -> Tuple[bool, bool, bool, bool]: """Find nodes that return value and are inside try/except/else/finally.""" try_has = any( is_contained(line, bad_returning_nodes) for line in node.body) except_has = any( is_contained(except_handler, bad_returning_nodes) for except_handler in node.handlers) else_has = any( is_contained(line, bad_returning_nodes) for line in node.orelse) finally_has = any( is_contained(line, bad_returning_nodes) for line in node.finalbody) return try_has, except_has, else_has, finally_has
def _check_break_or_continue_in_finally(self, node: ast.Try) -> None: has_wrong_nodes = any( is_contained(line, (ast.Break, ast.Continue)) for line in node.finalbody) if has_wrong_nodes: self.add_violation(LoopControlFinallyViolation(node))
def _check_useless_try_else(self, node: ast.Try) -> None: if not node.orelse or node.finalbody: # `finally` cancels this rule. # Because refactoring `try` with `else` and `finally` # by moving `else` body after `finally` will change # the execution order. return all_except_returning = all( walk.is_contained(except_, self._returning_nodes) for except_ in node.handlers) else_returning = any( walk.is_contained(sub, self._returning_nodes) for sub in node.orelse) if all_except_returning and else_returning: self.add_violation(UselessReturningElseViolation(node))
def _check_lambda_inside_loop( self, node: Union[AnyLoop, AnyComprehension], ) -> None: container_names = self._containers.get(type(node), ()) for container in container_names: body = getattr(node, container, []) if not isinstance(body, list): body = [body] for subnode in body: if walk.is_contained(subnode, ast.Lambda): self.add_violation(LambdaInsideLoopViolation(node))
def _get_non_negative_nodes( self, left: Optional[ast.AST], right: Optional[ast.AST] = None, ): non_negative_numbers = [] for node in filter(None, (left, right)): real_node = unwrap_unary_node(node) correct_node = (isinstance(real_node, ast.Num) and real_node.n in self._meaningless_operations and not (real_node.n == 1 and walk.is_contained(node, ast.USub))) if correct_node: non_negative_numbers.append(real_node) return non_negative_numbers
def _get_non_negative_nodes( self, left: ast.AST, right: Optional[ast.AST] = None, ): non_negative_numbers = [] for node in filter(None, (left, right)): real_node = unwrap_unary_node(node) if not isinstance(real_node, ast.Num): continue if real_node.n not in self._meaningless_operations: continue if real_node.n == 1 and walk.is_contained(node, ast.USub): continue non_negative_numbers.append(real_node) return non_negative_numbers
def _check_method_contents(self, node: types.AnyFunctionDef) -> None: if node.name == constants.INIT: if walk.is_contained(node, self._not_appropriate_for_init): self.add_violation(bp.YieldInsideInitViolation(node))
def _check_method_contents(self, node: types.AnyFunctionDef) -> None: if node.name in constants.YIELD_MAGIC_METHODS_BLACKLIST: if walk.is_contained(node, (ast.Yield, ast.YieldFrom)): self.add_violation(oop.YieldMagicMethodViolation(node))
def _check_lambda_inside_loop(self, node: _AnyLoop) -> None: for subnode in node.body: if is_contained(subnode, (ast.Lambda,)): self.add_violation(LambdaInsideLoopViolation(node))
def is_generator(node: AnyFunctionDef) -> bool: """Tells whether a given function is a generator.""" for body_item in node.body: if is_contained(node=body_item, to_check=(Yield, YieldFrom)): return True return False