| [case testSlotsDefinitionWithStrAndListAndTuple] |
| class A: |
| __slots__ = "a" |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" |
| |
| class B: |
| __slots__ = ("a", "b") |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.c = 3 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" |
| |
| class C: |
| __slots__ = ['c'] |
| def __init__(self) -> None: |
| self.a = 1 # E: Trying to assign name "a" that is not in "__slots__" of type "__main__.C" |
| self.c = 3 |
| |
| class WithVariable: |
| __fields__ = ['a', 'b'] |
| __slots__ = __fields__ |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.c = 3 |
| [builtins fixtures/list.pyi] |
| |
| |
| [case testSlotsDefinitionWithDict] |
| class D: |
| __slots__ = {'key': 'docs'} |
| def __init__(self) -> None: |
| self.key = 1 |
| self.missing = 2 # E: Trying to assign name "missing" that is not in "__slots__" of type "__main__.D" |
| [builtins fixtures/dict.pyi] |
| |
| |
| [case testSlotsDefinitionWithDynamicDict] |
| slot_kwargs = {'b': 'docs'} |
| class WithDictKwargs: |
| __slots__ = {'a': 'docs', **slot_kwargs} |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.c = 3 |
| [builtins fixtures/dict.pyi] |
| |
| |
| [case testSlotsDefinitionWithSet] |
| class E: |
| __slots__ = {'e'} |
| def __init__(self) -> None: |
| self.e = 1 |
| self.missing = 2 # E: Trying to assign name "missing" that is not in "__slots__" of type "__main__.E" |
| [builtins fixtures/set.pyi] |
| |
| |
| [case testSlotsDefinitionOutsideOfClass] |
| __slots__ = ("a", "b") |
| class A: |
| def __init__(self) -> None: |
| self.x = 1 |
| self.y = 2 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsDefinitionWithClassVar] |
| class A: |
| __slots__ = ('a',) |
| b = 4 |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| |
| # You cannot override class-level variables, but you can use them: |
| b = self.b |
| self.b = 2 # E: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" |
| |
| self.c = 3 # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" |
| |
| A.b = 1 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsDefinitionMultipleVars1] |
| class A: |
| __slots__ = __fields__ = ("a", "b") |
| def __init__(self) -> None: |
| self.x = 1 |
| self.y = 2 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsDefinitionMultipleVars2] |
| class A: |
| __fields__ = __slots__ = ("a", "b") |
| def __init__(self) -> None: |
| self.x = 1 |
| self.y = 2 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentEmptySlots] |
| class A: |
| __slots__ = () |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| |
| a = A() |
| a.a = 1 |
| a.b = 2 |
| a.missing = 2 |
| [out] |
| main:4: error: Trying to assign name "a" that is not in "__slots__" of type "__main__.A" |
| main:5: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" |
| main:8: error: Trying to assign name "a" that is not in "__slots__" of type "__main__.A" |
| main:9: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" |
| main:10: error: "A" has no attribute "missing" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithSuper] |
| class A: |
| __slots__ = ("a",) |
| class B(A): |
| __slots__ = ("b", "c") |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self._one = 1 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.c = 3 |
| b._one = 1 |
| b._two = 2 |
| [out] |
| main:9: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" |
| main:14: error: "B" has no attribute "c" |
| main:15: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" |
| main:16: error: "B" has no attribute "_two" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithSuperDuplicateSlots] |
| class A: |
| __slots__ = ("a",) |
| class B(A): |
| __slots__ = ("a", "b",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self._one = 1 # E: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithMixin] |
| class A: |
| __slots__ = ("a",) |
| class Mixin: |
| __slots__ = ("m",) |
| class B(A, Mixin): |
| __slots__ = ("b",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.m = 2 |
| self._one = 1 |
| |
| b = B() |
| b.a = 1 |
| b.m = 2 |
| b.b = 2 |
| b._two = 2 |
| [out] |
| main:11: error: Trying to assign name "_one" that is not in "__slots__" of type "__main__.B" |
| main:16: error: "B" has no attribute "b" |
| main:17: error: "B" has no attribute "_two" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithSlottedSuperButNoChildSlots] |
| class A: |
| __slots__ = ("a",) |
| class B(A): |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 1 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithoutSuperSlots] |
| class A: |
| pass # no slots |
| class B(A): |
| __slots__ = ("a", "b") |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.missing = 3 |
| b.extra = 4 # E: "B" has no attribute "extra" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithoutSuperMixingSlots] |
| class A: |
| __slots__ = () |
| class Mixin: |
| pass # no slots |
| class B(A, Mixin): |
| __slots__ = ("a", "b") |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.missing = 3 |
| b.extra = 4 # E: "B" has no attribute "extra" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithExplicitSetattr] |
| class A: |
| __slots__ = ("a",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| |
| def __setattr__(self, k, v) -> None: |
| ... |
| |
| a = A() |
| a.a = 1 |
| a.b = 2 |
| a.c = 3 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithParentSetattr] |
| class Parent: |
| __slots__ = () |
| |
| def __setattr__(self, k, v) -> None: |
| ... |
| |
| class A(Parent): |
| __slots__ = ("a",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| |
| a = A() |
| a.a = 1 |
| a.b = 2 |
| a.c = 3 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithProps] |
| from typing import Any |
| |
| custom_prop: Any |
| |
| class A: |
| __slots__ = ("a",) |
| |
| @property |
| def first(self) -> int: |
| ... |
| |
| @first.setter |
| def first(self, arg: int) -> None: |
| ... |
| |
| class B(A): |
| __slots__ = ("b",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.c = 3 |
| |
| @property |
| def second(self) -> int: |
| ... |
| |
| @second.setter |
| def second(self, arg: int) -> None: |
| ... |
| |
| def get_third(self) -> int: |
| ... |
| |
| def set_third(self, arg: int) -> None: |
| ... |
| |
| third = custom_prop(get_third, set_third) |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.c = 3 |
| b.first = 1 |
| b.second = 2 |
| b.third = 3 |
| b.extra = 'extra' |
| [out] |
| main:22: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" |
| main:43: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.B" |
| main:47: error: "B" has no attribute "extra" |
| [builtins fixtures/property.pyi] |
| |
| |
| [case testSlotsAssignmentWithUnionProps] |
| from typing import Any, Callable, Union |
| |
| custom_obj: Any |
| |
| class custom_property(object): |
| def __set__(self, *args, **kwargs): |
| ... |
| |
| class A: |
| __slots__ = ("a",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| |
| b: custom_property |
| c: Union[Any, custom_property] |
| d: Union[Callable, custom_property] |
| e: Callable |
| |
| a = A() |
| a.a = 1 |
| a.b = custom_obj |
| a.c = custom_obj |
| a.d = custom_obj |
| a.e = custom_obj |
| [out] |
| [builtins fixtures/dict.pyi] |
| |
| |
| [case testSlotsAssignmentWithMethodReassign] |
| class A: |
| __slots__ = () |
| |
| def __init__(self) -> None: |
| self.method = lambda: None # E: Cannot assign to a method |
| |
| def method(self) -> None: |
| ... |
| |
| a = A() |
| a.method = lambda: None # E: Cannot assign to a method |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithExplicitDict] |
| class A: |
| __slots__ = ("a",) |
| class B(A): |
| __slots__ = ("__dict__",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.c = 3 # E: "B" has no attribute "c" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithExplicitSuperDict] |
| class A: |
| __slots__ = ("__dict__",) |
| class B(A): |
| __slots__ = ("a",) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| |
| b = B() |
| b.a = 1 |
| b.b = 2 |
| b.c = 3 # E: "B" has no attribute "c" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentWithVariable] |
| slot_name = "b" |
| class A: |
| __slots__ = ("a", slot_name) |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.c = 3 |
| |
| a = A() |
| a.a = 1 |
| a.b = 2 |
| a.c = 3 |
| a.d = 4 # E: "A" has no attribute "d" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentMultipleLeftValues] |
| class A: |
| __slots__ = ("a", "b") |
| def __init__(self) -> None: |
| self.a, self.b, self.c = (1, 2, 3) # E: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsAssignmentMultipleAssignments] |
| class A: |
| __slots__ = ("a",) |
| def __init__(self) -> None: |
| self.a = self.b = self.c = 1 |
| [out] |
| main:4: error: Trying to assign name "b" that is not in "__slots__" of type "__main__.A" |
| main:4: error: Trying to assign name "c" that is not in "__slots__" of type "__main__.A" |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsWithTupleCall] |
| class A: |
| # TODO: for now this way of writing tuples are not recognised |
| __slots__ = tuple(("a", "b")) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testSlotsWithListCall] |
| class A: |
| # TODO: for now this way of writing lists are not recognised |
| __slots__ = list(("a", "b")) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| [builtins fixtures/list.pyi] |
| |
| |
| [case testSlotsWithSetCall] |
| class A: |
| # TODO: for now this way of writing sets are not recognised |
| __slots__ = set(("a", "b")) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| [builtins fixtures/set.pyi] |
| |
| |
| [case testSlotsWithDictCall] |
| class A: |
| # TODO: for now this way of writing dicts are not recognised |
| __slots__ = dict((("a", "docs"), ("b", "docs"))) |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| [builtins fixtures/dict.pyi] |
| |
| |
| [case testSlotsWithAny] |
| from typing import Any |
| |
| some_obj: Any |
| |
| class A: |
| # You can do anything with `Any`: |
| __slots__ = some_obj |
| |
| def __init__(self) -> None: |
| self.a = 1 |
| self.b = 2 |
| self.missing = 3 |
| [builtins fixtures/tuple.pyi] |
| |
| [case testSlotsWithClassVar] |
| from typing import ClassVar |
| class X: |
| __slots__ = ('a',) |
| a: int |
| x = X() |
| X.a # E: "a" in __slots__ conflicts with class variable access |
| x.a |
| [builtins fixtures/tuple.pyi] |