pylint/checkers/base.py
def _check_reversed(self, node):
        """ 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 infered.
                # Try to see if we have iter().
                if isinstance(node.args[0], astroid.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, (astroid.List, astroid.Tuple)):
                return

            if isinstance(argument, astroid.Instance):
                if argument._proxied.name == "dict" and utils.is_builtin_object(
                    argument._proxied
                ):
                    self.add_message("bad-reversed-sequence", node=node)
                    return
                if any(
                    ancestor.name == "dict" and utils.is_builtin_object(ancestor)
                    for ancestor in argument._proxied.ancestors()
                ):
                    # Mappings aren't accepted by reversed(), unless
                    # they provide explicitly a __reversed__ method.
                    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)
def _check_reversed(self, node):
        """ 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 infered.
                # Try to see if we have iter().
                if isinstance(node.args[0], astroid.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, (astroid.List, astroid.Tuple)):
                return

            if isinstance(argument, astroid.Instance):
                if argument._proxied.name == "dict" and utils.is_builtin_object(
                    argument._proxied
                ):
                    self.add_message("bad-reversed-sequence", node=node)
                    return
                if any(
                    ancestor.name == "dict" and utils.is_builtin_object(ancestor)
                    for ancestor in argument._proxied.ancestors()
                ):
                    # Mappings aren't accepted by reversed(), unless
                    # they provide explicitly a __reversed__ method.
                    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)
check that the argument to `reversed` is a sequence