コード例 #1
0
    def _check_reversed(self, node: nodes.Call) -> None:
        """Check that the argument to `reversed` is a sequence."""
        try:
            argument = utils.safe_infer(
                utils.get_argument_from_call(node, position=0))
        except utils.NoSuchArgumentError:
            pass
        else:
            if argument is astroid.Uninferable:
                return
            if argument is None:
                # Nothing was inferred.
                # Try to see if we have iter().
                if isinstance(node.args[0], nodes.Call):
                    try:
                        func = next(node.args[0].func.infer())
                    except astroid.InferenceError:
                        return
                    if getattr(
                            func, "name",
                            None) == "iter" and utils.is_builtin_object(func):
                        self.add_message("bad-reversed-sequence", node=node)
                return

            if isinstance(argument, (nodes.List, nodes.Tuple)):
                return

            # dicts are reversible, but only from Python 3.8 onward. Prior to
            # that, any class based on dict must explicitly provide a
            # __reversed__ method
            if not self._py38_plus and isinstance(argument, astroid.Instance):
                if any(ancestor.name == "dict"
                       and utils.is_builtin_object(ancestor)
                       for ancestor in itertools.chain((
                           argument._proxied,
                       ), argument._proxied.ancestors())):
                    try:
                        argument.locals[REVERSED_PROTOCOL_METHOD]
                    except KeyError:
                        self.add_message("bad-reversed-sequence", node=node)
                    return

            if hasattr(argument, "getattr"):
                # everything else is not a proper sequence for reversed()
                for methods in REVERSED_METHODS:
                    for meth in methods:
                        try:
                            argument.getattr(meth)
                        except astroid.NotFoundError:
                            break
                    else:
                        break
                else:
                    self.add_message("bad-reversed-sequence", node=node)
            else:
                self.add_message("bad-reversed-sequence", node=node)
コード例 #2
0
ファイル: base.py プロジェクト: noahpieta/Python-mode-klen
    def _check_reversed(self, node):
        """ check that the argument to `reversed` is a sequence """
        try:
            argument = safe_infer(get_argument_from_call(node, position=0))
        except NoSuchArgumentError:
            self.add_message('missing-reversed-argument', node=node)
        else:
            if argument is astroid.YES:
                return
            if argument is None:
                # nothing was infered
                # try to see if we have iter()
                if isinstance(node.args[0], astroid.CallFunc):
                    try:
                        func = node.args[0].func.infer().next()
                    except InferenceError:
                        return
                    if (getattr(func, 'name', None) == 'iter'
                            and is_builtin_object(func)):
                        self.add_message('bad-reversed-sequence', node=node)
                return

            if isinstance(argument, astroid.Instance):
                if (argument._proxied.name == 'dict'
                        and is_builtin_object(argument._proxied)):
                    self.add_message('bad-reversed-sequence', node=node)
                    return
                elif any(
                        ancestor.name == 'dict' and is_builtin_object(ancestor)
                        for ancestor in argument._proxied.ancestors()):
                    # mappings aren't accepted by reversed()
                    self.add_message('bad-reversed-sequence', node=node)
                    return

                for methods in REVERSED_METHODS:
                    for meth in methods:
                        try:
                            argument.getattr(meth)
                        except astroid.NotFoundError:
                            break
                    else:
                        break
                else:
                    # check if it is a .deque. It doesn't seem that
                    # we can retrieve special methods
                    # from C implemented constructs
                    if argument._proxied.qname().endswith(".deque"):
                        return
                    self.add_message('bad-reversed-sequence', node=node)
            elif not isinstance(argument, (astroid.List, astroid.Tuple)):
                # everything else is not a proper sequence for reversed()
                self.add_message('bad-reversed-sequence', node=node)
コード例 #3
0
ファイル: base.py プロジェクト: BearDrinkbeer/python-mode
    def _check_reversed(self, node):
        """ check that the argument to `reversed` is a sequence """
        try:
            argument = safe_infer(get_argument_from_call(node, position=0))
        except NoSuchArgumentError:
            self.add_message('missing-reversed-argument', node=node)
        else:
            if argument is astroid.YES:
                return
            if argument is None:
                # nothing was infered
                # try to see if we have iter()
                if isinstance(node.args[0], astroid.CallFunc):
                    try:
                        func = node.args[0].func.infer().next()
                    except InferenceError:
                        return
                    if (getattr(func, 'name', None) == 'iter' and
                        is_builtin_object(func)):
                        self.add_message('bad-reversed-sequence', node=node)
                return

            if isinstance(argument, astroid.Instance):
                if (argument._proxied.name == 'dict' and 
                    is_builtin_object(argument._proxied)):
                     self.add_message('bad-reversed-sequence', node=node)
                     return
                elif any(ancestor.name == 'dict' and is_builtin_object(ancestor)
                       for ancestor in argument._proxied.ancestors()):
                    # mappings aren't accepted by reversed()
                    self.add_message('bad-reversed-sequence', node=node)
                    return

                for methods in REVERSED_METHODS:
                    for meth in methods:
                        try:
                            argument.getattr(meth)
                        except astroid.NotFoundError:
                            break
                    else:
                        break
                else:             
                    # check if it is a .deque. It doesn't seem that
                    # we can retrieve special methods 
                    # from C implemented constructs    
                    if argument._proxied.qname().endswith(".deque"):
                        return
                    self.add_message('bad-reversed-sequence', node=node)
            elif not isinstance(argument, (astroid.List, astroid.Tuple)):
                # everything else is not a proper sequence for reversed()
                self.add_message('bad-reversed-sequence', node=node)
コード例 #4
0
ファイル: no_modules.py プロジェクト: acsone/pylint-odoo
 def visit_name(self, node):
     """Detect when a "bad" built-in is referenced."""
     node_infer = utils.safe_infer(node)
     if not utils.is_builtin_object(node_infer):
         # Skip not builtin objects
         return
     if node_infer.name == 'eval':
         self.add_message('eval-referenced', node=node)
コード例 #5
0
 def visit_name(self, node):
     """Detect when a "bad" built-in is referenced."""
     node_infer = utils.safe_infer(node)
     if not utils.is_builtin_object(node_infer):
         # Skip not builtin objects
         return
     if node_infer.name == 'eval':
         self.add_message('eval-referenced', node=node)
コード例 #6
0
    def _check_protected_attribute_access(self, node):
        '''Given an attribute access node (set or get), check if attribute
        access is legitimate. Call _check_first_attr with node before calling
        this method. Valid cases are:
        * self._attr in a method or cls._attr in a classmethod. Checked by
        _check_first_attr.
        * Klass._attr inside "Klass" class.
        * Klass2._attr inside "Klass" class when Klass2 is a base class of
            Klass.
        '''
        attrname = node.attrname

        if (is_attr_protected(attrname)
                and attrname not in self.config.exclude_protected):

            klass = node_frame_class(node)

            # XXX infer to be more safe and less dirty ??
            # in classes, check we are not getting a parent method
            # through the class object or through super
            callee = node.expr.as_string()

            # We are not in a class, no remaining valid case
            if klass is None:
                self.add_message('protected-access', node=node, args=attrname)
                return

            # If the expression begins with a call to super, that's ok.
            if isinstance(node.expr, astroid.CallFunc) and \
               isinstance(node.expr.func, astroid.Name) and \
               node.expr.func.name == 'super':
                return

            # We are in a class, one remaining valid cases, Klass._attr inside
            # Klass
            if not (callee == klass.name or callee in klass.basenames):
                # Detect property assignments in the body of the class.
                # This is acceptable:
                #
                # class A:
                #     b = property(lambda: self._b)

                stmt = node.parent.statement()
                try:
                    if (isinstance(stmt, astroid.Assign)
                            and (stmt in klass.body or klass.parent_of(stmt))
                            and isinstance(stmt.value, astroid.CallFunc)
                            and isinstance(stmt.value.func, astroid.Name)
                            and stmt.value.func.name == 'property'
                            and is_builtin_object(
                                next(stmt.value.func.infer(), None))):
                        return
                except astroid.InferenceError:
                    pass
                self.add_message('protected-access', node=node, args=attrname)
コード例 #7
0
ファイル: typecheck.py プロジェクト: Vauxoo/pylint
def _is_invalid_metaclass(metaclass):
    try:
        mro = metaclass.mro()
    except NotImplementedError:
        # Cannot have a metaclass which is not a newstyle class.
        return True
    else:
        if not any(is_builtin_object(cls) and cls.name == 'type'
                   for cls in mro):
            return True
    return False
コード例 #8
0
ファイル: classes.py プロジェクト: yannack/pylint
    def _check_init(self, node):
        """check that the __init__ method call super or ancestors'__init__
        method
        """
        if (not self.linter.is_message_enabled('super-init-not-called') and
                not self.linter.is_message_enabled('non-parent-init-called')):
            return
        klass_node = node.parent.frame()
        to_call = _ancestors_to_call(klass_node)
        not_called_yet = dict(to_call)
        for stmt in node.nodes_of_class(astroid.Call):
            expr = stmt.func
            if not isinstance(expr, astroid.Attribute) \
                   or expr.attrname != '__init__':
                continue
            # skip the test if using super
            if isinstance(expr.expr, astroid.Call) and \
                   isinstance(expr.expr.func, astroid.Name) and \
               expr.expr.func.name == 'super':
                return
            try:
                for klass in expr.expr.infer():
                    if klass is astroid.YES:
                        continue
                    # The infered klass can be super(), which was
                    # assigned to a variable and the `__init__`
                    # was called later.
                    #
                    # base = super()
                    # base.__init__(...)

                    if (isinstance(klass, astroid.Instance)
                            and isinstance(klass._proxied, astroid.ClassDef)
                            and is_builtin_object(klass._proxied)
                            and klass._proxied.name == 'super'):
                        return
                    elif isinstance(klass, objects.Super):
                        return
                    try:
                        del not_called_yet[klass]
                    except KeyError:
                        if klass not in to_call:
                            self.add_message('non-parent-init-called',
                                             node=expr,
                                             args=klass.name)
            except astroid.InferenceError:
                continue
        for klass, method in six.iteritems(not_called_yet):
            cls = node_frame_class(method)
            if klass.name == 'object' or (cls and cls.name == 'object'):
                continue
            self.add_message('super-init-not-called',
                             args=klass.name,
                             node=node)
コード例 #9
0
ファイル: typecheck.py プロジェクト: modulexcite/pylint
def _is_invalid_metaclass(metaclass):
    try:
        mro = metaclass.mro()
    except NotImplementedError:
        # Cannot have a metaclass which is not a newstyle class.
        return True
    else:
        if not any(is_builtin_object(cls) and cls.name == 'type'
                   for cls in mro):
            return True
    return False
コード例 #10
0
 def visit_callfunc(self, node):
     """visit a CallFunc node, check if map or filter are called with a
     lambda
     """
     if not node.args:
         return
     if not isinstance(node.args[0], astroid.Lambda):
         return
     infered = safe_infer(node.func)
     if (is_builtin_object(infered) and infered.name in ['map', 'filter']):
         self.add_message('deprecated-lambda', node=node)
コード例 #11
0
ファイル: classes.py プロジェクト: willemneal/Docky
    def _check_protected_attribute_access(self, node):
        '''Given an attribute access node (set or get), check if attribute
        access is legitimate. Call _check_first_attr with node before calling
        this method. Valid cases are:
        * self._attr in a method or cls._attr in a classmethod. Checked by
        _check_first_attr.
        * Klass._attr inside "Klass" class.
        * Klass2._attr inside "Klass" class when Klass2 is a base class of
            Klass.
        '''
        attrname = node.attrname

        if (is_attr_protected(attrname) and
                attrname not in self.config.exclude_protected):

            klass = node_frame_class(node)

            # XXX infer to be more safe and less dirty ??
            # in classes, check we are not getting a parent method
            # through the class object or through super
            callee = node.expr.as_string()

            # We are not in a class, no remaining valid case
            if klass is None:
                self.add_message('protected-access', node=node, args=attrname)
                return

            # If the expression begins with a call to super, that's ok.
            if isinstance(node.expr, astroid.CallFunc) and \
               isinstance(node.expr.func, astroid.Name) and \
               node.expr.func.name == 'super':
                return

            # We are in a class, one remaining valid cases, Klass._attr inside
            # Klass
            if not (callee == klass.name or callee in klass.basenames):
                # Detect property assignments in the body of the class.
                # This is acceptable:
                #
                # class A:
                #     b = property(lambda: self._b)

                stmt = node.parent.statement()
                try:
                    if (isinstance(stmt, astroid.Assign) and
                            (stmt in klass.body or klass.parent_of(stmt)) and
                            isinstance(stmt.value, astroid.CallFunc) and
                            isinstance(stmt.value.func, astroid.Name) and
                            stmt.value.func.name == 'property' and
                            is_builtin_object(next(stmt.value.func.infer(), None))):
                        return
                except astroid.InferenceError:
                    pass
                self.add_message('protected-access', node=node, args=attrname)
コード例 #12
0
ファイル: base.py プロジェクト: vbanos/grgov-mobile-search
 def visit_callfunc(self, node):
     """visit a CallFunc node, check if map or filter are called with a
     lambda
     """
     if not node.args:
         return
     if not isinstance(node.args[0], astroid.Lambda):
         return
     infered = safe_infer(node.func)
     if (is_builtin_object(infered)
         and infered.name in ['map', 'filter']):
         self.add_message('deprecated-lambda', node=node)
コード例 #13
0
ファイル: classes.py プロジェクト: DonJayamanne/pylint
    def _check_init(self, node):
        """check that the __init__ method call super or ancestors'__init__
        method
        """
        if (not self.linter.is_message_enabled('super-init-not-called') and
                not self.linter.is_message_enabled('non-parent-init-called')):
            return
        klass_node = node.parent.frame()
        to_call = _ancestors_to_call(klass_node)
        not_called_yet = dict(to_call)
        for stmt in node.nodes_of_class(astroid.Call):
            expr = stmt.func
            if not isinstance(expr, astroid.Attribute) \
                   or expr.attrname != '__init__':
                continue
            # skip the test if using super
            if isinstance(expr.expr, astroid.Call) and \
                   isinstance(expr.expr.func, astroid.Name) and \
               expr.expr.func.name == 'super':
                return
            try:
                for klass in expr.expr.infer():
                    if klass is astroid.YES:
                        continue
                    # The infered klass can be super(), which was
                    # assigned to a variable and the `__init__`
                    # was called later.
                    #
                    # base = super()
                    # base.__init__(...)

                    if (isinstance(klass, astroid.Instance) and
                            isinstance(klass._proxied, astroid.ClassDef) and
                            is_builtin_object(klass._proxied) and
                            klass._proxied.name == 'super'):
                        return
                    elif isinstance(klass, objects.Super):
                        return
                    try:
                        del not_called_yet[klass]
                    except KeyError:
                        if klass not in to_call:
                            self.add_message('non-parent-init-called',
                                             node=expr, args=klass.name)
            except astroid.InferenceError:
                continue
        for klass, method in six.iteritems(not_called_yet):
            cls = node_frame_class(method)
            if klass.name == 'object' or (cls and cls.name == 'object'):
                continue
            self.add_message('super-init-not-called', args=klass.name, node=node)
コード例 #14
0
ファイル: no_modules.py プロジェクト: Vauxoo/pylint-odoo
 def visit_call(self, node):
     node_infer = utils.safe_infer(node.func)
     if utils.is_builtin_object(node_infer) and \
             self.get_func_name(node.func) == 'format':
         self.add_message('prefer-other-formatting', node=node)
     if 'fields' == self.get_func_lib(node.func) and \
             isinstance(node.parent, astroid.Assign) and \
             isinstance(node.parent.parent, astroid.ClassDef):
         has_help = False
         args = misc.join_node_args_kwargs(node)
         for argument in args:
             argument_aux = argument
             if isinstance(argument, astroid.Keyword):
                 argument_aux = argument.value
                 if argument.arg in ['compute', 'search', 'inverse'] and \
                         isinstance(argument.value, astroid.Const) and \
                         argument_aux.value and \
                         not argument_aux.value.startswith(
                             '_' + argument.arg + '_'):
                     self.add_message('method-' + argument.arg,
                                      node=argument_aux)
                 elif argument.arg == 'help':
                     has_help = True
                 elif argument.arg == 'selection_add':
                     # The argument "selection_add" is for overwrite field.
                     # Then don't need help.
                     has_help = None
             if isinstance(argument_aux, astroid.CallFunc) and \
                     isinstance(argument_aux.func, astroid.Name) and \
                     argument_aux.func.name == '_':
                 self.add_message('translation-field', node=argument_aux)
         if has_help is False:
             self.add_message('consider-add-field-help', node=node)
     # Check cr.commit()
     if isinstance(node, astroid.CallFunc) and \
             isinstance(node.func, astroid.Getattr) and \
             node.func.attrname == 'commit' and \
             self.get_cursor_name(node.func) in self.config.cursor_expr:
         self.add_message('invalid-commit', node=node)
     # SQL Injection
     if isinstance(node, astroid.CallFunc) and node.args and \
             isinstance(node.func, astroid.Getattr) and \
             node.func.attrname == 'execute' and \
             self.get_cursor_name(node.func) in self.config.cursor_expr:
         first_arg = node.args[0]
         is_bin_op = isinstance(first_arg, astroid.BinOp) and \
             first_arg.op == '%'
         is_format = isinstance(first_arg, astroid.CallFunc) and \
             self.get_func_name(first_arg.func) == 'format'
         if is_bin_op or is_format:
             self.add_message('sql-injection', node=node)
コード例 #15
0
    def _duplicated_isinstance_types(node):
        """Get the duplicated types from the underlying isinstance calls.

        :param astroid.BoolOp node: Node which should contain a bunch of isinstance calls.
        :returns: Dictionary of the comparison objects from the isinstance calls,
                  to duplicate values from consecutive calls.
        :rtype: dict
        """
        duplicated_objects = set()
        all_types = collections.defaultdict(set)

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

            inferred = utils.safe_infer(call.func)
            if not inferred or not utils.is_builtin_object(inferred):
                continue

            if inferred.name != 'isinstance':
                continue

            isinstance_object = call.args[0].as_string()
            isinstance_types = call.args[1]

            if isinstance_object in all_types:
                duplicated_objects.add(isinstance_object)

            if isinstance(isinstance_types, astroid.Tuple):
                elems = [
                    class_type.as_string()
                    for class_type in isinstance_types.itered()
                ]
            else:
                elems = [isinstance_types.as_string()]
            all_types[isinstance_object].update(elems)

        # Remove all keys which not duplicated
        return {
            key: value
            for key, value in all_types.items() if key in duplicated_objects
        }
コード例 #16
0
ファイル: refactoring.py プロジェクト: truongductri/saverpart
    def _duplicated_isinstance_types(node):
        """Get the duplicated types from the underlying isinstance calls.

        :param astroid.BoolOp node: Node which should contain a bunch of isinstance calls.
        :returns: Dictionary of the comparison objects from the isinstance calls,
                  to duplicate values from consecutive calls.
        :rtype: dict
        """
        duplicated_objects = set()
        all_types = collections.defaultdict(set)

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

            inferred = utils.safe_infer(call.func)
            if not inferred or not utils.is_builtin_object(inferred):
                continue

            if inferred.name != 'isinstance':
                continue

            isinstance_object = call.args[0].as_string()
            isinstance_types = call.args[1]

            if isinstance_object in all_types:
                duplicated_objects.add(isinstance_object)

            if isinstance(isinstance_types, astroid.Tuple):
                elems = [class_type.as_string() for class_type in isinstance_types.itered()]
            else:
                elems = [isinstance_types.as_string()]
            all_types[isinstance_object].update(elems)

        # Remove all keys which not duplicated
        return {key: value for key, value in all_types.items()
                if key in duplicated_objects}
コード例 #17
0
    def visit_function(self, node):
        """check method arguments, overriding"""
        # ignore actual functions
        if not node.is_method():
            return

        method_name = node.name
        if method_name not in self.METHOD_NAMES:
            return

        klass_node = node.parent.frame()
        to_call = _ancestors_to_call(klass_node, method_name)

        not_called_yet = dict(to_call)
        for stmt in node.nodes_of_class(astroid.CallFunc):
            expr = stmt.func
            if not isinstance(expr, astroid.Getattr):
                continue
            if expr.attrname != method_name:
                continue

            # Skip the test if using super
            if (isinstance(expr.expr, astroid.CallFunc) and
                    isinstance(expr.expr.func, astroid.Name) and
                    expr.expr.func.name == 'super'):
                return

            try:
                klass = next(expr.expr.infer())
                if klass is astroid.YES:
                    continue

                # The infered klass can be super(), which was
                # assigned to a variable and the `__init__` was called later.
                #
                # base = super()
                # base.__init__(...)

                if (isinstance(klass, astroid.Instance) and
                        isinstance(klass._proxied, astroid.Class) and
                        utils.is_builtin_object(klass._proxied) and
                        klass._proxied.name == 'super'):
                    return
                try:
                    del not_called_yet[klass]
                except KeyError:
                    if klass not in to_call:
                        self.add_message(
                            self.NON_PARENT_MESSAGE_ID,
                            node=expr,
                            args=(method_name, klass.name),
                        )
            except astroid.InferenceError:
                continue

        for klass, method in six.iteritems(not_called_yet):
            if klass.name == 'object' or method.parent.name == 'object':
                continue
            self.add_message(
                self.NOT_CALLED_MESSAGE_ID,
                args=(method_name, klass.name),
                node=node,
            )
コード例 #18
0
    def visit_call(self, node):
        node_infer = utils.safe_infer(node.func)
        if utils.is_builtin_object(node_infer) and \
                self.get_func_name(node.func) == 'format':
            self.add_message('prefer-other-formatting', node=node)
        if ('fields' == self.get_func_lib(node.func) and
                isinstance(node.parent, astroid.Assign) and
                isinstance(node.parent.parent, astroid.ClassDef)):
            has_help = False
            args = misc.join_node_args_kwargs(node)
            index = 0
            field_name = ''
            if (isinstance(node.parent, astroid.Assign) and
                    node.parent.targets and
                    isinstance(node.parent.targets[0], astroid.AssignName)):
                field_name = (node.parent.targets[0].name
                              .replace('_', ' '))
            for argument in args:
                argument_aux = argument
                # Check this 'name = fields.Char("name")'
                if (isinstance(argument, astroid.Const) and
                    (index ==
                     FIELDS_METHOD.get(argument.parent.func.attrname, 0)) and
                    (argument.value in
                     [field_name.capitalize(), field_name.title()])):
                    self.add_message('attribute-string-redundant', node=node)
                if isinstance(argument, astroid.Keyword):
                    argument_aux = argument.value
                    deprecated = self.config.deprecated_field_parameters
                    if argument.arg in ['compute', 'search', 'inverse'] and \
                            isinstance(argument_aux, astroid.Const) and \
                            isinstance(argument_aux.value, string_types) and \
                            not argument_aux.value.startswith(
                                '_' + argument.arg + '_'):
                        self.add_message('method-' + argument.arg,
                                         node=argument_aux)
                    # Check if the param string is equal to the name
                    #   of variable
                    elif argument.arg == 'string' and \
                        (isinstance(argument_aux, astroid.Const) and
                         argument_aux.value in
                         [field_name.capitalize(), field_name.title()]):
                        self.add_message(
                            'attribute-string-redundant', node=node)
                    elif (argument.arg in deprecated):
                        self.add_message(
                            'renamed-field-parameter', node=node,
                            args=(argument.arg, deprecated[argument.arg])
                        )
                    elif argument.arg == 'help':
                        has_help = True
                    elif argument.arg == 'selection_add':
                        # The argument "selection_add" is for overwrite field.
                        # Then don't need help.
                        has_help = None
                if isinstance(argument_aux, astroid.CallFunc) and \
                        isinstance(argument_aux.func, astroid.Name) and \
                        argument_aux.func.name == '_':
                    self.add_message('translation-field', node=argument_aux)
                index += 1
            if has_help is False:
                self.add_message('consider-add-field-help', node=node)
        # Check cr.commit()
        if isinstance(node, astroid.CallFunc) and \
                isinstance(node.func, astroid.Getattr) and \
                node.func.attrname == 'commit' and \
                self.get_cursor_name(node.func) in self.config.cursor_expr:
            self.add_message('invalid-commit', node=node)

        # SQL Injection
        if isinstance(node, astroid.CallFunc) and node.args and \
                isinstance(node.func, astroid.Getattr) and \
                node.func.attrname in ('execute', 'executemany') and \
                self.get_cursor_name(node.func) in self.config.cursor_expr:

            first_arg = node.args[0]

            risky = self._check_node_for_sqli_risk(first_arg)

            if (not risky and isinstance(first_arg,
                                         (astroid.Name, astroid.Subscript))):

                # 1) look for parent method / controller
                current = node
                while (current and
                       not isinstance(current.parent, astroid.FunctionDef)):
                    current = current.parent
                parent = current.parent

                # 2) check how was the variable built
                for node in parent.nodes_of_class(astroid.Assign):
                    if node.targets[0].as_string() == first_arg.as_string():
                        risky = self._check_node_for_sqli_risk(node.value)
                        if risky:
                            break

            if risky:
                self.add_message('sql-injection', node=node)
コード例 #19
0
 def _is_builtin(node, function):
     inferred = utils.safe_infer(node)
     if not inferred:
         return False
     return utils.is_builtin_object(inferred) and inferred.name == function
コード例 #20
0
ファイル: classes.py プロジェクト: danbaehr/project2
def _is_invalid_base_class(cls):
    return cls.name in INVALID_BASE_CLASSES and is_builtin_object(cls)
コード例 #21
0
ファイル: no_modules.py プロジェクト: modoolar/pylint-odoo
    def visit_call(self, node):
        infer_node = utils.safe_infer(node.func)
        if utils.is_builtin_object(infer_node) and infer_node.name == 'print':
            self.add_message('print-used', node=node)
        if ('fields' == self.get_func_lib(node.func)
                and isinstance(node.parent, astroid.Assign)
                and isinstance(node.parent.parent, astroid.ClassDef)):
            args = misc.join_node_args_kwargs(node)
            index = 0
            field_name = ''
            if (isinstance(node.parent, astroid.Assign)
                    and node.parent.targets and isinstance(
                        node.parent.targets[0], astroid.AssignName)):
                field_name = (node.parent.targets[0].name.replace('_', ' '))
            is_related = bool(
                [1 for kw in node.keywords or [] if kw.arg == 'related'])
            for argument in args:
                argument_aux = argument
                # Check this 'name = fields.Char("name")'
                if (not is_related and isinstance(argument, astroid.Const)
                        and (index == FIELDS_METHOD.get(
                            argument.parent.func.attrname, 0))
                        and (argument.value
                             in [field_name.capitalize(),
                                 field_name.title()])):
                    self.add_message('attribute-string-redundant', node=node)
                if isinstance(argument, astroid.Keyword):
                    argument_aux = argument.value
                    deprecated = self.config.deprecated_field_parameters
                    if argument.arg in ['compute', 'search', 'inverse'] and \
                            isinstance(argument_aux, astroid.Const) and \
                            isinstance(argument_aux.value, string_types) and \
                            not argument_aux.value.startswith(
                                '_' + argument.arg + '_'):
                        self.add_message('method-' + argument.arg,
                                         node=argument_aux)
                    # Check if the param string is equal to the name
                    #   of variable
                    elif not is_related and argument.arg == 'string' and \
                        (isinstance(argument_aux, astroid.Const) and
                         argument_aux.value in
                         [field_name.capitalize(), field_name.title()]):
                        self.add_message('attribute-string-redundant',
                                         node=node)
                    elif (argument.arg in deprecated):
                        self.add_message('renamed-field-parameter',
                                         node=node,
                                         args=(argument.arg,
                                               deprecated[argument.arg]))
                if isinstance(argument_aux, astroid.Call) and \
                        isinstance(argument_aux.func, astroid.Name) and \
                        argument_aux.func.name == '_':
                    self.add_message('translation-field', node=argument_aux)
                index += 1
        # Check cr.commit()
        if isinstance(node, astroid.Call) and \
                isinstance(node.func, astroid.Attribute) and \
                node.func.attrname == 'commit' and \
                self.get_cursor_name(node.func) in self.config.cursor_expr:
            self.add_message('invalid-commit', node=node)

        if (isinstance(node, astroid.Call)
                and isinstance(node.func, astroid.Attribute)
                and node.func.attrname == 'with_context' and not node.keywords
                and node.args):
            # with_context(**ctx) is considered a keywords
            # So, if only one args is received it is overridden
            self.add_message('context-overridden',
                             node=node,
                             args=(node.args[0].as_string(), ))

        # Call the message_post()
        base_dirname = os.path.basename(
            os.path.normpath(os.path.dirname(self.linter.current_file)))
        if (base_dirname != 'tests' and isinstance(node, astroid.Call)
                and isinstance(node.func, astroid.Attribute)
                and node.func.attrname == 'message_post'):
            for arg in itertools.chain(node.args, node.keywords or []):
                if isinstance(arg, astroid.Keyword):
                    keyword = arg.arg
                    value = arg.value
                else:
                    keyword = ''
                    value = arg
                if keyword and keyword not in ('subject', 'body'):
                    continue
                as_string = ''
                # case: message_post(body='String')
                if isinstance(value, astroid.Const):
                    as_string = value.as_string()
                # case: message_post(body='String %s' % (...))
                elif (isinstance(value, astroid.BinOp) and value.op == '%'
                      and isinstance(value.left, astroid.Const)
                      # The right part is translatable only if it's a
                      # function or a list of functions
                      and not (isinstance(value.right, (
                          astroid.Call, astroid.Tuple, astroid.List)) and all([
                              isinstance(child, astroid.Call)
                              for child in getattr(value.right, 'elts', [])
                          ]))):
                    as_string = value.left.as_string()
                # case: message_post(body='String {...}'.format(...))
                elif (isinstance(value, astroid.Call)
                      and isinstance(value.func, astroid.Attribute)
                      and isinstance(value.func.expr, astroid.Const)
                      and value.func.attrname == 'format'):
                    as_string = value.func.expr.as_string()
                if as_string:
                    keyword = keyword and '%s=' % keyword
                    self.add_message('translation-required',
                                     node=node,
                                     args=('message_post', keyword, as_string))

        # Call _(...) with variables into the term to be translated
        if (isinstance(node.func, astroid.Name) and node.func.name == '_'
                and node.args):
            wrong = ''
            right = ''
            arg = node.args[0]
            # case: _('...' % (variables))
            if isinstance(arg, astroid.BinOp) and arg.op == '%':
                wrong = '%s %% %s' % (arg.left.as_string(),
                                      arg.right.as_string())
                right = '_(%s) %% %s' % (arg.left.as_string(),
                                         arg.right.as_string())
            # Case: _('...'.format(variables))
            elif (isinstance(arg, astroid.Call)
                  and isinstance(arg.func, astroid.Attribute)
                  and isinstance(arg.func.expr, astroid.Const)
                  and arg.func.attrname == 'format'):
                self.add_message('str-format-used', node=node)
                wrong = arg.as_string()
                params_as_string = ', '.join([
                    x.as_string()
                    for x in itertools.chain(arg.args, arg.keywords or [])
                ])
                right = '_(%s).format(%s)' % (arg.func.expr.as_string(),
                                              params_as_string)
            if wrong and right:
                self.add_message('translation-contains-variable',
                                 node=node,
                                 args=(wrong, right))

            # translation-positional-used: Check "string to translate"
            # to check "%s %s..." used where the position can't be changed
            str2translate = arg.as_string()
            printf_args = (misc.WrapperModuleChecker.
                           _get_printf_str_args_kwargs(str2translate))
            if isinstance(printf_args, tuple) and len(printf_args) >= 2:
                # Return tuple for %s and dict for %(varname)s
                # Check just the following cases "%s %s..."
                self.add_message('translation-positional-used',
                                 node=node,
                                 args=(str2translate, ))

        # SQL Injection
        if self._check_sql_injection_risky(node):
            self.add_message('sql-injection', node=node)

        # external-request-timeout
        lib_alias = self.get_func_lib(node.func)
        # Use dict "self._from_imports" to know the source library of the method
        lib_original = self._from_imports.get(lib_alias) or lib_alias
        func_name = self.get_func_name(node.func)
        lib_original_func_name = (
            # If it using "requests.request()"
            "%s.%s" % (lib_original, func_name) if lib_original
            # If it using "from requests import request;request()"
            else self._from_imports.get(func_name))
        if lib_original_func_name in self.config.external_request_timeout_methods:
            for argument in misc.join_node_args_kwargs(node):
                if not isinstance(argument, astroid.Keyword):
                    continue
                if argument.arg == 'timeout':
                    break
            else:
                self.add_message('external-request-timeout',
                                 node=node,
                                 args=(lib_original_func_name, ))
コード例 #22
0
ファイル: no_modules.py プロジェクト: wsdfsilva/pylint-odoo
    def visit_call(self, node):
        infer_node = utils.safe_infer(node.func)
        if utils.is_builtin_object(infer_node) and infer_node.name == 'print':
            self.add_message('print-used', node=node)
        if ('fields' == self.get_func_lib(node.func) and
                isinstance(node.parent, astroid.Assign) and
                isinstance(node.parent.parent, astroid.ClassDef)):
            args = misc.join_node_args_kwargs(node)
            index = 0
            field_name = ''
            if (isinstance(node.parent, astroid.Assign) and
                    node.parent.targets and
                    isinstance(node.parent.targets[0], astroid.AssignName)):
                field_name = (node.parent.targets[0].name
                              .replace('_', ' '))
            for argument in args:
                argument_aux = argument
                # Check this 'name = fields.Char("name")'
                if (isinstance(argument, astroid.Const) and
                    (index ==
                     FIELDS_METHOD.get(argument.parent.func.attrname, 0)) and
                    (argument.value in
                     [field_name.capitalize(), field_name.title()])):
                    self.add_message('attribute-string-redundant', node=node)
                if isinstance(argument, astroid.Keyword):
                    argument_aux = argument.value
                    deprecated = self.config.deprecated_field_parameters
                    if argument.arg in ['compute', 'search', 'inverse'] and \
                            isinstance(argument_aux, astroid.Const) and \
                            isinstance(argument_aux.value, string_types) and \
                            not argument_aux.value.startswith(
                                '_' + argument.arg + '_'):
                        self.add_message('method-' + argument.arg,
                                         node=argument_aux)
                    # Check if the param string is equal to the name
                    #   of variable
                    elif argument.arg == 'string' and \
                        (isinstance(argument_aux, astroid.Const) and
                         argument_aux.value in
                         [field_name.capitalize(), field_name.title()]):
                        self.add_message(
                            'attribute-string-redundant', node=node)
                    elif (argument.arg in deprecated):
                        self.add_message(
                            'renamed-field-parameter', node=node,
                            args=(argument.arg, deprecated[argument.arg])
                        )
                if isinstance(argument_aux, astroid.Call) and \
                        isinstance(argument_aux.func, astroid.Name) and \
                        argument_aux.func.name == '_':
                    self.add_message('translation-field', node=argument_aux)
                index += 1
        # Check cr.commit()
        if isinstance(node, astroid.Call) and \
                isinstance(node.func, astroid.Attribute) and \
                node.func.attrname == 'commit' and \
                self.get_cursor_name(node.func) in self.config.cursor_expr:
            self.add_message('invalid-commit', node=node)

        # Call the message_post()
        if (isinstance(node, astroid.Call) and
                isinstance(node.func, astroid.Attribute) and
                node.func.attrname == 'message_post'):
            for arg in itertools.chain(node.args, node.keywords or []):
                if isinstance(arg, astroid.Keyword):
                    keyword = arg.arg
                    value = arg.value
                else:
                    keyword = ''
                    value = arg
                if keyword and keyword not in ('subject', 'body'):
                    continue
                as_string = ''
                # case: message_post(body='String')
                if isinstance(value, astroid.Const):
                    as_string = value.as_string()
                # case: message_post(body='String %s' % (...))
                elif (isinstance(value, astroid.BinOp)
                        and value.op == '%'
                        and isinstance(value.left, astroid.Const)
                        # The right part is translatable only if it's a
                        # function or a list of functions
                        and not (
                            isinstance(value.right, (
                                astroid.Call, astroid.Tuple, astroid.List))
                            and all([
                                isinstance(child, astroid.Call)
                                for child in getattr(value.right, 'elts', [])
                            ]))):
                    as_string = value.left.as_string()
                # case: message_post(body='String {...}'.format(...))
                elif (isinstance(value, astroid.Call)
                        and isinstance(value.func, astroid.Attribute)
                        and isinstance(value.func.expr, astroid.Const)
                        and value.func.attrname == 'format'):
                    as_string = value.func.expr.as_string()
                if as_string:
                    keyword = keyword and '%s=' % keyword
                    self.add_message(
                        'translation-required', node=node,
                        args=('message_post', keyword, as_string))

        # Call _(...) with variables into the term to be translated
        if (isinstance(node.func, astroid.Name)
                and node.func.name == '_'
                and node.args):
            wrong = ''
            right = ''
            arg = node.args[0]
            # case: _('...' % (variables))
            if isinstance(arg, astroid.BinOp) and arg.op == '%':
                wrong = '%s %% %s' % (
                    arg.left.as_string(), arg.right.as_string())
                right = '_(%s) %% %s' % (
                    arg.left.as_string(), arg.right.as_string())
            # Case: _('...'.format(variables))
            elif (isinstance(arg, astroid.Call)
                    and isinstance(arg.func, astroid.Attribute)
                    and isinstance(arg.func.expr, astroid.Const)
                    and arg.func.attrname == 'format'):
                self.add_message('str-format-used', node=node)
                wrong = arg.as_string()
                params_as_string = ', '.join([
                    x.as_string()
                    for x in itertools.chain(arg.args, arg.keywords or [])])
                right = '_(%s).format(%s)' % (
                    arg.func.expr.as_string(), params_as_string)
            if wrong and right:
                self.add_message(
                    'translation-contains-variable', node=node,
                    args=(wrong, right))

            # translation-positional-used: Check "string to translate"
            # to check "%s %s..." used where the position can't be changed
            str2translate = arg.as_string()
            printf_args = (
                misc.WrapperModuleChecker.
                _get_printf_str_args_kwargs(str2translate))
            if isinstance(printf_args, tuple) and len(printf_args) >= 2:
                # Return tuple for %s and dict for %(varname)s
                # Check just the following cases "%s %s..."
                self.add_message('translation-positional-used',
                                 node=node, args=(str2translate,))

        # SQL Injection
        if isinstance(node, astroid.Call) and node.args and \
                isinstance(node.func, astroid.Attribute) and \
                node.func.attrname in ('execute', 'executemany') and \
                self.get_cursor_name(node.func) in self.config.cursor_expr:

            first_arg = node.args[0]

            risky = self._check_node_for_sqli_risk(first_arg)
            if not risky:
                for node_assignation in self._get_assignation_nodes(first_arg):
                    risky = self._check_node_for_sqli_risk(node_assignation)
                    if risky:
                        break

            if risky:
                self.add_message('sql-injection', node=node)
コード例 #23
0
ファイル: refactoring.py プロジェクト: truongductri/saverpart
 def _is_builtin(node, function):
     inferred = utils.safe_infer(node)
     if not inferred:
         return False
     return utils.is_builtin_object(inferred) and inferred.name == function
コード例 #24
0
ファイル: classes.py プロジェクト: yannack/pylint
def _is_invalid_base_class(cls):
    return cls.name in INVALID_BASE_CLASSES and is_builtin_object(cls)
コード例 #25
0
ファイル: super_check.py プロジェクト: polesye/edx-lint
    def visit_function(self, node):
        """Called for every function definition in the source code."""
        # ignore actual functions
        if not node.is_method():
            return

        method_name = node.name
        if method_name not in self.METHOD_NAMES:
            return

        klass_node = node.parent.frame()
        to_call = _ancestors_to_call(klass_node, method_name)

        not_called_yet = dict(to_call)
        for stmt in node.nodes_of_class(astroid.CallFunc):
            expr = stmt.func
            if not isinstance(expr, astroid.Getattr):
                continue
            if expr.attrname != method_name:
                continue

            # Skip the test if using super
            if (isinstance(expr.expr, astroid.CallFunc) and
                    isinstance(expr.expr.func, astroid.Name) and
                    expr.expr.func.name == 'super'):
                return

            try:
                klass = next(expr.expr.infer())
                if klass is astroid.YES:
                    continue

                # The infered klass can be super(), which was
                # assigned to a variable and the `__init__` was called later.
                #
                # base = super()
                # base.__init__(...)

                # pylint: disable=protected-access
                if (isinstance(klass, astroid.Instance) and
                        isinstance(klass._proxied, astroid.Class) and
                        utils.is_builtin_object(klass._proxied) and
                        klass._proxied.name == 'super'):
                    return
                try:
                    del not_called_yet[klass]
                except KeyError:
                    if klass not in to_call:
                        self.add_message(
                            self.NON_PARENT_MESSAGE_ID,
                            node=expr,
                            args=(method_name, klass.name),
                        )
            except astroid.InferenceError:
                continue

        for klass, method in six.iteritems(not_called_yet):
            if klass.name == 'object' or method.parent.name == 'object':
                continue
            self.add_message(
                self.NOT_CALLED_MESSAGE_ID,
                args=(method_name, klass.name),
                node=node,
            )
コード例 #26
0
    def visit_functiondef(self, node):
        """Called for every function definition in the source code."""
        # ignore actual functions
        if not node.is_method():
            return

        method_name = node.name
        if method_name not in self.METHOD_NAMES:
            return

        klass_node = node.parent.frame()
        to_call = _ancestors_to_call(klass_node, method_name)

        not_called_yet = dict(to_call)
        for stmt in node.nodes_of_class(astroid.Call):
            expr = stmt.func
            if not isinstance(expr, astroid.Attribute):
                continue
            if expr.attrname != method_name:
                continue

            # Skip the test if using super
            if (
                isinstance(expr.expr, astroid.Call)
                and isinstance(expr.expr.func, astroid.Name)
                and expr.expr.func.name == "super"
            ):
                return

            try:
                klass = next(expr.expr.infer())
                if klass is astroid.Uninferable:
                    continue

                # The infered klass can be super(), which was
                # assigned to a variable and the `__init__` was called later.
                #
                # base = super()
                # base.__init__(...)

                # pylint: disable=protected-access
                if (
                    isinstance(klass, astroid.Instance)
                    and isinstance(klass._proxied, astroid.ClassDef)
                    and utils.is_builtin_object(klass._proxied)
                    and klass._proxied.name == "super"
                ):
                    return
                if isinstance(klass, astroid.objects.Super):
                    return
                try:
                    del not_called_yet[klass]
                except KeyError:
                    if klass not in to_call:
                        self.add_message(
                            self.NON_PARENT_MESSAGE_ID, node=expr, args=(method_name, usable_class_name(klass))
                        )
            except astroid.InferenceError:
                continue

        for klass, method in not_called_yet.items():
            if klass.name == "object" or method.parent.name == "object":
                continue
            self.add_message(self.NOT_CALLED_MESSAGE_ID, args=(method_name, usable_class_name(klass)), node=node)