diff options
Diffstat (limited to 'tests/functional/t')
65 files changed, 3292 insertions, 0 deletions
diff --git a/tests/functional/t/__init__.py b/tests/functional/t/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/functional/t/__init__.py diff --git a/tests/functional/t/ternary.py b/tests/functional/t/ternary.py new file mode 100644 index 000000000..deac01e3c --- /dev/null +++ b/tests/functional/t/ternary.py @@ -0,0 +1,33 @@ +"""Test for old ternary constructs""" +from UNINFERABLE import condition, true_value, false_value, some_callable # pylint: disable=import-error + +SOME_VALUE1 = true_value if condition else false_value +SOME_VALUE2 = condition and true_value or false_value # [consider-using-ternary] +SOME_VALUE3 = condition + +def func1(): + """Ternary return value correct""" + return true_value if condition else false_value + + +def func2(): + """Ternary return value incorrect""" + return condition and true_value or false_value # [consider-using-ternary] + + +SOME_VALUE4 = some_callable(condition) and 'ERROR' or 'SUCCESS' # [consider-using-ternary] +SOME_VALUE5 = SOME_VALUE1 > 3 and 'greater' or 'not greater' # [consider-using-ternary] +SOME_VALUE6 = (SOME_VALUE2 > 4 and SOME_VALUE3) and 'both' or 'not' # [consider-using-ternary] +SOME_VALUE7 = 'both' if (SOME_VALUE2 > 4) and (SOME_VALUE3) else 'not' +SOME_VALUE8 = SOME_VALUE1 and SOME_VALUE2 and SOME_VALUE3 or SOME_VALUE4 +SOME_VALUE9 = SOME_VALUE1 and False or SOME_VALUE2 # [simplify-boolean-expression] + +YEAR = 1992 +# Cannot be simplified with a ternary. +IS_LEAP_YEAR = YEAR % 4 == 0 and YEAR % 100 != 0 or YEAR % 400 == 0 + + +def func4(): + """"Using a Name as a condition but still emits""" + truth_value = 42 + return condition and truth_value or false_value # [consider-using-ternary] diff --git a/tests/functional/t/ternary.txt b/tests/functional/t/ternary.txt new file mode 100644 index 000000000..d78aa45a6 --- /dev/null +++ b/tests/functional/t/ternary.txt @@ -0,0 +1,7 @@ +consider-using-ternary:5:0::Consider using ternary (true_value if condition else false_value) +consider-using-ternary:15:4:func2:Consider using ternary (true_value if condition else false_value) +consider-using-ternary:18:0::Consider using ternary ('ERROR' if some_callable(condition) else 'SUCCESS') +consider-using-ternary:19:0::Consider using ternary ('greater' if SOME_VALUE1 > 3 else 'not greater') +consider-using-ternary:20:0::Consider using ternary ('both' if SOME_VALUE2 > 4 and SOME_VALUE3 else 'not') +simplify-boolean-expression:23:0::Boolean expression may be simplified to SOME_VALUE2 +consider-using-ternary:33:4:func4:Consider using ternary (truth_value if condition else false_value) diff --git a/tests/functional/t/test_compile.py b/tests/functional/t/test_compile.py new file mode 100644 index 000000000..d4a4ac2aa --- /dev/null +++ b/tests/functional/t/test_compile.py @@ -0,0 +1,6 @@ +# pylint: disable=missing-docstring, unused-variable, pointless-statement, too-few-public-methods, useless-object-inheritance + +class WrapperClass(object): + def method(self): + var = +4294967296 + self.method.__code__.co_consts diff --git a/tests/functional/t/tokenize_error.py b/tests/functional/t/tokenize_error.py new file mode 100644 index 000000000..323950d91 --- /dev/null +++ b/tests/functional/t/tokenize_error.py @@ -0,0 +1,6 @@ +"""A module that is accepted by Python but rejected by tokenize. + +The problem is the trailing line continuation at the end of the line, +which produces a TokenError.""" +# +2: [syntax-error] +""\ diff --git a/tests/functional/t/tokenize_error.rc b/tests/functional/t/tokenize_error.rc new file mode 100644 index 000000000..58b5a9413 --- /dev/null +++ b/tests/functional/t/tokenize_error.rc @@ -0,0 +1 @@ +[testoptions] diff --git a/tests/functional/t/tokenize_error.txt b/tests/functional/t/tokenize_error.txt new file mode 100644 index 000000000..bf780eb96 --- /dev/null +++ b/tests/functional/t/tokenize_error.txt @@ -0,0 +1 @@ +syntax-error:7:0::EOF in multi-line statement diff --git a/tests/functional/t/tokenize_error_jython.py b/tests/functional/t/tokenize_error_jython.py new file mode 100644 index 000000000..205f5fc6b --- /dev/null +++ b/tests/functional/t/tokenize_error_jython.py @@ -0,0 +1,7 @@ +# [syntax-error] +"""A module that is accepted by Python but rejected by tokenize. + +The problem is the trailing line continuation at the end of the line, +which produces a TokenError.""" + +""\ diff --git a/tests/functional/t/tokenize_error_jython.rc b/tests/functional/t/tokenize_error_jython.rc new file mode 100644 index 000000000..0dd078923 --- /dev/null +++ b/tests/functional/t/tokenize_error_jython.rc @@ -0,0 +1,2 @@ +[testoptions] +except_implementations=CPython,PyPy,IronPython diff --git a/tests/functional/t/tokenize_error_jython.txt b/tests/functional/t/tokenize_error_jython.txt new file mode 100644 index 000000000..6c1abf4a3 --- /dev/null +++ b/tests/functional/t/tokenize_error_jython.txt @@ -0,0 +1 @@ +syntax-error:1::unexpected character after line continuation character diff --git a/tests/functional/t/too/__init__.py b/tests/functional/t/too/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/functional/t/too/__init__.py diff --git a/tests/functional/t/too/too_few_public_methods.py b/tests/functional/t/too/too_few_public_methods.py new file mode 100644 index 000000000..5ba528f79 --- /dev/null +++ b/tests/functional/t/too/too_few_public_methods.py @@ -0,0 +1,50 @@ +# pylint: disable=missing-docstring, useless-object-inheritance +from __future__ import print_function + + +from enum import Enum + + +class Aaaa(object): # [too-few-public-methods] + + def __init__(self): + pass + + def meth1(self): + print(self) + + def _dontcount(self): + print(self) + + +# Don't emit for these cases. +class Klass(object): + """docstring""" + + def meth1(self): + """first""" + + def meth2(self): + """second""" + + +class EnoughPublicMethods(Klass): + """We shouldn't emit too-few-public-methods for this.""" + + +class BossMonster(Enum): + """An enum does not need methods to be useful.""" + MEGASHARK = 1 + OCTOPUS = 2 + + +class DumbList: + """A class can define only special methods.""" + def __init__(self, iterable): + self._list = list(iterable) + + def __len__(self): + return len(self._list) + + def __getitem__(self, index): + return self._list[index] diff --git a/tests/functional/t/too/too_few_public_methods.txt b/tests/functional/t/too/too_few_public_methods.txt new file mode 100644 index 000000000..a86ba6d81 --- /dev/null +++ b/tests/functional/t/too/too_few_public_methods.txt @@ -0,0 +1 @@ +too-few-public-methods:8:0:Aaaa:Too few public methods (1/2) diff --git a/tests/functional/t/too/too_few_public_methods_37.py b/tests/functional/t/too/too_few_public_methods_37.py new file mode 100644 index 000000000..55fc54484 --- /dev/null +++ b/tests/functional/t/too/too_few_public_methods_37.py @@ -0,0 +1,37 @@ +# pylint: disable=missing-docstring +import dataclasses +import typing +from dataclasses import dataclass + + +@dataclasses.dataclass +class ScheduledTxSearchModel: + date_from = None + date_to = None + + +@dataclass +class ScheduledTxSearchModelOne: + date = None + + +@dataclass(frozen=True) +class Test: + some_integer: int + + +class Example(typing.NamedTuple): + some_int: int + + +@dataclasses.dataclass(frozen=True) +class Point: + """A three dimensional point with x, y and z components.""" + + attr1: float + attr2: float + attr3: float + + def to_array(self): + """Convert to a NumPy array `np.array((x, y, z))`.""" + return self.attr1 diff --git a/tests/functional/t/too/too_few_public_methods_37.rc b/tests/functional/t/too/too_few_public_methods_37.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/t/too/too_few_public_methods_37.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/t/too/too_many_ancestors.py b/tests/functional/t/too/too_many_ancestors.py new file mode 100644 index 000000000..2c105ba28 --- /dev/null +++ b/tests/functional/t/too/too_many_ancestors.py @@ -0,0 +1,45 @@ +# pylint: disable=missing-docstring, too-few-public-methods, useless-object-inheritance, arguments-differ +from collections.abc import MutableSequence + +class Aaaa(object): + pass +class Bbbb(object): + pass +class Cccc(object): + pass +class Dddd(object): + pass +class Eeee(object): + pass +class Ffff(object): + pass +class Gggg(object): + pass +class Hhhh(object): + pass + +class Iiii(Aaaa, Bbbb, Cccc, Dddd, Eeee, Ffff, Gggg, Hhhh): # [too-many-ancestors] + pass + +class Jjjj(Iiii): # [too-many-ancestors] + pass + + +# https://github.com/PyCQA/pylint/issues/4166 +# https://github.com/PyCQA/pylint/issues/4415 +class ItemSequence(MutableSequence): + """Minimal MutableSequence.""" + def __getitem__(self, key): + return key + + def __setitem__(self, key, value): + _ = key, value + + def __delitem__(self, key): + _ = key + + def insert(self, index, value): + _ = index, value + + def __len__(self): + return 1 diff --git a/tests/functional/t/too/too_many_ancestors.txt b/tests/functional/t/too/too_many_ancestors.txt new file mode 100644 index 000000000..d913ce4ef --- /dev/null +++ b/tests/functional/t/too/too_many_ancestors.txt @@ -0,0 +1,2 @@ +too-many-ancestors:21:0:Iiii:Too many ancestors (8/7) +too-many-ancestors:24:0:Jjjj:Too many ancestors (9/7) diff --git a/tests/functional/t/too/too_many_ancestors_ignored_parents.py b/tests/functional/t/too/too_many_ancestors_ignored_parents.py new file mode 100644 index 000000000..93598d941 --- /dev/null +++ b/tests/functional/t/too/too_many_ancestors_ignored_parents.py @@ -0,0 +1,40 @@ +# pylint: disable=missing-docstring, too-few-public-methods, invalid-name + +# Inheritance diagram: +# F +# / +# D E +# \/ +# B C +# \/ +# A +# +# Once `E` is pruned from the tree, we have: +# D +# \ +# B C +# \/ +# A +# +# By setting `max-parents=2`, we're able to check that tree-pruning works +# correctly; in the new diagram, `B` has only 1 parent, so it doesn't raise a +# message, and `A` has 3, so it does raise a message with the specific number +# of parents. + +class F: + """0 parents""" + +class E(F): + """1 parent""" + +class D: + """0 parents""" + +class B(D, E): + """3 parents""" + +class C: + """0 parents""" + +class A(B, C): # [too-many-ancestors] + """5 parents""" diff --git a/tests/functional/t/too/too_many_ancestors_ignored_parents.rc b/tests/functional/t/too/too_many_ancestors_ignored_parents.rc new file mode 100644 index 000000000..1d06dad25 --- /dev/null +++ b/tests/functional/t/too/too_many_ancestors_ignored_parents.rc @@ -0,0 +1,3 @@ +[testoptions] +max-parents=2 +ignored-parents=functional.t.too.too_many_ancestors_ignored_parents.E diff --git a/tests/functional/t/too/too_many_ancestors_ignored_parents.txt b/tests/functional/t/too/too_many_ancestors_ignored_parents.txt new file mode 100644 index 000000000..e1eea426a --- /dev/null +++ b/tests/functional/t/too/too_many_ancestors_ignored_parents.txt @@ -0,0 +1 @@ +too-many-ancestors:39:0:A:Too many ancestors (3/2) diff --git a/tests/functional/t/too/too_many_arguments.py b/tests/functional/t/too/too_many_arguments.py new file mode 100644 index 000000000..689745e27 --- /dev/null +++ b/tests/functional/t/too/too_many_arguments.py @@ -0,0 +1,32 @@ +# pylint: disable=missing-docstring,wrong-import-position + +def stupid_function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9): # [too-many-arguments] + return arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 + + +class MyClass: + text = "MyText" + + def mymethod1(self): + return self.text + + def mymethod2(self): + return self.mymethod1.__get__(self, MyClass) + + +MyClass().mymethod2()() + + +# Check a false positive does not occur +from functools import partial + + +def root_function(first, second, third): + return first + second + third + + +def func_call(): + """Test we don't emit a FP for https://github.com/PyCQA/pylint/issues/2588""" + partial_func = partial(root_function, 1, 2, 3) + partial_func() + return root_function(1, 2, 3) diff --git a/tests/functional/t/too/too_many_arguments.txt b/tests/functional/t/too/too_many_arguments.txt new file mode 100644 index 000000000..d4f551634 --- /dev/null +++ b/tests/functional/t/too/too_many_arguments.txt @@ -0,0 +1 @@ +too-many-arguments:3:0:stupid_function:Too many arguments (9/5) diff --git a/tests/functional/t/too/too_many_arguments_issue_1045.py b/tests/functional/t/too/too_many_arguments_issue_1045.py new file mode 100644 index 000000000..e5aa76d75 --- /dev/null +++ b/tests/functional/t/too/too_many_arguments_issue_1045.py @@ -0,0 +1,13 @@ +# pylint: disable=missing-docstring + +# pylint: disable=unused-import, undefined-variable; false positives :-( + +import functools + + +@functools.lru_cache() +def func(): + pass + + +func.cache_clear() diff --git a/tests/functional/t/too/too_many_arguments_overload.py b/tests/functional/t/too/too_many_arguments_overload.py new file mode 100644 index 000000000..1155deb0c --- /dev/null +++ b/tests/functional/t/too/too_many_arguments_overload.py @@ -0,0 +1,38 @@ +# pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring +# pylint: disable=too-few-public-methods +from typing import overload + + +class ClassA: + @classmethod + @overload + def method(cls, arg1): + pass + + @classmethod + @overload + def method(cls, arg1, arg2): + pass + + @classmethod + def method(cls, arg1, arg2=None): + pass + + +ClassA.method(1, 2) + + +class ClassB: + @overload + def method(self, arg1): + pass + + @overload + def method(self, arg1, arg2): + pass + + def method(self, arg1, arg2=None): + pass + + +ClassB().method(1, arg2=2) diff --git a/tests/functional/t/too/too_many_boolean_expressions.py b/tests/functional/t/too/too_many_boolean_expressions.py new file mode 100644 index 000000000..e8753859c --- /dev/null +++ b/tests/functional/t/too/too_many_boolean_expressions.py @@ -0,0 +1,20 @@ +"""Checks for if statements containing too many boolean expressions""" + +# pylint: disable=invalid-name, comparison-with-itself, chained-comparison, condition-evals-to-constant + +x = y = z = 5 +if x > -5 and x < 5 and y > -5 and y < 5 and z > -5 and z < 5: # [too-many-boolean-expressions] + pass +elif True and False and 1 and 2 and 3: + pass +elif True and False and 1 and 2 and 3 and 4 and 5: # [too-many-boolean-expressions] + pass +elif True and (True and True) and (x == 5 or True or True): # [too-many-boolean-expressions] + pass +elif True and (True or (x > -5 and x < 5 and (z > -5 or z < 5))): # [too-many-boolean-expressions] + pass +elif True == True == True == True == True == True: + pass + +if True and False and 1 and 2 and 3: + pass diff --git a/tests/functional/t/too/too_many_boolean_expressions.txt b/tests/functional/t/too/too_many_boolean_expressions.txt new file mode 100644 index 000000000..6055e7437 --- /dev/null +++ b/tests/functional/t/too/too_many_boolean_expressions.txt @@ -0,0 +1,4 @@ +too-many-boolean-expressions:6:3::Too many boolean expressions in if statement (6/5) +too-many-boolean-expressions:10:5::Too many boolean expressions in if statement (7/5) +too-many-boolean-expressions:12:5::Too many boolean expressions in if statement (6/5) +too-many-boolean-expressions:14:5::Too many boolean expressions in if statement (6/5) diff --git a/tests/functional/t/too/too_many_branches.py b/tests/functional/t/too/too_many_branches.py new file mode 100644 index 000000000..7b0b068ad --- /dev/null +++ b/tests/functional/t/too/too_many_branches.py @@ -0,0 +1,69 @@ +""" Test for too many branches. """
+# pylint: disable=using-constant-test
+def wrong(): # [too-many-branches]
+ """ Has too many branches. """
+ if 1:
+ pass
+ elif 1:
+ pass
+ elif 1:
+ pass
+ elif 1:
+ pass
+ elif 1:
+ pass
+ elif 1:
+ pass
+ try:
+ pass
+ finally:
+ pass
+ if 2:
+ pass
+ while True:
+ pass
+ if 1:
+ pass
+ elif 2:
+ pass
+ elif 3:
+ pass
+
+def good():
+ """ Too many branches only if we take
+ into consideration the nested functions.
+ """
+ def nested_1():
+ """ empty """
+ if 1:
+ pass
+ elif 2:
+ pass
+ elif 3:
+ pass
+ elif 4:
+ pass
+
+ nested_1()
+ try:
+ pass
+ finally:
+ pass
+ try:
+ pass
+ finally:
+ pass
+ if 1:
+ pass
+ elif 2:
+ pass
+ elif 3:
+ pass
+ elif 4:
+ pass
+ elif 5:
+ pass
+ elif 6:
+ pass
+ elif 7:
+ pass
diff --git a/tests/functional/t/too/too_many_branches.txt b/tests/functional/t/too/too_many_branches.txt new file mode 100644 index 000000000..e5bfd4d49 --- /dev/null +++ b/tests/functional/t/too/too_many_branches.txt @@ -0,0 +1 @@ +too-many-branches:3:0:wrong:Too many branches (13/12) diff --git a/tests/functional/t/too/too_many_instance_attributes.py b/tests/functional/t/too/too_many_instance_attributes.py new file mode 100644 index 000000000..565b8ec10 --- /dev/null +++ b/tests/functional/t/too/too_many_instance_attributes.py @@ -0,0 +1,27 @@ +# pylint: disable=missing-docstring, too-few-public-methods, useless-object-inheritance + + +class Aaaa(object): # [too-many-instance-attributes] + + def __init__(self): + self.aaaa = 1 + self.bbbb = 2 + self.cccc = 3 + self.dddd = 4 + self.eeee = 5 + self.ffff = 6 + self.gggg = 7 + self.hhhh = 8 + self.iiii = 9 + self.jjjj = 10 + self._aaaa = 1 + self._bbbb = 2 + self._cccc = 3 + self._dddd = 4 + self._eeee = 5 + self._ffff = 6 + self._gggg = 7 + self._hhhh = 8 + self._iiii = 9 + self._jjjj = 10 + self.tomuch = None diff --git a/tests/functional/t/too/too_many_instance_attributes.txt b/tests/functional/t/too/too_many_instance_attributes.txt new file mode 100644 index 000000000..b749ae9a9 --- /dev/null +++ b/tests/functional/t/too/too_many_instance_attributes.txt @@ -0,0 +1 @@ +too-many-instance-attributes:4:0:Aaaa:Too many instance attributes (21/7):HIGH diff --git a/tests/functional/t/too/too_many_instance_attributes_py37.py b/tests/functional/t/too/too_many_instance_attributes_py37.py new file mode 100644 index 000000000..904475783 --- /dev/null +++ b/tests/functional/t/too/too_many_instance_attributes_py37.py @@ -0,0 +1,18 @@ +# pylint: disable=missing-docstring, too-few-public-methods, useless-object-inheritance +from dataclasses import dataclass, InitVar + +# InitVars should not count as instance attributes (see issue #3754) +# Default max_instance_attributes is 7 +@dataclass +class Hello: + a_1: int + a_2: int + a_3: int + a_4: int + a_5: int + a_6: int + a_7: int + a_8: InitVar[int] + + def __post_init__(self, a_8): + self.a_1 += a_8 diff --git a/tests/functional/t/too/too_many_instance_attributes_py37.rc b/tests/functional/t/too/too_many_instance_attributes_py37.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/t/too/too_many_instance_attributes_py37.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/t/too/too_many_lines.py b/tests/functional/t/too/too_many_lines.py new file mode 100644 index 000000000..78e568c23 --- /dev/null +++ b/tests/functional/t/too/too_many_lines.py @@ -0,0 +1,1015 @@ +# pylint: disable=missing-docstring +# -1: [too-many-lines] +__revision__ = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ZERFZAER = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HEHEHE = 2 diff --git a/tests/functional/t/too/too_many_lines.txt b/tests/functional/t/too/too_many_lines.txt new file mode 100644 index 000000000..5c228ac49 --- /dev/null +++ b/tests/functional/t/too/too_many_lines.txt @@ -0,0 +1 @@ +too-many-lines:1:0::Too many lines in module (1015/1000) diff --git a/tests/functional/t/too/too_many_lines_disabled.py b/tests/functional/t/too/too_many_lines_disabled.py new file mode 100644 index 000000000..1b0866db2 --- /dev/null +++ b/tests/functional/t/too/too_many_lines_disabled.py @@ -0,0 +1,1018 @@ +"""Test that disabling too-many-lines on any line works.""" + + + +# pylint: disable=too-many-lines +__revision__ = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ZERFZAER = 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +HEHEHE = 2 diff --git a/tests/functional/t/too/too_many_locals.py b/tests/functional/t/too/too_many_locals.py new file mode 100644 index 000000000..ac38a9e01 --- /dev/null +++ b/tests/functional/t/too/too_many_locals.py @@ -0,0 +1,60 @@ +# pylint: disable=missing-docstring +from __future__ import print_function + +def function(arg1, arg2, arg3, arg4, arg5): # [too-many-locals] + arg6, arg7, arg8, arg9 = arg1, arg2, arg3, arg4 + print(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) + loc1, loc2, loc3, loc4, loc5, loc6, loc7 = arg1, arg2, arg3, arg4, arg5, \ + arg6, arg7 + print(loc1, loc2, loc3, loc4, loc5, loc6, loc7) + + +def too_many_locals_function(): # [too-many-locals] + """pylint will complains about too many local variables""" + args0 = 0 + args1 = args0 * 1 + args2 = args1 * 2 + args3 = args2 * 3 + args4 = args3 * 4 + args5 = args4 * 5 + args6 = args5 * 6 + args7 = args6 * 7 + args8 = args7 * 8 + args9 = args8 * 9 + args10 = args9 * 10 + args11 = args10 * 11 + args12 = args11 * 12 + args13 = args12 * 13 + args14 = args13 * 14 + args15 = args14 * 15 + return args15 + +def too_many_arguments_function(arga, argu, argi, arge, argt, args): # [too-many-arguments] + """pylint will complains about too many arguments.""" + arga = argu + arga += argi + arga += arge + arga += argt + arga += args + return arga + +def ignored_arguments_function(arga, argu, argi, + _arge=0, _argt=1, _args=None): + """pylint will ignore _arge, _argt, _args. + + Consequently pylint will only coun 13 arguments. + """ + arg0 = 0 + arg1 = arg0 * 1 + arga + arg2 = arg1 * 2 + argu + arg3 = arg2 * 3 + argi + arg4 = arg3 * 4 + _arge + arg5 = arg4 * 5 + _argt + arg6 = arg5 * 6 + arg7 = arg6 * 7 + arg8 = arg7 * 8 + arg9 = arg8 * 9 + arg9 += arg0 + if _args: + arg9 += sum(_args) + return arg9 diff --git a/tests/functional/t/too/too_many_locals.txt b/tests/functional/t/too/too_many_locals.txt new file mode 100644 index 000000000..4af7f0307 --- /dev/null +++ b/tests/functional/t/too/too_many_locals.txt @@ -0,0 +1,3 @@ +too-many-locals:4:0:function:Too many local variables (16/15) +too-many-locals:12:0:too_many_locals_function:Too many local variables (16/15) +too-many-arguments:32:0:too_many_arguments_function:Too many arguments (6/5) diff --git a/tests/functional/t/too/too_many_nested_blocks.py b/tests/functional/t/too/too_many_nested_blocks.py new file mode 100644 index 000000000..e7c007957 --- /dev/null +++ b/tests/functional/t/too/too_many_nested_blocks.py @@ -0,0 +1,97 @@ +"""Checks the maximum block level is smaller than 6 in function definitions""" + +#pylint: disable=using-constant-test, missing-docstring, too-many-return-statements,no-else-return + +def my_function(): + if 1: # [too-many-nested-blocks] + for i in range(10): + if i == 2: + while True: + try: + if True: + i += 1 + except IOError: + pass + + if 1: + for i in range(10): + if i == 2: + while True: + try: + i += 1 + except IOError: + pass + + def nested_func(): + if True: + for i in range(10): + while True: + if True: + if True: + yield i + + nested_func() + +def more_complex_function(): + attr1 = attr2 = attr3 = [1, 2, 3] + if attr1: + for i in attr1: + if attr2: + return i + else: + return 'duh' + elif attr2: + for i in attr2: + if attr2: + return i + else: + return 'duh' + else: + for i in range(15): + if attr3: + return i + else: + return 'doh' + return None + +def elif_function(): + arg = None + if arg == 1: + return 1 + elif arg == 2: + return 2 + elif arg == 3: + return 3 + elif arg == 4: + return 4 + elif arg == 5: + return 5 + elif arg == 6: + return 6 + elif arg == 7: + return 7 + return None + +def else_if_function(): + arg = None + if arg == 1: # [too-many-nested-blocks] + return 1 + else: + if arg == 2: + return 2 + else: + if arg == 3: + return 3 + else: + if arg == 4: + return 4 + else: + if arg == 5: + return 5 + else: + if arg == 6: + return 6 + else: + if arg == 7: + return 7 + return None diff --git a/tests/functional/t/too/too_many_nested_blocks.txt b/tests/functional/t/too/too_many_nested_blocks.txt new file mode 100644 index 000000000..6232b9ff0 --- /dev/null +++ b/tests/functional/t/too/too_many_nested_blocks.txt @@ -0,0 +1,2 @@ +too-many-nested-blocks:6:4:my_function:Too many nested blocks (6/5) +too-many-nested-blocks:77:4:else_if_function:Too many nested blocks (7/5) diff --git a/tests/functional/t/too/too_many_public_methods.py b/tests/functional/t/too/too_many_public_methods.py new file mode 100644 index 000000000..11b4b367d --- /dev/null +++ b/tests/functional/t/too/too_many_public_methods.py @@ -0,0 +1,79 @@ +# pylint: disable=missing-docstring, useless-object-inheritance + +class Aaaa(object): # [too-many-public-methods] + + def __init__(self): + pass + + def meth1(self): + """hehehe""" + + def meth2(self): + """hehehe""" + + def meth3(self): + """hehehe""" + + def meth4(self): + """hehehe""" + + def meth5(self): + """hehehe""" + + def meth6(self): + """hehehe""" + + def meth7(self): + """hehehe""" + + def meth8(self): + """hehehe""" + + def meth9(self): + """hehehe""" + + def meth10(self): + """hehehe""" + + def meth11(self): + """hehehe""" + + def meth12(self): + """hehehe""" + + def meth13(self): + """hehehe""" + + def meth14(self): + """hehehe""" + + def meth15(self): + """hehehe""" + + def meth16(self): + """hehehe""" + + def meth17(self): + """hehehe""" + + def meth18(self): + """hehehe""" + + def meth19(self): + """hehehe""" + + def meth20(self): + """hehehe""" + + def meth21(self): + """hehehe""" + + def _dontcount(self): + """not public""" + +class BBB(Aaaa): + """Don't emit for methods defined in the parent.""" + def meth1(self): + """trop""" + def meth2(self): + """tzop""" diff --git a/tests/functional/t/too/too_many_public_methods.txt b/tests/functional/t/too/too_many_public_methods.txt new file mode 100644 index 000000000..61e47e8eb --- /dev/null +++ b/tests/functional/t/too/too_many_public_methods.txt @@ -0,0 +1 @@ +too-many-public-methods:3:0:Aaaa:Too many public methods (21/20) diff --git a/tests/functional/t/too/too_many_return_statements.py b/tests/functional/t/too/too_many_return_statements.py new file mode 100644 index 000000000..b9f35a2ad --- /dev/null +++ b/tests/functional/t/too/too_many_return_statements.py @@ -0,0 +1,40 @@ +# pylint: disable=missing-docstring + +def stupid_function(arg): # [too-many-return-statements] + if arg == 1: + return 1 + if arg == 2: + return 2 + if arg == 3: + return 3 + if arg == 4: + return 4 + if arg == 5: + return 5 + if arg == 6: + return 6 + if arg == 7: + return 7 + if arg == 8: + return 8 + if arg == 9: + return 9 + if arg == 10: + return 10 + return None + + +def many_yield(text): + """Not a problem""" + if text: + yield f" line 1: {text}\n" + yield " line 2\n" + yield " line 3\n" + yield " line 4\n" + yield " line 5\n" + else: + yield " line 6\n" + yield " line 7\n" + yield " line 8\n" + yield " line 9\n" + yield " line 10\n" diff --git a/tests/functional/t/too/too_many_return_statements.txt b/tests/functional/t/too/too_many_return_statements.txt new file mode 100644 index 000000000..5abbb71b3 --- /dev/null +++ b/tests/functional/t/too/too_many_return_statements.txt @@ -0,0 +1 @@ +too-many-return-statements:3:0:stupid_function:Too many return statements (11/6) diff --git a/tests/functional/t/too/too_many_star_expressions.py b/tests/functional/t/too/too_many_star_expressions.py new file mode 100644 index 000000000..c1bbfb9d3 --- /dev/null +++ b/tests/functional/t/too/too_many_star_expressions.py @@ -0,0 +1,7 @@ +"""Test for too-many-star-expressions."""
+# pylint: disable=unbalanced-tuple-unpacking
+*FIRST, *SECOND = [1, 2, 3] # [too-many-star-expressions]
+(FIRST, *SECOND), *THIRD = ((1, 2, 3), 4, 5)
+*FIRST_1, SECOND = (1, 2, 3)
+(*FIRST, *SECOND), THIRD = [...] # [too-many-star-expressions]
+((*FIRST, SECOND), *THIRD), *FOURTH = [...]
diff --git a/tests/functional/t/too/too_many_star_expressions.txt b/tests/functional/t/too/too_many_star_expressions.txt new file mode 100644 index 000000000..d1e74b624 --- /dev/null +++ b/tests/functional/t/too/too_many_star_expressions.txt @@ -0,0 +1,2 @@ +too-many-star-expressions:3:0::More than one starred expression in assignment +too-many-star-expressions:6:0::More than one starred expression in assignment diff --git a/tests/functional/t/too/too_many_statements.py b/tests/functional/t/too/too_many_statements.py new file mode 100644 index 000000000..7de72bc2c --- /dev/null +++ b/tests/functional/t/too/too_many_statements.py @@ -0,0 +1,133 @@ +# pylint: disable=missing-docstring, invalid-name + +from __future__ import print_function + +def stupid_function(arg): # [too-many-statements] + if arg == 1: + print(1) + elif arg == 2: + print(1) + elif arg == 3: + print(1) + elif arg == 4: + print(1) + elif arg == 5: + print(1) + elif arg == 6: + print(1) + elif arg == 7: + print(1) + elif arg == 8: + print(1) + elif arg == 9: + print(1) + elif arg == 10: + print(1) + elif arg < 1: + print(1) + print(1) + arg = 0 + for _ in range(arg): + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + print(1) + +def long_function_with_inline_def(fake): # [too-many-statements] + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + def an_inline_function(var): + return var + var + fake = an_inline_function(fake) + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + fake += 1 + + +def exmaple_function(): # [too-many-statements] + a = 1 + b = 2 + c = 3 + d = a * b + c + print(d) diff --git a/tests/functional/t/too/too_many_statements.rc b/tests/functional/t/too/too_many_statements.rc new file mode 100644 index 000000000..d6d22f237 --- /dev/null +++ b/tests/functional/t/too/too_many_statements.rc @@ -0,0 +1,2 @@ +[testoptions] +max-statements=5 diff --git a/tests/functional/t/too/too_many_statements.txt b/tests/functional/t/too/too_many_statements.txt new file mode 100644 index 000000000..c723dba13 --- /dev/null +++ b/tests/functional/t/too/too_many_statements.txt @@ -0,0 +1,3 @@ +too-many-statements:5:0:stupid_function:Too many statements (55/5):HIGH +too-many-statements:62:0:long_function_with_inline_def:Too many statements (62/5):HIGH +too-many-statements:128:0:exmaple_function:Too many statements (6/5):HIGH diff --git a/tests/functional/t/trailing_comma_tuple.py b/tests/functional/t/trailing_comma_tuple.py new file mode 100644 index 000000000..de60184ca --- /dev/null +++ b/tests/functional/t/trailing_comma_tuple.py @@ -0,0 +1,50 @@ +"""Check trailing comma one element tuples.""" +# pylint: disable=missing-docstring +AAA = 1, # [trailing-comma-tuple] +BBB = "aaaa", # [trailing-comma-tuple] +CCC="aaa", # [trailing-comma-tuple] +FFF=['f'], # [trailing-comma-tuple] + +BBB = 1, 2 +CCC = (1, 2, 3) +DDD = ( + 1, 2, 3, +) +EEE = ( + "aaa", +) + + +def test(*args, **kwargs): + return args, kwargs + + +test(widget=1, label='test') +test(widget=1, + label='test') +test(widget=1, \ + label='test') + + +def some_func(first, second): + if first: + return first, # [trailing-comma-tuple] + if second: + return (first, second,) + return first, second, # [trailing-comma-tuple] + + +def some_other_func(): + yield 'hello', # [trailing-comma-tuple] + +GGG = ["aaa" +], # [trailing-comma-tuple] + +HHH = ["aaa" +] + +III = some_func(0, + 0), # [trailing-comma-tuple] + +JJJ = some_func(0, + 0) diff --git a/tests/functional/t/trailing_comma_tuple.txt b/tests/functional/t/trailing_comma_tuple.txt new file mode 100644 index 000000000..0f98b2283 --- /dev/null +++ b/tests/functional/t/trailing_comma_tuple.txt @@ -0,0 +1,9 @@ +trailing-comma-tuple:3:0::Disallow trailing comma tuple +trailing-comma-tuple:4:0::Disallow trailing comma tuple +trailing-comma-tuple:5:0::Disallow trailing comma tuple +trailing-comma-tuple:6:0::Disallow trailing comma tuple +trailing-comma-tuple:31:0::Disallow trailing comma tuple +trailing-comma-tuple:34:0::Disallow trailing comma tuple +trailing-comma-tuple:38:0::Disallow trailing comma tuple +trailing-comma-tuple:41:0::Disallow trailing comma tuple +trailing-comma-tuple:47:0::Disallow trailing comma tuple diff --git a/tests/functional/t/trailing_newlines.py b/tests/functional/t/trailing_newlines.py new file mode 100644 index 000000000..8fbadbb3e --- /dev/null +++ b/tests/functional/t/trailing_newlines.py @@ -0,0 +1,3 @@ +"""Regression test for trailing-newlines (C0304).""" +# +1: [trailing-newlines] + diff --git a/tests/functional/t/trailing_newlines.txt b/tests/functional/t/trailing_newlines.txt new file mode 100644 index 000000000..2558a71f8 --- /dev/null +++ b/tests/functional/t/trailing_newlines.txt @@ -0,0 +1 @@ +trailing-newlines:3:0::Trailing newlines diff --git a/tests/functional/t/trailing_whitespaces.py b/tests/functional/t/trailing_whitespaces.py new file mode 100644 index 000000000..48de809c6 --- /dev/null +++ b/tests/functional/t/trailing_whitespaces.py @@ -0,0 +1,11 @@ +"""Regression test for trailing-whitespace (C0303).""" +# pylint: disable=mixed-line-endings +from __future__ import print_function + +# +1: [trailing-whitespace] +print('some trailing whitespace') +# +1: [trailing-whitespace] +print('trailing whitespace does not count towards the line length limit') +print('windows line ends are ok')
+# +1: [trailing-whitespace]
+print('but trailing whitespace on win is not')
diff --git a/tests/functional/t/trailing_whitespaces.txt b/tests/functional/t/trailing_whitespaces.txt new file mode 100644 index 000000000..1faabc84a --- /dev/null +++ b/tests/functional/t/trailing_whitespaces.txt @@ -0,0 +1,3 @@ +trailing-whitespace:6:33::Trailing whitespace +trailing-whitespace:8:73::Trailing whitespace +trailing-whitespace:11:46::Trailing whitespace diff --git a/tests/functional/t/try_except_raise.py b/tests/functional/t/try_except_raise.py new file mode 100644 index 000000000..006a29bf9 --- /dev/null +++ b/tests/functional/t/try_except_raise.py @@ -0,0 +1,111 @@ +# pylint:disable=missing-docstring, unreachable, bad-except-order, bare-except, unnecessary-pass +# pylint: disable=undefined-variable, broad-except, raise-missing-from +try: + int("9a") +except: # [try-except-raise] + raise + +try: + int("9a") +except: + raise ValueError('Invalid integer') + + +try: + int("9a") +except: # [try-except-raise] + raise + print('caught exception') + +try: + int("9a") +except: + print('caught exception') + raise + + +class AAAException(Exception): + """AAAException""" + pass + +class BBBException(AAAException): + """BBBException""" + pass + +def ccc(): + """try-except-raise test function""" + + try: + raise BBBException("asdf") + except BBBException: + raise + except AAAException: + raise BBBException("raised from AAAException") + + +def ddd(): + """try-except-raise test function""" + + try: + raise BBBException("asdf") + except AAAException: + raise BBBException("raised from AAAException") + except: # [try-except-raise] + raise + +try: + pass +except RuntimeError: + raise +except: + print("a failure") + +try: + pass +except: + print("a failure") +except RuntimeError: # [try-except-raise] + raise + +try: + pass +except: # [try-except-raise] + raise +except RuntimeError: + print("a failure") + +try: + pass +except (FileNotFoundError, PermissionError): + raise +except OSError: + print("a failure") + +# also consider tuples for subsequent exception handler instead of just bare except handler +try: + pass +except (FileNotFoundError, PermissionError): + raise +except (OverflowError, OSError): + print("a failure") + +try: + pass +except (FileNotFoundError, PermissionError): # [try-except-raise] + raise +except (OverflowError, ZeroDivisionError): + print("a failure") + +try: + pass +except (FileNotFoundError, PermissionError): + raise +except Exception: + print("a failure") + +try: + pass +except (FileNotFoundError, PermissionError): + raise +except (Exception,): + print("a failure") diff --git a/tests/functional/t/try_except_raise.txt b/tests/functional/t/try_except_raise.txt new file mode 100644 index 000000000..81e1fd417 --- /dev/null +++ b/tests/functional/t/try_except_raise.txt @@ -0,0 +1,6 @@ +try-except-raise:5:0::The except handler raises immediately +try-except-raise:16:0::The except handler raises immediately +try-except-raise:53:4:ddd:The except handler raises immediately +try-except-raise:67:0::The except handler raises immediately +try-except-raise:72:0::The except handler raises immediately +try-except-raise:94:0::The except handler raises immediately diff --git a/tests/functional/t/try_except_raise_crash.py b/tests/functional/t/try_except_raise_crash.py new file mode 100644 index 000000000..48a043493 --- /dev/null +++ b/tests/functional/t/try_except_raise_crash.py @@ -0,0 +1,26 @@ +# pylint: disable=missing-docstring,too-many-ancestors, broad-except +import collections.abc +from typing import TYPE_CHECKING, Sized + +if TYPE_CHECKING: + BaseClass = Sized +else: + BaseClass = collections.abc.Sized + + +class TestBaseException(BaseClass): + def __len__(self): + return 0 + + +class TestException(TestBaseException): + pass + + +def test(): + try: + 1 / 0 + except TestException: # [catching-non-exception,try-except-raise] + raise + except Exception: + pass diff --git a/tests/functional/t/try_except_raise_crash.rc b/tests/functional/t/try_except_raise_crash.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/t/try_except_raise_crash.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/t/try_except_raise_crash.txt b/tests/functional/t/try_except_raise_crash.txt new file mode 100644 index 000000000..0fab918b9 --- /dev/null +++ b/tests/functional/t/try_except_raise_crash.txt @@ -0,0 +1,2 @@ +catching-non-exception:23:11:test:"Catching an exception which doesn't inherit from Exception: TestException" +try-except-raise:23:4:test:The except handler raises immediately diff --git a/tests/functional/t/typedDict.py b/tests/functional/t/typedDict.py new file mode 100644 index 000000000..3ce96b256 --- /dev/null +++ b/tests/functional/t/typedDict.py @@ -0,0 +1,31 @@ +"""Test typing.TypedDict""" +# pylint: disable=invalid-name,missing-class-docstring,pointless-statement +import typing +from typing import TypedDict + + +class CustomTD(TypedDict): + var: int + + +class CustomTD2(typing.TypedDict, total=False): + var2: str + + +class CustomTD3(CustomTD2): + var3: int + + +CustomTD4 = TypedDict("CustomTD4", var4=bool) + +CustomTD5 = TypedDict("CustomTD5", {"var5": bool}) + +my_dict = CustomTD(var=1) +my_dict["var"] +my_dict["var"] = 2 + + +# https://github.com/PyCQA/pylint/issues/4715 +# Instance of TypedDict should be callable +Link = TypedDict("Link", {"href": str}) +Link(href="foo") diff --git a/tests/functional/t/typedDict.rc b/tests/functional/t/typedDict.rc new file mode 100644 index 000000000..85fc502b3 --- /dev/null +++ b/tests/functional/t/typedDict.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.8 diff --git a/tests/functional/t/typing_generic.py b/tests/functional/t/typing_generic.py new file mode 100644 index 000000000..191d9982d --- /dev/null +++ b/tests/functional/t/typing_generic.py @@ -0,0 +1,32 @@ +# pylint: disable=missing-docstring,invalid-name,too-few-public-methods + +# https://github.com/PyCQA/pylint/issues/2822 +# Base should be subscriptable, even with ABCMeta as metaclass +from abc import ABC, ABCMeta +from typing import Generic, TypeVar + +T = TypeVar("T") + +class Base(Generic[T], metaclass=ABCMeta): + """Base""" + +class Impl(Base[str]): + """Impl""" + + +# https://github.com/PyCQA/astroid/issues/942 +Anything = TypeVar("Anything") +MoreSpecific = TypeVar("MoreSpecific", str, int) + +class A(ABC, Generic[Anything]): + def a_method(self) -> None: # pylint: disable=no-self-use + print("hello") + +class B(A[MoreSpecific]): + pass + +class C(B[str]): + pass + +c = C() +c.a_method() # should NOT emit `no-member` error diff --git a/tests/functional/t/typing_generic.rc b/tests/functional/t/typing_generic.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/t/typing_generic.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/t/typing_use.py b/tests/functional/t/typing_use.py new file mode 100644 index 000000000..b92a08722 --- /dev/null +++ b/tests/functional/t/typing_use.py @@ -0,0 +1,65 @@ +# pylint: disable=missing-docstring + +import typing +from typing import overload + +@typing.overload +def double_with_docstring(arg: str) -> str: + """Return arg, concatenated with itself.""" + + +@typing.overload +def double_with_docstring(arg: int) -> int: + """Return twice arg.""" + + +def double_with_docstring(arg): + """Return 2 * arg.""" + return 2 * arg + + +def double_with_docstring(arg): # [function-redefined] + """Redefined function implementation""" + return 2 * arg + + +@typing.overload +def double_with_ellipsis(arg: str) -> str: + ... + + +@typing.overload +def double_with_ellipsis(arg: int) -> int: + ... + + +def double_with_ellipsis(arg): + return 2 * arg + + +@typing.overload +def double_with_pass(arg: str) -> str: + pass + + +@typing.overload +def double_with_pass(arg: int) -> int: + pass + + +def double_with_pass(arg): + return 2 * arg + +# pylint: disable=too-few-public-methods +class Cls: + @typing.overload + def method(self, param: int) -> None: + ... + + @overload + def method(self, param: str) -> None: + ... + + def method(self, param): + return (self, param) +# pylint: enable=too-few-public-methods diff --git a/tests/functional/t/typing_use.txt b/tests/functional/t/typing_use.txt new file mode 100644 index 000000000..1ff53a13e --- /dev/null +++ b/tests/functional/t/typing_use.txt @@ -0,0 +1 @@ +function-redefined:21:0:double_with_docstring:function already defined line 16 |