"""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, missing-docstring, wrong-import-order,wrong-import-position,no-else-return from os import rename as nonseq_func from functional.u.unpacking.unpacking import nonseq from typing import NamedTuple # Working class Seq: """ 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: """ 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: "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: """ 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: """ 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: '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