Example #1
0
 def _check_open_encoding(self, node):
     """Check that an open() call always has an encoding set."""
     try:
         mode_arg = utils.get_argument_from_call(node, position=1,
                                                 keyword='mode')
     except utils.NoSuchArgumentError:
         mode_arg = None
     _encoding = None
     try:
         _encoding = utils.get_argument_from_call(node, position=2)
     except utils.NoSuchArgumentError:
         try:
             _encoding = utils.get_argument_from_call(node,
                                                      keyword='encoding')
         except utils.NoSuchArgumentError:
             pass
     if _encoding is None:
         if mode_arg is not None:
             mode = utils.safe_infer(mode_arg)
         if (mode_arg is not None and isinstance(mode, astroid.Const) and
                 'b' in getattr(mode, 'value', '')):
             # Files opened as binary don't need an encoding.
             return
         else:
             self.add_message('open-without-encoding', node=node)
Example #2
0
    def _check_config(self, node):
        """Check that the arguments to config.get(...) are valid.

        FIXME: We should check all ConfigManager calls.
        https://github.com/The-Compiler/qutebrowser/issues/107
        """
        try:
            sect_arg = utils.get_argument_from_call(node, position=0, keyword="sectname")
            opt_arg = utils.get_argument_from_call(node, position=1, keyword="optname")
        except utils.NoSuchArgumentError:
            return
        sect_arg = utils.safe_infer(sect_arg)
        opt_arg = utils.safe_infer(opt_arg)
        if not (isinstance(sect_arg, astroid.Const) and isinstance(opt_arg, astroid.Const)):
            return
        try:
            configdata.DATA[sect_arg.value][opt_arg.value]
        except KeyError:
            self.add_message("bad-config-call", node=node, args=(sect_arg.value, opt_arg.value))
Example #3
0
 def _check_config(self, node):
     """Check that the arguments to config.get(...) are valid."""
     try:
         sect_arg = utils.get_argument_from_call(node, position=0,
                                                 keyword='sectname')
         opt_arg = utils.get_argument_from_call(node, position=1,
                                                keyword='optname')
     except utils.NoSuchArgumentError:
         return
     sect_arg = utils.safe_infer(sect_arg)
     opt_arg = utils.safe_infer(opt_arg)
     if not (isinstance(sect_arg, astroid.Const) and
             isinstance(opt_arg, astroid.Const)):
         return
     try:
         configdata.DATA[sect_arg.value][opt_arg.value]
     except KeyError:
         self.add_message('bad-config-call', node=node,
                          args=(sect_arg.value, opt_arg.value))
Example #4
0
 def _check_open_mode(self, node):
     """Check that the mode argument of an open or file call is valid."""
     try:
         mode_arg = utils.get_argument_from_call(node, position=1, keyword="mode")
     except utils.NoSuchArgumentError:
         return
     if mode_arg:
         mode_arg = utils.safe_infer(mode_arg)
         if isinstance(mode_arg, astroid.Const) and not _check_mode_str(mode_arg.value):
             self.add_message("bad-open-mode", node=node, args=mode_arg.value)
Example #5
0
 def _check_open_mode(self, node):
     """Check that the mode argument of an open or file call is valid."""
     try:
         mode_arg = utils.get_argument_from_call(node, position=1, keyword='mode')
         if mode_arg:
             mode_arg = utils.safe_infer(mode_arg)
             if (isinstance(mode_arg, astroid.Const)
                 and not re.match(_VALID_OPEN_MODE_REGEX, mode_arg.value)):
                 self.add_message('W1501', node=node, args=(mode_arg.value))
     except (utils.NoSuchArgumentError, TypeError):
         pass
Example #6
0
    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)
def testGetArgumentFromCall():
    node = astroid.extract_node("foo(a, not_this_one=1, this_one=2)")
    arg = utils.get_argument_from_call(node, position=2, keyword="this_one")
    assert 2 == arg.value

    node = astroid.extract_node("foo(a)")
    with pytest.raises(utils.NoSuchArgumentError):
        utils.get_argument_from_call(node, position=1)
    with pytest.raises(ValueError):
        utils.get_argument_from_call(node, None, None)
    name = utils.get_argument_from_call(node, position=0)
    assert name.name == "a"
def testGetArgumentFromCallExists(fn, kw):
    node = astroid.extract_node(fn)
    assert utils.get_argument_from_call(node, **kw) is not None
def testGetArgumentFromCallError(fn, kw):
    with pytest.raises(utils.NoSuchArgumentError):
        node = astroid.extract_node(fn)
        utils.get_argument_from_call(node, **kw)
def testGetArgumentFromCallExists(fn, kw):
    node = astroid.extract_node(fn)
    assert utils.get_argument_from_call(node, **kw) is not None
Example #11
0
    def _check_new_format_specifiers(self, node, fields, named):
        """
        Check attribute and index access in the format
        string ("{0.a}" and "{0[a]}").
        """
        for key, specifiers in fields:
            # Obtain the argument. If it can't be obtained
            # or inferred, skip this check.
            if key == "":
                # {[0]} will have an unnamed argument, defaulting
                # to 0. It will not be present in `named`, so use the value
                # 0 for it.
                key = 0
            if isinstance(key, numbers.Number):
                try:
                    argname = utils.get_argument_from_call(node, key)
                except utils.NoSuchArgumentError:
                    continue
            else:
                if key not in named:
                    continue
                argname = named[key]
            if argname in (astroid.Uninferable, None):
                continue
            try:
                argument = utils.safe_infer(argname)
            except astroid.InferenceError:
                continue
            if not specifiers or not argument:
                # No need to check this key if it doesn't
                # use attribute / item access
                continue
            if argument.parent and isinstance(argument.parent,
                                              astroid.Arguments):
                # Ignore any object coming from an argument,
                # because we can't infer its value properly.
                continue
            previous = argument
            parsed = []
            for is_attribute, specifier in specifiers:
                if previous is astroid.Uninferable:
                    break
                parsed.append((is_attribute, specifier))
                if is_attribute:
                    try:
                        previous = previous.getattr(specifier)[0]
                    except astroid.NotFoundError:
                        if (hasattr(previous, "has_dynamic_getattr")
                                and previous.has_dynamic_getattr()):
                            # Don't warn if the object has a custom __getattr__
                            break
                        path = get_access_path(key, parsed)
                        self.add_message(
                            "missing-format-attribute",
                            args=(specifier, path),
                            node=node,
                        )
                        break
                else:
                    warn_error = False
                    if hasattr(previous, "getitem"):
                        try:
                            previous = previous.getitem(
                                astroid.Const(specifier))
                        except (
                                astroid.AstroidIndexError,
                                astroid.AstroidTypeError,
                                astroid.AttributeInferenceError,
                        ):
                            warn_error = True
                        except astroid.InferenceError:
                            break
                        if previous is astroid.Uninferable:
                            break
                    else:
                        try:
                            # Lookup __getitem__ in the current node,
                            # but skip further checks, because we can't
                            # retrieve the looked object
                            previous.getattr("__getitem__")
                            break
                        except astroid.NotFoundError:
                            warn_error = True
                    if warn_error:
                        path = get_access_path(key, parsed)
                        self.add_message("invalid-format-index",
                                         args=(specifier, path),
                                         node=node)
                        break

                try:
                    previous = next(previous.infer())
                except astroid.InferenceError:
                    # can't check further if we can't infer it
                    break
Example #12
0
    def testGetArgumentFromCall(self):
        node = test_utils.extract_node('foo(bar=3)')
        self.assertIsNotNone(utils.get_argument_from_call(node, keyword='bar'))
        with self.assertRaises(utils.NoSuchArgumentError):
            node = test_utils.extract_node('foo(3)')
            utils.get_argument_from_call(node, keyword='bar')
        with self.assertRaises(utils.NoSuchArgumentError):
            node = test_utils.extract_node('foo(one=a, two=b, three=c)')
            utils.get_argument_from_call(node, position=1)
        node = test_utils.extract_node('foo(a, b, c)')
        self.assertIsNotNone(utils.get_argument_from_call(node, position=1))
        node = test_utils.extract_node('foo(a, not_this_one=1, this_one=2)')
        arg = utils.get_argument_from_call(node,
                                           position=2,
                                           keyword='this_one')
        self.assertEqual(2, arg.value)
        node = test_utils.extract_node('foo(a)')
        with self.assertRaises(utils.NoSuchArgumentError):
            utils.get_argument_from_call(node, position=1)
        with self.assertRaises(ValueError):
            utils.get_argument_from_call(node, None, None)

        name = utils.get_argument_from_call(node, position=0)
        self.assertEqual(name.name, 'a')
Example #13
0
 def _check_shallow_copy_environ(self, node):
     arg = utils.get_argument_from_call(node, position=0)
     for inferred in arg.inferred():
         if inferred.qname() == OS_ENVIRON:
             self.add_message("shallow-copy-environ", node=node)
             break
Example #14
0
    def _check_new_format_specifiers(self, node, fields, named):
        """
        Check attribute and index access in the format
        string ("{0.a}" and "{0[a]}").
        """
        for key, specifiers in fields:
            # Obtain the argument. If it can't be obtained
            # or infered, skip this check.
            if key == '':
                # {[0]} will have an unnamed argument, defaulting
                # to 0. It will not be present in `named`, so use the value
                # 0 for it.
                key = 0
            if isinstance(key, numbers.Number):
                try:
                    argname = utils.get_argument_from_call(node, key)
                except utils.NoSuchArgumentError:
                    continue
            else:
                if key not in named:
                    continue
                argname = named[key]
            if argname in (astroid.YES, None):
                continue
            try:
                argument = argname.infer().next()
            except astroid.InferenceError:
                continue
            if not specifiers or argument is astroid.YES:
                # No need to check this key if it doesn't
                # use attribute / item access
                continue
            if argument.parent and isinstance(argument.parent, astroid.Arguments):
                # Check to see if our argument is kwarg or vararg,
                # and skip the check for this argument if so, because when inferring,
                # astroid will return empty objects (dicts and tuples) and
                # that can lead to false positives.
                if argname.name in (argument.parent.kwarg, argument.parent.vararg):
                    continue
            previous = argument
            parsed = []
            for is_attribute, specifier in specifiers:
                if previous is astroid.YES:
                    break
                parsed.append((is_attribute, specifier))
                if is_attribute:
                    try:
                        previous = previous.getattr(specifier)[0]
                    except astroid.NotFoundError:
                        if (hasattr(previous, 'has_dynamic_getattr') and
                                previous.has_dynamic_getattr()):
                            # Don't warn if the object has a custom __getattr__
                            break
                        path = get_access_path(key, parsed)
                        self.add_message('missing-format-attribute',
                                         args=(specifier, path),
                                         node=node)
                        break
                else:
                    warn_error = False
                    if hasattr(previous, 'getitem'):
                        try:
                            previous = previous.getitem(specifier)
                        except (IndexError, TypeError):
                            warn_error = True
                    else:
                        try:
                            # Lookup __getitem__ in the current node,
                            # but skip further checks, because we can't
                            # retrieve the looked object
                            previous.getattr('__getitem__')
                            break
                        except astroid.NotFoundError:
                            warn_error = True
                    if warn_error:
                        path = get_access_path(key, parsed)
                        self.add_message('invalid-format-index',
                                         args=(specifier, path),
                                         node=node)
                        break

                try:
                    previous = previous.infer().next()
                except astroid.InferenceError:
                    # can't check further if we can't infer it
                    break
Example #15
0
def testGetArgumentFromCallExists(
        fn: str, kw: Union[Dict[str, int], Dict[str, str]]) -> None:
    node = astroid.extract_node(fn)
    assert utils.get_argument_from_call(node, **kw) is not None
 def testGetArgumentFromCall(self):
     node = test_utils.extract_node('foo(bar=3)')
     self.assertIsNotNone(utils.get_argument_from_call(node, keyword='bar'))
     with self.assertRaises(utils.NoSuchArgumentError):
         node = test_utils.extract_node('foo(3)')
         utils.get_argument_from_call(node, keyword='bar')
     with self.assertRaises(utils.NoSuchArgumentError):
         node = test_utils.extract_node('foo(one=a, two=b, three=c)')
         utils.get_argument_from_call(node, position=1)
     node = test_utils.extract_node('foo(a, b, c)')
     self.assertIsNotNone(utils.get_argument_from_call(node, position=1))
     node = test_utils.extract_node('foo(a, not_this_one=1, this_one=2)')
     arg = utils.get_argument_from_call(node, position=1, keyword='this_one')
     self.assertEqual(2, arg.value)
     node = test_utils.extract_node('foo(a)')
     with self.assertRaises(utils.NoSuchArgumentError):
         utils.get_argument_from_call(node, position=1)
     with self.assertRaises(ValueError):
         utils.get_argument_from_call(node, None, None)
             
     name = utils.get_argument_from_call(node, position=0)
     self.assertEqual(name.name, 'a')
Example #17
0
    def _check_new_format_specifiers(self, node, fields, named):
        """
        Check attribute and index access in the format
        string ("{0.a}" and "{0[a]}").
        """
        for key, specifiers in fields:
            # Obtain the argument. If it can't be obtained
            # or infered, skip this check.
            if key == "":
                # {[0]} will have an unnamed argument, defaulting
                # to 0. It will not be present in `named`, so use the value
                # 0 for it.
                key = 0
            if isinstance(key, numbers.Number):
                try:
                    argname = utils.get_argument_from_call(node, key)
                except utils.NoSuchArgumentError:
                    continue
            else:
                if key not in named:
                    continue
                argname = named[key]
            if argname in (astroid.Uninferable, None):
                continue
            try:
                argument = next(argname.infer())
            except astroid.InferenceError:
                continue
            if not specifiers or argument is astroid.Uninferable:
                # No need to check this key if it doesn't
                # use attribute / item access
                continue
            if argument.parent and isinstance(argument.parent, astroid.Arguments):
                # Ignore any object coming from an argument,
                # because we can't infer its value properly.
                continue
            previous = argument
            parsed = []
            for is_attribute, specifier in specifiers:
                if previous is astroid.Uninferable:
                    break
                parsed.append((is_attribute, specifier))
                if is_attribute:
                    try:
                        previous = previous.getattr(specifier)[0]
                    except astroid.NotFoundError:
                        if (
                            hasattr(previous, "has_dynamic_getattr")
                            and previous.has_dynamic_getattr()
                        ):
                            # Don't warn if the object has a custom __getattr__
                            break
                        path = get_access_path(key, parsed)
                        self.add_message(
                            "missing-format-attribute",
                            args=(specifier, path),
                            node=node,
                        )
                        break
                else:
                    warn_error = False
                    if hasattr(previous, "getitem"):
                        try:
                            previous = previous.getitem(astroid.Const(specifier))
                        except (
                            astroid.AstroidIndexError,
                            astroid.AstroidTypeError,
                            astroid.AttributeInferenceError,
                        ):
                            warn_error = True
                        except astroid.InferenceError:
                            break
                        if previous is astroid.Uninferable:
                            break
                    else:
                        try:
                            # Lookup __getitem__ in the current node,
                            # but skip further checks, because we can't
                            # retrieve the looked object
                            previous.getattr("__getitem__")
                            break
                        except astroid.NotFoundError:
                            warn_error = True
                    if warn_error:
                        path = get_access_path(key, parsed)
                        self.add_message(
                            "invalid-format-index", args=(specifier, path), node=node
                        )
                        break

                try:
                    previous = next(previous.infer())
                except astroid.InferenceError:
                    # can't check further if we can't infer it
                    break
Example #18
0
    def _check_new_format_specifiers(self, node, fields, named):
        """
        Check attribute and index access in the format
        string ("{0.a}" and "{0[a]}").
        """
        for key, specifiers in fields:
            # Obtain the argument. If it can't be obtained
            # or infered, skip this check.
            if key == '':
                # {[0]} will have an unnamed argument, defaulting
                # to 0. It will not be present in `named`, so use the value
                # 0 for it.
                key = 0
            if isinstance(key, numbers.Number):
                try:
                    argname = utils.get_argument_from_call(node, key)
                except utils.NoSuchArgumentError:
                    continue
            else:
                if key not in named:
                    continue
                argname = named[key]
            if argname in (astroid.YES, None):
                continue
            try:
                argument = argname.infer().next()
            except astroid.InferenceError:
                continue
            if not specifiers or argument is astroid.YES:
                # No need to check this key if it doesn't
                # use attribute / item access
                continue
            if argument.parent and isinstance(argument.parent,
                                              astroid.Arguments):
                # Check to see if our argument is kwarg or vararg,
                # and skip the check for this argument if so, because when inferring,
                # astroid will return empty objects (dicts and tuples) and
                # that can lead to false positives.
                if argname.name in (argument.parent.kwarg,
                                    argument.parent.vararg):
                    continue
            previous = argument
            parsed = []
            for is_attribute, specifier in specifiers:
                if previous is astroid.YES:
                    break
                parsed.append((is_attribute, specifier))
                if is_attribute:
                    try:
                        previous = previous.getattr(specifier)[0]
                    except astroid.NotFoundError:
                        if (hasattr(previous, 'has_dynamic_getattr')
                                and previous.has_dynamic_getattr()):
                            # Don't warn if the object has a custom __getattr__
                            break
                        path = get_access_path(key, parsed)
                        self.add_message('missing-format-attribute',
                                         args=(specifier, path),
                                         node=node)
                        break
                else:
                    warn_error = False
                    if hasattr(previous, 'getitem'):
                        try:
                            previous = previous.getitem(specifier)
                        except (IndexError, TypeError):
                            warn_error = True
                    else:
                        try:
                            # Lookup __getitem__ in the current node,
                            # but skip further checks, because we can't
                            # retrieve the looked object
                            previous.getattr('__getitem__')
                            break
                        except astroid.NotFoundError:
                            warn_error = True
                    if warn_error:
                        path = get_access_path(key, parsed)
                        self.add_message('invalid-format-index',
                                         args=(specifier, path),
                                         node=node)
                        break

                try:
                    previous = previous.infer().next()
                except astroid.InferenceError:
                    # can't check further if we can't infer it
                    break
Example #19
0
 def _check_shallow_copy_environ(self, node):
     arg = utils.get_argument_from_call(node, position=0)
     for inferred in arg.inferred():
         if inferred.qname() == OS_ENVIRON:
             self.add_message('shallow-copy-environ', node=node)
             break
def includes_exc_info(node):
    try:
        exc_info = utils.get_argument_from_call(node, keyword='exc_info')
    except utils.NoSuchArgumentError:
        return False
    return bool(exc_info.value)
    def _check_use_maxsplit_arg(self, node: astroid.Call) -> None:
        """Add message when accessing first or last elements of a str.split() or str.rsplit()."""

        # Check if call is split() or rsplit()
        if not (isinstance(node.func, astroid.Attribute)
                and node.func.attrname in ("split", "rsplit") and isinstance(
                    utils.safe_infer(node.func), astroid.BoundMethod)):
            return

        try:
            utils.get_argument_from_call(node, 0, "sep")
        except utils.NoSuchArgumentError:
            return

        try:
            # Ignore if maxsplit arg has been set
            utils.get_argument_from_call(node, 1, "maxsplit")
            return
        except utils.NoSuchArgumentError:
            pass

        if isinstance(node.parent, astroid.Subscript):
            try:
                subscript_value = utils.get_subscript_const_value(
                    node.parent).value
            except utils.InferredTypeError:
                return

            # Check for cases where variable (Name) subscripts may be mutated within a loop
            if isinstance(node.parent.slice, astroid.Name):
                # Check if loop present within the scope of the node
                scope = node.scope()
                for loop_node in scope.nodes_of_class(
                    (astroid.For, astroid.While)):
                    loop_node = cast(astroid.node_classes.NodeNG, loop_node)
                    if not loop_node.parent_of(node):
                        continue

                    # Check if var is mutated within loop (Assign/AugAssign)
                    for assignment_node in loop_node.nodes_of_class(
                            astroid.AugAssign):
                        assignment_node = cast(astroid.AugAssign,
                                               assignment_node)
                        if node.parent.slice.name == assignment_node.target.name:
                            return
                    for assignment_node in loop_node.nodes_of_class(
                            astroid.Assign):
                        assignment_node = cast(astroid.Assign, assignment_node)
                        if node.parent.slice.name in [
                                n.name for n in assignment_node.targets
                        ]:
                            return

            if subscript_value in (-1, 0):
                fn_name = node.func.attrname
                new_fn = "rsplit" if subscript_value == -1 else "split"
                new_name = (
                    node.func.as_string().rsplit(fn_name, maxsplit=1)[0] +
                    new_fn +
                    f"({node.args[0].as_string()}, maxsplit=1)[{subscript_value}]"
                )
                self.add_message("use-maxsplit-arg",
                                 node=node,
                                 args=(new_name, ))
Example #22
0
def testGetArgumentFromCallError(fn, kw):
    with pytest.raises(utils.NoSuchArgumentError):
        node = astroid.extract_node(fn)
        utils.get_argument_from_call(node, **kw)
Example #23
0
def testGetArgumentFromCallError(
        fn: str, kw: Union[Dict[str, int], Dict[str, str]]) -> None:
    with pytest.raises(utils.NoSuchArgumentError):
        node = astroid.extract_node(fn)
        utils.get_argument_from_call(node, **kw)