summaryrefslogtreecommitdiff
path: root/tests/extensions/test_check_raise_docs.py
diff options
context:
space:
mode:
authorAshley Whetter <ashley@awhetter.co.uk>2019-06-14 22:28:42 -0700
committerClaudiu Popa <pcmanticore@gmail.com>2019-06-20 10:02:14 +0200
commit33b8185a455c1686d038258697bb93005f2441c2 (patch)
tree4a50ccac775c009436e45803129e428ed694065f /tests/extensions/test_check_raise_docs.py
parent7081d91f30728653000bdfc59ea85a3395f96418 (diff)
downloadpylint-git-33b8185a455c1686d038258697bb93005f2441c2.tar.gz
Stopped installing tests with package
Diffstat (limited to 'tests/extensions/test_check_raise_docs.py')
-rw-r--r--tests/extensions/test_check_raise_docs.py781
1 files changed, 781 insertions, 0 deletions
diff --git a/tests/extensions/test_check_raise_docs.py b/tests/extensions/test_check_raise_docs.py
new file mode 100644
index 000000000..c51a1fdaa
--- /dev/null
+++ b/tests/extensions/test_check_raise_docs.py
@@ -0,0 +1,781 @@
+# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
+# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
+# Copyright (c) 2016 Glenn Matthews <glenn@e-dad.net>
+# Copyright (c) 2016 Ashley Whetter <ashley@awhetter.co.uk>
+# Copyright (c) 2018 Adam Dangoor <adamdangoor@gmail.com>
+
+# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+# For details: https://github.com/PyCQA/pylint/blob/master/COPYING
+
+"""Unit tests for the raised exception documentation checking in the
+`DocstringChecker` in :mod:`pylint.extensions.check_docs`
+"""
+from __future__ import absolute_import, division, print_function
+
+import astroid
+
+from pylint.extensions.docparams import DocstringParameterChecker
+from pylint.testutils import CheckerTestCase, Message, set_config
+
+
+class TestDocstringCheckerRaise(CheckerTestCase):
+ """Tests for pylint_plugin.RaiseDocChecker"""
+ CHECKER_CLASS = DocstringParameterChecker
+
+ def test_ignores_no_docstring(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ raise RuntimeError('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_unknown_style(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring."""
+ raise RuntimeError('hi')
+ ''')
+ raise_node = node.body[0]
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ @set_config(accept_no_raise_doc=False)
+ def test_warns_unknown_style(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring."""
+ raise RuntimeError('hi')
+ ''')
+ raise_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_missing_sphinx_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Never
+ """
+ raise RuntimeError('hi')
+ raise NameError('hi')
+ ''')
+ raise_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_missing_google_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises:
+ NameError: Never
+ """
+ raise RuntimeError('hi')
+ raise NameError('hi')
+ ''')
+ raise_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_google_attr_raises_exact_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a google docstring.
+
+ Raises:
+ re.error: Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+ pass
+
+ def test_find_google_attr_raises_substr_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a google docstring.
+
+ Raises:
+ re.error: Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_valid_missing_google_attr_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a google docstring.
+
+ Raises:
+ re.anothererror: Sometimes
+ """
+ from re import error
+ raise error('hi')
+ ''')
+ raise_node = node.body[1]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('error', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_invalid_missing_google_attr_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a google docstring.
+
+ Raises:
+ bogusmodule.error: Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ # pylint allows this to pass since the comparison between Raises and
+ # raise are based on the class name, not the qualified name.
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ @set_config(accept_no_raise_doc=False)
+ def test_google_raises_with_prefix(self):
+ code_snippet = '''
+ def my_func(self):
+ """This is a google docstring.
+
+ Raises:
+ {prefix}re.error: Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ '''
+ for prefix in ["~", "!"]:
+ raise_node = astroid.extract_node(code_snippet.format(prefix=prefix))
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_missing_numpy_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises
+ ------
+ NameError
+ Never
+ """
+ raise RuntimeError('hi')
+ raise NameError('hi')
+ ''')
+ raise_node = node.body[0]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_ignore_spurious_sphinx_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises RuntimeError: Always
+ :except NameError: Never
+ :raise OSError: Never
+ :exception ValueError: Never
+ """
+ raise RuntimeError('Blah') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_all_sphinx_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises RuntimeError: Always
+ :except NameError: Never
+ :raise OSError: Never
+ :exception ValueError: Never
+ """
+ raise RuntimeError('hi') #@
+ raise NameError('hi')
+ raise OSError(2, 'abort!')
+ raise ValueError('foo')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_all_google_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises:
+ RuntimeError: Always
+ NameError: Never
+ """
+ raise RuntimeError('hi') #@
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_all_numpy_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises
+ ------
+ RuntimeError
+ Always
+ NameError
+ Never
+ """
+ raise RuntimeError('hi') #@
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_finds_rethrown_sphinx_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Sometimes
+ """
+ try:
+ fake_func()
+ except RuntimeError:
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_rethrown_google_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises:
+ NameError: Sometimes
+ """
+ try:
+ fake_func()
+ except RuntimeError:
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_rethrown_numpy_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises
+ ------
+ NameError
+ Sometimes
+ """
+ try:
+ fake_func()
+ except RuntimeError:
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_finds_rethrown_sphinx_multiple_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Sometimes
+ """
+ try:
+ fake_func()
+ except (RuntimeError, ValueError):
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError, ValueError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_rethrown_google_multiple_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises:
+ NameError: Sometimes
+ """
+ try:
+ fake_func()
+ except (RuntimeError, ValueError):
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError, ValueError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_rethrown_numpy_multiple_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises
+ ------
+ NameError
+ Sometimes
+ """
+ try:
+ fake_func()
+ except (RuntimeError, ValueError):
+ raise #@
+
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError, ValueError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_caught_sphinx_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Sometimes
+ """
+ try:
+ raise RuntimeError('hi') #@
+ except RuntimeError:
+ pass
+
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_caught_google_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ Raises:
+ NameError: Sometimes
+ """
+ try:
+ raise RuntimeError('hi') #@
+ except RuntimeError:
+ pass
+
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_caught_numpy_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ NameError
+ Sometimes
+ """
+ try:
+ raise RuntimeError('hi') #@
+ except RuntimeError:
+ pass
+
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_numpy_attr_raises_exact_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ re.error
+ Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+ pass
+
+ def test_find_numpy_attr_raises_substr_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ re.error
+ Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_valid_missing_numpy_attr_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ re.anothererror
+ Sometimes
+ """
+ from re import error
+ raise error('hi')
+ ''')
+ raise_node = node.body[1]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('error', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_invalid_missing_numpy_attr_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ bogusmodule.error
+ Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ # pylint allows this to pass since the comparison between Raises and
+ # raise are based on the class name, not the qualified name.
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ @set_config(accept_no_raise_doc=False)
+ def test_numpy_raises_with_prefix(self):
+ code_snippet = '''
+ def my_func(self):
+ """This is a numpy docstring.
+
+ Raises
+ ------
+ {prefix}re.error
+ Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ '''
+ for prefix in ["~", "!"]:
+ raise_node = astroid.extract_node(code_snippet.format(prefix=prefix))
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_missing_sphinx_raises_infer_from_instance(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Never
+ """
+ my_exception = RuntimeError('hi')
+ raise my_exception #@
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_missing_sphinx_raises_infer_from_function(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Never
+ """
+ def ex_func(val):
+ return RuntimeError(val)
+ raise ex_func('hi') #@
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_sphinx_attr_raises_exact_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a sphinx docstring.
+
+ :raises re.error: Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_sphinx_attr_raises_substr_exc(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a sphinx docstring.
+
+ :raises re.error: Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_find_valid_missing_sphinx_attr_raises(self):
+ node = astroid.extract_node('''
+ def my_func(self):
+ """This is a sphinx docstring.
+
+ :raises re.anothererror: Sometimes
+ """
+ from re import error
+ raise error('hi')
+ ''')
+ raise_node = node.body[1]
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('error', ))):
+ self.checker.visit_raise(raise_node)
+
+ def test_find_invalid_missing_sphinx_attr_raises(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a sphinx docstring.
+
+ :raises bogusmodule.error: Sometimes
+ """
+ from re import error
+ raise error('hi') #@
+ ''')
+ # pylint allows this to pass since the comparison between Raises and
+ # raise are based on the class name, not the qualified name.
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ @set_config(accept_no_raise_doc=False)
+ def test_sphinx_raises_with_prefix(self):
+ code_snippet = '''
+ def my_func(self):
+ """This is a sphinx docstring.
+
+ :raises {prefix}re.error: Sometimes
+ """
+ import re
+ raise re.error('hi') #@
+ '''
+ for prefix in ["~", "!"]:
+ raise_node = astroid.extract_node(code_snippet.format(prefix=prefix))
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_raise_uninferable(self):
+ raise_node = astroid.extract_node('''
+ from unknown import Unknown
+
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Never
+ """
+ raise Unknown('hi') #@
+ raise NameError('hi')
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_returns_from_inner_functions(self):
+ raise_node = astroid.extract_node('''
+ def my_func(self):
+ """This is a docstring.
+
+ :raises NameError: Never
+ """
+ def ex_func(val):
+ def inner_func(value):
+ return OSError(value)
+ return RuntimeError(val)
+ raise ex_func('hi') #@
+ raise NameError('hi')
+ ''')
+ node = raise_node.frame()
+ with self.assertAddsMessages(
+ Message(
+ msg_id='missing-raises-doc',
+ node=node,
+ args=('RuntimeError', ))):
+ # we do NOT expect a warning about the OSError in inner_func!
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_returns_use_only_names(self):
+ raise_node = astroid.extract_node('''
+ def myfunc():
+ """This is a docstring
+
+ :raises NameError: Never
+ """
+ def inner_func():
+ return 42
+
+ raise inner_func() #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_ignores_returns_use_only_exception_instances(self):
+ raise_node = astroid.extract_node('''
+ def myfunc():
+ """This is a docstring
+
+ :raises MyException: Never
+ """
+ class MyException(Exception):
+ pass
+ def inner_func():
+ return MyException
+
+ raise inner_func() #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_no_crash_when_inferring_handlers(self):
+ raise_node = astroid.extract_node('''
+ import collections
+
+ def test():
+ """raises
+
+ :raise U: pass
+ """
+ try:
+ pass
+ except collections.U as exc:
+ raise #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_no_crash_when_cant_find_exception(self):
+ raise_node = astroid.extract_node('''
+ import collections
+
+ def test():
+ """raises
+
+ :raise U: pass
+ """
+ try:
+ pass
+ except U as exc:
+ raise #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)
+
+ def test_no_error_notimplemented_documented(self):
+ raise_node = astroid.extract_node('''
+ def my_func():
+ """
+ Raises:
+ NotImplementedError: When called.
+ """
+ raise NotImplementedError #@
+ ''')
+ with self.assertNoMessages():
+ self.checker.visit_raise(raise_node)