def check_single_constructor_params(self, class_doc: Docstring, init_doc: Docstring, class_node: nodes.ClassDef) -> None: if class_doc.has_params() and init_doc.has_params(): self.add_message("multiple-constructor-doc", args=(class_node.name, ), node=class_node)
def check_functiondef_params(self, node: nodes.FunctionDef, node_doc: Docstring) -> None: node_allow_no_param = None if node.name in self.constructor_names: class_node = checker_utils.node_frame_class(node) if class_node is not None: class_doc = utils.docstringify( class_node.doc_node, self.linter.config.default_docstring_type) self.check_single_constructor_params(class_doc, node_doc, class_node) # __init__ or class docstrings can have no parameters documented # as long as the other documents them. node_allow_no_param = (class_doc.has_params() or class_doc.params_documented_elsewhere() or None) class_allow_no_param = (node_doc.has_params() or node_doc.params_documented_elsewhere() or None) self.check_arguments_in_docstring(class_doc, node.args, class_node, class_allow_no_param) self.check_arguments_in_docstring(node_doc, node.args, node, node_allow_no_param)
def check_functiondef_yields(self, node: nodes.FunctionDef, node_doc: Docstring) -> None: if not node_doc.supports_yields or node.is_abstract(): return if (node_doc.has_yields() or node_doc.has_yields_type()) and not node.is_generator(): self.add_message("redundant-yields-doc", node=node)
def check_functiondef_returns(self, node: nodes.FunctionDef, node_doc: Docstring) -> None: if (not node_doc.supports_yields and node.is_generator()) or node.is_abstract(): return return_nodes = node.nodes_of_class(astroid.Return) if (node_doc.has_returns() or node_doc.has_rtype()) and not any( utils.returns_something(ret_node) for ret_node in return_nodes): self.add_message("redundant-returns-doc", node=node)
def check_arguments_in_docstring( self, doc: Docstring, arguments_node: astroid.Arguments, warning_node: astroid.NodeNG, accept_no_param_doc: Optional[bool] = None, ): """Check that all parameters are consistent with the parameters mentioned in the parameter documentation (e.g. the Sphinx tags 'param' and 'type'). * Undocumented parameters except 'self' are noticed. * Undocumented parameter types except for 'self' and the ``*<args>`` and ``**<kwargs>`` parameters are noticed. * Parameters mentioned in the parameter documentation that don't or no longer exist in the function parameter list are noticed. * If the text "For the parameters, see" or "For the other parameters, see" (ignoring additional whitespace) is mentioned in the docstring, missing parameter documentation is tolerated. * If there's no Sphinx style, Google style or NumPy style parameter documentation at all, i.e. ``:param`` is never mentioned etc., the checker assumes that the parameters are documented in another format and the absence is tolerated. :param doc: Docstring for the function, method or class. :type doc: :class:`Docstring` :param arguments_node: Arguments node for the function, method or class constructor. :type arguments_node: :class:`astroid.scoped_nodes.Arguments` :param warning_node: The node to assign the warnings to :type warning_node: :class:`astroid.scoped_nodes.Node` :param accept_no_param_doc: Whether to allow no parameters to be documented. If None then this value is read from the configuration. :type accept_no_param_doc: bool or None """ # Tolerate missing param or type declarations if there is a link to # another method carrying the same name. if not doc.doc: return if accept_no_param_doc is None: accept_no_param_doc = self.linter.namespace.accept_no_param_doc tolerate_missing_params = doc.params_documented_elsewhere() # Collect the function arguments. expected_argument_names = {arg.name for arg in arguments_node.args} expected_argument_names.update(arg.name for arg in arguments_node.kwonlyargs) not_needed_type_in_docstring = self.not_needed_param_in_docstring.copy( ) expected_but_ignored_argument_names = set() ignored_argument_names = get_global_option(self, "ignored-argument-names") if ignored_argument_names: expected_but_ignored_argument_names = { arg for arg in expected_argument_names if ignored_argument_names.match(arg) } if arguments_node.vararg is not None: expected_argument_names.add(f"*{arguments_node.vararg}") not_needed_type_in_docstring.add(f"*{arguments_node.vararg}") if arguments_node.kwarg is not None: expected_argument_names.add(f"**{arguments_node.kwarg}") not_needed_type_in_docstring.add(f"**{arguments_node.kwarg}") params_with_doc, params_with_type = doc.match_param_docs() # Tolerate no parameter documentation at all. if not params_with_doc and not params_with_type and accept_no_param_doc: tolerate_missing_params = True # This is before the update of param_with_type because this must check only # the type documented in a docstring, not the one using pep484 # See #4117 and #4593 self._compare_ignored_args( params_with_type, "useless-type-doc", expected_but_ignored_argument_names, warning_node, ) for index, arg_name in enumerate(arguments_node.args): if arguments_node.annotations[index]: params_with_type.add(arg_name.name) for index, arg_name in enumerate(arguments_node.kwonlyargs): if arguments_node.kwonlyargs_annotations[index]: params_with_type.add(arg_name.name) if not tolerate_missing_params: missing_param_doc = (expected_argument_names - params_with_doc) - ( self.not_needed_param_in_docstring | expected_but_ignored_argument_names) missing_type_doc = (expected_argument_names - params_with_type) - ( not_needed_type_in_docstring | expected_but_ignored_argument_names) if (missing_param_doc == expected_argument_names == missing_type_doc and len(expected_argument_names) != 0): self.add_message( "missing-any-param-doc", args=(warning_node.name, ), node=warning_node, ) else: self._compare_missing_args( params_with_doc, "missing-param-doc", self.not_needed_param_in_docstring | expected_but_ignored_argument_names, expected_argument_names, warning_node, ) self._compare_missing_args( params_with_type, "missing-type-doc", not_needed_type_in_docstring | expected_but_ignored_argument_names, expected_argument_names, warning_node, ) self._compare_different_args( params_with_doc, "differing-param-doc", self.not_needed_param_in_docstring, expected_argument_names, warning_node, ) self._compare_different_args( params_with_type, "differing-type-doc", not_needed_type_in_docstring, expected_argument_names, warning_node, ) self._compare_ignored_args( params_with_doc, "useless-param-doc", expected_but_ignored_argument_names, warning_node, )