diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 70a111978e..4b806579c1 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -290,6 +290,7 @@ contributors: - Made C0412 (ungrouped import) compatible with isort - Made multiple message with the same old name possible - Made Pylint a little faster by refactoring the message store + - Broke down "missing-docstrings" between "module", "class" and "function" * Nathan Marrow diff --git a/ChangeLog b/ChangeLog index 4ea9dd2a52..20b7c8bab4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1076,6 +1076,13 @@ Release date: 2018-07-15 Close 1992 + * Broke down "missing-docstrings" between "module", "class" and "function" + + For this to work we had to make multiple messages with the same old name + possible. + + Closes #1164 + What's New in Pylint 1.9? ========================= diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 15310cca26..f195fc1661 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -1942,18 +1942,34 @@ def _name_became_keyword_in_version(name, rules): class DocStringChecker(_BasicChecker): msgs = { - "C0111": ( - "Missing %s docstring", # W0131 - "missing-docstring", - "Used when a module, function, class or method has no docstring. " - "Some special methods like __init__ don't necessarily require a " - "docstring.", - ), "C0112": ( - "Empty %s docstring", # W0132 + "Empty %s docstring", "empty-docstring", "Used when a module, function, class or method has an empty " "docstring (it would be too easy ;).", + {"old_names": [("W0132", "old-empty-docstring")]}, + ), + "C0114": ( + "Missing module docstring", + "missing-module-docstring", + "Used when a module has no docstring." + "Empty modules do not require a docstring.", + {"old_names": [("C0111", "missing-docstring")]}, + ), + "C0115": ( + "Missing class docstring", + "missing-class-docstring", + "Used when a class has no docstring." + "Even an empty class must have a docstring.", + {"old_names": [("C0111", "missing-docstring")]}, + ), + "C0116": ( + "Missing function or method docstring", + "missing-function-docstring", + "Used when a function or method has no docstring." + "Some special methods like __init__ do not require a " + "docstring.", + {"old_names": [("C0111", "missing-docstring")]}, ), } options = ( @@ -2064,9 +2080,13 @@ def _check_docstring( return if func.bound.name in ("str", "unicode", "bytes"): return - self.add_message( - "missing-docstring", node=node, args=(node_type,), confidence=confidence - ) + if node_type == "module": + message = "missing-module-docstring" + elif node_type == "class": + message = "missing-class-docstring" + else: + message = "missing-function-docstring" + self.add_message(message, node=node, confidence=confidence) elif not docstring.strip(): self.stats["undocumented_" + node_type] += 1 self.add_message( diff --git a/tests/functional/d/docstrings.py b/tests/functional/d/docstrings.py index 8168167c53..a113501114 100644 --- a/tests/functional/d/docstrings.py +++ b/tests/functional/d/docstrings.py @@ -1,12 +1,12 @@ # pylint: disable=R0201, useless-object-inheritance, unnecessary-pass -# -1: [missing-docstring] +# -1: [missing-module-docstring] from __future__ import print_function # +1: [empty-docstring] def function0(): """""" -# +1: [missing-docstring] +# +1: [missing-function-docstring] def function1(value): # missing docstring print(value) @@ -19,7 +19,7 @@ def function3(value): """docstring""" print(value) -# +1: [missing-docstring] +# +1: [missing-class-docstring] class AAAA(object): # missing docstring @@ -36,7 +36,7 @@ class AAAA(object): ## """ yeah !""" ## pass - # +1: [missing-docstring] + # +1: [missing-function-docstring] def method1(self): pass @@ -66,7 +66,7 @@ def method2(self): def method3(self): pass - # +1: [missing-docstring] + # +1: [missing-function-docstring] def method4(self): pass diff --git a/tests/functional/d/docstrings.txt b/tests/functional/d/docstrings.txt index e30e4629c1..4e5f4058ab 100644 --- a/tests/functional/d/docstrings.txt +++ b/tests/functional/d/docstrings.txt @@ -1,8 +1,8 @@ -missing-docstring:1::Missing module docstring +missing-module-docstring:1::Missing module docstring empty-docstring:6:function0:Empty function docstring -missing-docstring:10:function1:Missing function docstring -missing-docstring:23:AAAA:Missing class docstring -missing-docstring:40:AAAA.method1:Missing method docstring:INFERENCE +missing-function-docstring:10:function1:Missing function or method docstring +missing-class-docstring:23:AAAA:Missing class docstring +missing-function-docstring:40:AAAA.method1:Missing function or method docstring:INFERENCE empty-docstring:48:AAAA.method3:Empty method docstring:INFERENCE empty-docstring:62:DDDD.method2:Empty method docstring:INFERENCE -missing-docstring:70:DDDD.method4:Missing method docstring:INFERENCE +missing-function-docstring:70:DDDD.method4:Missing function or method docstring:INFERENCE diff --git a/tests/functional/m/messages_managed_by_id.py b/tests/functional/m/messages_managed_by_id.py index a96ac5cc56..67b74ec884 100644 --- a/tests/functional/m/messages_managed_by_id.py +++ b/tests/functional/m/messages_managed_by_id.py @@ -6,6 +6,6 @@ def foo(): #pylint: disable=C0102 def toto(): #pylint: disable=C0102,R1711 return -# +1: [missing-docstring] +# +1: [missing-function-docstring] def test_enabled_by_id_msg(): #pylint: enable=C0111 pass diff --git a/tests/functional/m/messages_managed_by_id.txt b/tests/functional/m/messages_managed_by_id.txt index e766ab0b38..c4e475c676 100644 --- a/tests/functional/m/messages_managed_by_id.txt +++ b/tests/functional/m/messages_managed_by_id.txt @@ -3,4 +3,4 @@ use-symbolic-message-instead:3::"Id 'C0102' is used to disable 'blacklisted-name use-symbolic-message-instead:6::"Id 'C0102' is used to disable 'blacklisted-name' message emission" use-symbolic-message-instead:6::"Id 'R1711' is used to disable 'useless-return' message emission" use-symbolic-message-instead:10::"Id 'C0111' is used to enable 'missing-docstring' message emission" -missing-docstring:10:test_enabled_by_id_msg:"Missing function docstring" +missing-function-docstring:10:test_enabled_by_id_msg:"Missing function or method docstring" diff --git a/tests/functional/m/missing_docstring.py b/tests/functional/m/missing_docstring.py index 657af5c7e9..1169f7ce56 100644 --- a/tests/functional/m/missing_docstring.py +++ b/tests/functional/m/missing_docstring.py @@ -1,4 +1,4 @@ -# [missing-docstring] +# [missing-module-docstring] # pylint: disable=too-few-public-methods, useless-object-inheritance def public_documented(): @@ -18,11 +18,11 @@ class ClassDocumented(object): """It has a docstring.""" -class ClassUndocumented(object): # [missing-docstring] +class ClassUndocumented(object): # [missing-class-docstring] pass -def public_undocumented(): # [missing-docstring] +def public_undocumented(): # [missing-function-docstring] pass diff --git a/tests/functional/m/missing_docstring.txt b/tests/functional/m/missing_docstring.txt index 2680319b63..d4f89ed967 100644 --- a/tests/functional/m/missing_docstring.txt +++ b/tests/functional/m/missing_docstring.txt @@ -1,3 +1,3 @@ -missing-docstring:1::Missing module docstring -missing-docstring:21:ClassUndocumented:Missing class docstring -missing-docstring:25:public_undocumented:Missing function docstring +missing-module-docstring:1::Missing module docstring +missing-class-docstring:21:ClassUndocumented:Missing class docstring +missing-function-docstring:25:public_undocumented:Missing function or method docstring diff --git a/tests/functional/m/missing_docstring_new_style.py b/tests/functional/m/missing_docstring_new_style.py new file mode 100644 index 0000000000..58c7c1ec8a --- /dev/null +++ b/tests/functional/m/missing_docstring_new_style.py @@ -0,0 +1,47 @@ +# [missing-module-docstring] +# pylint: disable=too-few-public-methods + + +class ClassDocumented: + """It has a docstring.""" + + +class UndocumentedClass: # [missing-class-docstring] + pass + + +# pylint: disable=missing-class-docstring +class ClassUndocumented: + pass + + +# pylint: enable=missing-class-docstring +class OtherClassUndocumented: # [missing-class-docstring] + pass + + +def public_documented(): + """It has a docstring.""" + + +def _private_undocumented(): + # Doesn't need a docstring + pass + + +def _private_documented(): + """It has a docstring.""" + + +def public_undocumented(): # [missing-function-docstring] + pass + + +# pylint: disable=missing-function-docstring +def undocumented_function(): + pass + + +# pylint: enable=missing-function-docstring +def undocumented_other_function(): # [missing-function-docstring] + pass diff --git a/tests/functional/m/missing_docstring_new_style.txt b/tests/functional/m/missing_docstring_new_style.txt new file mode 100644 index 0000000000..c19bb19952 --- /dev/null +++ b/tests/functional/m/missing_docstring_new_style.txt @@ -0,0 +1,5 @@ +missing-module-docstring:1::Missing module docstring +missing-class-docstring:9:UndocumentedClass:Missing class docstring +missing-class-docstring:19:OtherClassUndocumented:Missing class docstring +missing-function-docstring:36:public_undocumented:Missing function or method docstring +missing-function-docstring:46:undocumented_other_function:Missing function or method docstring diff --git a/tests/functional/m/missing_module_docstring_disabled.py b/tests/functional/m/missing_module_docstring_disabled.py new file mode 100644 index 0000000000..d4d9edf3f4 --- /dev/null +++ b/tests/functional/m/missing_module_docstring_disabled.py @@ -0,0 +1,5 @@ +# pylint: disable=missing-module-docstring, too-few-public-methods + + +class Documented: + "Something." diff --git a/tests/functional/m/missing_module_docstring_disabled.txt b/tests/functional/m/missing_module_docstring_disabled.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_self.py b/tests/test_self.py index 3f029e131d..75118f587c 100644 --- a/tests/test_self.py +++ b/tests/test_self.py @@ -344,8 +344,8 @@ def test_enable_all_works(self): """ ************* Module data.clientmodule_test {0}:10:8: W0612: Unused variable 'local_variable' (unused-variable) - {0}:18:4: C0111: Missing method docstring (missing-docstring) - {0}:22:0: C0111: Missing class docstring (missing-docstring) + {0}:18:4: C0116: Missing function or method docstring (missing-function-docstring) + {0}:22:0: C0115: Missing class docstring (missing-class-docstring) """.format( module ) @@ -542,8 +542,8 @@ def test_pylintrc_comments_in_values(self): """ ************* Module test_pylintrc_comments {0}:2:0: W0311: Bad indentation. Found 1 spaces, expected 4 (bad-indentation) - {0}:1:0: C0111: Missing module docstring (missing-docstring) - {0}:1:0: C0111: Missing function docstring (missing-docstring) + {0}:1:0: C0114: Missing module docstring (missing-module-docstring) + {0}:1:0: C0116: Missing function or method docstring (missing-function-docstring) """.format( path ) diff --git a/tests/unittest_checker_base.py b/tests/unittest_checker_base.py index 203a05990a..aa87a2035d 100644 --- a/tests/unittest_checker_base.py +++ b/tests/unittest_checker_base.py @@ -32,7 +32,7 @@ class TestDocstring(CheckerTestCase): def test_missing_docstring_module(self): module = astroid.parse("something") - message = Message("missing-docstring", node=module, args=("module",)) + message = Message("missing-module-docstring", node=module) with self.assertAddsMessages(message): self.checker.visit_module(module) @@ -53,7 +53,7 @@ def test_empty_docstring_function(self): def func(tion): pass""" ) - message = Message("missing-docstring", node=func, args=("function",)) + message = Message("missing-function-docstring", node=func) with self.assertAddsMessages(message): self.checker.visit_functiondef(func) @@ -76,7 +76,7 @@ def func(tion): pass """ ) - message = Message("missing-docstring", node=func, args=("function",)) + message = Message("missing-function-docstring", node=func) with self.assertAddsMessages(message): self.checker.visit_functiondef(func) @@ -91,7 +91,7 @@ def func(tion): pass """ ) - message = Message("missing-docstring", node=func, args=("function",)) + message = Message("missing-function-docstring", node=func) with self.assertAddsMessages(message): self.checker.visit_functiondef(func) @@ -111,7 +111,7 @@ def test_class_no_docstring(self): class Klass(object): pass""" ) - message = Message("missing-docstring", node=klass, args=("class",)) + message = Message("missing-class-docstring", node=klass) with self.assertAddsMessages(message): self.checker.visit_classdef(klass)