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
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)
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)
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
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()
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
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
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()
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 ()
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)
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)
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)
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)
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)
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
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