8th day of python challenges 111-117
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
TEST = map(str, (1, 2, 3)) # [bad-builtin]
|
||||
TEST1 = filter(str, (1, 2, 3)) # [bad-builtin]
|
@@ -0,0 +1,28 @@
|
||||
# pylint: disable=literal-comparison,missing-docstring,misplaced-comparison-constant
|
||||
|
||||
X = 123
|
||||
Y = len('test')
|
||||
|
||||
if X is 0: # [compare-to-zero]
|
||||
pass
|
||||
|
||||
if Y is not 0: # [compare-to-zero]
|
||||
pass
|
||||
|
||||
if X == 0: # [compare-to-zero]
|
||||
pass
|
||||
|
||||
if Y != 0: # [compare-to-zero]
|
||||
pass
|
||||
|
||||
if X > 0:
|
||||
pass
|
||||
|
||||
if X < 0:
|
||||
pass
|
||||
|
||||
if 0 < X:
|
||||
pass
|
||||
|
||||
if 0 > X:
|
||||
pass
|
@@ -0,0 +1,40 @@
|
||||
"""Checks of Dosctrings 'docstring-first-line-empty' 'bad-docstring-quotes'"""
|
||||
|
||||
|
||||
def check_messages(*messages):
|
||||
"""
|
||||
docstring"""
|
||||
return messages
|
||||
|
||||
def function2():
|
||||
"""Test Ok"""
|
||||
|
||||
class FFFF:
|
||||
"""
|
||||
Test Docstring First Line Empty
|
||||
"""
|
||||
|
||||
def method1(self):
|
||||
'''
|
||||
Test Triple Single Quotes docstring
|
||||
'''
|
||||
|
||||
def method2(self):
|
||||
"bad docstring 1"
|
||||
|
||||
def method3(self):
|
||||
'bad docstring 2'
|
||||
|
||||
def method4(self):
|
||||
' """bad docstring 3 '
|
||||
|
||||
@check_messages('bad-open-mode', 'redundant-unittest-assert',
|
||||
'deprecated-module')
|
||||
def method5(self):
|
||||
"""Test OK 1 with decorators"""
|
||||
|
||||
def method6(self):
|
||||
r"""Test OK 2 with raw string"""
|
||||
|
||||
def method7(self):
|
||||
u"""Test OK 3 with unicode string"""
|
@@ -0,0 +1,26 @@
|
||||
"""Checks use of "else if" triggers a refactor message"""
|
||||
|
||||
def my_function():
|
||||
"""docstring"""
|
||||
myint = 2
|
||||
if myint > 5:
|
||||
pass
|
||||
else:
|
||||
if myint <= 5:
|
||||
pass
|
||||
else:
|
||||
myint = 3
|
||||
if myint > 2:
|
||||
if myint > 3:
|
||||
pass
|
||||
elif myint == 3:
|
||||
pass
|
||||
elif myint < 3:
|
||||
pass
|
||||
else:
|
||||
if myint:
|
||||
pass
|
||||
else:
|
||||
if myint:
|
||||
pass
|
||||
myint = 4
|
@@ -0,0 +1,16 @@
|
||||
# pylint: disable=literal-comparison,missing-docstring
|
||||
|
||||
X = ''
|
||||
Y = 'test'
|
||||
|
||||
if X is '': # [compare-to-empty-string]
|
||||
pass
|
||||
|
||||
if Y is not "": # [compare-to-empty-string]
|
||||
pass
|
||||
|
||||
if X == "": # [compare-to-empty-string]
|
||||
pass
|
||||
|
||||
if Y != '': # [compare-to-empty-string]
|
||||
pass
|
@@ -0,0 +1,205 @@
|
||||
"""Checks use of "too-complex" check"""
|
||||
|
||||
|
||||
def f1():
|
||||
"""McCabe rating: 1"""
|
||||
pass
|
||||
|
||||
|
||||
def f2(n):
|
||||
"""McCabe rating: 1"""
|
||||
k = n + 4
|
||||
s = k + n
|
||||
return s
|
||||
|
||||
|
||||
def f3(n):
|
||||
"""McCabe rating: 3"""
|
||||
if n > 3:
|
||||
return "bigger than three"
|
||||
elif n > 4:
|
||||
return "is never executed"
|
||||
else:
|
||||
return "smaller than or equal to three"
|
||||
|
||||
|
||||
def f4():
|
||||
"""McCabe rating: 2"""
|
||||
for i in range(10):
|
||||
print(i)
|
||||
|
||||
|
||||
def f5(mylist):
|
||||
"""McCabe rating: 2"""
|
||||
for i in mylist:
|
||||
print(i)
|
||||
else:
|
||||
print(None)
|
||||
|
||||
|
||||
def f6(n):
|
||||
"""McCabe rating: 2"""
|
||||
if n > 4:
|
||||
return f(n - 1)
|
||||
else:
|
||||
return n
|
||||
|
||||
|
||||
def f7():
|
||||
"""McCabe rating: 3"""
|
||||
def b():
|
||||
"""McCabe rating: 2"""
|
||||
def c():
|
||||
"""McCabe rating: 1"""
|
||||
pass
|
||||
c()
|
||||
b()
|
||||
|
||||
|
||||
def f8():
|
||||
"""McCabe rating: 4"""
|
||||
try:
|
||||
print(1)
|
||||
except TypeA:
|
||||
print(2)
|
||||
except TypeB:
|
||||
print(3)
|
||||
else:
|
||||
print(4)
|
||||
|
||||
|
||||
def f9():
|
||||
"""McCabe rating: 9"""
|
||||
myint = 2
|
||||
if myint > 5:
|
||||
pass
|
||||
else:
|
||||
if myint <= 5:
|
||||
pass
|
||||
else:
|
||||
myint = 3
|
||||
if myint > 2:
|
||||
if myint > 3:
|
||||
pass
|
||||
elif myint == 3:
|
||||
pass
|
||||
elif myint < 3:
|
||||
pass
|
||||
else:
|
||||
if myint:
|
||||
pass
|
||||
else:
|
||||
if myint:
|
||||
pass
|
||||
myint = 4
|
||||
|
||||
|
||||
def f10():
|
||||
"""McCabe rating: 11"""
|
||||
myint = 2
|
||||
if myint == 5:
|
||||
return myint
|
||||
elif myint == 6:
|
||||
return myint
|
||||
elif myint == 7:
|
||||
return myint
|
||||
elif myint == 8:
|
||||
return myint
|
||||
elif myint == 9:
|
||||
return myint
|
||||
elif myint == 10:
|
||||
if myint == 8:
|
||||
while True:
|
||||
return True
|
||||
elif myint == 8:
|
||||
with myint:
|
||||
return 8
|
||||
else:
|
||||
if myint == 2:
|
||||
return myint
|
||||
return myint
|
||||
return myint
|
||||
|
||||
|
||||
class MyClass1(object):
|
||||
"""Class of example to test mccabe"""
|
||||
_name = 'MyClass' # To force a tail.node=None
|
||||
|
||||
def method1():
|
||||
"""McCabe rating: 1"""
|
||||
pass
|
||||
|
||||
def method2(self, param1):
|
||||
"""McCabe rating: 18"""
|
||||
if not param1:
|
||||
pass
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
pass
|
||||
if param1:
|
||||
for value in range(5):
|
||||
pass
|
||||
|
||||
pass
|
||||
for count in range(6):
|
||||
with open('myfile') as fp:
|
||||
count += 1
|
||||
pass
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
if not param1:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
if param1:
|
||||
raise BaseException('Error')
|
||||
with open('myfile2') as fp2:
|
||||
pass
|
||||
pass
|
||||
finally:
|
||||
if param1 is not None:
|
||||
pass
|
||||
for count2 in range(8):
|
||||
try:
|
||||
pass
|
||||
except BaseException('Error2'):
|
||||
pass
|
||||
return param1
|
||||
|
||||
|
||||
for count in range(10):
|
||||
if count == 1:
|
||||
exit(0)
|
||||
elif count == 2:
|
||||
exit(1)
|
||||
else:
|
||||
exit(2)
|
||||
|
||||
|
||||
def method3(self):
|
||||
try:
|
||||
if True:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
return True
|
@@ -0,0 +1,45 @@
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
class SomeException(Exception):
|
||||
pass
|
||||
|
||||
class SubclassException(SomeException):
|
||||
pass
|
||||
|
||||
AliasException = SomeException
|
||||
|
||||
try:
|
||||
pass
|
||||
except (SomeException, SomeException): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (SomeException, SubclassException): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (SomeException, AliasException): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (AliasException, SubclassException): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
# +1:[overlapping-except, overlapping-except, overlapping-except]
|
||||
except (SomeException, AliasException, SubclassException):
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ArithmeticError, FloatingPointError): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, UnicodeDecodeError): # [overlapping-except]
|
||||
pass
|
@@ -0,0 +1,18 @@
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
import socket
|
||||
|
||||
try:
|
||||
pass
|
||||
except (IOError, OSError): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (socket.error, OSError): # [overlapping-except]
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ConnectionError, socket.error): # [overlapping-except]
|
||||
pass
|
@@ -0,0 +1,85 @@
|
||||
"""Checks variable types aren't redefined within a method or a function"""
|
||||
|
||||
# pylint: disable=too-few-public-methods,missing-docstring,unused-variable,invalid-name, useless-object-inheritance
|
||||
|
||||
_OK = True
|
||||
|
||||
class MyClass(object):
|
||||
|
||||
class Klass(object):
|
||||
def __init__(self):
|
||||
self.var2 = 'var'
|
||||
|
||||
def __init__(self):
|
||||
self.var = True
|
||||
self.var1 = 2
|
||||
self.var2 = 1.
|
||||
self.var1 = 2. # [redefined-variable-type]
|
||||
self.a_str = "hello"
|
||||
a_str = False
|
||||
(a_str, b_str) = (1, 2) # no support for inference on tuple assignment
|
||||
a_str = 2.0 if self.var else 1.0 # no support for inference on ifexpr
|
||||
|
||||
def _getter(self):
|
||||
return self.a_str
|
||||
def _setter(self, val):
|
||||
self.a_str = val
|
||||
var2 = property(_getter, _setter)
|
||||
|
||||
def some_method(self):
|
||||
def func():
|
||||
var = 1
|
||||
test = 'bar'
|
||||
var = 'baz' # [redefined-variable-type]
|
||||
self.var = 1 # the rule checks for redefinitions in the scope of a function or method
|
||||
test = 'foo'
|
||||
myint = 2
|
||||
myint = False # [redefined-variable-type]
|
||||
|
||||
_OK = "This is OK" # [redefined-variable-type]
|
||||
|
||||
if _OK:
|
||||
SOME_FLOAT = 1.
|
||||
|
||||
def dummy_function():
|
||||
return 2
|
||||
|
||||
def other_function():
|
||||
instance = MyClass()
|
||||
instance = True # [redefined-variable-type]
|
||||
|
||||
SOME_FLOAT = dummy_function() # [redefined-variable-type]
|
||||
|
||||
A_GLOB = None
|
||||
A_GLOB = [1, 2, 3]
|
||||
|
||||
def func2(x):
|
||||
if x:
|
||||
var = 'foo'
|
||||
else:
|
||||
var = True
|
||||
|
||||
if x:
|
||||
var2 = 'foo'
|
||||
elif not x:
|
||||
var2 = 2
|
||||
else:
|
||||
pass
|
||||
|
||||
if x:
|
||||
var3 = 'foo'
|
||||
var3 = 2 # [redefined-variable-type]
|
||||
else:
|
||||
pass
|
||||
|
||||
var = 2 # [redefined-variable-type]
|
||||
|
||||
if x:
|
||||
pass
|
||||
elif not x:
|
||||
var4 = True
|
||||
elif _OK:
|
||||
pass
|
||||
else:
|
||||
var4 = 2.
|
||||
var4 = 'baz' # [redefined-variable-type]
|
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.bad_builtin
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
|
||||
import pytest
|
||||
|
||||
from pylint.extensions.bad_builtin import BadBuiltinChecker
|
||||
from pylint.lint import fix_import_path
|
||||
|
||||
|
||||
EXPECTED = [
|
||||
"Used builtin function 'map'. Using a list comprehension can be clearer.",
|
||||
"Used builtin function 'filter'. Using a list comprehension can be clearer.",
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def checker(checker):
|
||||
return BadBuiltinChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def disable(disable):
|
||||
return ['I']
|
||||
|
||||
|
||||
def test_types_redefined(linter):
|
||||
elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'bad_builtin.py')
|
||||
with fix_import_path([elif_test]):
|
||||
linter.check([elif_test])
|
||||
msgs = sorted(linter.reporter.messages, key=lambda item: item.line)
|
||||
assert len(msgs) == 2
|
||||
for msg, expected in zip(msgs, EXPECTED):
|
||||
assert msg.symbol == 'bad-builtin'
|
||||
assert msg.msg == expected
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
|
||||
# Copyright (c) 2016 Ashley Whetter <ashley@awhetter.co.uk>
|
||||
# Copyright (c) 2018 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/COPYING
|
||||
|
||||
"""Unit tests for the pylint checkers in :mod:`pylint.extensions.check_docs`,
|
||||
in particular the parameter documentation checker `DocstringChecker`
|
||||
"""
|
||||
from __future__ import division, print_function, absolute_import
|
||||
|
||||
import pytest
|
||||
|
||||
import astroid
|
||||
|
||||
import pylint.extensions._check_docs_utils as utils
|
||||
|
||||
|
||||
@pytest.mark.parametrize("string,count", [
|
||||
('abc', 0),
|
||||
('', 0),
|
||||
(' abc', 2),
|
||||
('\n abc', 0),
|
||||
(' \n abc', 3),
|
||||
])
|
||||
def test_space_indentation(string, count):
|
||||
"""Test for pylint_plugin.ParamDocChecker"""
|
||||
assert utils.space_indentation(string) == count
|
||||
|
||||
|
||||
@pytest.mark.parametrize("raise_node,expected", [
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
raise NotImplementedError #@
|
||||
'''), {"NotImplementedError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
raise NotImplementedError("Not implemented!") #@
|
||||
'''), {"NotImplementedError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except RuntimeError:
|
||||
raise #@
|
||||
'''), {"RuntimeError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except RuntimeError:
|
||||
if another_func():
|
||||
raise #@
|
||||
'''), {"RuntimeError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except RuntimeError:
|
||||
try:
|
||||
another_func()
|
||||
raise #@
|
||||
except NameError:
|
||||
pass
|
||||
'''), {"RuntimeError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except RuntimeError:
|
||||
try:
|
||||
another_func()
|
||||
except NameError:
|
||||
raise #@
|
||||
'''), {"NameError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except:
|
||||
raise #@
|
||||
'''), set()),
|
||||
|
||||
(astroid.extract_node('''
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except (RuntimeError, ValueError):
|
||||
raise #@
|
||||
'''), {"RuntimeError", "ValueError"}),
|
||||
|
||||
(astroid.extract_node('''
|
||||
import not_a_module
|
||||
def my_func():
|
||||
try:
|
||||
fake_func()
|
||||
except not_a_module.Error:
|
||||
raise #@
|
||||
'''), set()),
|
||||
|
||||
])
|
||||
def test_exception(raise_node, expected):
|
||||
found = utils.possible_exc_types(raise_node)
|
||||
assert found == expected
|
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com>
|
||||
# Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.check_mccabe
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
|
||||
import pytest
|
||||
|
||||
from pylint.extensions import mccabe
|
||||
|
||||
EXPECTED_MSGS = [
|
||||
"'f1' is too complex. The McCabe rating is 1",
|
||||
"'f2' is too complex. The McCabe rating is 1",
|
||||
"'f3' is too complex. The McCabe rating is 3",
|
||||
"'f4' is too complex. The McCabe rating is 2",
|
||||
"'f5' is too complex. The McCabe rating is 2",
|
||||
"'f6' is too complex. The McCabe rating is 2",
|
||||
"'f7' is too complex. The McCabe rating is 3",
|
||||
"'f8' is too complex. The McCabe rating is 4",
|
||||
"'f9' is too complex. The McCabe rating is 9",
|
||||
"'method1' is too complex. The McCabe rating is 1",
|
||||
"This 'for' is too complex. The McCabe rating is 4",
|
||||
"'method3' is too complex. The McCabe rating is 2",
|
||||
"'f10' is too complex. The McCabe rating is 11",
|
||||
"'method2' is too complex. The McCabe rating is 18",
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def enable(enable):
|
||||
return ['too-complex']
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def disable(disable):
|
||||
return ['all']
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def register(register):
|
||||
return mccabe.register
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fname_mccabe_example():
|
||||
return osp.join(osp.dirname(osp.abspath(__file__)), 'data', 'mccabe.py')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("complexity, expected", [
|
||||
(0, EXPECTED_MSGS),
|
||||
(9, EXPECTED_MSGS[-2:]),
|
||||
])
|
||||
def test_max_mccabe_rate(linter, fname_mccabe_example, complexity, expected):
|
||||
linter.global_set_option('max-complexity', complexity)
|
||||
linter.check([fname_mccabe_example])
|
||||
real_msgs = [message.msg for message in linter.reporter.messages]
|
||||
assert sorted(expected) == sorted(real_msgs)
|
@@ -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 division, print_function, absolute_import
|
||||
|
||||
import astroid
|
||||
from pylint.testutils import CheckerTestCase, Message, set_config
|
||||
|
||||
from pylint.extensions.docparams import DocstringParameterChecker
|
||||
|
||||
|
||||
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)
|
@@ -0,0 +1,600 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 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) 2016 Moises Lopez <moylop260@vauxoo.com>
|
||||
# Copyright (c) 2018 Sushobhit <31987769+sushobhit27@users.noreply.github.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 return documentation checking in the
|
||||
`DocstringChecker` in :mod:`pylint.extensions.check_docs`
|
||||
"""
|
||||
from __future__ import division, print_function, absolute_import
|
||||
|
||||
import astroid
|
||||
from pylint.testutils import CheckerTestCase, Message, set_config
|
||||
|
||||
from pylint.extensions.docparams import DocstringParameterChecker
|
||||
|
||||
|
||||
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_returns_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_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_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)
|
@@ -0,0 +1,397 @@
|
||||
# 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>
|
||||
|
||||
# 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 yield documentation checking in the
|
||||
`DocstringChecker` in :mod:`pylint.extensions.check_docs`
|
||||
"""
|
||||
from __future__ import division, print_function, absolute_import
|
||||
|
||||
import astroid
|
||||
from pylint.testutils import CheckerTestCase, Message, set_config
|
||||
|
||||
from pylint.extensions.docparams import DocstringParameterChecker
|
||||
|
||||
|
||||
class TestDocstringCheckerYield(CheckerTestCase):
|
||||
"""Tests for pylint_plugin.RaiseDocChecker"""
|
||||
CHECKER_CLASS = DocstringParameterChecker
|
||||
|
||||
def test_ignores_no_docstring(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
yield False #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
@set_config(accept_no_yields_doc=False)
|
||||
def test_warns_no_docstring(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring."""
|
||||
yield False #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_warn_partial_sphinx_yields(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:returns: Always False
|
||||
"""
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
Message(msg_id='missing-yield-type-doc', node=node)):
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_warn_partial_sphinx_yields_type(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:rtype: 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_sphinx_yields(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self, doc_type):
|
||||
"""This is a docstring.
|
||||
|
||||
:param doc_type: Sphinx
|
||||
:type doc_type: str
|
||||
"""
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
Always False
|
||||
"""
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self, doc_type):
|
||||
"""This is a docstring.
|
||||
|
||||
Parameters:
|
||||
doc_type (str): Google
|
||||
"""
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self, doc_type):
|
||||
"""This is a docstring.
|
||||
|
||||
Arguments
|
||||
---------
|
||||
doc_type : str
|
||||
Numpy
|
||||
"""
|
||||
yield False
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:return: Always False
|
||||
:rtype: bool
|
||||
"""
|
||||
yield False #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_find_google_yields(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
bool: Always False
|
||||
"""
|
||||
yield False #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_find_numpy_yields(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
bool
|
||||
Always False
|
||||
"""
|
||||
yield False #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_sphinx_yield_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:returns: An object
|
||||
:rtype: :class:`mymodule.Class`
|
||||
"""
|
||||
yield mymodule.Class() #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_google_yield_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
mymodule.Class: An object
|
||||
"""
|
||||
yield mymodule.Class() #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_numpy_yield_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
mymodule.Class
|
||||
An object
|
||||
"""
|
||||
yield mymodule.Class() #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_sphinx_yield_list_of_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:returns: An object
|
||||
:rtype: list(:class:`mymodule.Class`)
|
||||
"""
|
||||
yield [mymodule.Class()] #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_google_yield_list_of_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
list(:class:`mymodule.Class`): An object
|
||||
"""
|
||||
yield [mymodule.Class()] #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_finds_numpy_yield_list_of_custom_class(self):
|
||||
yield_node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
list(:class:`mymodule.Class`)
|
||||
An object
|
||||
"""
|
||||
yield [mymodule.Class()] #@
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_yield(yield_node)
|
||||
|
||||
def test_warns_sphinx_yield_list_of_custom_class_without_description(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
:rtype: list(:class:`mymodule.Class`)
|
||||
"""
|
||||
yield [mymodule.Class()]
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
list(:class:`mymodule.Class`):
|
||||
"""
|
||||
yield [mymodule.Class()]
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
list(:class:`mymodule.Class`)
|
||||
"""
|
||||
yield [mymodule.Class()]
|
||||
''')
|
||||
yield_node = node.body[0]
|
||||
with self.assertAddsMessages(
|
||||
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
|
||||
# doesn't support yield documentation
|
||||
|
||||
def test_ignores_google_redundant_yield_doc_multiple_yields(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
int or None: One, or sometimes None.
|
||||
"""
|
||||
if a_func():
|
||||
yield None
|
||||
yield 1
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_functiondef(node)
|
||||
|
||||
def test_ignores_numpy_redundant_yield_doc_multiple_yields(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
int
|
||||
One
|
||||
None
|
||||
Sometimes
|
||||
"""
|
||||
if a_func():
|
||||
yield None
|
||||
yield 1
|
||||
''')
|
||||
with self.assertNoMessages():
|
||||
self.checker.visit_functiondef(node)
|
||||
|
||||
# No such thing as redundant yield documentation for sphinx because it
|
||||
# doesn't support yield documentation
|
||||
|
||||
def test_warns_google_redundant_yield_doc_return(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields:
|
||||
int: One
|
||||
"""
|
||||
return 1
|
||||
''')
|
||||
with self.assertAddsMessages(
|
||||
Message(msg_id='redundant-yields-doc', node=node)):
|
||||
self.checker.visit_functiondef(node)
|
||||
|
||||
def test_warns_numpy_redundant_yield_doc_return(self):
|
||||
node = astroid.extract_node('''
|
||||
def my_func(self):
|
||||
"""This is a docstring.
|
||||
|
||||
Yields
|
||||
-------
|
||||
int
|
||||
One
|
||||
"""
|
||||
return 1
|
||||
''')
|
||||
with self.assertAddsMessages(
|
||||
Message(msg_id='redundant-yields-doc', node=node)):
|
||||
self.checker.visit_functiondef(node)
|
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2016 Alexander Todorov <atodorov@otb.bg>
|
||||
# Copyright (c) 2016 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||
# Copyright (c) 2017 Claudiu Popa <pcmanticore@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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.emptystring
|
||||
"""
|
||||
|
||||
import os
|
||||
import os.path as osp
|
||||
import unittest
|
||||
|
||||
from pylint import checkers
|
||||
from pylint.extensions.comparetozero import CompareToZeroChecker
|
||||
from pylint.lint import PyLinter
|
||||
from pylint.reporters import BaseReporter
|
||||
|
||||
|
||||
class CompareToZeroTestReporter(BaseReporter):
|
||||
|
||||
def handle_message(self, msg):
|
||||
self.messages.append(msg)
|
||||
|
||||
def on_set_current_module(self, module, filepath):
|
||||
self.messages = []
|
||||
|
||||
|
||||
class CompareToZeroUsedTC(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls._linter = PyLinter()
|
||||
cls._linter.set_reporter(CompareToZeroTestReporter())
|
||||
checkers.initialize(cls._linter)
|
||||
cls._linter.register_checker(CompareToZeroChecker(cls._linter))
|
||||
cls._linter.disable('I')
|
||||
|
||||
def test_comparetozero_message(self):
|
||||
elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'compare_to_zero.py')
|
||||
self._linter.check([elif_test])
|
||||
msgs = self._linter.reporter.messages
|
||||
self.assertEqual(len(msgs), 4)
|
||||
for msg in msgs:
|
||||
self.assertEqual(msg.symbol, 'compare-to-zero')
|
||||
self.assertEqual(msg.msg, 'Avoid comparisons to zero')
|
||||
self.assertEqual(msgs[0].line, 6)
|
||||
self.assertEqual(msgs[1].line, 9)
|
||||
self.assertEqual(msgs[2].line, 12)
|
||||
self.assertEqual(msgs[3].line, 15)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@@ -0,0 +1,54 @@
|
||||
# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com>
|
||||
# Copyright (c) 2016 Luis Escobar <lescobar@vauxoo.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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.check_docstring
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
|
||||
import pytest
|
||||
|
||||
from pylint.extensions.docstyle import DocStringStyleChecker
|
||||
|
||||
|
||||
EXPECTED_MSGS = [
|
||||
'First line empty in function docstring',
|
||||
'First line empty in class docstring',
|
||||
'First line empty in method docstring',
|
||||
'Bad docstring quotes in method, expected """, given \'\'\'',
|
||||
'Bad docstring quotes in method, expected """, given "',
|
||||
'Bad docstring quotes in method, expected """, given \'',
|
||||
'Bad docstring quotes in method, expected """, given \'',
|
||||
]
|
||||
|
||||
EXPECTED_SYMBOLS = [
|
||||
'docstring-first-line-empty',
|
||||
'docstring-first-line-empty',
|
||||
'docstring-first-line-empty',
|
||||
'bad-docstring-quotes',
|
||||
'bad-docstring-quotes',
|
||||
'bad-docstring-quotes',
|
||||
'bad-docstring-quotes',
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def checker(checker):
|
||||
return DocStringStyleChecker
|
||||
|
||||
|
||||
def test_docstring_message(linter):
|
||||
docstring_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'docstring.py')
|
||||
linter.check([docstring_test])
|
||||
msgs = linter.reporter.messages
|
||||
assert len(msgs) == 7
|
||||
for msg, expected_symbol, expected_msg in zip(msgs,
|
||||
EXPECTED_SYMBOLS,
|
||||
EXPECTED_MSGS):
|
||||
assert msg.symbol == expected_symbol
|
||||
assert msg.msg == expected_msg
|
@@ -0,0 +1,33 @@
|
||||
# Copyright (c) 2015-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.check_elif
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
|
||||
import pytest
|
||||
|
||||
from pylint.extensions.check_elif import ElseifUsedChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def checker(checker):
|
||||
return ElseifUsedChecker
|
||||
|
||||
|
||||
def test_elseif_message(linter):
|
||||
elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'elif.py')
|
||||
linter.check([elif_test])
|
||||
msgs = linter.reporter.messages
|
||||
assert len(msgs) == 2
|
||||
for msg in msgs:
|
||||
assert msg.symbol == 'else-if-used'
|
||||
assert msg.msg == 'Consider using "elif" instead of "else if"'
|
||||
assert msgs[0].line == 9
|
||||
assert msgs[1].line == 21
|
@@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2016 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||
# Copyright (c) 2016 Alexander Todorov <atodorov@otb.bg>
|
||||
# Copyright (c) 2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2017 Derek Gustafson <degustaf@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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.emptystring
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
import pytest
|
||||
|
||||
from pylint.extensions.emptystring import CompareToEmptyStringChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def checker(checker):
|
||||
return CompareToEmptyStringChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def disable(disable):
|
||||
return ['I']
|
||||
|
||||
|
||||
def test_emptystring_message(linter):
|
||||
elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'empty_string_comparison.py')
|
||||
linter.check([elif_test])
|
||||
msgs = linter.reporter.messages
|
||||
expected_lineno = [6, 9, 12, 15]
|
||||
assert len(msgs) == len(expected_lineno)
|
||||
for msg, lineno in zip(msgs, expected_lineno):
|
||||
assert msg.symbol == 'compare-to-empty-string'
|
||||
assert msg.msg == 'Avoid comparisons to empty string'
|
||||
assert msg.line == lineno
|
@@ -0,0 +1,69 @@
|
||||
# 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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.overlapping_exceptions
|
||||
"""
|
||||
|
||||
from sys import version_info
|
||||
from os.path import join, dirname
|
||||
|
||||
from pylint.extensions.overlapping_exceptions import OverlappingExceptionsChecker
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def checker(checker):
|
||||
return OverlappingExceptionsChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def disable(disable):
|
||||
return ['I']
|
||||
|
||||
|
||||
def test_overlapping_exceptions(linter):
|
||||
test = join(dirname(__file__), 'data', 'overlapping_exceptions.py')
|
||||
linter.check([test])
|
||||
msgs = linter.reporter.messages
|
||||
|
||||
expected = [
|
||||
(13, 'Overlapping exceptions (SomeException and SomeException are the same)'),
|
||||
(18, 'Overlapping exceptions (SomeException is an ancestor class of SubclassException)'),
|
||||
(23, 'Overlapping exceptions (SomeException and AliasException are the same)'),
|
||||
(28, 'Overlapping exceptions (AliasException is an ancestor class of SubclassException)'),
|
||||
(34, 'Overlapping exceptions (SomeException and AliasException are the same)'),
|
||||
(34, 'Overlapping exceptions (SomeException is an ancestor class of SubclassException)'),
|
||||
(34, 'Overlapping exceptions (AliasException is an ancestor class of SubclassException)'),
|
||||
(39, 'Overlapping exceptions (ArithmeticError is an ancestor class of FloatingPointError)'),
|
||||
(44, 'Overlapping exceptions (ValueError is an ancestor class of UnicodeDecodeError)')
|
||||
]
|
||||
|
||||
assert len(msgs) == len(expected)
|
||||
for msg, exp in zip(msgs, expected):
|
||||
assert msg.msg_id == 'W0714'
|
||||
assert msg.symbol == 'overlapping-except'
|
||||
assert msg.category == 'warning'
|
||||
assert (msg.line, msg.msg) == exp
|
||||
|
||||
|
||||
@pytest.mark.skipif(version_info < (3, 3),
|
||||
reason="not relevant to Python version")
|
||||
def test_overlapping_exceptions_py33(linter):
|
||||
"""From Python 3.3 both IOError and socket.error are aliases for OSError."""
|
||||
test = join(dirname(__file__), 'data', 'overlapping_exceptions_py33.py')
|
||||
linter.check([test])
|
||||
msgs = linter.reporter.messages
|
||||
|
||||
expected = [
|
||||
(7, 'Overlapping exceptions (IOError and OSError are the same)'),
|
||||
(12, 'Overlapping exceptions (socket.error and OSError are the same)'),
|
||||
(17, 'Overlapping exceptions (socket.error is an ancestor class of ConnectionError)'),
|
||||
]
|
||||
|
||||
assert len(msgs) == len(expected)
|
||||
for msg, exp in zip(msgs, expected):
|
||||
assert msg.msg_id == 'W0714'
|
||||
assert msg.symbol == 'overlapping-except'
|
||||
assert msg.category == 'warning'
|
||||
assert (msg.line, msg.msg) == exp
|
@@ -0,0 +1,50 @@
|
||||
# Copyright (c) 2016-2017 Claudiu Popa <pcmanticore@gmail.com>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@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
|
||||
|
||||
"""Tests for the pylint checker in :mod:`pylint.extensions.check_elif
|
||||
"""
|
||||
|
||||
import os.path as osp
|
||||
|
||||
import pytest
|
||||
|
||||
from pylint.extensions.redefined_variable_type import MultipleTypesChecker
|
||||
from pylint.lint import fix_import_path
|
||||
|
||||
|
||||
EXPECTED = [
|
||||
'Redefinition of self.var1 type from int to float',
|
||||
'Redefinition of var type from int to str',
|
||||
'Redefinition of myint type from int to bool',
|
||||
'Redefinition of _OK type from bool to str',
|
||||
'Redefinition of instance type from redefined.MyClass to bool',
|
||||
'Redefinition of SOME_FLOAT type from float to int',
|
||||
'Redefinition of var3 type from str to int',
|
||||
'Redefinition of var type from bool to int',
|
||||
'Redefinition of var4 type from float to str',
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def checker(checker):
|
||||
return MultipleTypesChecker
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def disable(disable):
|
||||
return ['I']
|
||||
|
||||
|
||||
def test_types_redefined(linter):
|
||||
elif_test = osp.join(osp.dirname(osp.abspath(__file__)), 'data',
|
||||
'redefined.py')
|
||||
with fix_import_path([elif_test]):
|
||||
linter.check([elif_test])
|
||||
msgs = sorted(linter.reporter.messages, key=lambda item: item.line)
|
||||
assert len(msgs) == 9
|
||||
for msg, expected in zip(msgs, EXPECTED):
|
||||
assert msg.symbol == 'redefined-variable-type'
|
||||
assert msg.msg == expected
|
Reference in New Issue
Block a user