diff options
Diffstat (limited to 'tests/functional/u/unpacking')
7 files changed, 222 insertions, 0 deletions
diff --git a/tests/functional/u/unpacking/unpacking.py b/tests/functional/u/unpacking/unpacking.py new file mode 100644 index 000000000..59d9abbe4 --- /dev/null +++ b/tests/functional/u/unpacking/unpacking.py @@ -0,0 +1,11 @@ +""" Code for checking the display of the module
+for unbalanced-tuple-unpacking and unpacking-non-sequence
+"""
+
+def unpack():
+ """ Return something"""
+ return (1, 2, 3)
+
+def nonseq():
+ """ Return non sequence """
+ return 1
diff --git a/tests/functional/u/unpacking/unpacking_generalizations.py b/tests/functional/u/unpacking/unpacking_generalizations.py new file mode 100644 index 000000000..1c5fb16b8 --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_generalizations.py @@ -0,0 +1,29 @@ +"""Various tests for unpacking generalizations added in Python 3.5"""
+
+# pylint: disable=missing-docstring, invalid-name
+
+def func_variadic_args(*args):
+ return args
+
+
+def func_variadic_positional_args(a, b, *args):
+ return a, b, args
+
+def func_positional_args(a, b, c, d):
+ return a, b, c, d
+
+
+func_variadic_args(*(2, 3), *(3, 4), *(4, 5))
+func_variadic_args(1, 2, *(2, 3), 2, 3, *(4, 5))
+func_variadic_positional_args(1, 2, *(4, 5), *(5, 6))
+func_variadic_positional_args(*(2, 3), *(4, 5), *(5, 6))
+func_variadic_positional_args(*(2, 3))
+func_variadic_positional_args(*(2, 3, 4))
+func_variadic_positional_args(1, 2, 3, *(3, 4))
+
+func_positional_args(*(2, 3, 4), *(2, 3)) # [too-many-function-args]
+func_positional_args(*(1, 2), 3) # [no-value-for-parameter]
+func_positional_args(1, *(2, ), 3, *(4, 5)) # [too-many-function-args]
+func_positional_args(1, 2, c=24, d=32, **{'d': 32}) # [repeated-keyword]
+# +1: [repeated-keyword,repeated-keyword]
+func_positional_args(1, 2, c=24, **{'c': 34, 'd': 33}, **{'d': 24})
diff --git a/tests/functional/u/unpacking/unpacking_generalizations.txt b/tests/functional/u/unpacking/unpacking_generalizations.txt new file mode 100644 index 000000000..caecb193e --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_generalizations.txt @@ -0,0 +1,6 @@ +too-many-function-args:24:0:24:41::Too many positional arguments for function call:UNDEFINED +no-value-for-parameter:25:0:25:32::No value for argument 'd' in function call:UNDEFINED +too-many-function-args:26:0:26:43::Too many positional arguments for function call:UNDEFINED +repeated-keyword:27:0:27:51::Got multiple values for keyword argument 'd' in function call:UNDEFINED +repeated-keyword:29:0:29:67::Got multiple values for keyword argument 'c' in function call:UNDEFINED +repeated-keyword:29:0:29:67::Got multiple values for keyword argument 'd' in function call:UNDEFINED diff --git a/tests/functional/u/unpacking/unpacking_non_sequence.py b/tests/functional/u/unpacking/unpacking_non_sequence.py new file mode 100644 index 000000000..0299af762 --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_non_sequence.py @@ -0,0 +1,149 @@ +"""Check unpacking non-sequences in assignments. """ + +# pylint: disable=too-few-public-methods, invalid-name, attribute-defined-outside-init, unused-variable +# pylint: disable=using-constant-test, no-init, missing-docstring, wrong-import-order,wrong-import-position,no-else-return, useless-object-inheritance +from os import rename as nonseq_func +from functional.u.unpacking.unpacking import nonseq +from typing import NamedTuple + +__revision__ = 0 + +# Working + +class Seq(object): + """ sequence """ + def __init__(self): + self.items = range(2) + + def __getitem__(self, item): + return self.items[item] + + def __len__(self): + return len(self.items) + +class Iter(object): + """ Iterator """ + def __iter__(self): + for number in range(2): + yield number + +def good_unpacking(): + """ returns should be unpackable """ + if True: + return [1, 2] + else: + return (3, 4) + +def good_unpacking2(): + """ returns should be unpackable """ + return good_unpacking() + +class MetaIter(type): + "metaclass that makes classes that use it iterables" + def __iter__(cls): + return iter((1, 2)) + +class IterClass(metaclass=MetaIter): + "class that is iterable (and unpackable)" + +class AbstrClass(object): + "abstract class" + pair = None + + def setup_pair(self): + "abstract method" + raise NotImplementedError + + def __init__(self): + "error should not be emitted because setup_pair is abstract" + self.setup_pair() + x, y = self.pair + +a, b = [1, 2] +a, b = (1, 2) +a, b = set([1, 2]) +a, b = {1: 2, 2: 3} +a, b = "xy" +a, b = Seq() +a, b = Iter() +a, b = (number for number in range(2)) +a, b = good_unpacking() +a, b = good_unpacking2() +a, b = IterClass + +# Not working +class NonSeq(object): + """ does nothing """ + +a, b = NonSeq() # [unpacking-non-sequence] +a, b = ValueError # [unpacking-non-sequence] +a, b = None # [unpacking-non-sequence] +a, b = 1 # [unpacking-non-sequence] +a, b = nonseq # [unpacking-non-sequence] +a, b = nonseq() # [unpacking-non-sequence] +a, b = nonseq_func # [unpacking-non-sequence] + +class ClassUnpacking(object): + """ Check unpacking as instance attributes. """ + + def test(self): + """ test unpacking in instance attributes. """ + + self.a, self.b = 1, 2 + self.a, self.b = {1: 2, 2: 3} + self.a, self.b = "xy" + self.a, c = "xy" + c, self.a = good_unpacking() + self.a, self.b = Iter() + + self.a, self.b = NonSeq() # [unpacking-non-sequence] + self.a, self.b = ValueError # [unpacking-non-sequence] + self.a, c = nonseq_func # [unpacking-non-sequence] + +class TestBase(object): + 'base class with `test` method implementation' + @staticmethod + def test(data): + 'default implementation' + return data + +class Test(TestBase): + 'child class that overrides `test` method' + def __init__(self): + # no error should be emitted here as `test` is overridden in this class + (self.aaa, self.bbb, self.ccc) = self.test(None) + + @staticmethod + def test(data): + 'overridden implementation' + return (1, 2, 3) + + +import platform + + +def flow_control_false_positive(): + # This used to trigger an unpacking-non-sequence error. The problem was + # partially related to the fact that pylint does not understand flow control, + # but now it does not emit anymore, for this example, due to skipping it when + # determining an inference of multiple potential values. + # In any case, it is good having this repro as a test. + system, node, release, version, machine, processor = platform.uname() + # The previous line raises W0633 + return system, node, release, version, machine, processor + + +def flow_control_unpacking(var=None): + if var is not None: + var0, var1 = var + return var0, var1 + return None + + +class MyClass(NamedTuple): + x: float + y: float + + def sum(self): + x, y = self + return x + y diff --git a/tests/functional/u/unpacking/unpacking_non_sequence.txt b/tests/functional/u/unpacking/unpacking_non_sequence.txt new file mode 100644 index 000000000..c3c65050c --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_non_sequence.txt @@ -0,0 +1,10 @@ +unpacking-non-sequence:78:0:78:15::Attempting to unpack a non-sequence defined at line 75:UNDEFINED +unpacking-non-sequence:79:0:79:17::Attempting to unpack a non-sequence:UNDEFINED +unpacking-non-sequence:80:0:80:11::Attempting to unpack a non-sequence None:UNDEFINED +unpacking-non-sequence:81:0:81:8::Attempting to unpack a non-sequence 1:UNDEFINED +unpacking-non-sequence:82:0:82:13::Attempting to unpack a non-sequence defined at line 9 of functional.u.unpacking.unpacking:UNDEFINED +unpacking-non-sequence:83:0:83:15::Attempting to unpack a non-sequence defined at line 11 of functional.u.unpacking.unpacking:UNDEFINED +unpacking-non-sequence:84:0:84:18::Attempting to unpack a non-sequence:UNDEFINED +unpacking-non-sequence:99:8:99:33:ClassUnpacking.test:Attempting to unpack a non-sequence defined at line 75:UNDEFINED +unpacking-non-sequence:100:8:100:35:ClassUnpacking.test:Attempting to unpack a non-sequence:UNDEFINED +unpacking-non-sequence:101:8:101:31:ClassUnpacking.test:Attempting to unpack a non-sequence:UNDEFINED diff --git a/tests/functional/u/unpacking/unpacking_non_sequence_py37.py b/tests/functional/u/unpacking/unpacking_non_sequence_py37.py new file mode 100644 index 000000000..dd8af1136 --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_non_sequence_py37.py @@ -0,0 +1,15 @@ +# pylint: disable=missing-docstring + +# https://github.com/PyCQA/pylint/issues/4895 +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass + + +@dataclass +class Metric: + function: Callable[..., tuple[int, int]] + + def update(self): + _, _ = self.function() diff --git a/tests/functional/u/unpacking/unpacking_non_sequence_py37.rc b/tests/functional/u/unpacking/unpacking_non_sequence_py37.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/u/unpacking/unpacking_non_sequence_py37.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 |