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

View File

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

View File

@@ -0,0 +1,2 @@
#!/usr/bin/python
"""ttttttttttttttttttttoooooooooooooooooooooooooooooooooooooooooooooooooooooo lllllllllllooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnngggggggggggggggggg"""

View File

@@ -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"];
}

View File

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

View File

@@ -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"];
}

View File

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

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

View File

@@ -0,0 +1,17 @@
""" This should not warn about `prop` being abstract in Child """
# pylint: disable=too-few-public-methods, no-absolute-import,metaclass-assignment, useless-object-inheritance
import abc
class Parent(object):
"""Abstract Base Class """
__metaclass__ = abc.ABCMeta
@property
@abc.abstractmethod
def prop(self):
""" Abstract """
class Child(Parent):
""" No warning for the following. """
prop = property(lambda self: 1)

View File

@@ -0,0 +1,20 @@
"""Don't warn if the class is instantiated in its own body."""
# pylint: disable=missing-docstring, useless-object-inheritance
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class Ala(object):
@abc.abstractmethod
def bala(self):
pass
@classmethod
def portocala(cls):
instance = cls()
return instance

View File

@@ -0,0 +1,82 @@
"""Check that instantiating a class with
`abc.ABCMeta` as metaclass fails if it defines
abstract methods.
"""
# pylint: disable=too-few-public-methods, missing-docstring, useless-object-inheritance
# pylint: disable=no-absolute-import, metaclass-assignment
# pylint: disable=abstract-method, import-error, wildcard-import
import abc
from abc import ABCMeta
from lala import Bala
class GoodClass(object):
__metaclass__ = abc.ABCMeta
class SecondGoodClass(object):
__metaclass__ = abc.ABCMeta
def test(self):
""" do nothing. """
class ThirdGoodClass(object):
__metaclass__ = abc.ABCMeta
def test(self):
raise NotImplementedError()
class FourthGoodClass(object):
__metaclass__ = ABCMeta
class BadClass(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def test(self):
""" do nothing. """
class SecondBadClass(object):
__metaclass__ = abc.ABCMeta
@property
@abc.abstractmethod
def test(self):
""" do nothing. """
class ThirdBadClass(object):
__metaclass__ = ABCMeta
@abc.abstractmethod
def test(self):
pass
class FourthBadClass(ThirdBadClass):
pass
class SomeMetaclass(object):
__metaclass__ = ABCMeta
@abc.abstractmethod
def prop(self):
pass
class FifthGoodClass(SomeMetaclass):
"""Don't consider this abstract if some attributes are
there, but can't be inferred.
"""
prop = Bala # missing
def main():
""" do nothing """
GoodClass()
SecondGoodClass()
ThirdGoodClass()
FourthGoodClass()
BadClass() # [abstract-class-instantiated]
SecondBadClass() # [abstract-class-instantiated]
ThirdBadClass() # [abstract-class-instantiated]
FourthBadClass() # [abstract-class-instantiated]

View File

@@ -0,0 +1,2 @@
[testoptions]
max_pyver=3.0

View File

@@ -0,0 +1,4 @@
abstract-class-instantiated:79:main:Abstract class 'BadClass' with abstract methods instantiated
abstract-class-instantiated:80:main:Abstract class 'SecondBadClass' with abstract methods instantiated
abstract-class-instantiated:81:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
abstract-class-instantiated:82:main:Abstract class 'FourthBadClass' with abstract methods instantiated

View File

@@ -0,0 +1,128 @@
"""Check that instantiating a class with
`abc.ABCMeta` as metaclass fails if it defines
abstract methods.
"""
# pylint: disable=too-few-public-methods, missing-docstring
# pylint: disable=abstract-method, import-error, useless-object-inheritance
import abc
import weakref
from lala import Bala
class GoodClass(object, metaclass=abc.ABCMeta):
pass
class SecondGoodClass(object, metaclass=abc.ABCMeta):
def test(self):
""" do nothing. """
class ThirdGoodClass(object, metaclass=abc.ABCMeta):
""" This should not raise the warning. """
def test(self):
raise NotImplementedError()
class BadClass(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def test(self):
""" do nothing. """
class SecondBadClass(object, metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def test(self):
""" do nothing. """
class ThirdBadClass(SecondBadClass):
pass
class Structure(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def __iter__(self):
pass
@abc.abstractmethod
def __len__(self):
pass
@abc.abstractmethod
def __contains__(self, _):
pass
@abc.abstractmethod
def __hash__(self):
pass
class Container(Structure):
def __contains__(self, _):
pass
class Sizable(Structure):
def __len__(self):
pass
class Hashable(Structure):
__hash__ = 42
class Iterator(Structure):
def keys(self): # pylint: disable=no-self-use
return iter([1, 2, 3])
__iter__ = keys
class AbstractSizable(Structure):
@abc.abstractmethod
def length(self):
pass
__len__ = length
class NoMroAbstractMethods(Container, Iterator, Sizable, Hashable):
pass
class BadMroAbstractMethods(Container, Iterator, AbstractSizable):
pass
class SomeMetaclass(metaclass=abc.ABCMeta):
@abc.abstractmethod
def prop(self):
pass
class FourthGoodClass(SomeMetaclass):
"""Don't consider this abstract if some attributes are
there, but can't be inferred.
"""
prop = Bala # missing
def main():
""" do nothing """
GoodClass()
SecondGoodClass()
ThirdGoodClass()
FourthGoodClass()
weakref.WeakKeyDictionary()
weakref.WeakValueDictionary()
NoMroAbstractMethods()
BadMroAbstractMethods() # [abstract-class-instantiated]
BadClass() # [abstract-class-instantiated]
SecondBadClass() # [abstract-class-instantiated]
ThirdBadClass() # [abstract-class-instantiated]
if 1: # pylint: disable=using-constant-test
class FourthBadClass(object, metaclass=abc.ABCMeta):
def test(self):
pass
else:
class FourthBadClass(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def test(self):
pass
def main2():
FourthBadClass() # [abstract-class-instantiated]

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0

View File

@@ -0,0 +1,5 @@
abstract-class-instantiated:108:main:Abstract class 'BadMroAbstractMethods' with abstract methods instantiated
abstract-class-instantiated:109:main:Abstract class 'BadClass' with abstract methods instantiated
abstract-class-instantiated:110:main:Abstract class 'SecondBadClass' with abstract methods instantiated
abstract-class-instantiated:111:main:Abstract class 'ThirdBadClass' with abstract methods instantiated
abstract-class-instantiated:128:main2:Abstract class 'FourthBadClass' with abstract methods instantiated

View File

@@ -0,0 +1,19 @@
"""
Check that instantiating a class with `abc.ABCMeta` as ancestor fails if it
defines abstract methods.
"""
# pylint: disable=too-few-public-methods, missing-docstring, no-init
import abc
class BadClass(abc.ABC):
@abc.abstractmethod
def test(self):
pass
def main():
""" do nothing """
BadClass() # [abstract-class-instantiated]

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.4

View File

@@ -0,0 +1 @@
abstract-class-instantiated:19:main:Abstract class 'BadClass' with abstract methods instantiated

View File

@@ -0,0 +1,90 @@
"""Test abstract-method warning."""
from __future__ import print_function
# pylint: disable=missing-docstring, no-init, no-self-use
# pylint: disable=too-few-public-methods, useless-object-inheritance
import abc
class Abstract(object):
def aaaa(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
def bbbb(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
class AbstractB(Abstract):
"""Abstract class.
this class is checking that it does not output an error msg for
unimplemeted methods in abstract classes
"""
def cccc(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
class Concrete(Abstract): # [abstract-method]
"""Concrete class"""
def aaaa(self):
"""overidden form Abstract"""
class Structure(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def __iter__(self):
pass
@abc.abstractmethod
def __len__(self):
pass
@abc.abstractmethod
def __contains__(self, _):
pass
@abc.abstractmethod
def __hash__(self):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Container(Structure):
def __contains__(self, _):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Sizable(Structure):
def __len__(self):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Hashable(Structure):
__hash__ = 42
# +1: [abstract-method, abstract-method, abstract-method]
class Iterator(Structure):
def keys(self):
return iter([1, 2, 3])
__iter__ = keys
class AbstractSizable(Structure):
@abc.abstractmethod
def length(self):
pass
__len__ = length
class GoodComplexMRO(Container, Iterator, Sizable, Hashable):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class BadComplexMro(Container, Iterator, AbstractSizable):
pass

View File

@@ -0,0 +1,2 @@
[testoptions]
max_pyver=3.0

View File

@@ -0,0 +1,16 @@
abstract-method:28:Concrete:"Method 'bbbb' is abstract in class 'Abstract' but is not overridden"
abstract-method:53:Container:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:53:Container:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:53:Container:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:59:Sizable:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:59:Sizable:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:59:Sizable:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:65:Hashable:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:65:Hashable:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:65:Hashable:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:70:Iterator:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:70:Iterator:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:70:Iterator:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:89:BadComplexMro:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:89:BadComplexMro:"Method '__len__' is abstract in class 'AbstractSizable' but is not overridden"
abstract-method:89:BadComplexMro:"Method 'length' is abstract in class 'AbstractSizable' but is not overridden"

View File

@@ -0,0 +1,88 @@
"""Test abstract-method warning."""
from __future__ import print_function
# pylint: disable=missing-docstring, no-init, no-self-use
# pylint: disable=too-few-public-methods, useless-object-inheritance
import abc
class Abstract(object):
def aaaa(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
def bbbb(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
class AbstractB(Abstract):
"""Abstract class.
this class is checking that it does not output an error msg for
unimplemeted methods in abstract classes
"""
def cccc(self):
"""should be overridden in concrete class"""
raise NotImplementedError()
class Concrete(Abstract): # [abstract-method]
"""Concrete class"""
def aaaa(self):
"""overidden form Abstract"""
class Structure(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def __iter__(self):
pass
@abc.abstractmethod
def __len__(self):
pass
@abc.abstractmethod
def __contains__(self, _):
pass
@abc.abstractmethod
def __hash__(self):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Container(Structure):
def __contains__(self, _):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Sizable(Structure):
def __len__(self):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class Hashable(Structure):
__hash__ = 42
# +1: [abstract-method, abstract-method, abstract-method]
class Iterator(Structure):
def keys(self):
return iter([1, 2, 3])
__iter__ = keys
class AbstractSizable(Structure):
@abc.abstractmethod
def length(self):
pass
__len__ = length
class GoodComplexMRO(Container, Iterator, Sizable, Hashable):
pass
# +1: [abstract-method, abstract-method, abstract-method]
class BadComplexMro(Container, Iterator, AbstractSizable):
pass

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0

View File

@@ -0,0 +1,16 @@
abstract-method:28:Concrete:"Method 'bbbb' is abstract in class 'Abstract' but is not overridden"
abstract-method:51:Container:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:51:Container:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:51:Container:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:57:Sizable:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:57:Sizable:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:57:Sizable:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:63:Hashable:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:63:Hashable:"Method '__iter__' is abstract in class 'Structure' but is not overridden"
abstract-method:63:Hashable:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:68:Iterator:"Method '__contains__' is abstract in class 'Structure' but is not overridden"
abstract-method:68:Iterator:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:68:Iterator:"Method '__len__' is abstract in class 'Structure' but is not overridden"
abstract-method:87:BadComplexMro:"Method '__hash__' is abstract in class 'Structure' but is not overridden"
abstract-method:87:BadComplexMro:"Method '__len__' is abstract in class 'AbstractSizable' but is not overridden"
abstract-method:87:BadComplexMro:"Method 'length' is abstract in class 'AbstractSizable' but is not overridden"

View File

@@ -0,0 +1,40 @@
# pylint: disable=missing-docstring,too-few-public-methods,invalid-name
# pylint: disable=attribute-defined-outside-init, useless-object-inheritance
class Aaaa(object):
"""class with attributes defined in wrong order"""
def __init__(self):
var1 = self._var2 # [access-member-before-definition]
self._var2 = 3
self._var3 = var1
class Bbbb(object):
A = 23
B = A
def __getattr__(self, attr):
try:
return self.__repo
except AttributeError:
self.__repo = attr
return attr
def catchme(self, attr):
"""no AttributeError catched"""
try:
return self._repo # [access-member-before-definition]
except ValueError:
self._repo = attr
return attr
class Mixin(object):
def test_mixin(self):
"""Don't emit access-member-before-definition for mixin classes."""
if self.already_defined:
# pylint: disable=attribute-defined-outside-init
self.already_defined = None

View File

@@ -0,0 +1,2 @@
access-member-before-definition:8:Aaaa.__init__:Access to member '_var2' before its definition line 9
access-member-before-definition:28:Bbbb.catchme:Access to member '_repo' before its definition line 30

View File

@@ -0,0 +1,21 @@
# pylint: disable=too-few-public-methods, print-statement, useless-object-inheritance
"""test access to __name__ gives undefined member on new/old class instances
but not on new/old class object
"""
from __future__ import print_function
class Aaaa:
"""old class"""
def __init__(self):
print(self.__name__) # [no-member]
print(self.__class__.__name__)
class NewClass(object):
"""new class"""
def __new__(cls, *args, **kwargs):
print('new', cls.__name__)
return object.__new__(cls, *args, **kwargs)
def __init__(self):
print('init', self.__name__) # [no-member]

View File

@@ -0,0 +1,2 @@
no-member:10:Aaaa.__init__:Instance of 'Aaaa' has no '__name__' member:INFERENCE
no-member:21:NewClass.__init__:Instance of 'NewClass' has no '__name__' member:INFERENCE

View File

@@ -0,0 +1,59 @@
# pylint: disable=too-few-public-methods, W0231, print-statement, useless-object-inheritance
# pylint: disable=no-classmethod-decorator
"""Test external access to protected class members."""
from __future__ import print_function
class MyClass(object):
"""Class with protected members."""
_cls_protected = 5
def __init__(self, other):
MyClass._cls_protected = 6
self._protected = 1
self.public = other
self.attr = 0
def test(self):
"""Docstring."""
self._protected += self._cls_protected
print(self.public._haha) # [protected-access]
def clsmeth(cls):
"""Docstring."""
cls._cls_protected += 1
print(cls._cls_protected)
clsmeth = classmethod(clsmeth)
def _private_method(self):
"""Doing nothing."""
class Subclass(MyClass):
"""Subclass with protected members."""
def __init__(self):
MyClass._protected = 5
super(Subclass, self)._private_method()
INST = Subclass()
INST.attr = 1
print(INST.attr)
INST._protected = 2 # [protected-access]
print(INST._protected) # [protected-access]
INST._cls_protected = 3 # [protected-access]
print(INST._cls_protected) # [protected-access]
class Issue1031(object):
"""Test for GitHub issue 1031"""
_attr = 1
def correct_access(self):
"""Demonstrates correct access"""
return type(self)._attr
def incorrect_access(self):
"""Demonstrates incorrect access"""
if self._attr == 1:
return type(INST)._protected # [protected-access]
return None

View File

@@ -0,0 +1,6 @@
protected-access:19:MyClass.test:Access to a protected member _haha of a client class
protected-access:41::Access to a protected member _protected of a client class
protected-access:42::Access to a protected member _protected of a client class
protected-access:43::Access to a protected member _cls_protected of a client class
protected-access:44::Access to a protected member _cls_protected of a client class
protected-access:58:Issue1031.incorrect_access:Access to a protected member _protected of a client class

View File

@@ -0,0 +1,20 @@
# pylint:disable=W0105, W0511
"""Test for backslash escapes in byte vs unicode strings"""
# Would be valid in Unicode, but probably not what you want otherwise
BAD_UNICODE = b'\u0042' # [anomalous-unicode-escape-in-string]
BAD_LONG_UNICODE = b'\U00000042' # [anomalous-unicode-escape-in-string]
# +1:[anomalous-unicode-escape-in-string]
BAD_NAMED_UNICODE = b'\N{GREEK SMALL LETTER ALPHA}'
GOOD_UNICODE = u'\u0042'
GOOD_LONG_UNICODE = u'\U00000042'
GOOD_NAMED_UNICODE = u'\N{GREEK SMALL LETTER ALPHA}'
# Valid raw strings
RAW_BACKSLASHES = r'raw'
RAW_UNICODE = ur"\u0062\n"
# In a comment you can have whatever you want: \ \\ \n \m
# even things that look like bad strings: "C:\Program Files"

View File

@@ -0,0 +1,2 @@
[testoptions]
max_pyver=3.0

View File

@@ -0,0 +1,3 @@
anomalous-unicode-escape-in-string:5::"Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix."
anomalous-unicode-escape-in-string:6::"Anomalous Unicode escape in byte string: '\U'. String constant might be missing an r or u prefix."
anomalous-unicode-escape-in-string:8::"Anomalous Unicode escape in byte string: '\N'. String constant might be missing an r or u prefix."

View File

@@ -0,0 +1,19 @@
# pylint:disable=W0105, W0511
"""Test for backslash escapes in byte vs unicode strings"""
# Would be valid in Unicode, but probably not what you want otherwise
BAD_UNICODE = b'\u0042' # [anomalous-unicode-escape-in-string]
BAD_LONG_UNICODE = b'\U00000042' # [anomalous-unicode-escape-in-string]
# +1:[anomalous-unicode-escape-in-string]
BAD_NAMED_UNICODE = b'\N{GREEK SMALL LETTER ALPHA}'
GOOD_UNICODE = u'\u0042'
GOOD_LONG_UNICODE = u'\U00000042'
GOOD_NAMED_UNICODE = u'\N{GREEK SMALL LETTER ALPHA}'
# Valid raw strings
RAW_BACKSLASHES = r'raw'
# In a comment you can have whatever you want: \ \\ \n \m
# even things that look like bad strings: "C:\Program Files"

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0

View File

@@ -0,0 +1,3 @@
anomalous-unicode-escape-in-string:5::"Anomalous Unicode escape in byte string: '\u'. String constant might be missing an r or u prefix."
anomalous-unicode-escape-in-string:6::"Anomalous Unicode escape in byte string: '\U'. String constant might be missing an r or u prefix."
anomalous-unicode-escape-in-string:8::"Anomalous Unicode escape in byte string: '\N'. String constant might be missing an r or u prefix."

View File

@@ -0,0 +1,217 @@
# pylint: disable=too-few-public-methods, no-absolute-import,missing-docstring,import-error,wrong-import-position
# pylint: disable=wrong-import-order, useless-object-inheritance
def decorator(fun):
"""Decorator"""
return fun
class DemoClass(object):
"""Test class for method invocations."""
@staticmethod
def static_method(arg):
"""static method."""
return arg + arg
@classmethod
def class_method(cls, arg):
"""class method"""
return arg + arg
def method(self, arg):
"""method."""
return (self, arg)
@decorator
def decorated_method(self, arg):
"""decorated method."""
return (self, arg)
def function_1_arg(first_argument):
"""one argument function"""
return first_argument
def function_3_args(first_argument, second_argument, third_argument):
"""three arguments function"""
return first_argument, second_argument, third_argument
def function_default_arg(one=1, two=2):
"""fonction with default value"""
return two, one
function_1_arg(420)
function_1_arg() # [no-value-for-parameter]
function_1_arg(1337, 347) # [too-many-function-args]
function_3_args(420, 789) # [no-value-for-parameter]
# +1:[no-value-for-parameter,no-value-for-parameter,no-value-for-parameter]
function_3_args()
function_3_args(1337, 347, 456)
function_3_args('bab', 'bebe', None, 5.6) # [too-many-function-args]
function_default_arg(1, two=5)
function_default_arg(two=5)
function_1_arg(bob=4) # [unexpected-keyword-arg,no-value-for-parameter]
function_default_arg(1, 4, coin="hello") # [unexpected-keyword-arg]
function_default_arg(1, one=5) # [redundant-keyword-arg]
# Remaining tests are for coverage of correct names in messages.
LAMBDA = lambda arg: 1
LAMBDA() # [no-value-for-parameter]
def method_tests():
"""Method invocations."""
demo = DemoClass()
demo.static_method() # [no-value-for-parameter]
DemoClass.static_method() # [no-value-for-parameter]
demo.class_method() # [no-value-for-parameter]
DemoClass.class_method() # [no-value-for-parameter]
demo.method() # [no-value-for-parameter]
DemoClass.method(demo) # [no-value-for-parameter]
demo.decorated_method() # [no-value-for-parameter]
DemoClass.decorated_method(demo) # [no-value-for-parameter]
# Test a regression (issue #234)
import sys
class Text(object):
""" Regression """
if sys.version_info > (3,):
def __new__(cls):
""" empty """
return object.__new__(cls)
else:
def __new__(cls):
""" empty """
return object.__new__(cls)
Text()
class TestStaticMethod(object):
@staticmethod
def test(first, second=None, **kwargs):
return first, second, kwargs
def func(self):
self.test(42)
self.test(42, second=34)
self.test(42, 42)
self.test() # [no-value-for-parameter]
self.test(42, 42, 42) # [too-many-function-args]
class TypeCheckConstructor(object):
def __init__(self, first, second):
self.first = first
self.second = second
def test(self):
type(self)(1, 2, 3) # [too-many-function-args]
# +1: [no-value-for-parameter,no-value-for-parameter]
type(self)()
type(self)(1, lala=2) # [no-value-for-parameter,unexpected-keyword-arg]
type(self)(1, 2)
type(self)(first=1, second=2)
class Test(object):
""" lambda needs Test instance as first argument """
lam = lambda self, icon: (self, icon)
def test(self):
self.lam(42)
self.lam() # [no-value-for-parameter]
self.lam(1, 2, 3) # [too-many-function-args]
Test().lam() # [no-value-for-parameter]
# Don't emit a redundant-keyword-arg for this example,
# it's perfectly valid
class Issue642(object):
attr = 0
def __str__(self):
return "{self.attr}".format(self=self)
# These should not emit anything regarding the number of arguments,
# since they have something invalid.
from ala_bala_portocola import unknown
# pylint: disable=not-a-mapping,not-an-iterable
function_1_arg(*unknown)
function_1_arg(1, *2)
function_1_arg(1, 2, 3, **unknown)
function_1_arg(4, 5, **1)
function_1_arg(5, 6, **{unknown: 1})
function_1_arg(**{object: 1})
function_1_arg(**{1: 2})
def no_context_but_redefined(*args):
args = [1]
#+1: [no-value-for-parameter, no-value-for-parameter]
expect_three(*list(args))
def no_context_one_elem(*args):
expect_three(args) # [no-value-for-parameter, no-value-for-parameter]
# Don't emit no-value-for-parameter for this, since we
# don't have the context at our disposal.
def expect_three(one, two, three):
return one + two + three
def no_context(*args):
expect_three(*args)
def no_context_two(*args):
expect_three(*list(args))
def no_context_three(*args):
expect_three(*set(args))
def compare_prices(arg):
return set((arg, ))
def find_problems2(prob_dates):
for fff in range(10):
prob_dates |= compare_prices(fff)
from collections import namedtuple
def namedtuple_replace_issue_1036():
cls = namedtuple('cls', 'a b c')
new_instance = cls(1, 2, 3)._replace(
a=24,
b=24,
c=42
)
# +1:[unexpected-keyword-arg,unexpected-keyword-arg]
new_bad_instance = cls(1, 2, 3)._replace(d=24, e=32)
return new_instance, new_bad_instance
from functools import partial
def some_func(first, second, third):
return first + second + third
partial(some_func, 1, 2)(3)
partial(some_func, third=1, second=2)(3)
partial(some_func, 1, third=2)(second=3)
partial(some_func, 1)(1) # [no-value-for-parameter]
partial(some_func, 1)(third=1) # [no-value-for-parameter]
partial(some_func, 1, 2)(third=1, fourth=4) # [unexpected-keyword-arg]

View File

@@ -0,0 +1,39 @@
no-value-for-parameter:46::No value for argument 'first_argument' in function call
too-many-function-args:47::Too many positional arguments for function call
no-value-for-parameter:49::No value for argument 'third_argument' in function call
no-value-for-parameter:51::No value for argument 'first_argument' in function call
no-value-for-parameter:51::No value for argument 'second_argument' in function call
no-value-for-parameter:51::No value for argument 'third_argument' in function call
too-many-function-args:53::Too many positional arguments for function call
no-value-for-parameter:58::No value for argument 'first_argument' in function call
unexpected-keyword-arg:58::Unexpected keyword argument 'bob' in function call
unexpected-keyword-arg:59::Unexpected keyword argument 'coin' in function call
redundant-keyword-arg:61::Argument 'one' passed by position and keyword in function call
no-value-for-parameter:66::No value for argument 'arg' in lambda call
no-value-for-parameter:71:method_tests:No value for argument 'arg' in staticmethod call
no-value-for-parameter:72:method_tests:No value for argument 'arg' in staticmethod call
no-value-for-parameter:74:method_tests:No value for argument 'arg' in classmethod call
no-value-for-parameter:75:method_tests:No value for argument 'arg' in classmethod call
no-value-for-parameter:77:method_tests:No value for argument 'arg' in method call
no-value-for-parameter:78:method_tests:No value for argument 'arg' in unbound method call
no-value-for-parameter:80:method_tests:No value for argument 'arg' in method call
no-value-for-parameter:81:method_tests:No value for argument 'arg' in unbound method call
no-value-for-parameter:110:TestStaticMethod.func:No value for argument 'first' in staticmethod call
too-many-function-args:111:TestStaticMethod.func:Too many positional arguments for staticmethod call
too-many-function-args:119:TypeCheckConstructor.test:Too many positional arguments for constructor call
no-value-for-parameter:121:TypeCheckConstructor.test:No value for argument 'first' in constructor call
no-value-for-parameter:121:TypeCheckConstructor.test:No value for argument 'second' in constructor call
no-value-for-parameter:122:TypeCheckConstructor.test:No value for argument 'second' in constructor call
unexpected-keyword-arg:122:TypeCheckConstructor.test:Unexpected keyword argument 'lala' in constructor call
no-value-for-parameter:133:Test.test:No value for argument 'icon' in method call
too-many-function-args:134:Test.test:Too many positional arguments for method call
no-value-for-parameter:136::No value for argument 'icon' in method call
no-value-for-parameter:163:no_context_but_redefined:No value for argument 'three' in function call
no-value-for-parameter:163:no_context_but_redefined:No value for argument 'two' in function call
no-value-for-parameter:166:no_context_one_elem:No value for argument 'three' in function call
no-value-for-parameter:166:no_context_one_elem:No value for argument 'two' in function call
unexpected-keyword-arg:202:namedtuple_replace_issue_1036:Unexpected keyword argument 'd' in method call
unexpected-keyword-arg:202:namedtuple_replace_issue_1036:Unexpected keyword argument 'e' in method call
no-value-for-parameter:215::No value for argument 'third' in function call
no-value-for-parameter:216::No value for argument 'second' in function call
unexpected-keyword-arg:217::Unexpected keyword argument 'fourth' in function call

View File

@@ -0,0 +1,210 @@
"""Test that we are emitting arguments-differ when the arguments are different."""
# pylint: disable=missing-docstring, too-few-public-methods, unused-argument,useless-super-delegation, useless-object-inheritance
class Parent(object):
def test(self):
pass
class Child(Parent):
def test(self, arg): # [arguments-differ]
pass
class ParentDefaults(object):
def test(self, arg=None, barg=None):
pass
class ChildDefaults(ParentDefaults):
def test(self, arg=None): # [arguments-differ]
pass
class Classmethod(object):
@classmethod
def func(cls, data):
return data
@classmethod
def func1(cls):
return cls
class ClassmethodChild(Classmethod):
@staticmethod
def func(): # [arguments-differ]
pass
@classmethod
def func1(cls):
return cls()
class Builtins(dict):
"""Ignore for builtins, for which we don't know the number of required args."""
@classmethod
def fromkeys(cls, arg, arg1):
pass
class Varargs(object):
def has_kwargs(self, arg, **kwargs):
pass
def no_kwargs(self, args):
pass
class VarargsChild(Varargs):
def has_kwargs(self, arg): # [arguments-differ]
"Not okay to lose capabilities."
def no_kwargs(self, arg, **kwargs): # [arguments-differ]
"Not okay to add extra capabilities."
class Super(object):
def __init__(self):
pass
def __private(self):
pass
def __private2_(self):
pass
def ___private3(self):
pass
def method(self, param):
raise NotImplementedError
class Sub(Super):
# pylint: disable=unused-argument
def __init__(self, arg):
super(Sub, self).__init__()
def __private(self, arg):
pass
def __private2_(self, arg):
pass
def ___private3(self, arg):
pass
def method(self, param='abc'):
pass
class Staticmethod(object):
@staticmethod
def func(data):
return data
class StaticmethodChild(Staticmethod):
@classmethod
def func(cls, data):
return data
class Property(object):
@property
def close(self):
pass
class PropertySetter(Property):
@property
def close(self):
pass
@close.setter
def close(self, attr):
return attr
class StaticmethodChild2(Staticmethod):
def func(self, data):
super(StaticmethodChild2, self).func(data)
class SuperClass(object):
@staticmethod
def impl(arg1, arg2, **kwargs):
return arg1 + arg2
class MyClass(SuperClass):
def impl(self, *args, **kwargs): # [arguments-differ]
super(MyClass, self).impl(*args, **kwargs)
class FirstHasArgs(object):
def test(self, *args):
pass
class SecondChangesArgs(FirstHasArgs):
def test(self, first, second, *args): # [arguments-differ]
pass
class Positional(object):
def test(self, first, second):
pass
class PositionalChild(Positional):
def test(self, *args): # [arguments-differ]
"""Accepts too many.
Why subclassing in the first case if the behavior is different?
"""
super(PositionalChild, self).test(args[0], args[1])
class HasSpecialMethod(object):
def __getitem__(self, key):
return key
class OverridesSpecialMethod(HasSpecialMethod):
def __getitem__(self, cheie):
return cheie + 1
class ParentClass(object):
def meth(self, arg, arg1):
raise NotImplementedError
class ChildClass(ParentClass):
def meth(self, _arg, dummy):
pass

View File

@@ -0,0 +1,8 @@
arguments-differ:12:Child.test:Parameters differ from overridden 'test' method
arguments-differ:23:ChildDefaults.test:Parameters differ from overridden 'test' method
arguments-differ:41:ClassmethodChild.func:Parameters differ from overridden 'func' method
arguments-differ:68:VarargsChild.has_kwargs:Parameters differ from overridden 'has_kwargs' method
arguments-differ:71:VarargsChild.no_kwargs:Parameters differ from overridden 'no_kwargs' method
arguments-differ:157:MyClass.impl:Parameters differ from overridden 'impl' method
arguments-differ:170:SecondChangesArgs.test:Parameters differ from overridden 'test' method
arguments-differ:181:PositionalChild.test:Parameters differ from overridden 'test' method

View File

@@ -0,0 +1,36 @@
# pylint: disable=missing-docstring,too-few-public-methods
class AbstractFoo:
def kwonly_1(self, first, *, second, third):
"Normal positional with two positional only params."
def kwonly_2(self, *, first, second):
"Two positional only parameter."
def kwonly_3(self, *, first, second):
"Two positional only params."
def kwonly_4(self, *, first, second=None):
"One positional only and another with a default."
def kwonly_5(self, *, first, **kwargs):
"Keyword only and keyword variadics."
class Foo(AbstractFoo):
def kwonly_1(self, first, *, second): # [arguments-differ]
"One positional and only one positional only param."
def kwonly_2(self, first): # [arguments-differ]
"Only one positional parameter instead of two positional only parameters."
def kwonly_3(self, first, second): # [arguments-differ]
"Two positional params."
def kwonly_4(self, first, second): # [arguments-differ]
"Two positional params."
def kwonly_5(self, *, first): # [arguments-differ]
"Keyword only, but no variadics."

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0

View File

@@ -0,0 +1,5 @@
arguments-differ:22:Foo.kwonly_1:Parameters differ from overridden 'kwonly_1' method
arguments-differ:25:Foo.kwonly_2:Parameters differ from overridden 'kwonly_2' method
arguments-differ:28:Foo.kwonly_3:Parameters differ from overridden 'kwonly_3' method
arguments-differ:31:Foo.kwonly_4:Parameters differ from overridden 'kwonly_4' method
arguments-differ:34:Foo.kwonly_5:Parameters differ from overridden 'kwonly_5' method

View File

@@ -0,0 +1,11 @@
'''Assert check example'''
# pylint: disable=misplaced-comparison-constant, comparison-with-itself
assert (1 == 1, 2 == 2), "no error"
assert (1 == 1, 2 == 2) # [assert-on-tuple]
assert 1 == 1, "no error"
assert (1 == 1, ), "no error"
assert (1 == 1, )
assert (1 == 1, 2 == 2, 3 == 5), "no error"
assert ()
assert (True, 'error msg') # [assert-on-tuple]

View File

@@ -0,0 +1,2 @@
assert-on-tuple:5::Assert called on a 2-uple. Did you mean 'assert x,y'?
assert-on-tuple:11::Assert called on a 2-uple. Did you mean 'assert x,y'?

View File

@@ -0,0 +1,150 @@
""" Checks assigning attributes not found in class slots
will trigger assigning-non-slot warning.
"""
# pylint: disable=too-few-public-methods, no-init, missing-docstring, no-absolute-import, import-error, useless-object-inheritance
from collections import deque
from missing import Unknown
class Empty(object):
""" empty """
class Bad(object):
""" missing not in slots. """
__slots__ = ['member']
def __init__(self):
self.missing = 42 # [assigning-non-slot]
class Bad2(object):
""" missing not in slots """
__slots__ = [deque.__name__, 'member']
def __init__(self):
self.deque = 42
self.missing = 42 # [assigning-non-slot]
class Bad3(Bad):
""" missing not found in slots """
__slots__ = ['component']
def __init__(self):
self.component = 42
self.member = 24
self.missing = 42 # [assigning-non-slot]
super(Bad3, self).__init__()
class Good(Empty):
""" missing not in slots, but Empty doesn't
specify __slots__.
"""
__slots__ = ['a']
def __init__(self):
self.missing = 42
class Good2(object):
""" Using __dict__ in slots will be safe. """
__slots__ = ['__dict__', 'comp']
def __init__(self):
self.comp = 4
self.missing = 5
class PropertyGood(object):
""" Using properties is safe. """
__slots__ = ['tmp', '_value']
@property
def test(self):
return self._value
@test.setter
def test(self, value):
# pylint: disable=attribute-defined-outside-init
self._value = value
def __init__(self):
self.test = 42
class PropertyGood2(object):
""" Using properties in the body of the class is safe. """
__slots__ = ['_value']
def _getter(self):
return self._value
def _setter(self, value):
# pylint: disable=attribute-defined-outside-init
self._value = value
test = property(_getter, _setter)
def __init__(self):
self.test = 24
class UnicodeSlots(object):
"""Using unicode objects in __slots__ is okay.
On Python 3.3 onward, u'' is equivalent to '',
so this test should be safe for both versions.
"""
__slots__ = (u'first', u'second')
def __init__(self):
self.first = 42
self.second = 24
class DataDescriptor(object):
def __init__(self, name, default=''):
self.__name = name
self.__default = default
def __get__(self, inst, cls):
return getattr(inst, self.__name, self.__default)
def __set__(self, inst, value):
setattr(inst, self.__name, value)
class NonDataDescriptor(object):
def __get__(self, inst, cls):
return 42
class SlotsWithDescriptor(object):
__slots__ = ['_err']
data_descriptor = DataDescriptor('_err')
non_data_descriptor = NonDataDescriptor()
missing_descriptor = Unknown()
def dont_emit_for_descriptors():
inst = SlotsWithDescriptor()
# This should not emit, because attr is
# a data descriptor
inst.data_descriptor = 'foo'
inst.non_data_descriptor = 'lala' # [assigning-non-slot]
class ClassWithSlots(object):
__slots__ = ['foobar']
class ClassReassigningDunderClass(object):
__slots__ = ['foobar']
def release(self):
self.__class__ = ClassWithSlots
class ClassReassingingInvalidLayoutClass(object):
__slots__ = []
def release(self):
self.__class__ = ClassWithSlots # [assigning-non-slot]

View File

@@ -0,0 +1,5 @@
assigning-non-slot:18:Bad.__init__:Assigning to attribute 'missing' not defined in class slots
assigning-non-slot:26:Bad2.__init__:Assigning to attribute 'missing' not defined in class slots
assigning-non-slot:36:Bad3.__init__:Assigning to attribute 'missing' not defined in class slots
assigning-non-slot:132:dont_emit_for_descriptors:Assigning to attribute 'non_data_descriptor' not defined in class slots
assigning-non-slot:150:ClassReassingingInvalidLayoutClass.release:Assigning to attribute '__class__' not defined in class slots

View File

@@ -0,0 +1,31 @@
# pylint: disable=missing-docstring
def some_func():
pass
def decorate(func):
"""Decorate *fn* to return ``self`` to enable chained method calls."""
def wrapper(self, *args, **kw):
func(self, *args, **kw)
return 42
return wrapper
class Class:
def some_method(self):
pass
@decorate
def some_other_decorated_method(self):
pass
def some_other_method(self):
value = self.some_method() # [assignment-from-no-return]
other_value = self.some_other_decorated_method()
return value + other_value
VALUE = some_func() # [assignment-from-no-return]

View File

@@ -0,0 +1,2 @@
assignment-from-no-return:26:Class.some_other_method:Assigning result of a function call, where the function has no return
assignment-from-no-return:31::Assigning result of a function call, where the function has no return

View File

@@ -0,0 +1,28 @@
# pylint: disable=missing-docstring
import asyncio
async def bla1():
await asyncio.sleep(1)
async def bla2():
await asyncio.sleep(2)
async def combining_coroutine1():
await bla1()
await bla2()
async def combining_coroutine2():
future1 = bla1()
future2 = bla2()
await asyncio.gather(future1, future2)
def do_stuff():
loop = asyncio.get_event_loop()
loop.run_until_complete(combining_coroutine1())
loop.run_until_complete(combining_coroutine2())

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.6

View File

@@ -0,0 +1,63 @@
"""Check that Python 3.5's async functions are properly analyzed by Pylint."""
# pylint: disable=missing-docstring,invalid-name,too-few-public-methods
# pylint: disable=using-constant-test, useless-object-inheritance
async def next(): # [redefined-builtin]
pass
async def some_function(arg1, arg2): # [unused-argument]
await arg1
class OtherClass(object):
@staticmethod
def test():
return 42
class Class(object):
async def some_method(self):
super(OtherClass, self).test() # [bad-super-call]
# +1: [too-many-arguments,too-many-return-statements, too-many-branches]
async def complex_function(this, function, has, more, arguments, than,
one, _, should, have):
if 1:
return this
if 1:
return function
if 1:
return has
if 1:
return more
if 1:
return arguments
if 1:
return than
try:
return one
finally:
pass
if 2:
return should
while True:
pass
if 1:
return have
if 2:
return function
if 3:
pass
# +1: [duplicate-argument-name, duplicate-argument-name, dangerous-default-value]
async def func(a, a, b=[]):
return a, b
# +1: [empty-docstring, blacklisted-name]
async def foo():
""

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.5

View File

@@ -0,0 +1,11 @@
redefined-builtin:5:next:"Redefining built-in 'next'"
unused-argument:8:some_function:"Unused argument 'arg2'"
bad-super-call:22:Class.some_method:"Bad first argument 'OtherClass' given to super()"
too-many-arguments:26:complex_function:Too many arguments (10/5)
too-many-branches:26:complex_function:Too many branches (13/12)
too-many-return-statements:26:complex_function:Too many return statements (10/6)
dangerous-default-value:57:func:Dangerous default value [] as argument
duplicate-argument-name:57:func:Duplicate argument name a in function definition
duplicate-argument-name:57:func:Duplicate argument name a in function definition
blacklisted-name:62:foo:Black listed name "foo"
empty-docstring:62:foo:Empty function docstring

View File

@@ -0,0 +1,62 @@
# pylint: disable=missing-docstring,too-few-public-methods,invalid-name, useless-object-inheritance
class A(object):
def __init__(self):
self.x = 0
self.setUp()
def set_y(self, y):
self.y = y
def set_x(self, x):
self.x = x
def set_z(self, z):
self.z = z # [attribute-defined-outside-init]
def setUp(self):
self.x = 0
self.y = 0
class B(A):
def test(self):
self.z = 44 # [attribute-defined-outside-init]
class C(object):
def __init__(self):
self._init()
def _init(self):
self.z = 44
class D(object):
def setUp(self):
self.set_z()
def set_z(self):
self.z = 42
class E(object):
def __init__(self):
i = self._init
i()
def _init(self):
self.z = 44
class Mixin(object):
def test_mixin(self):
"""Don't emit attribute-defined-outside-init for mixin classes."""
if self.defined_already: # pylint: disable=access-member-before-definition
self.defined_already = None

View File

@@ -0,0 +1,2 @@
attribute-defined-outside-init:16:A.set_z:Attribute 'z' defined outside __init__
attribute-defined-outside-init:26:B.test:Attribute 'z' defined outside __init__

View File

@@ -0,0 +1,232 @@
"""Regression test case for bad-continuation."""
# pylint: disable=print-statement,implicit-str-concat-in-sequence,using-constant-test,missing-docstring,wrong-import-position
# Various alignment for brackets
from __future__ import print_function
LIST0 = [
1, 2, 3
]
LIST1 = [
1, 2, 3
]
LIST2 = [
1, 2, 3
] # [bad-continuation]
# Alignment inside literals
W0 = [1, 2, 3,
4, 5, 6,
7, # [bad-continuation]
8, 9, 10,
11, 12, 13,
# and a comment
14, 15, 16]
W1 = {
'a': 1,
'b': 2, # [bad-continuation]
'c': 3,
}
W2 = {
'a': 1,
'b': 2, # [bad-continuation]
'c': 3,
}
W2 = ['some', 'contents' # with a continued comment that may be aligned
# under the previous comment (optionally)
'and',
'more', # but this
# [bad-continuation] is not accepted
'contents', # [bad-continuation] nor this.
]
# Values in dictionaries should be indented 4 spaces further if they are on a
# different line than their key
W4 = {
'key1':
'value1', # Grandfather in the old style
'key2':
'value2', # [bad-continuation]
'key3':
'value3', # Comma here
}
# And should follow the same rules as continuations within parens
W5 = {
'key1': 'long value'
'long continuation',
'key2': 'breaking'
'wrong', # [bad-continuation]
'key3': 2*(
2+2),
'key4': ('parenthesis',
'continuation') # No comma here
}
# Allow values to line up with their keys when the key is next to the brace
W6 = {'key1':
'value1',
'key2':
'value2',
}
# Or allow them to be indented
W7 = {'key1':
'value1',
'key2':
'value2'
}
# Bug that caused a warning on the previous two cases permitted these odd
# incorrect indentations
W8 = {'key1':
'value1', # [bad-continuation]
}
W9 = {'key1':
'value1', # [bad-continuation]
}
# Alignment of arguments in function definitions
def continue1(some_arg,
some_other_arg):
"""A function with well-aligned arguments."""
print(some_arg, some_other_arg)
def continue2(
some_arg,
some_other_arg):
"""A function with well-aligned arguments."""
print(some_arg, some_other_arg)
def continue3(
some_arg, # [bad-continuation]
some_other_arg): # [bad-continuation]
"""A function with misaligned arguments"""
print(some_arg, some_other_arg)
def continue4( # pylint:disable=missing-docstring
arg1,
arg2): print(arg1, arg2)
def callee(*args):
"""noop"""
print(args)
callee(
"a",
"b"
)
callee("a",
"b") # [bad-continuation]
callee(5, {'a': 'b',
'c': 'd'})
if (
1
): pass
if (
1
): pass
if (
1
): pass # [bad-continuation]
if (1 and
2): # [bad-continuation]
pass
while (1 and
2):
pass
while (1 and
2 and # [bad-continuation]
3):
pass
if (
2): pass # [bad-continuation]
if (1 or
2 or
3): pass
if (1 or
2 or # [bad-continuation]
3): print(1, 2)
if (1 and
2): pass # [bad-continuation]
if (
2): pass
if (
2): # [bad-continuation]
pass
L1 = (lambda a,
b: a + b)
if not (1 and
2):
print(3)
if not (1 and
2): # [bad-continuation]
print(3)
continue2("foo",
some_other_arg="this "
"is "
"fine")
from contextlib import contextmanager
@contextmanager
def mycontext(*args):
yield args
with mycontext(
"this is",
"great stuff",
"mane"):
pass
# pylint: disable=using-constant-test
# More indentation included to distinguish this from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one, var_two, var_three, var_four)
def short_func_name(first, second, third):
# Add some extra indentation on the conditional continuation line.
if (first
and second == first == 'some_big_long_statement_that_should_not_trigger'):
third()
# Some normal multi-line statements with double-indented continuation lines.
LARGE_COLLECTION = [
"spam",
"eggs",
"beans",
]
long_function_name(
"1", "2", "3", "4")
CONCATENATED_TEXT = (
"spam"
"eggs"
"beans")

View File

@@ -0,0 +1,63 @@
bad-continuation:14::"Wrong hanging indentation.
] # [bad-continuation]
| ^|"
bad-continuation:19::"Wrong continued indentation (remove 3 spaces).
7, # [bad-continuation]
| ^"
bad-continuation:27::"Wrong hanging indentation (add 1 space).
'b': 2, # [bad-continuation]
^|"
bad-continuation:33::"Wrong hanging indentation (add 1 space).
'b': 2, # [bad-continuation]
^|"
bad-continuation:41::"Wrong continued indentation.
# [bad-continuation] is not accepted
| | ^"
bad-continuation:42::"Wrong continued indentation (remove 20 spaces).
'contents', # [bad-continuation] nor this.
| ^"
bad-continuation:51::"Wrong hanging indentation in dict value.
'value2', # [bad-continuation]
| ^ |"
bad-continuation:61::"Wrong continued indentation (add 4 spaces).
'wrong', # [bad-continuation]
^ |"
bad-continuation:85::"Wrong hanging indentation in dict value.
'value1', # [bad-continuation]
^ | |"
bad-continuation:89::"Wrong hanging indentation in dict value.
'value1', # [bad-continuation]
^ | |"
bad-continuation:106::"Wrong hanging indentation before block (add 4 spaces).
some_arg, # [bad-continuation]
^ |"
bad-continuation:107::"Wrong hanging indentation before block (add 4 spaces).
some_other_arg): # [bad-continuation]
^ |"
bad-continuation:127::"Wrong continued indentation (add 3 spaces).
""b"") # [bad-continuation]
^ |"
bad-continuation:141::"Wrong hanging indentation before block.
): pass # [bad-continuation]
| ^|"
bad-continuation:144::"Wrong continued indentation before block (add 4 spaces).
2): # [bad-continuation]
^ |"
bad-continuation:152::"Wrong continued indentation (remove 2 spaces).
2 and # [bad-continuation]
| ^"
bad-continuation:157::"Wrong hanging indentation before block.
2): pass # [bad-continuation]
^ | |"
bad-continuation:164::"Wrong continued indentation before block.
2 or # [bad-continuation]
|^ |"
bad-continuation:168::"Wrong continued indentation before block.
2): pass # [bad-continuation]
^ | |"
bad-continuation:174::"Wrong hanging indentation before block.
2): # [bad-continuation]
^ | |"
bad-continuation:185::"Wrong continued indentation (add 4 spaces).
2): # [bad-continuation]
^ |"

View File

@@ -0,0 +1,8 @@
# pylint: disable=missing-docstring, unused-argument
async def upload_post(
content: bytes,
source: str,
tags: dict) -> dict:
# regression test for https://github.com/PyCQA/pylint/issues/1415
raise NotImplementedError('Not implemented')

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.6

View File

@@ -0,0 +1,52 @@
"""Regression test case for bad-continuation with tabs"""
# pylint: disable=too-few-public-methods,missing-docstring,invalid-name,unused-variable, useless-object-inheritance
# Various alignment for brackets
# Issue 638
TEST1 = ["foo",
"bar",
"baz"
]
MY_LIST = [
1, 2, 3,
4, 5, 6
]
# Issue 1148
class Abc(object):
def b(self, c):
# bock indentation
self.d(
c) # (is: tabs only)
def d(self, e):
# bad hanging indentation
self.b(
e) # [bad-continuation] (is: 2 tabs + 7 spaces)
def f(self):
# block indentiation (is: all tabs only)
return [
self.b,
self.d
]
def g(self):
# bad hanging indentation
# the closing ] requires 7 - 8 more spcaes; see h(), i()
return [self.b,
self.d # (is: 2 tabs + 8 spaces)
] # [bad-continuation] (is: tabs only)
def h(self):
# hanging indentation: all lined up with first token 'self.b'
return [self.b,
self.d # (is: 2 tabs + 8 spaces)
] # (is: 2 tabs + 8 spaces)
def i(self):
# hangin identation: closing ] lined up with opening [
return [self.b,
self.d # (2 tabs + 8 spaces)
] # (2 tabs + 7 spaces)

View File

@@ -0,0 +1,3 @@
[FORMAT]
indent-string='\t'
indent-after-paren=1

View File

@@ -0,0 +1,6 @@
bad-continuation:26::"Wrong hanging indentation (add 1 space).
e) # [bad-continuation] (is: 2 tabs + 7 spaces)
^|"
bad-continuation:40::"Wrong continued indentation.
] # [bad-continuation] (is: tabs only)
^ ||"

View File

@@ -0,0 +1,45 @@
# pylint: disable=missing-docstring, bare-except, broad-except
__revision__ = 1
try:
__revision__ += 1
except Exception:
__revision__ = 0
except TypeError: # [bad-except-order]
__revision__ = 0
try:
__revision__ += 1
except LookupError:
__revision__ = 0
except IndexError: # [bad-except-order]
__revision__ = 0
try:
__revision__ += 1
except (LookupError, NameError):
__revision__ = 0
except (IndexError, UnboundLocalError): # [bad-except-order, bad-except-order]
__revision__ = 0
try: # [bad-except-order]
__revision__ += 1
except:
pass
except Exception:
pass
try:
__revision__ += 1
except TypeError:
__revision__ = 0
except:
__revision__ = 0
try:
__revision__ += 1
except Exception:
pass
except:
pass

View File

@@ -0,0 +1,5 @@
bad-except-order:9::Bad except clauses order (Exception is an ancestor class of TypeError)
bad-except-order:16::Bad except clauses order (LookupError is an ancestor class of IndexError)
bad-except-order:23::Bad except clauses order (LookupError is an ancestor class of IndexError)
bad-except-order:23::Bad except clauses order (NameError is an ancestor class of UnboundLocalError)
bad-except-order:26::Bad except clauses order (empty except clause should always appear last)

View File

@@ -0,0 +1,24 @@
"""Check that raise ... from .. uses a proper exception context """
# pylint: disable=unreachable, import-error, multiple-imports
import socket, unknown
__revision__ = 0
class ExceptionSubclass(Exception):
""" subclass """
def test():
""" docstring """
raise IndexError from 1 # [bad-exception-context]
raise IndexError from None
raise IndexError from ZeroDivisionError
raise IndexError from object() # [bad-exception-context]
raise IndexError from ExceptionSubclass
raise IndexError from socket.error
raise IndexError() from None
raise IndexError() from ZeroDivisionError
raise IndexError() from ZeroDivisionError()
raise IndexError() from object() # [bad-exception-context]
raise IndexError() from unknown

View File

@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0

View File

@@ -0,0 +1,3 @@
bad-exception-context:14:test:Exception context set to something which is not an exception, nor None
bad-exception-context:17:test:Exception context set to something which is not an exception, nor None
bad-exception-context:23:test:Exception context set to something which is not an exception, nor None

View File

@@ -0,0 +1,19 @@
# pylint: disable=missing-docstring, pointless-statement
from __future__ import print_function
def totoo():
print('malindented') # [bad-indentation]
def tutuu():
print('good indentation')
def titii():
1 # and this. # [bad-indentation]
def tataa(kdict):
for key in ['1', '2', '3']:
key = key.lower()
if key in kdict:
del kdict[key]

View File

@@ -0,0 +1,2 @@
bad-indentation:6::Bad indentation. Found 1 spaces, expected 4
bad-indentation:12::Bad indentation. Found 5 spaces, expected 4

View File

@@ -0,0 +1,5 @@
"""errors-only is not usable as an inline option"""
# +1: [bad-inline-option]
# pylint: errors-only
CONST = "This is not a pylint: inline option."

View File

@@ -0,0 +1,2 @@
[Messages Control]
enable=I

View File

@@ -0,0 +1 @@
bad-inline-option:3::Unable to consider inline option 'errors-only'

View File

@@ -0,0 +1,37 @@
"""Warnings for using open() with an invalid mode string."""
open('foo.bar', 'w', 2)
open('foo.bar', 'rw') # [bad-open-mode]
open(name='foo.bar', buffering=10, mode='rw') # [bad-open-mode]
open(mode='rw', name='foo.bar') # [bad-open-mode]
open('foo.bar', 'U+')
open('foo.bar', 'rb+')
open('foo.bar', 'Uw') # [bad-open-mode]
open('foo.bar', 2) # [bad-open-mode]
open('foo.bar', buffering=2)
WRITE_MODE = 'w'
open('foo.bar', 'U' + WRITE_MODE + 'z') # [bad-open-mode]
open('foo.bar', 'br') # [bad-open-mode]
open('foo.bar', 'wU') # [bad-open-mode]
open('foo.bar', 'r+b')
open('foo.bar', 'r+')
open('foo.bar', 'w+')
open('foo.bar', 'xb') # [bad-open-mode]
open('foo.bar', 'rx') # [bad-open-mode]
open('foo.bar', 'Ur')
open('foo.bar', 'rU')
open('foo.bar', 'rUb')
open('foo.bar', 'rUb+')
open('foo.bar', 'rU+b')
open('foo.bar', 'r+Ub')
open('foo.bar', '+rUb') # [bad-open-mode]
open('foo.bar', 'ab+')
open('foo.bar', 'a+b')
open('foo.bar', 'aU') # [bad-open-mode]
open('foo.bar', 'U+b')
open('foo.bar', '+Ub')
open('foo.bar', 'b+U')
open('foo.bar', 'Urb+')
open('foo.bar', 'Ur+b')
open('foo.bar', 'Ubr') # [bad-open-mode]
open('foo.bar', 'Ut') # [bad-open-mode]

Some files were not shown because too many files have changed in this diff Show More