Initial commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
# 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
|
||||
|
||||
import contextlib
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
import pylint.lint
|
||||
|
||||
|
||||
def is_module(filename):
|
||||
return filename.endswith(".py")
|
||||
|
||||
|
||||
def is_package(filename, location):
|
||||
return os.path.exists(os.path.join(location, filename, "__init__.py"))
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _patch_stdout(out):
|
||||
sys.stdout = out
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
|
||||
|
||||
LIB_DIRS = [os.path.dirname(os.__file__)]
|
||||
MODULES_TO_CHECK = [
|
||||
(location, module)
|
||||
for location in LIB_DIRS
|
||||
for module in os.listdir(location)
|
||||
if is_module(module) or is_package(module, location)
|
||||
]
|
||||
MODULES_NAMES = [m[1] for m in MODULES_TO_CHECK]
|
||||
|
||||
|
||||
@pytest.mark.acceptance
|
||||
@pytest.mark.parametrize(
|
||||
("test_module_location", "test_module_name"), MODULES_TO_CHECK, ids=MODULES_NAMES
|
||||
)
|
||||
def test_libmodule(test_module_location, test_module_name):
|
||||
os.chdir(test_module_location)
|
||||
with _patch_stdout(io.StringIO()):
|
||||
try:
|
||||
pylint.lint.Run([test_module_name, "--enable=all", "--ignore=test"])
|
||||
except SystemExit as ex:
|
||||
assert ex.code != 32
|
||||
return
|
||||
|
||||
assert False, "shouldn't get there"
|
||||
@@ -0,0 +1,53 @@
|
||||
# pylint: disable=redefined-outer-name
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from pylint import checkers
|
||||
from pylint.lint import PyLinter
|
||||
|
||||
# pylint: disable=no-name-in-module
|
||||
from pylint.testutils import MinimalTestReporter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def linter(checker, register, enable, disable, reporter):
|
||||
_linter = PyLinter()
|
||||
_linter.set_reporter(reporter())
|
||||
checkers.initialize(_linter)
|
||||
if register:
|
||||
register(_linter)
|
||||
if checker:
|
||||
_linter.register_checker(checker(_linter))
|
||||
if disable:
|
||||
for msg in disable:
|
||||
_linter.disable(msg)
|
||||
if enable:
|
||||
for msg in enable:
|
||||
_linter.enable(msg)
|
||||
os.environ.pop("PYLINTRC", None)
|
||||
return _linter
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def checker():
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def register():
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def enable():
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def disable():
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def reporter():
|
||||
return MinimalTestReporter
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/python
|
||||
"""ttttttttttttttttttttoooooooooooooooooooooooooooooooooooooooooooooooooooooo lllllllllllooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnngggggggggggggggggg"""
|
||||
@@ -0,0 +1,12 @@
|
||||
digraph "classes_No_Name" {
|
||||
charset="utf-8"
|
||||
rankdir=BT
|
||||
"0" [label="{Ancestor|attr : str\lcls_member\l|get_value()\lset_value()\l}", shape="record"];
|
||||
"1" [label="{DoNothing|\l|}", shape="record"];
|
||||
"2" [label="{Interface|\l|get_value()\lset_value()\l}", shape="record"];
|
||||
"3" [label="{Specialization|TYPE : str\lrelation\ltop : str\l|}", shape="record"];
|
||||
"3" -> "0" [arrowhead="empty", arrowtail="none"];
|
||||
"0" -> "2" [arrowhead="empty", arrowtail="node", style="dashed"];
|
||||
"1" -> "0" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="cls_member", style="solid"];
|
||||
"1" -> "3" [arrowhead="diamond", arrowtail="none", fontcolor="green", label="relation", style="solid"];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
""" docstring for file clientmodule.py """
|
||||
from data.suppliermodule_test import Interface, DoNothing
|
||||
|
||||
class Ancestor:
|
||||
""" Ancestor method """
|
||||
__implements__ = (Interface,)
|
||||
cls_member = DoNothing()
|
||||
|
||||
def __init__(self, value):
|
||||
local_variable = 0
|
||||
self.attr = 'this method shouldn\'t have a docstring'
|
||||
self.__value = value
|
||||
|
||||
def get_value(self):
|
||||
""" nice docstring ;-) """
|
||||
return self.__value
|
||||
|
||||
def set_value(self, value):
|
||||
self.__value = value
|
||||
return 'this method shouldn\'t have a docstring'
|
||||
|
||||
class Specialization(Ancestor):
|
||||
TYPE = 'final class'
|
||||
top = 'class'
|
||||
|
||||
def __init__(self, value, _id):
|
||||
Ancestor.__init__(self, value)
|
||||
self._id = _id
|
||||
self.relation = DoNothing()
|
||||
@@ -0,0 +1,8 @@
|
||||
digraph "packages_No_Name" {
|
||||
charset="utf-8"
|
||||
rankdir=BT
|
||||
"0" [label="data", shape="box"];
|
||||
"1" [label="data.clientmodule_test", shape="box"];
|
||||
"2" [label="data.suppliermodule_test", shape="box"];
|
||||
"1" -> "2" [arrowhead="open", arrowtail="none"];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""" file suppliermodule.py """
|
||||
|
||||
class Interface:
|
||||
def get_value(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_value(self, value):
|
||||
raise NotImplementedError
|
||||
|
||||
class DoNothing: pass
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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
|
||||
+16
@@ -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
|
||||
+45
@@ -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
|
||||
+18
@@ -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 <[email protected]>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Ashley Whetter <[email protected]>
|
||||
# Copyright (c) 2018 Anthony Sottile <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Moises Lopez <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Glenn Matthews <[email protected]>
|
||||
# Copyright (c) 2016 Ashley Whetter <[email protected]>
|
||||
# Copyright (c) 2018 Adam Dangoor <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Glenn Matthews <[email protected]>
|
||||
# Copyright (c) 2016 Ashley Whetter <[email protected]>
|
||||
# Copyright (c) 2016 Moises Lopez <[email protected]>
|
||||
# Copyright (c) 2018 Sushobhit <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Glenn Matthews <[email protected]>
|
||||
# Copyright (c) 2016 Ashley Whetter <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Łukasz Rogalski <[email protected]>
|
||||
# Copyright (c) 2017 Claudiu Popa <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <[email protected]>
|
||||
# Copyright (c) 2016 Luis Escobar <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2015 LOGILAB S.A. (Paris, FRANCE) <[email protected]>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <[email protected]>
|
||||
|
||||
# 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 <[email protected]>
|
||||
# Copyright (c) 2016 Alexander Todorov <[email protected]>
|
||||
# Copyright (c) 2017 Claudiu Popa <[email protected]>
|
||||
# Copyright (c) 2017 Derek Gustafson <[email protected]>
|
||||
|
||||
# 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
|
||||
+69
@@ -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 <[email protected]>
|
||||
# Copyright (c) 2016-2017 Derek Gustafson <[email protected]>
|
||||
|
||||
# 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
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user