Beispiel #1
0
    def _check_range_len(self, node: ast.Call) -> None:
        if not isinstance(nodes.get_parent(node), ForNodes):
            return
        if not functions.given_function_called(node, {'range'}):
            return

        args_len = len(node.args)

        is_one_arg_range = (
            args_len == 1 and
            isinstance(node.args[0], ast.Call) and
            functions.given_function_called(node.args[0], {'len'})
        )
        is_two_args_range = (
            self._is_multiple_args_range_with_len(node) and
            args_len == 2
        )
        # for three args add violation
        # only if `step` arg do not equals 1 or -1
        step_arg = args_len == 3 and operators.unwrap_unary_node(node.args[2])
        is_three_args_range = (
            self._is_multiple_args_range_with_len(node) and
            args_len == 3 and
            isinstance(step_arg, ast.Num) and
            abs(step_arg.n) == 1
        )
        if any([is_one_arg_range, is_two_args_range, is_three_args_range]):
            self.add_violation(ImplicitEnumerateViolation(node))
Beispiel #2
0
    def _check_range_len(self, node: ast.Call) -> None:
        function_name = functions.given_function_called(node, {'range'})
        if not function_name:
            return

        is_one_argument_range = (len(node.args) == 1
                                 and isinstance(node.args[0], ast.Call)
                                 and functions.given_function_called(
                                     node.args[0], {'len'}))
        is_two_arguments_range = (len(node.args) in {2, 3}
                                  and isinstance(node.args[1], ast.Call)
                                  and functions.given_function_called(
                                      node.args[1], {'len'}))
        if is_one_argument_range or is_two_arguments_range:
            self.add_violation(ImplicitEnumerateViolation(node))
Beispiel #3
0
    def _check_type_compare(self, node: ast.Call) -> None:
        function_name = functions.given_function_called(node, {'type'})
        if not function_name:
            return

        if isinstance(nodes.get_parent(node), ast.Compare):
            self.add_violation(TypeCompareViolation(node))
Beispiel #4
0
 def _check_unnecessary_literals(self, node: ast.Call) -> None:
     function_name = functions.given_function_called(
         node,
         LITERALS_BLACKLIST,
     )
     if function_name and not node.args:
         self.add_violation(consistency.UnnecessaryLiteralsViolation(node))
Beispiel #5
0
    def _check_isinstance_call(self, node: ast.Call) -> None:
        function_name = functions.given_function_called(node, {'isinstance'})
        if not function_name or len(node.args) != 2:
            return

        if isinstance(node.args[1], ast.Tuple):
            if len(node.args[1].elts) == 1:
                self.add_violation(WrongIsinstanceWithTupleViolation(node))
Beispiel #6
0
 def _check_wrong_function_called(self, node: ast.Call) -> None:
     function_name = functions.given_function_called(
         node,
         FUNCTIONS_BLACKLIST,
     )
     if function_name:
         self.add_violation(
             WrongFunctionCallViolation(node, text=function_name), )
def test_given_function_called_no_split(
    parse_ast_tree,
    function_call: str,
    function_name: str,
) -> None:
    """Test given_function_called without splitting the modules."""
    tree = parse_ast_tree(function_call)
    node = tree.body[0].value
    called_function = functions.given_function_called(node, [function_name])
    assert called_function == function_name
Beispiel #8
0
    def _check_open_call_context(self, node: ast.Call) -> None:
        function_name = functions.given_function_called(node, {'open'})
        if not function_name:
            return

        if isinstance(nodes.get_parent(node), ast.withitem):
            # We do not care about `with` or `async with` - both are fine.
            return

        self.add_violation(OpenWithoutContextManagerViolation(node))
    def _check_unpythonic_compare(self, node: ast.Compare) -> None:
        all_nodes = [node.left, *node.comparators]

        for index, compare in enumerate(all_nodes):
            if not isinstance(compare, ast.Call):
                continue
            if functions.given_function_called(compare, {'len'}):
                ps = index - len(all_nodes) + 1
                if not _is_correct_len(node.ops[ps], node.comparators[ps]):
                    self.add_violation(UselessLenCompareViolation(node))
    def visit_Call(self, node: ast.Call) -> None:
        """Used to find ``FUNCTIONS_BLACKLIST`` calls."""
        self._check_wrong_function_called(node)
        self._check_boolean_arguments(node)
        self._check_isinstance_call(node)

        if functions.given_function_called(node, {'super'}):
            self._check_super_context(node)
            self._check_super_arguments(node)

        self.generic_visit(node)
Beispiel #11
0
    def _check_floating_nan(self, node: ast.Call) -> None:
        if len(node.args) != 1:
            return

        if not isinstance(node.args[0], (ast.Str, ast.Bytes)):
            return

        if not functions.given_function_called(node, 'float'):
            return

        if node.args[0].s.lower() in self._nan_variants:
            self.add_violation(FloatingNanViolation(node))
Beispiel #12
0
    def _is_call_ignored(self, node: ast.Call) -> bool:
        call = source.node_to_string(node.func)
        func_called = functions.given_function_called(
            node,
            self._functions.keys(),
        )

        return bool(
            func_called
            and len(node.args) == self._functions[func_called], ) or any(
                call.endswith(post) for post in self._postfixes
                if len(node.args) == self._postfixes[post])
Beispiel #13
0
    def _check_slice_assignment(self, node: ast.Subscript) -> None:
        if not isinstance(node.ctx, ast.Store):
            return

        subscript_slice_assignment = isinstance(node.slice, ast.Slice)

        slice_expr = get_slice_expr(node)
        slice_function_assignment = (isinstance(slice_expr, ast.Call)
                                     and functions.given_function_called(
                                         slice_expr, {'slice'}))

        if subscript_slice_assignment or slice_function_assignment:
            self.add_violation(consistency.AssignToSliceViolation(node), )
def _duplicated_isinstance_call(node: ast.BoolOp) -> List[str]:
    counter: DefaultDict[str, int] = defaultdict(int)

    for call in node.values:
        if not isinstance(call, ast.Call) or len(call.args) != 2:
            continue

        if not given_function_called(call, {'isinstance'}):
            continue

        isinstance_object = source.node_to_string(call.args[0])
        counter[isinstance_object] += 1

    return [node_name for node_name, count in counter.items() if count > 1]
    def _is_modulo_pattern_exception(self, parent: Optional[ast.AST]) -> bool:
        """
        Check if string with modulo pattern is in an exceptional situation.

        Basically we have some function names in which we allow strings with
        modulo patterns because they must have them for the functions to work
        properly.
        """
        if parent and isinstance(parent, ast.Call):
            return bool(
                functions.given_function_called(
                    parent,
                    self._modulo_pattern_exceptions,
                    split_modules=True,
                ))
        return False
Beispiel #16
0
    def visit_Call(self, node: ast.Call) -> None:
        """
        Used to find ``FUNCTIONS_BLACKLIST`` calls.

        Raises:
            BooleanPositionalArgumentViolation
            WrongFunctionCallViolation
            WrongIsinstanceWithTupleViolation
            WrongSuperCallAccessViolation
            WrongSuperCallViolation

        """
        self._check_wrong_function_called(node)
        self._check_boolean_arguments(node)
        self._check_isinstance_call(node)

        if functions.given_function_called(node, {'super'}):
            self._check_super_context(node)
            self._check_super_arguments(node)

        self.generic_visit(node)
def _is_self_call(func: AnyFunctionDef, node: AST) -> bool:
    return (
        isinstance(node, Call) and
        isinstance(node.func, Attribute) and
        bool(given_function_called(node, {'self.{0}'.format(func.name)}))
    )
 def _check_useless_len(self, node: AnyIf) -> None:
     if isinstance(node.test, ast.Call):
         if given_function_called(node.test, {'len'}):
             self.add_violation(UselessLenCompareViolation(node))
 def _check_super_call(self, node: ast.Call) -> None:
     function_name = functions.given_function_called(node, {'super'})
     if function_name:
         self._ensure_super_context(node)
         self._ensure_super_arguments(node)
Beispiel #20
0
 def _is_wrong_len(self, node: ast.BinOp, element: str) -> bool:
     return (isinstance(node.left, ast.Call)
             and bool(functions.given_function_called(node.left, {'len'}))
             and source.node_to_string(node.left.args[0]) == element)
Beispiel #21
0
 def _is_multiple_args_range_with_len(self, node: ast.Call) -> bool:
     return bool(
         len(node.args) in {2, 3} and isinstance(node.args[1], ast.Call)
         and functions.given_function_called(node.args[1], {'len'}), )
def _check_function_recursion(func: AnyFunctionDef) -> bool:
    return bool([
        node
        for node in walk(func)
        if isinstance(node, Call) and given_function_called(node, {func.name})
    ])