def visit_functiondef(self, node: nodes.FunctionDef) -> None: self._check_nonlocal_and_global(node) self._check_name_used_prior_global(node) if not redefined_by_decorator( node) and not utils.is_registered_in_singledispatch_function( node): self._check_redefinition( node.is_method() and "method" or "function", node) # checks for max returns, branch, return in __init__ returns = node.nodes_of_class(nodes.Return, skip_klass=(nodes.FunctionDef, nodes.ClassDef)) if node.is_method() and node.name == "__init__": if node.is_generator(): self.add_message("init-is-generator", node=node) else: values = [r.value for r in returns] # Are we returning anything but None from constructors if any(v for v in values if not utils.is_none(v)): self.add_message("return-in-init", node=node) # Check for duplicate names by clustering args with same name for detailed report arg_clusters = {} arguments: Iterator[Any] = filter( None, [node.args.args, node.args.kwonlyargs]) for arg in itertools.chain.from_iterable(arguments): if arg.name in arg_clusters: self.add_message( "duplicate-argument-name", node=arg, args=(arg.name, ), confidence=HIGH, ) else: arg_clusters[arg.name] = arg
def visit_functiondef(self, node: nodes.FunctionDef) -> None: if self.linter.namespace.no_docstring_rgx.match(node.name) is None: ftype = "method" if node.is_method() else "function" if (is_property_setter(node) or is_property_deleter(node) or is_overload_stub(node)): return if isinstance(node.parent.frame(future=True), nodes.ClassDef): overridden = False confidence = (interfaces.INFERENCE if utils.has_known_bases( node.parent.frame( future=True)) else interfaces.INFERENCE_FAILURE) # check if node is from a method overridden by its ancestor for ancestor in node.parent.frame(future=True).ancestors(): if ancestor.qname() == "builtins.object": continue if node.name in ancestor and isinstance( ancestor[node.name], nodes.FunctionDef): overridden = True break self._check_docstring( ftype, node, report_missing=not overridden, confidence=confidence # type: ignore[arg-type] ) elif isinstance(node.parent.frame(future=True), nodes.Module): self._check_docstring(ftype, node) # type: ignore[arg-type] else: return
def leave_functiondef(self, node: nodes.FunctionDef) -> None: """On method node, check if this method couldn't be a function. ignore class, static and abstract methods, initializer, methods overridden from a parent class. """ if node.is_method(): first = self._first_attrs.pop() if first is None: return class_node = node.parent.frame(future=True) if ( self._meth_could_be_func and node.type == "method" and node.name not in PYMETHODS and not ( node.is_abstract() or overrides_a_method(class_node, node.name) or decorated_with_property(node) or _has_bare_super_call(node) or is_protocol_class(class_node) or is_overload_stub(node) ) ): self.add_message("no-self-use", node=node, confidence=INFERENCE)
def _determine_function_name_type(node: nodes.FunctionDef, config=None): """Determine the name type whose regex the function's name should match. :param node: A function node. :param config: Configuration from which to pull additional property classes. :type config: :class:`optparse.Values` :returns: One of ('function', 'method', 'attr') :rtype: str """ property_classes, property_names = _get_properties(config) if not node.is_method(): return "function" if is_property_setter(node) or is_property_deleter(node): # If the function is decorated using the prop_method.{setter,getter} # form, treat it like an attribute as well. return "attr" decorators = node.decorators.nodes if node.decorators else [] for decorator in decorators: # If the function is a property (decorated with @property # or @abc.abstractproperty), the name type is 'attr'. if isinstance( decorator, nodes.Name) or (isinstance(decorator, nodes.Attribute) and decorator.attrname in property_names): inferred = utils.safe_infer(decorator) if (inferred and hasattr(inferred, "qname") and inferred.qname() in property_classes): return "attr" return "method"
def visit_functiondef(self, node: nodes.FunctionDef) -> None: """Check function name, docstring, arguments, redefinition, variable names, max locals. """ if node.is_method(): self.linter.stats.node_count["method"] += 1 else: self.linter.stats.node_count["function"] += 1 self._check_dangerous_default(node)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: if not node.is_method(): return inferred = _safe_infer_call_result(node, node) # Only want to check types that we are able to infer if (inferred and node.name in self._protocol_map and not is_function_body_ellipsis(node)): self._protocol_map[node.name](node, inferred) if node.name in PYMETHODS: self._check_unexpected_method_signature(node)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: """Called when a FunctionDef node is visited.""" if not node.is_method() or node.name != "__init__": return # Check that all arguments are annotated. # The first argument is "self". args = node.args annotations = (args.posonlyargs_annotations + args.annotations + args.kwonlyargs_annotations)[1:] if args.vararg is not None: annotations.append(args.varargannotation) if args.kwarg is not None: annotations.append(args.kwargannotation) if not annotations or None in annotations: return # Check that return type is specified and it is "None". if not isinstance(node.returns, nodes.Const) or node.returns.value is not None: self.add_message("hass-constructor-return", node=node)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: # Do not emit any warnings if the method is just an implementation # of a base class method. confidence = interfaces.HIGH if node.is_method(): if utils.overrides_a_method(node.parent.frame(future=True), node.name): return confidence = (interfaces.INFERENCE if utils.has_known_bases( node.parent.frame( future=True)) else interfaces.INFERENCE_FAILURE) self._check_name( _determine_function_name_type(node, config=self.linter.config), node.name, node, confidence, ) # Check argument names args = node.args.args if args is not None: self._recursive_check_names(args)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: """check use of super""" # ignore actual functions or method within a new style class if not node.is_method(): return klass = node.parent.frame() for stmt in node.nodes_of_class(nodes.Call): if node_frame_class(stmt) != node_frame_class(node): # Don't look down in other scopes. continue expr = stmt.func if not isinstance(expr, nodes.Attribute): continue call = expr.expr # skip the test if using super if not (isinstance(call, nodes.Call) and isinstance( call.func, nodes.Name) and call.func.name == "super"): continue # super should not be used on an old style class if klass.newstyle or not has_known_bases(klass): # super first arg should not be the class if not call.args: continue # calling super(type(self), self) can lead to recursion loop # in derived classes arg0 = call.args[0] if (isinstance(arg0, nodes.Call) and isinstance(arg0.func, nodes.Name) and arg0.func.name == "type"): self.add_message("bad-super-call", node=call, args=("type", )) continue # calling super(self.__class__, self) can lead to recursion loop # in derived classes if (len(call.args) >= 2 and isinstance(call.args[1], nodes.Name) and call.args[1].name == "self" and isinstance(arg0, nodes.Attribute) and arg0.attrname == "__class__"): self.add_message("bad-super-call", node=call, args=("self.__class__", )) continue try: supcls = call.args and next(call.args[0].infer(), None) except astroid.InferenceError: continue if klass is not supcls: name = None # if supcls is not Uninferable, then supcls was inferred # and use its name. Otherwise, try to look # for call.args[0].name if supcls: name = supcls.name elif call.args and hasattr(call.args[0], "name"): name = call.args[0].name if name: self.add_message("bad-super-call", node=call, args=(name, ))
def visit_functiondef(self, node: nodes.FunctionDef) -> None: ftype = "method" if node.is_method() else "function" self._check_docstring(ftype, node)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: if not node.is_method(): return self._meth_could_be_func = True self._check_first_arg_for_type(node)
def visit_functiondef(self, node: nodes.FunctionDef) -> None: """Called when a FunctionDef node is visited.""" for match in self._function_matchers: if node.name != match.function_name or node.is_method(): continue self._check_function(node, match)