diff --git a/ChangeLog b/ChangeLog index 4bbf23c016..f68cdb2260 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,10 @@ Release date: TBA Close #560 +* ``missing-*-docstring`` can look for ``__doc__`` assignments. + + Close #3301 + * ``safe_infer`` can infer a value as long as all the paths share the same type. Close #2503 diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 6aa4f70873..d81686e5b1 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -2097,6 +2097,9 @@ def _check_docstring( ): """check the node has a non empty docstring""" docstring = node.doc + if docstring is None: + docstring = _infer_dunder_doc_attribute(node) + if docstring is None: if not report_missing: return @@ -2167,6 +2170,21 @@ def _is_one_arg_pos_call(call): return isinstance(call, astroid.Call) and len(call.args) == 1 and not call.keywords +def _infer_dunder_doc_attribute(node): + # Try to see if we have a `__doc__` attribute. + try: + docstring = node["__doc__"] + except KeyError: + return None + + docstring = utils.safe_infer(docstring) + if not docstring: + return None + if not isinstance(docstring, astroid.Const): + return None + return docstring.value + + class ComparisonChecker(_BasicChecker): """Checks for comparisons diff --git a/tests/functional/m/missing_docstring.py b/tests/functional/m/missing_docstring.py index 1169f7ce56..72d6762aa2 100644 --- a/tests/functional/m/missing_docstring.py +++ b/tests/functional/m/missing_docstring.py @@ -52,3 +52,7 @@ def test(self, value): @test.deleter def test(self): pass + + +class DocumentedViaDunderDoc(object): + __doc__ = "This one"