8th day of python challenges 111-117

This commit is contained in:
abd.shallal
2019-08-04 15:26:35 +03:00
parent b04c1b055f
commit 627802c383
3215 changed files with 760227 additions and 491 deletions

View File

@@ -0,0 +1,4 @@
# pylint: disable=missing-docstring
TEST = map(str, (1, 2, 3)) # [bad-builtin]
TEST1 = filter(str, (1, 2, 3)) # [bad-builtin]

View File

@@ -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

View File

@@ -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"""

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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