summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--doc/whatsnew/2.0.rst24
-rw-r--r--pylint/extensions/_check_docs_utils.py52
-rw-r--r--pylint/extensions/docparams.py51
-rw-r--r--pylint/test/extensions/test_check_return_docs.py145
-rw-r--r--pylint/test/extensions/test_check_yields_docs.py69
6 files changed, 245 insertions, 101 deletions
diff --git a/ChangeLog b/ChangeLog
index 359ee56c6..6537938f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -143,6 +143,11 @@ Release date: tba
* UnknownMessage and EmptyReport are renamed to UnknownMessageError and
EmptyReportError.
+ * Warnings 'missing-returns-type-doc' and 'missing-yields-type-doc'
+ have each been split into two warnings - 'missing-[return|yield]-doc'
+ and 'missing-[return|yield]-type-doc'.
+
+
What's new in Pylint 1.6.3?
===========================
diff --git a/doc/whatsnew/2.0.rst b/doc/whatsnew/2.0.rst
index 9e5a0ba5c..8ec21d29c 100644
--- a/doc/whatsnew/2.0.rst
+++ b/doc/whatsnew/2.0.rst
@@ -89,7 +89,31 @@ New checkers
def not_useless_1(self, first, *args):
return super(Impl, self).not_useless_1(first + some_value, *args)
+* The warnings ``missing-returns-doc`` and ``missing-yields-doc`` have each
+ been replaced with two new warnings - ``missing-[return|yield]-doc`` and
+ ``missing-[return|yield]-type-doc``. Having these as separate warnings
+ allows the user to choose whether their documentation style requires
+ text descriptions of function return/yield, specification of return/yield
+ types, or both.
+ .. code-block:: python
+
+ # This will raise missing-return-type-doc but not missing-return-doc
+ def my_sphinx_style_func(self):
+ """This is a Sphinx-style docstring.
+
+ :returns: Always False
+ """
+ return False
+
+ # This will raise missing-return-doc but not missing-return-type-doc
+ def my_google_style_func(self):
+ """This is a Google-style docstring.
+
+ Returns:
+ bool:
+ """
+ return False
Other Changes
=============
diff --git a/pylint/extensions/_check_docs_utils.py b/pylint/extensions/_check_docs_utils.py
index f6ad4be13..61b7a86d8 100644
--- a/pylint/extensions/_check_docs_utils.py
+++ b/pylint/extensions/_check_docs_utils.py
@@ -137,9 +137,15 @@ class Docstring(object):
def has_returns(self):
return False
+ def has_rtype(self):
+ return False
+
def has_yields(self):
return False
+ def has_yields_type(self):
+ return False
+
def match_param_docs(self):
return set(), set()
@@ -231,8 +237,13 @@ class SphinxDocstring(Docstring):
if not self.doc:
return False
- return bool(self.re_rtype_in_docstring.search(self.doc) and
- self.re_returns_in_docstring.search(self.doc))
+ return bool(self.re_returns_in_docstring.search(self.doc))
+
+ def has_rtype(self):
+ if not self.doc:
+ return False
+
+ return bool(self.re_rtype_in_docstring.search(self.doc))
def match_param_docs(self):
params_with_doc = set()
@@ -334,9 +345,24 @@ class GoogleDocstring(Docstring):
if not match:
continue
- return_type = match.group(1)
return_desc = match.group(2)
- if return_type and return_desc:
+ if return_desc:
+ return True
+
+ return False
+
+ def has_rtype(self):
+ if not self.doc:
+ return False
+
+ entries = self._parse_section(self.re_returns_section)
+ for entry in entries:
+ match = self.re_returns_line.match(entry)
+ if not match:
+ continue
+
+ return_type = match.group(1)
+ if return_type:
return True
return False
@@ -351,13 +377,27 @@ class GoogleDocstring(Docstring):
if not match:
continue
- yield_type = match.group(1)
yield_desc = match.group(2)
- if yield_type and yield_desc:
+ if yield_desc:
return True
return False
+ def has_yields_type(self):
+ if not self.doc:
+ return False
+
+ entries = self._parse_section(self.re_yields_section)
+ for entry in entries:
+ match = self.re_yields_line.match(entry)
+ if not match:
+ continue
+
+ yield_type = match.group(1)
+ if yield_type:
+ return True
+
+ return False
def exceptions(self):
types = set()
diff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py
index cf83421e0..8b3a80e24 100644
--- a/pylint/extensions/docparams.py
+++ b/pylint/extensions/docparams.py
@@ -54,18 +54,32 @@ class DocstringParameterChecker(BaseChecker):
'W9006': ('"%s" not documented as being raised',
'missing-raises-doc',
'Please document exceptions for all raised exception types.'),
- 'W9007': ('Missing return type documentation',
- 'missing-returns-doc',
- 'Please add documentation about what this method returns.'),
'W9008': ('Redundant returns documentation',
'redundant-returns-doc',
- 'Please remove the return documentation from this method.'),
- 'W9009': ('Missing yield type documentation',
- 'missing-yields-doc',
- 'Please add documentation about what this generator yields.'),
+ 'Please remove the return/rtype documentation from this method.'),
'W9010': ('Redundant yields documentation',
'redundant-yields-doc',
'Please remove the yields documentation from this method.'),
+ 'W9011': ('Missing return documentation',
+ 'missing-return-doc',
+ 'Please add documentation about what this method returns.',
+ {'old_names': [('W9007', 'missing-returns-doc')]}),
+ 'W9012': ('Missing return type documentation',
+ 'missing-return-type-doc',
+ 'Please document the type returned by this method.',
+ # we can't use the same old_name for two different warnings
+ # {'old_names': [('W9007', 'missing-returns-doc')]},
+ ),
+ 'W9013': ('Missing yield documentation',
+ 'missing-yield-doc',
+ 'Please add documentation about what this generator yields.',
+ {'old_names': [('W9009', 'missing-yields-doc')]}),
+ 'W9014': ('Missing yield type documentation',
+ 'missing-yield-type-doc',
+ 'Please document the type yielded by this method.',
+ # we can't use the same old_name for two different warnings
+ # {'old_names': [('W9009', 'missing-yields-doc')]},
+ ),
}
options = (('accept-no-param-doc',
@@ -141,7 +155,7 @@ class DocstringParameterChecker(BaseChecker):
return
return_nodes = node.nodes_of_class(astroid.Return)
- if (node_doc.has_returns() and
+ 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',
@@ -151,7 +165,8 @@ class DocstringParameterChecker(BaseChecker):
if not node_doc.supports_yields:
return
- if node_doc.has_yields() and not node.is_generator():
+ if ((node_doc.has_yields() or node_doc.has_yields_type()) and
+ not node.is_generator()):
self.add_message(
'redundant-yields-doc',
node=node)
@@ -189,7 +204,13 @@ class DocstringParameterChecker(BaseChecker):
if not doc.has_returns():
self.add_message(
- 'missing-returns-doc',
+ 'missing-return-doc',
+ node=func_node
+ )
+
+ if not doc.has_rtype():
+ self.add_message(
+ 'missing-return-type-doc',
node=func_node
)
@@ -204,12 +225,20 @@ class DocstringParameterChecker(BaseChecker):
if doc.supports_yields:
doc_has_yields = doc.has_yields()
+ doc_has_yields_type = doc.has_yields_type()
else:
doc_has_yields = doc.has_returns()
+ doc_has_yields_type = doc.has_rtype()
if not doc_has_yields:
self.add_message(
- 'missing-yields-doc',
+ 'missing-yield-doc',
+ node=func_node
+ )
+
+ if not doc_has_yields_type:
+ self.add_message(
+ 'missing-yield-type-doc',
node=func_node
)
diff --git a/pylint/test/extensions/test_check_return_docs.py b/pylint/test/extensions/test_check_return_docs.py
index c2966c601..4be854ac9 100644
--- a/pylint/test/extensions/test_check_return_docs.py
+++ b/pylint/test/extensions/test_check_return_docs.py
@@ -36,9 +36,8 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node),
+ Message(msg_id='missing-return-type-doc', node=node)):
self.checker.visit_return(return_node)
def test_ignores_unknown_style(self):
@@ -61,9 +60,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-type-doc', node=node)):
self.checker.visit_return(return_node)
def test_warn_partial_sphinx_returns_type(self):
@@ -77,9 +74,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warn_missing_sphinx_returns(self):
@@ -94,9 +89,8 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node),
+ Message(msg_id='missing-return-type-doc', node=node)):
self.checker.visit_return(return_node)
def test_warn_partial_google_returns(self):
@@ -111,9 +105,22 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-type-doc', node=node)):
+ self.checker.visit_return(return_node)
+
+ def test_warn_partial_google_returns_type(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Returns:
+ bool:
+ """
+ return False
+ ''')
+ return_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warn_missing_google_returns(self):
@@ -128,9 +135,29 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node),
+ Message(msg_id='missing-return-type-doc', node=node)):
+ self.checker.visit_return(return_node)
+
+ def test_warn_partial_numpy_returns_type(self):
+ node = astroid.extract_node('''
+ def my_func(self, doc_type):
+ """This is a docstring.
+
+ Arguments
+ ---------
+ doc_type : str
+ Numpy
+
+ Returns
+ -------
+ bool
+ """
+ return False
+ ''')
+ return_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warn_missing_numpy_returns(self):
@@ -147,9 +174,8 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node),
+ Message(msg_id='missing-return-type-doc', node=node)):
self.checker.visit_return(return_node)
def test_find_sphinx_returns(self):
@@ -327,9 +353,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warns_google_return_list_of_custom_class_without_description(self):
@@ -338,15 +362,13 @@ class DocstringCheckerReturnTest(CheckerTestCase):
"""This is a docstring.
Returns:
- list(:class:`mymodule.Class`)
+ list(:class:`mymodule.Class`):
"""
return [mymodule.Class()]
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warns_numpy_return_list_of_custom_class_without_description(self):
@@ -362,9 +384,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
''')
return_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-returns-doc',
- node=node)):
+ Message(msg_id='missing-return-doc', node=node)):
self.checker.visit_return(return_node)
def test_warns_sphinx_redundant_return_doc(self):
@@ -373,14 +393,24 @@ class DocstringCheckerReturnTest(CheckerTestCase):
"""This is a docstring.
:returns: One
+ """
+ return None
+ ''')
+ with self.assertAddsMessages(
+ Message(msg_id='redundant-returns-doc', node=node)):
+ self.checker.visit_functiondef(node)
+
+ def test_warns_sphinx_redundant_rtype_doc(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
:rtype: int
"""
return None
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-returns-doc',
- node=node)):
+ Message(msg_id='redundant-returns-doc', node=node)):
self.checker.visit_functiondef(node)
def test_warns_google_redundant_return_doc(self):
@@ -389,14 +419,26 @@ class DocstringCheckerReturnTest(CheckerTestCase):
"""This is a docstring.
Returns:
- int: One
+ One
"""
return None
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-returns-doc',
- node=node)):
+ Message(msg_id='redundant-returns-doc', node=node)):
+ self.checker.visit_functiondef(node)
+
+ def test_warns_google_redundant_rtype_doc(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Returns:
+ int:
+ """
+ return None
+ ''')
+ with self.assertAddsMessages(
+ Message(msg_id='redundant-returns-doc', node=node)):
self.checker.visit_functiondef(node)
def test_warns_numpy_redundant_return_doc(self):
@@ -412,9 +454,22 @@ class DocstringCheckerReturnTest(CheckerTestCase):
return None
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-returns-doc',
- node=node)):
+ Message(msg_id='redundant-returns-doc', node=node)):
+ self.checker.visit_functiondef(node)
+
+ def test_warns_numpy_redundant_rtype_doc(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Returns
+ -------
+ int
+ """
+ return None
+ ''')
+ with self.assertAddsMessages(
+ Message(msg_id='redundant-returns-doc', node=node)):
self.checker.visit_functiondef(node)
def test_ignores_sphinx_redundant_return_doc_multiple_returns(self):
@@ -494,9 +549,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
yield 1
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-returns-doc',
- node=node)):
+ Message(msg_id='redundant-returns-doc', node=node)):
self.checker.visit_functiondef(node)
def test_warns_numpy_redundant_return_doc_yield(self):
@@ -512,9 +565,7 @@ class DocstringCheckerReturnTest(CheckerTestCase):
yield 1
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-returns-doc',
- node=node)):
+ Message(msg_id='redundant-returns-doc', node=node)):
self.checker.visit_functiondef(node)
diff --git a/pylint/test/extensions/test_check_yields_docs.py b/pylint/test/extensions/test_check_yields_docs.py
index 98fb82780..42455aa4b 100644
--- a/pylint/test/extensions/test_check_yields_docs.py
+++ b/pylint/test/extensions/test_check_yields_docs.py
@@ -36,9 +36,8 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node),
+ Message(msg_id='missing-yield-type-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_ignores_unknown_style(self):
@@ -61,9 +60,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-type-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warn_partial_sphinx_yields_type(self):
@@ -77,9 +74,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warn_missing_sphinx_yields(self):
@@ -94,9 +89,8 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node),
+ Message(msg_id='missing-yield-type-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warn_partial_google_yields(self):
@@ -111,9 +105,22 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-type-doc', node=node)):
+ self.checker.visit_yield(yield_node)
+
+ def test_warn_partial_google_yields_type(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Yields:
+ bool:
+ """
+ yield False
+ ''')
+ yield_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(msg_id='missing-yield-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warn_missing_google_yields(self):
@@ -128,9 +135,8 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node),
+ Message(msg_id='missing-yield-type-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warn_missing_numpy_yields(self):
@@ -147,9 +153,8 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node),
+ Message(msg_id='missing-yield-type-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_find_sphinx_yields(self):
@@ -286,9 +291,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warns_google_yield_list_of_custom_class_without_description(self):
@@ -297,15 +300,13 @@ class DocstringCheckerYieldTest(CheckerTestCase):
"""This is a docstring.
Yields:
- list(:class:`mymodule.Class`)
+ list(:class:`mymodule.Class`):
"""
yield [mymodule.Class()]
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node)):
self.checker.visit_yield(yield_node)
def test_warns_numpy_yield_list_of_custom_class_without_description(self):
@@ -321,9 +322,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
''')
yield_node = node.body[0]
with self.assertAddsMessages(
- Message(
- msg_id='missing-yields-doc',
- node=node)):
+ Message(msg_id='missing-yield-doc', node=node)):
self.checker.visit_yield(yield_node)
# No such thing as redundant yield documentation for sphinx because it
@@ -377,9 +376,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
return 1
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-yields-doc',
- node=node)):
+ Message(msg_id='redundant-yields-doc', node=node)):
self.checker.visit_functiondef(node)
def test_warns_numpy_redundant_yield_doc_return(self):
@@ -395,9 +392,7 @@ class DocstringCheckerYieldTest(CheckerTestCase):
return 1
''')
with self.assertAddsMessages(
- Message(
- msg_id='redundant-yields-doc',
- node=node)):
+ Message(msg_id='redundant-yields-doc', node=node)):
self.checker.visit_functiondef(node)