Пример #1
0
def _annotated_unpack_infer(stmt, context=None):
    """
    Recursively generate nodes inferred by the given statement.
    If the inferred value is a list or a tuple, recurse on the elements.
    Returns an iterator which yields tuples in the format
    ('original node', 'infered node').
    """
    # TODO: the same code as unpack_infer, except for the annotated
    # return. We need this type of annotation only here and
    # there is no point in complicating the API for unpack_infer.
    # If the need arises, this behaviour can be promoted to unpack_infer
    # as well.
    if isinstance(stmt, (List, Tuple)):
        for elt in stmt.elts:
            for infered_elt in unpack_infer(elt, context):
                yield elt, infered_elt
        return
    # if infered is a final node, return it and stop
    infered = next(stmt.infer(context))
    if infered is stmt:
        yield stmt, infered
        return
    # else, infer recursivly, except YES object that should be returned as is
    for infered in stmt.infer(context):
        if infered is YES:
            yield stmt, infered
        else:
            for inf_inf in unpack_infer(infered, context):
                yield stmt, inf_inf
Пример #2
0
 def visit_raise(self, node):
     """visit raise possibly inferring value"""
     # ignore empty raise
     if node.exc is None:
         return
     if PY3K and node.cause:
         try:
             cause = node.cause.infer().next()
         except astroid.InferenceError:
             pass
         else:
             if isinstance(cause, astroid.Const):
                 if cause.value is not None:
                     self.add_message('bad-exception-context',
                                      node=node)
             elif (not isinstance(cause, astroid.Class) and
                   not inherit_from_std_ex(cause)):
                 self.add_message('bad-exception-context',
                                   node=node)
     expr = node.exc
     if self._check_raise_value(node, expr):
         return
     else:
         try:
             value = unpack_infer(expr).next()
         except astroid.InferenceError:
             return
         self._check_raise_value(node, value)
Пример #3
0
 def visit_raise(self, node):
     """visit raise possibly inferring value"""
     # ignore empty raise
     if node.exc is None:
         return
     if PY3K and node.cause:
         try:
             cause = node.cause.infer().next()
         except astroid.InferenceError:
             pass
         else:
             if cause is YES:
                 return
             if isinstance(cause, astroid.Const):
                 if cause.value is not None:
                     self.add_message('bad-exception-context', node=node)
             elif (not isinstance(cause, astroid.Class)
                   and not inherit_from_std_ex(cause)):
                 self.add_message('bad-exception-context', node=node)
     expr = node.exc
     if self._check_raise_value(node, expr):
         return
     else:
         try:
             value = unpack_infer(expr).next()
         except astroid.InferenceError:
             return
         self._check_raise_value(node, value)
Пример #4
0
def possible_exc_types(node):
    """
    Gets all of the possible raised exception types for the given raise node.

    .. note::

        Caught exception types are ignored.


    :param node: The raise node to find exception types for.

    :returns: A list of exception types possibly raised by :param:`node`.
    :rtype: list(str)
    """
    excs = []
    if isinstance(node.exc, astroid.Name):
        excs = [node.exc.name]
    elif (isinstance(node.exc, astroid.Call) and
          isinstance(node.exc.func, astroid.Name)):
        excs = [node.exc.func.name]
    elif node.exc is None:
        handler = node.parent
        while handler and not isinstance(handler, astroid.ExceptHandler):
            handler = handler.parent

        if handler and handler.type:
            excs = (exc.name for exc in astroid.unpack_infer(handler.type))

    excs = set(exc for exc in excs if not node_ignores_exception(node, exc))
    return excs
Пример #5
0
def possible_exc_types(node: nodes.NodeNG) -> set[nodes.ClassDef]:
    """Gets all the possible raised exception types for the given raise node.

    .. note::

        Caught exception types are ignored.

    :param node: The raise node to find exception types for.

    :returns: A list of exception types possibly raised by :param:`node`.
    """
    exceptions = []
    if isinstance(node.exc, nodes.Name):
        inferred = utils.safe_infer(node.exc)
        if inferred:
            exceptions = [inferred]
    elif node.exc is None:
        handler = node.parent
        while handler and not isinstance(handler, nodes.ExceptHandler):
            handler = handler.parent

        if handler and handler.type:
            try:
                for exception in astroid.unpack_infer(handler.type):
                    if exception is not astroid.Uninferable:
                        exceptions.append(exception)
            except astroid.InferenceError:
                pass
    else:
        target = _get_raise_target(node)
        if isinstance(target, nodes.ClassDef):
            exceptions = [target]
        elif isinstance(target, nodes.FunctionDef):
            for ret in target.nodes_of_class(nodes.Return):
                if ret.value is None:
                    continue
                if ret.frame(future=True) != target:
                    # return from inner function - ignore it
                    continue

                val = utils.safe_infer(ret.value)
                if val and utils.inherit_from_std_ex(val):
                    if isinstance(val, nodes.ClassDef):
                        exceptions.append(val)
                    elif isinstance(val, astroid.Instance):
                        exceptions.append(val.getattr("__class__")[0])

    try:
        return {
            exc
            for exc in exceptions
            if not utils.node_ignores_exception(node, exc.name)
        }
    except astroid.InferenceError:
        return set()
Пример #6
0
    def visit_tryexcept(self, node):
        """check for empty except"""
        exceptions_classes = []
        nb_handlers = len(node.handlers)
        for index, handler in enumerate(node.handlers):
            # single except doing nothing but "pass" without else clause
            if nb_handlers == 1 and is_empty(handler.body) and not node.orelse:
                self.add_message('W0704', node=handler.type or handler.body[0])
            if handler.type is None:
                if nb_handlers == 1 and not is_raising(handler.body):
                    self.add_message('W0702', node=handler)
                # check if a "except:" is followed by some other
                # except
                elif index < (nb_handlers - 1):
                    msg = 'empty except clause should always appear last'
                    self.add_message('E0701', node=node, args=msg)

            elif isinstance(handler.type, astroid.BoolOp):
                self.add_message('W0711', node=handler, args=handler.type.op)
            else:
                try:
                    excs = list(unpack_infer(handler.type))
                except astroid.InferenceError:
                    continue
                for exc in excs:
                    # XXX skip other non class nodes
                    if exc is YES or not isinstance(exc, astroid.Class):
                        continue
                    exc_ancestors = [
                        anc for anc in exc.ancestors()
                        if isinstance(anc, astroid.Class)
                    ]
                    for previous_exc in exceptions_classes:
                        if previous_exc in exc_ancestors:
                            msg = '%s is an ancestor class of %s' % (
                                previous_exc.name, exc.name)
                            self.add_message('E0701',
                                             node=handler.type,
                                             args=msg)
                    if (exc.name in self.config.overgeneral_exceptions
                            and exc.root().name == EXCEPTIONS_MODULE
                            and nb_handlers == 1
                            and not is_raising(handler.body)):
                        self.add_message('W0703',
                                         args=exc.name,
                                         node=handler.type)

                    if (not inherit_from_std_ex(exc)
                            and exc.root().name != BUILTINS_NAME):
                        self.add_message('catching-non-exception',
                                         node=handler.type,
                                         args=(exc.name, ))

                exceptions_classes += excs
Пример #7
0
    def visit_tryexcept(self, node):
        """check for empty except"""
        exceptions_classes = []
        nb_handlers = len(node.handlers)
        for index, handler  in enumerate(node.handlers):
            # single except doing nothing but "pass" without else clause
            if nb_handlers == 1 and is_empty(handler.body) and not node.orelse:
                self.add_message('pointless-except', node=handler.type or handler.body[0])
            if handler.type is None:
                if nb_handlers == 1 and not is_raising(handler.body):
                    self.add_message('bare-except', node=handler)
                # check if a "except:" is followed by some other
                # except
                elif index < (nb_handlers - 1):
                    msg = 'empty except clause should always appear last'
                    self.add_message('bad-except-order', node=node, args=msg)

            elif isinstance(handler.type, astroid.BoolOp):
                self.add_message('binary-op-exception', node=handler, args=handler.type.op)
            else:
                try:
                    excs = list(unpack_infer(handler.type))
                except astroid.InferenceError:
                    continue
                for exc in excs:
                    # XXX skip other non class nodes
                    if exc is YES or not isinstance(exc, astroid.Class):
                        continue
                    exc_ancestors = [anc for anc in exc.ancestors()
                                     if isinstance(anc, astroid.Class)]
                    for previous_exc in exceptions_classes:
                        if previous_exc in exc_ancestors:
                            msg = '%s is an ancestor class of %s' % (
                                previous_exc.name, exc.name)
                            self.add_message('bad-except-order', node=handler.type, args=msg)
                    if (exc.name in self.config.overgeneral_exceptions
                        and exc.root().name == EXCEPTIONS_MODULE
                        and nb_handlers == 1 and not is_raising(handler.body)):
                        self.add_message('broad-except', args=exc.name, node=handler.type)

                    if (not inherit_from_std_ex(exc) and
                        exc.root().name != BUILTINS_NAME):
                        # try to see if the exception is based on a C based
                        # exception, by infering all the base classes and
                        # looking for inference errors
                        bases = infer_bases(exc)
                        fully_infered = all(inferit is not YES
                                            for inferit in bases)
                        if fully_infered:
                            self.add_message('catching-non-exception',
                                             node=handler.type,
                                             args=(exc.name, ))

                exceptions_classes += excs
Пример #8
0
def possible_exc_types(node):
    """
    Gets all of the possible raised exception types for the given raise node.

    .. note::

        Caught exception types are ignored.


    :param node: The raise node to find exception types for.
    :type node: astroid.node_classes.NodeNG

    :returns: A list of exception types possibly raised by :param:`node`.
    :rtype: set(str)
    """
    excs = []
    if isinstance(node.exc, astroid.Name):
        inferred = utils.safe_infer(node.exc)
        if inferred:
            excs = [inferred.name]
    elif (isinstance(node.exc, astroid.Call)
          and isinstance(node.exc.func, astroid.Name)):
        target = utils.safe_infer(node.exc.func)
        if isinstance(target, astroid.ClassDef):
            excs = [target.name]
        elif isinstance(target, astroid.FunctionDef):
            for ret in target.nodes_of_class(astroid.Return):
                if ret.frame() != target:
                    # return from inner function - ignore it
                    continue

                val = utils.safe_infer(ret.value)
                if (val and isinstance(val,
                                       (astroid.Instance, astroid.ClassDef))
                        and utils.inherit_from_std_ex(val)):
                    excs.append(val.name)
    elif node.exc is None:
        handler = node.parent
        while handler and not isinstance(handler, astroid.ExceptHandler):
            handler = handler.parent

        if handler and handler.type:
            inferred_excs = astroid.unpack_infer(handler.type)
            excs = (exc.name for exc in inferred_excs
                    if exc is not astroid.Uninferable)

    try:
        return {
            exc
            for exc in excs if not utils.node_ignores_exception(node, exc)
        }
    except astroid.InferenceError:
        return set()
Пример #9
0
def possible_exc_types(node):
    """
    Gets all of the possible raised exception types for the given raise node.

    .. note::

        Caught exception types are ignored.


    :param node: The raise node to find exception types for.
    :type node: astroid.node_classes.NodeNG

    :returns: A list of exception types possibly raised by :param:`node`.
    :rtype: list(str)
    """
    excs = []
    if isinstance(node.exc, astroid.Name):
        inferred = safe_infer(node.exc)
        if inferred:
            excs = [inferred.name]
    elif (isinstance(node.exc, astroid.Call) and
          isinstance(node.exc.func, astroid.Name)):
        target = safe_infer(node.exc.func)
        if isinstance(target, astroid.ClassDef):
            excs = [target.name]
        elif isinstance(target, astroid.FunctionDef):
            for ret in target.nodes_of_class(astroid.Return):
                if ret.frame() != target:
                    # return from inner function - ignore it
                    continue

                val = safe_infer(ret.value)
                if (val and isinstance(val, (astroid.Instance, astroid.ClassDef))
                        and inherit_from_std_ex(val)):
                    excs.append(val.name)
    elif node.exc is None:
        handler = node.parent
        while handler and not isinstance(handler, astroid.ExceptHandler):
            handler = handler.parent

        if handler and handler.type:
            inferred_excs = astroid.unpack_infer(handler.type)
            excs = (exc.name for exc in inferred_excs
                    if exc is not astroid.Uninferable)


    try:
        return set(exc for exc in excs if not node_ignores_exception(node, exc))
    except astroid.InferenceError:
        return ()
Пример #10
0
 def visit_raise(self, node):
     """visit raise possibly inferring value"""
     # ignore empty raise
     if node.exc is None:
         return
     expr = node.exc
     if self._check_raise_value(node, expr):
         return
     else:
         try:
             value = unpack_infer(expr).next()
         except astroid.InferenceError:
             return
         self._check_raise_value(node, value)
Пример #11
0
 def visit_raise(self, node):
     """visit raise possibly inferring value"""
     # ignore empty raise
     if node.exc is None:
         return
     expr = node.exc
     if self._check_raise_value(node, expr):
         return
     else:
         try:
             value = unpack_infer(expr).next()
         except astroid.InferenceError:
             return
         self._check_raise_value(node, value)
Пример #12
0
    def visit_raise(self, node):
        """Visit a raise statement and check for raising
        strings or old-raise-syntax.
        """

        # Ignore empty raise.
        if node.exc is None:
            return
        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        try:
            value = next(astroid.unpack_infer(expr))
        except astroid.InferenceError:
            return
        self._check_raise_value(node, value)
Пример #13
0
    def visit_raise(self, node):
        """Visit a raise statement and check for raising
        strings or old-raise-syntax.
        """

        # Ignore empty raise.
        if node.exc is None:
            return
        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        try:
            value = next(astroid.unpack_infer(expr))
        except astroid.InferenceError:
            return
        self._check_raise_value(node, value)
Пример #14
0
    def visit_raise(self, node):
        """visit raise possibly inferring value"""
        # ignore empty raise
        if node.exc is None:
            return
        if PY3K and node.cause:
            self._check_bad_exception_context(node)

        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        else:
            try:
                value = next(unpack_infer(expr))
            except astroid.InferenceError:
                return
            self._check_raise_value(node, value)
Пример #15
0
    def visit_raise(self, node):
        """visit raise possibly inferring value"""
        if node.exc is None:
            self._check_misplaced_bare_raise(node)
            return
        if PY3K and node.cause:
            self._check_bad_exception_context(node)

        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        else:
            try:
                value = next(astroid.unpack_infer(expr))
            except astroid.InferenceError:
                return
            self._check_raise_value(node, value)
Пример #16
0
    def visit_raise(self, node):
        """Visit a raise statement and check for raising
        strings or old-raise-syntax.
        """
        if six.PY2:
            if (node.exc is not None and node.inst is not None):
                self.add_message('old-raise-syntax', node=node)

        # Ignore empty raise.
        if node.exc is None:
            return
        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        try:
            value = next(astroid.unpack_infer(expr))
        except astroid.InferenceError:
            return
        self._check_raise_value(node, value)
Пример #17
0
    def visit_raise(self, node):
        """Visit a raise statement and check for raising
        strings or old-raise-syntax.
        """
        if six.PY2:
            if (node.exc is not None and
                    node.inst is not None):
                self.add_message('old-raise-syntax', node=node)

        # Ignore empty raise.
        if node.exc is None:
            return
        expr = node.exc
        if self._check_raise_value(node, expr):
            return
        try:
            value = next(astroid.unpack_infer(expr))
        except astroid.InferenceError:
            return
        self._check_raise_value(node, value)
Пример #18
0
    def visit_tryexcept(self, node):
        """check for empty except"""
        exceptions_classes = []
        nb_handlers = len(node.handlers)
        for index, handler  in enumerate(node.handlers):
            # single except doing nothing but "pass" without else clause
            if nb_handlers == 1 and is_empty(handler.body) and not node.orelse:
                self.add_message('W0704', node=handler.type or handler.body[0])
            if handler.type is None:
                if nb_handlers == 1 and not is_raising(handler.body):
                    self.add_message('W0702', node=handler)
                # check if a "except:" is followed by some other
                # except
                elif index < (nb_handlers - 1):
                    msg = 'empty except clause should always appear last'
                    self.add_message('E0701', node=node, args=msg)

            elif isinstance(handler.type, astroid.BoolOp):
                self.add_message('W0711', node=handler, args=handler.type.op)
            else:
                try:
                    excs = list(unpack_infer(handler.type))
                except astroid.InferenceError:
                    continue
                for exc in excs:
                    # XXX skip other non class nodes
                    if exc is YES or not isinstance(exc, astroid.Class):
                        continue
                    exc_ancestors = [anc for anc in exc.ancestors()
                                     if isinstance(anc, astroid.Class)]
                    for previous_exc in exceptions_classes:
                        if previous_exc in exc_ancestors:
                            msg = '%s is an ancestor class of %s' % (
                                previous_exc.name, exc.name)
                            self.add_message('E0701', node=handler.type, args=msg)
                    if (exc.name in self.config.overgeneral_exceptions
                        and exc.root().name == EXCEPTIONS_MODULE
                        and nb_handlers == 1 and not is_raising(handler.body)):
                        self.add_message('W0703', args=exc.name, node=handler.type)
                exceptions_classes += excs
Пример #19
0
    def visit_tryexcept(self, node):
        """check for empty except"""
        exceptions_classes = []
        nb_handlers = len(node.handlers)
        for index, handler in enumerate(node.handlers):
            # single except doing nothing but "pass" without else clause
            if is_empty(handler.body) and not node.orelse:
                self.add_message('pointless-except',
                                 node=handler.type or handler.body[0])
            if handler.type is None:
                if not is_raising(handler.body):
                    self.add_message('bare-except', node=handler)
                # check if a "except:" is followed by some other
                # except
                if index < (nb_handlers - 1):
                    msg = 'empty except clause should always appear last'
                    self.add_message('bad-except-order', node=node, args=msg)

            elif isinstance(handler.type, astroid.BoolOp):
                self.add_message('binary-op-exception',
                                 node=handler,
                                 args=handler.type.op)
            else:
                try:
                    excs = list(unpack_infer(handler.type))
                except astroid.InferenceError:
                    continue
                for exc in excs:
                    # XXX skip other non class nodes
                    if exc is YES or not isinstance(exc, astroid.Class):
                        continue
                    exc_ancestors = [
                        anc for anc in exc.ancestors()
                        if isinstance(anc, astroid.Class)
                    ]
                    for previous_exc in exceptions_classes:
                        if previous_exc in exc_ancestors:
                            msg = '%s is an ancestor class of %s' % (
                                previous_exc.name, exc.name)
                            self.add_message('bad-except-order',
                                             node=handler.type,
                                             args=msg)
                    if (exc.name in self.config.overgeneral_exceptions
                            and exc.root().name == EXCEPTIONS_MODULE
                            and not is_raising(handler.body)):
                        self.add_message('broad-except',
                                         args=exc.name,
                                         node=handler.type)

                    if (not inherit_from_std_ex(exc)
                            and exc.root().name != BUILTINS_NAME):
                        # try to see if the exception is based on a C based
                        # exception, by infering all the base classes and
                        # looking for inference errors
                        bases = infer_bases(exc)
                        fully_infered = all(inferit is not YES
                                            for inferit in bases)
                        if fully_infered:
                            self.add_message('catching-non-exception',
                                             node=handler.type,
                                             args=(exc.name, ))

                exceptions_classes += excs