def test_node_ignores_exception(self): nodes = test_utils.extract_node(""" try: 1/0 #@ except ZeroDivisionError: pass try: 1/0 #@ except Exception: pass try: 2/0 #@ except: pass try: 1/0 #@ except ValueError: pass """) self.assertTrue( utils.node_ignores_exception(nodes[0], ZeroDivisionError)) self.assertFalse( utils.node_ignores_exception(nodes[1], ZeroDivisionError)) self.assertFalse( utils.node_ignores_exception(nodes[2], ZeroDivisionError)) self.assertFalse( utils.node_ignores_exception(nodes[3], ZeroDivisionError))
def test_node_ignores_exception(): nodes = astroid.extract_node( """ try: 1/0 #@ except ZeroDivisionError: pass try: 1/0 #@ except Exception: pass try: 2/0 #@ except: pass try: 1/0 #@ except ValueError: pass """ ) assert utils.node_ignores_exception(nodes[0], ZeroDivisionError) assert not utils.node_ignores_exception(nodes[1], ZeroDivisionError) assert utils.node_ignores_exception(nodes[2], ZeroDivisionError) assert not utils.node_ignores_exception(nodes[3], ZeroDivisionError)
def _check_raising_stopiteration_in_generator_next_call(self, node): """Check if a StopIteration exception is raised by the call to next function If the next value has a default value, then do not add message. :param node: Check to see if this Call node is a next function :type node: :class:`astroid.node_classes.Call` """ def _looks_like_infinite_iterator(param): inferred = utils.safe_infer(param) if inferred is not None or inferred is not astroid.Uninferable: return inferred.qname() in KNOWN_INFINITE_ITERATORS return False inferred = utils.safe_infer(node.func) if getattr(inferred, 'name', '') == 'next': frame = node.frame() # The next builtin can only have up to two # positional arguments and no keyword arguments has_sentinel_value = len(node.args) > 1 if (isinstance(frame, astroid.FunctionDef) and frame.is_generator() and not has_sentinel_value and not utils.node_ignores_exception(node, StopIteration) and not _looks_like_infinite_iterator(node.args[0])): self.add_message('stop-iteration-return', node=node)
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 _check_raising_stopiteration_in_generator_next_call(self, node): """Check if a StopIteration exception is raised by the call to next function If the next value has a default value, then do not add message. :param node: Check to see if this Call node is a next function :type node: :class:`astroid.node_classes.Call` """ def _looks_like_infinite_iterator(param): inferred = utils.safe_infer(param) if inferred is not None or inferred is not astroid.Uninferable: return inferred.qname() in KNOWN_INFINITE_ITERATORS return False inferred = utils.safe_infer(node.func) if getattr(inferred, 'name', '') == 'next': frame = node.frame() # The next builtin can only have up to two # positional arguments and no keyword arguments has_sentinel_value = len(node.args) > 1 if (isinstance(frame, astroid.FunctionDef) and frame.is_generator() and not has_sentinel_value and not utils.node_ignores_exception(node, StopIteration) and not _looks_like_infinite_iterator(node.args[0])): self.add_message('stop-iteration-return', node=node)
def _check_raising_stopiteration_in_generator_next_call(self, node): """Check if a StopIteration exception is raised by the call to next function""" inferred = utils.safe_infer(node.func) if getattr(inferred, 'name', '') == 'next': frame = node.frame() if (isinstance(frame, astroid.FunctionDef) and frame.is_generator() and not utils.node_ignores_exception(node, StopIteration)): self.add_message('stop-iteration-return', node=node)
def _check_raising_stopiteration_in_generator_next_call(self, node): """Check if a StopIteration exception is raised by the call to next function""" inferred = utils.safe_infer(node.func) if getattr(inferred, 'name', '') == 'next': frame = node.frame() if (isinstance(frame, astroid.FunctionDef) and frame.is_generator() and not utils.node_ignores_exception(node, StopIteration)): self.add_message('stop-iteration-return', node=node)
def _check_stop_iteration_inside_generator(self, node): """Check if an exception of type StopIteration is raised inside a generator""" frame = node.frame() if not isinstance(frame, astroid.FunctionDef) or not frame.is_generator(): return if utils.node_ignores_exception(node, StopIteration): return exc = utils.safe_infer(node.exc) if exc is not None and self._check_exception_inherit_from_stopiteration(exc): self.add_message('stop-iteration-return', node=node)
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 _ignore_import_failure(node, modname, ignored_modules): for submodule in _qualified_names(modname): if submodule in ignored_modules: return True if is_node_in_guarded_import_block(node): # Ignore import failure if part of guarded import block # I.e. `sys.version_info` or `typing.TYPE_CHECKING` return True return node_ignores_exception(node, ImportError)
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 visit_name(self, node): """Detect when a "bad" built-in is referenced.""" found_node, _ = node.lookup(node.name) if not _is_builtin(found_node): return if node.name not in self._bad_builtins: return if (node_ignores_exception(node) or isinstance( find_try_except_wrapper_node(node), astroid.ExceptHandler)): return message = node.name.lower() + '-builtin' self.add_message(message, node=node)
def visit_name(self, node): """Detect when a "bad" built-in is referenced.""" found_node, _ = node.lookup(node.name) if not _is_builtin(found_node): return if node.name not in self._bad_builtins: return if (node_ignores_exception(node) or isinstance(find_try_except_wrapper_node(node), astroid.ExceptHandler)): return message = node.name.lower() + '-builtin' self.add_message(message, node=node)
def test_node_ignores_exception(self): nodes = test_utils.extract_node(""" try: 1/0 #@ except ZeroDivisionError: pass try: 1/0 #@ except Exception: pass try: 2/0 #@ except: pass try: 1/0 #@ except ValueError: pass """) self.assertTrue(utils.node_ignores_exception(nodes[0], ZeroDivisionError)) self.assertFalse(utils.node_ignores_exception(nodes[1], ZeroDivisionError)) self.assertFalse(utils.node_ignores_exception(nodes[2], ZeroDivisionError)) self.assertFalse(utils.node_ignores_exception(nodes[3], ZeroDivisionError))
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 get_imported_module(self, importnode, modname): try: return importnode.do_import_module(modname) except astroid.InferenceError as ex: dotted_modname = _get_import_name(importnode, modname) if str(ex) != modname: args = "%r (%s)" % (dotted_modname, ex) else: args = repr(dotted_modname) for submodule in _qualified_names(modname): if submodule in self._ignored_modules: return None if not node_ignores_exception(importnode, ImportError): self.add_message("import-error", args=args, node=importnode)
def get_imported_module(self, importnode, modname): try: return importnode.do_import_module(modname) except astroid.InferenceError as ex: dotted_modname = _get_import_name(importnode, modname) if str(ex) != modname: args = '%r (%s)' % (dotted_modname, ex) else: args = repr(dotted_modname) for submodule in _qualified_names(modname): if submodule in self._ignored_modules: return None if not node_ignores_exception(importnode, ImportError): self.add_message("import-error", args=args, node=importnode)
def _ignore_import_failure(node, modname, ignored_modules): for submodule in _qualified_names(modname): if submodule in ignored_modules: return True # ignore import failure if guarded by `sys.version_info` test if isinstance(node.parent, astroid.If) and isinstance( node.parent.test, astroid.Compare): value = node.parent.test.left if isinstance(value, astroid.Subscript): value = value.value if (isinstance(value, astroid.Attribute) and value.as_string() == "sys.version_info"): return True return node_ignores_exception(node, ImportError)
def _emit_no_member(node, owner, owner_name, ignored_mixins): """Try to see if no-member should be emitted for the given owner. The following cases are ignored: * the owner is a function and it has decorators. * the owner is an instance and it has __getattr__, __getattribute__ implemented * the module is explicitly ignored from no-member checks * the owner is a class and the name can be found in its metaclass. * The access node is protected by an except handler, which handles AttributeError, Exception or bare except. """ if node_ignores_exception(node, AttributeError): return False # skip None anyway if isinstance(owner, astroid.Const) and owner.value is None: return False if is_super(owner) or getattr(owner, "type", None) == "metaclass": return False if ignored_mixins and owner_name[-5:].lower() == "mixin": return False if isinstance(owner, astroid.FunctionDef) and owner.decorators: return False if isinstance(owner, astroid.Instance): if owner.has_dynamic_getattr() or not has_known_bases(owner): return False if isinstance(owner, objects.Super): # Verify if we are dealing with an invalid Super object. # If it is invalid, then there's no point in checking that # it has the required attribute. Also, don't fail if the # MRO is invalid. try: owner.super_mro() except (exceptions.MroError, exceptions.SuperError): return False if not all(map(has_known_bases, owner.type.mro())): return False return True
def _emit_no_member(node, owner, owner_name, ignored_mixins): """Try to see if no-member should be emitted for the given owner. The following cases are ignored: * the owner is a function and it has decorators. * the owner is an instance and it has __getattr__, __getattribute__ implemented * the module is explicitly ignored from no-member checks * the owner is a class and the name can be found in its metaclass. * The access node is protected by an except handler, which handles AttributeError, Exception or bare except. """ if node_ignores_exception(node, AttributeError): return False # skip None anyway if isinstance(owner, astroid.Const) and owner.value is None: return False if is_super(owner) or getattr(owner, 'type', None) == 'metaclass': return False if ignored_mixins and owner_name[-5:].lower() == 'mixin': return False if isinstance(owner, astroid.FunctionDef) and owner.decorators: return False if isinstance(owner, astroid.Instance): if owner.has_dynamic_getattr() or not has_known_bases(owner): return False if isinstance(owner, objects.Super): # Verify if we are dealing with an invalid Super object. # If it is invalid, then there's no point in checking that # it has the required attribute. Also, don't fail if the # MRO is invalid. try: owner.super_mro() except (exceptions.MroError, exceptions.SuperError): return False if not all(map(has_known_bases, owner.type.mro())): return False return True
def _ignore_import_failure(node, modname, ignored_modules): for submodule in _qualified_names(modname): if submodule in ignored_modules: return True return node_ignores_exception(node, ImportError)
def _ignore_import_failure(node, modname, ignored_modules): for submodule in _qualified_names(modname): if submodule in ignored_modules: return True return node_ignores_exception(node, ImportError)