| # Copyright (c) 2016-2018, 2020 Claudiu Popa <pcmanticore@gmail.com> |
| # Copyright (c) 2016, 2019 Ashley Whetter <ashley@awhetter.co.uk> |
| # Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com> |
| # Copyright (c) 2016 Glenn Matthews <glenn@e-dad.net> |
| # Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com> |
| # Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.com> |
| # Copyright (c) 2019-2021 Pierre Sassoulas <pierre.sassoulas@gmail.com> |
| # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com> |
| # Copyright (c) 2019 Zeb Nicholls <zebedee.nicholls@climate-energy-college.org> |
| # Copyright (c) 2020 hippo91 <guillaume.peillex@gmail.com> |
| # Copyright (c) 2020 Anthony Sottile <asottile@umich.edu> |
| |
| # Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
| # For details: https://github.com/PyCQA/pylint/blob/master/LICENSE |
| |
| """Unit tests for the return documentation checking in the |
| `DocstringChecker` in :mod:`pylint.extensions.check_docs` |
| """ |
| |
| # pylint: disable=too-many-public-methods |
| |
| import astroid |
| |
| from pylint.extensions.docparams import DocstringParameterChecker |
| from pylint.testutils import CheckerTestCase, Message, set_config |
| |
| |
| class TestDocstringCheckerReturn(CheckerTestCase): |
| """Tests for pylint_plugin.RaiseDocChecker""" |
| |
| CHECKER_CLASS = DocstringParameterChecker |
| |
| def test_ignores_no_docstring(self): |
| return_node = astroid.extract_node( |
| """ |
| def my_func(self): |
| return False #@ |
| """ |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| @set_config(accept_no_return_doc=False) |
| def test_warns_no_docstring(self): |
| node = astroid.extract_node( |
| """ |
| def my_func(self): |
| return False |
| """ |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| 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): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring.""" |
| return False #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_warn_partial_sphinx_returns(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :returns: Always False |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| Message(msg_id="missing-return-type-doc", node=node) |
| ): |
| self.checker.visit_return(return_node) |
| |
| def test_sphinx_missing_return_type_with_annotations(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self) -> bool: |
| """This is a docstring. |
| |
| :returns: Always False |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_warn_partial_sphinx_returns_type(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :rtype: 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_sphinx_returns(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| :param doc_type: Sphinx |
| :type doc_type: str |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| 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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| Always False |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| 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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| Parameters: |
| doc_type (str): Google |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| 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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| Arguments |
| --------- |
| doc_type : str |
| Numpy |
| """ |
| return False |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages( |
| 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): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :return: Always False |
| :rtype: bool |
| """ |
| return False #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_find_google_returns(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| bool: Always False |
| """ |
| return False #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_find_numpy_returns(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| bool |
| Always False |
| """ |
| return False #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_find_numpy_returns_with_of(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| :obj:`list` of :obj:`str` |
| List of strings |
| """ |
| return ["hi", "bye"] #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_ignores_sphinx_return_none(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| :param doc_type: Sphinx |
| :type doc_type: str |
| """ |
| return #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_ignores_google_return_none(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| Args: |
| doc_type (str): Google |
| """ |
| return #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_ignores_numpy_return_none(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self, doc_type): |
| """This is a docstring. |
| |
| Arguments |
| --------- |
| doc_type : str |
| Numpy |
| """ |
| return #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_sphinx_return_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :returns: An object |
| :rtype: :class:`mymodule.Class` |
| """ |
| return mymodule.Class() #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_google_return_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| mymodule.Class: An object |
| """ |
| return mymodule.Class() #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_numpy_return_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| mymodule.Class |
| An object |
| """ |
| return mymodule.Class() #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_sphinx_return_list_of_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :returns: An object |
| :rtype: list(:class:`mymodule.Class`) |
| """ |
| return [mymodule.Class()] #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_google_return_list_of_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| list(:class:`mymodule.Class`): An object |
| """ |
| return [mymodule.Class()] #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_finds_numpy_return_list_of_custom_class(self): |
| return_node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| list(:class:`mymodule.Class`) |
| An object |
| """ |
| return [mymodule.Class()] #@ |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_return(return_node) |
| |
| def test_warns_sphinx_return_list_of_custom_class_without_description(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :rtype: list(:class:`mymodule.Class`) |
| """ |
| return [mymodule.Class()] |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages(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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| list(:class:`mymodule.Class`): |
| """ |
| return [mymodule.Class()] |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages(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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| list(:class:`mymodule.Class`) |
| """ |
| return [mymodule.Class()] |
| ''' |
| ) |
| return_node = node.body[0] |
| with self.assertAddsMessages(Message(msg_id="missing-return-doc", node=node)): |
| self.checker.visit_return(return_node) |
| |
| def test_warns_sphinx_redundant_return_doc(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """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) |
| ): |
| self.checker.visit_functiondef(node) |
| |
| def test_warns_google_redundant_return_doc(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """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_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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| int |
| One |
| """ |
| return None |
| ''' |
| ) |
| with self.assertAddsMessages( |
| 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): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| :returns: One |
| :rtype: int |
| |
| :returns: None sometimes |
| :rtype: None |
| """ |
| if a_func(): |
| return None |
| return 1 |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| |
| def test_ignores_google_redundant_return_doc_multiple_returns(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| int or None: One, or sometimes None. |
| """ |
| if a_func(): |
| return None |
| return 1 |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| |
| def test_ignores_numpy_redundant_return_doc_multiple_returns(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| int |
| One |
| None |
| Sometimes |
| """ |
| if a_func(): |
| return None |
| return 1 |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| |
| def test_ignore_sphinx_redundant_return_doc_yield(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func_with_yield(self): |
| """This is a docstring. |
| |
| :returns: One |
| :rtype: generator |
| """ |
| for value in range(3): |
| yield value |
| ''' |
| ) |
| with self.assertNoMessages(): |
| self.checker.visit_functiondef(node) |
| |
| def test_warns_google_redundant_return_doc_yield(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns: |
| int: One |
| """ |
| yield 1 |
| ''' |
| ) |
| with self.assertAddsMessages( |
| Message(msg_id="redundant-returns-doc", node=node) |
| ): |
| self.checker.visit_functiondef(node) |
| |
| def test_warns_numpy_redundant_return_doc_yield(self): |
| node = astroid.extract_node( |
| ''' |
| def my_func(self): |
| """This is a docstring. |
| |
| Returns |
| ------- |
| int |
| One |
| """ |
| yield 1 |
| ''' |
| ) |
| with self.assertAddsMessages( |
| Message(msg_id="redundant-returns-doc", node=node) |
| ): |
| self.checker.visit_functiondef(node) |