| [case testDataclassesBasic] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Person: |
| name: str |
| age: int |
| |
| def summary(self): |
| return "%s is %d years old." % (self.name, self.age) |
| |
| reveal_type(Person) # N: Revealed type is "def (name: builtins.str, age: builtins.int) -> __main__.Person" |
| Person('John', 32) |
| Person('Jonh', 21, None) # E: Too many arguments for "Person" |
| |
| [builtins fixtures/dataclasses.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testDataclassesCustomInit] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| a: int |
| |
| def __init__(self, a: str) -> None: |
| pass |
| |
| A('1') |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesBasicInheritance] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Mammal: |
| age: int |
| |
| @dataclass |
| class Person(Mammal): |
| name: str |
| |
| def summary(self): |
| return "%s is %d years old." % (self.name, self.age) |
| |
| reveal_type(Person) # N: Revealed type is "def (age: builtins.int, name: builtins.str) -> __main__.Person" |
| Mammal(10) |
| Person(32, 'John') |
| Person(21, 'Jonh', None) # E: Too many arguments for "Person" |
| |
| [builtins fixtures/dataclasses.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testDataclassesDeepInheritance] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| a: int |
| |
| @dataclass |
| class B(A): |
| b: int |
| |
| @dataclass |
| class C(B): |
| c: int |
| |
| @dataclass |
| class D(C): |
| d: int |
| |
| reveal_type(A) # N: Revealed type is "def (a: builtins.int) -> __main__.A" |
| reveal_type(B) # N: Revealed type is "def (a: builtins.int, b: builtins.int) -> __main__.B" |
| reveal_type(C) # N: Revealed type is "def (a: builtins.int, b: builtins.int, c: builtins.int) -> __main__.C" |
| reveal_type(D) # N: Revealed type is "def (a: builtins.int, b: builtins.int, c: builtins.int, d: builtins.int) -> __main__.D" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesMultipleInheritance] |
| from dataclasses import dataclass, field, InitVar |
| @dataclass |
| class A: |
| a: bool |
| |
| @dataclass |
| class B: |
| b: InitVar[bool] |
| _b: bool = field(init=False) |
| |
| def __post_init__(self, b: bool): |
| self._b = b |
| |
| @dataclass |
| class C(A, B): |
| pass |
| |
| reveal_type(C) # N: Revealed type is "def (b: builtins.bool, a: builtins.bool) -> __main__.C" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDeepInitVarInheritance] |
| from dataclasses import dataclass, field, InitVar |
| @dataclass |
| class A: |
| a: bool |
| |
| @dataclass |
| class B: |
| b: InitVar[bool] |
| _b: bool = field(init=False) |
| |
| def __post_init__(self, b: bool): |
| self._b = b |
| |
| @dataclass(init=False) |
| class C(B): |
| def __init__(self): |
| super().__init__(True) |
| |
| @dataclass |
| class D(C): |
| pass |
| |
| reveal_type(C) # N: Revealed type is "def () -> __main__.C" |
| reveal_type(D) # N: Revealed type is "def (b: builtins.bool) -> __main__.D" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOverriding] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Mammal: |
| age: int |
| |
| @dataclass |
| class Person(Mammal): |
| name: str |
| age: int |
| |
| @dataclass |
| class SpecialPerson(Person): |
| special_factor: float |
| |
| @dataclass |
| class ExtraSpecialPerson(SpecialPerson): |
| age: int |
| special_factor: float |
| name: str |
| |
| reveal_type(Person) # N: Revealed type is "def (age: builtins.int, name: builtins.str) -> __main__.Person" |
| reveal_type(SpecialPerson) # N: Revealed type is "def (age: builtins.int, name: builtins.str, special_factor: builtins.float) -> __main__.SpecialPerson" |
| reveal_type(ExtraSpecialPerson) # N: Revealed type is "def (age: builtins.int, name: builtins.str, special_factor: builtins.float) -> __main__.ExtraSpecialPerson" |
| Person(32, 'John') |
| Person(21, 'John', None) # E: Too many arguments for "Person" |
| SpecialPerson(21, 'John', 0.5) |
| ExtraSpecialPerson(21, 'John', 0.5) |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOverridingWithDefaults] |
| # Issue #5681 https://github.com/python/mypy/issues/5681 |
| from dataclasses import dataclass |
| from typing import Any |
| |
| @dataclass |
| class Base: |
| some_int: Any |
| some_str: str = 'foo' |
| |
| |
| @dataclass |
| class C(Base): |
| some_int: int |
| |
| reveal_type(C) # N: Revealed type is "def (some_int: builtins.int, some_str: builtins.str =) -> __main__.C" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassIncompatibleOverrides] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Base: |
| foo: int |
| |
| @dataclass |
| class BadDerived1(Base): |
| def foo(self) -> int: # E: Dataclass attribute may only be overridden by another attribute \ |
| # E: Signature of "foo" incompatible with supertype "Base" \ |
| # N: Superclass: \ |
| # N: int \ |
| # N: Subclass: \ |
| # N: def foo(self) -> int |
| return 1 |
| |
| @dataclass |
| class BadDerived2(Base): |
| @property # E: Dataclass attribute may only be overridden by another attribute |
| def foo(self) -> int: # E: Cannot override writeable attribute with read-only property |
| return 2 |
| |
| @dataclass |
| class BadDerived3(Base): |
| class foo: pass # E: Dataclass attribute may only be overridden by another attribute |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassMultipleInheritance] |
| from dataclasses import dataclass |
| |
| class Unrelated: |
| foo: str |
| |
| @dataclass |
| class Base: |
| bar: int |
| |
| @dataclass |
| class Derived(Base, Unrelated): |
| pass |
| |
| d = Derived(3) |
| reveal_type(d.foo) # N: Revealed type is "builtins.str" |
| reveal_type(d.bar) # N: Revealed type is "builtins.int" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassIncompatibleFrozenOverride] |
| from dataclasses import dataclass |
| |
| @dataclass(frozen=True) |
| class Base: |
| foo: int |
| |
| @dataclass(frozen=True) |
| class BadDerived(Base): |
| @property # E: Dataclass attribute may only be overridden by another attribute |
| def foo(self) -> int: |
| return 3 |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesFreezing] |
| from dataclasses import dataclass |
| |
| @dataclass(frozen=True) |
| class Person: |
| name: str |
| |
| john = Person('John') |
| john.name = 'Ben' # E: Property "name" defined in "Person" is read-only |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInconsistentFreezing] |
| from dataclasses import dataclass |
| |
| @dataclass(frozen=True) |
| class FrozenBase: |
| pass |
| |
| @dataclass |
| class BadNormalDerived(FrozenBase): # E: Cannot inherit non-frozen dataclass from a frozen one |
| pass |
| |
| @dataclass |
| class NormalBase: |
| pass |
| |
| @dataclass(frozen=True) |
| class BadFrozenDerived(NormalBase): # E: Cannot inherit frozen dataclass from a non-frozen one |
| pass |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesFields] |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Person: |
| name: str |
| age: int = field(default=0, init=False) |
| |
| reveal_type(Person) # N: Revealed type is "def (name: builtins.str) -> __main__.Person" |
| john = Person('John') |
| john.age = 'invalid' # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| john.age = 24 |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesBadInit] |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Person: |
| name: str |
| age: int = field(init=None) # E: No overload variant of "field" matches argument type "None" \ |
| # N: Possible overload variants: \ |
| # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ |
| # N: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ |
| # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesMultiInit] |
| from dataclasses import dataclass, field |
| from typing import List |
| |
| @dataclass |
| class Person: |
| name: str |
| age: int = field(init=False) |
| friend_names: List[str] = field(init=True) |
| enemy_names: List[str] |
| |
| reveal_type(Person) # N: Revealed type is "def (name: builtins.str, friend_names: builtins.list[builtins.str], enemy_names: builtins.list[builtins.str]) -> __main__.Person" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesMultiInitDefaults] |
| from dataclasses import dataclass, field |
| from typing import List, Optional |
| |
| @dataclass |
| class Person: |
| name: str |
| age: int = field(init=False) |
| friend_names: List[str] = field(init=True) |
| enemy_names: List[str] |
| nickname: Optional[str] = None |
| |
| reveal_type(Person) # N: Revealed type is "def (name: builtins.str, friend_names: builtins.list[builtins.str], enemy_names: builtins.list[builtins.str], nickname: Union[builtins.str, None] =) -> __main__.Person" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaults] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int = 0 |
| |
| reveal_type(Application) # N: Revealed type is "def (name: builtins.str =, rating: builtins.int =) -> __main__.Application" |
| app = Application() |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaultFactories] |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int = field(default_factory=int) |
| rating_count: int = field() # E: Attributes without a default cannot follow attributes with one |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaultFactoryTypeChecking] |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int = field(default_factory=str) # E: Incompatible types in assignment (expression has type "str", variable has type "int") |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaultOrdering] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int # E: Attributes without a default cannot follow attributes with one |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnly] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass(kw_only=True) |
| class Application: |
| name: str = 'Unnamed' |
| rating: int |
| |
| Application(rating=5) |
| Application(name='name', rating=5) |
| Application() # E: Missing named argument "rating" for "Application" |
| Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" |
| Application('name', 123) # E: Too many positional arguments for "Application" |
| Application('name', rating=123) # E: Too many positional arguments for "Application" |
| Application(name=123, rating='name') # E: Argument "name" to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" |
| Application(rating='name', name=123) # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" # E: Argument "name" to "Application" has incompatible type "int"; expected "str" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyOnField] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int = field(kw_only=True) |
| |
| Application(rating=5) |
| Application('name', rating=123) |
| Application(name='name', rating=5) |
| Application() # E: Missing named argument "rating" for "Application" |
| Application('name') # E: Missing named argument "rating" for "Application" |
| Application('name', 123) # E: Too many positional arguments for "Application" |
| Application(123, rating='name') # E: Argument 1 to "Application" has incompatible type "int"; expected "str" # E: Argument "rating" to "Application" has incompatible type "str"; expected "int" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyOnFieldFalse] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Application: |
| name: str = 'Unnamed' |
| rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one |
| |
| Application(name='name', rating=5) |
| Application('name', 123) |
| Application('name', rating=123) |
| Application() # E: Missing positional argument "name" in call to "Application" |
| Application('name') # E: Too few arguments for "Application" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyWithSentinel] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, KW_ONLY |
| |
| @dataclass |
| class Application: |
| _: KW_ONLY |
| name: str = 'Unnamed' |
| rating: int |
| |
| Application(rating=5) |
| Application(name='name', rating=5) |
| Application() # E: Missing named argument "rating" for "Application" |
| Application('name') # E: Too many positional arguments for "Application" # E: Missing named argument "rating" for "Application" |
| Application('name', 123) # E: Too many positional arguments for "Application" |
| Application('name', rating=123) # E: Too many positional arguments for "Application" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyWithSentinelAndFieldOverride] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, field, KW_ONLY |
| |
| @dataclass |
| class Application: |
| _: KW_ONLY |
| name: str = 'Unnamed' |
| rating: int = field(kw_only=False) # E: Attributes without a default cannot follow attributes with one |
| |
| Application(name='name', rating=5) |
| Application() # E: Missing positional argument "name" in call to "Application" |
| Application('name') # E: Too many positional arguments for "Application" # E: Too few arguments for "Application" |
| Application('name', 123) # E: Too many positional arguments for "Application" |
| Application('name', rating=123) # E: Too many positional arguments for "Application" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyWithSentinelAndSubclass] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, field, KW_ONLY |
| |
| @dataclass |
| class Base: |
| x: str |
| _: KW_ONLY |
| y: int = 0 |
| w: int = 1 |
| |
| @dataclass |
| class D(Base): |
| z: str |
| a: str = "a" |
| |
| D("Hello", "World") |
| D(x="Hello", z="World") |
| D("Hello", "World", y=1, w=2, a="b") |
| D("Hello") # E: Missing positional argument "z" in call to "D" |
| D() # E: Missing positional arguments "x", "z" in call to "D" |
| D(123, "World") # E: Argument 1 to "D" has incompatible type "int"; expected "str" |
| D("Hello", False) # E: Argument 2 to "D" has incompatible type "bool"; expected "str" |
| D(123, False) # E: Argument 1 to "D" has incompatible type "int"; expected "str" # E: Argument 2 to "D" has incompatible type "bool"; expected "str" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOrderingKwOnlyWithMultipleSentinel] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass, field, KW_ONLY |
| |
| @dataclass |
| class Base: |
| x: str |
| _: KW_ONLY |
| y: int = 0 |
| __: KW_ONLY # E: There may not be more than one field with the KW_ONLY type |
| w: int = 1 |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesClassmethods] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Application: |
| name: str |
| |
| @classmethod |
| def parse(cls, request: str) -> "Application": |
| return cls(name='...') |
| |
| app = Application.parse('') |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesOverloadsAndClassmethods] |
| from dataclasses import dataclass |
| from typing import overload, Union |
| |
| @dataclass |
| class A: |
| a: int |
| b: str |
| |
| @classmethod |
| def other(cls) -> str: |
| return "..." |
| |
| @overload |
| @classmethod |
| def foo(cls, x: int) -> int: ... |
| |
| @overload |
| @classmethod |
| def foo(cls, x: str) -> str: ... |
| |
| @classmethod |
| def foo(cls, x: Union[int, str]) -> Union[int, str]: |
| reveal_type(cls) # N: Revealed type is "Type[__main__.A]" |
| reveal_type(cls.other()) # N: Revealed type is "builtins.str" |
| return x |
| |
| reveal_type(A.foo(3)) # N: Revealed type is "builtins.int" |
| reveal_type(A.foo("foo")) # N: Revealed type is "builtins.str" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testClassmethodShadowingFieldDoesNotCrash] |
| from dataclasses import dataclass |
| |
| # This used to crash -- see #6217 |
| @dataclass |
| class Foo: |
| bar: str |
| @classmethod # E: Name "bar" already defined on line 6 |
| def bar(cls) -> "Foo": |
| return cls('asdf') |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesClassVars] |
| from dataclasses import dataclass |
| from typing import ClassVar |
| |
| @dataclass |
| class Application: |
| name: str |
| |
| COUNTER: ClassVar[int] = 0 |
| |
| reveal_type(Application) # N: Revealed type is "def (name: builtins.str) -> __main__.Application" |
| application = Application("example") |
| application.COUNTER = 1 # E: Cannot assign to class variable "COUNTER" via instance |
| Application.COUNTER = 1 |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testTypeAliasInDataclassDoesNotCrash] |
| from dataclasses import dataclass |
| from typing import Callable |
| from typing_extensions import TypeAlias |
| |
| @dataclass |
| class Foo: |
| x: int |
| |
| @dataclass |
| class One: |
| S: TypeAlias = Foo # E: Type aliases inside dataclass definitions are not supported at runtime |
| |
| a = One() |
| reveal_type(a.S) # N: Revealed type is "def (x: builtins.int) -> __main__.Foo" |
| a.S() # E: Missing positional argument "x" in call to "Foo" |
| reveal_type(a.S(5)) # N: Revealed type is "__main__.Foo" |
| |
| @dataclass |
| class Two: |
| S: TypeAlias = Callable[[int], str] # E: Type aliases inside dataclass definitions are not supported at runtime |
| |
| c = Two() |
| x = c.S |
| reveal_type(x) # N: Revealed type is "typing._SpecialForm" |
| [builtins fixtures/dataclasses.pyi] |
| [typing fixtures/typing-medium.pyi] |
| |
| [case testDataclassOrdering] |
| from dataclasses import dataclass |
| |
| @dataclass(order=True) |
| class Application: |
| name: str |
| rating: int |
| |
| app1 = Application('example-1', 5) |
| app2 = Application('example-2', 5) |
| app1 < app2 |
| app1 > app2 |
| app1 <= app2 |
| app1 >= app2 |
| app1 < 5 # E: Unsupported operand types for < ("Application" and "int") |
| app1 > 5 # E: Unsupported operand types for > ("Application" and "int") |
| app1 <= 5 # E: Unsupported operand types for <= ("Application" and "int") |
| app1 >= 5 # E: Unsupported operand types for >= ("Application" and "int") |
| |
| class SpecializedApplication(Application): |
| ... |
| |
| app3 = SpecializedApplication('example-3', 5) |
| app1 < app3 |
| app1 > app3 |
| app1 <= app3 |
| app1 >= app3 |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassOrderingWithoutEquality] |
| from dataclasses import dataclass |
| |
| @dataclass(eq=False, order=True) # E: "eq" must be True if "order" is True |
| class Application: |
| ... |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassOrderingWithCustomMethods] |
| from dataclasses import dataclass |
| |
| @dataclass(order=True) |
| class Application: |
| def __lt__(self, other: 'Application') -> bool: # E: You may not have a custom "__lt__" method when "order" is True |
| ... |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassDefaultsInheritance] |
| from dataclasses import dataclass |
| from typing import Optional |
| |
| @dataclass(order=True) |
| class Application: |
| id: Optional[int] |
| name: str |
| |
| @dataclass |
| class SpecializedApplication(Application): |
| rating: int = 0 |
| |
| reveal_type(SpecializedApplication) # N: Revealed type is "def (id: Union[builtins.int, None], name: builtins.str, rating: builtins.int =) -> __main__.SpecializedApplication" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenerics] |
| from dataclasses import dataclass |
| from typing import Generic, List, Optional, TypeVar |
| |
| T = TypeVar('T') |
| |
| @dataclass |
| class A(Generic[T]): |
| x: T |
| y: T |
| z: List[T] |
| |
| def foo(self) -> List[T]: |
| return [self.x, self.y] |
| |
| def bar(self) -> T: |
| return self.z[0] |
| |
| def problem(self) -> T: |
| return self.z # E: Incompatible return value type (got "List[T]", expected "T") |
| |
| reveal_type(A) # N: Revealed type is "def [T] (x: T`1, y: T`1, z: builtins.list[T`1]) -> __main__.A[T`1]" |
| A(1, 2, ["a", "b"]) # E: Cannot infer type argument 1 of "A" |
| a = A(1, 2, [1, 2]) |
| reveal_type(a) # N: Revealed type is "__main__.A[builtins.int]" |
| reveal_type(a.x) # N: Revealed type is "builtins.int" |
| reveal_type(a.y) # N: Revealed type is "builtins.int" |
| reveal_type(a.z) # N: Revealed type is "builtins.list[builtins.int]" |
| s: str = a.bar() # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericCovariant] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T_co = TypeVar("T_co", covariant=True) |
| |
| @dataclass |
| class MyDataclass(Generic[T_co]): |
| a: T_co |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassUntypedGenericInheritance] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class Base(Generic[T]): |
| attr: T |
| |
| @dataclass |
| class Sub(Base): |
| pass |
| |
| sub = Sub(attr=1) |
| reveal_type(sub) # N: Revealed type is "__main__.Sub" |
| reveal_type(sub.attr) # N: Revealed type is "Any" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericSubtype] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class Base(Generic[T]): |
| attr: T |
| |
| S = TypeVar("S") |
| |
| @dataclass |
| class Sub(Base[S]): |
| pass |
| |
| sub_int = Sub[int](attr=1) |
| reveal_type(sub_int) # N: Revealed type is "__main__.Sub[builtins.int]" |
| reveal_type(sub_int.attr) # N: Revealed type is "builtins.int" |
| |
| sub_str = Sub[str](attr='ok') |
| reveal_type(sub_str) # N: Revealed type is "__main__.Sub[builtins.str]" |
| reveal_type(sub_str.attr) # N: Revealed type is "builtins.str" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericInheritance] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T1 = TypeVar("T1") |
| T2 = TypeVar("T2") |
| T3 = TypeVar("T3") |
| |
| @dataclass |
| class Base(Generic[T1, T2, T3]): |
| one: T1 |
| two: T2 |
| three: T3 |
| |
| @dataclass |
| class Sub(Base[int, str, float]): |
| pass |
| |
| sub = Sub(one=1, two='ok', three=3.14) |
| reveal_type(sub) # N: Revealed type is "__main__.Sub" |
| reveal_type(sub.one) # N: Revealed type is "builtins.int" |
| reveal_type(sub.two) # N: Revealed type is "builtins.str" |
| reveal_type(sub.three) # N: Revealed type is "builtins.float" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassMultiGenericInheritance] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class Base(Generic[T]): |
| base_attr: T |
| |
| S = TypeVar("S") |
| |
| @dataclass |
| class Middle(Base[int], Generic[S]): |
| middle_attr: S |
| |
| @dataclass |
| class Sub(Middle[str]): |
| pass |
| |
| sub = Sub(base_attr=1, middle_attr='ok') |
| reveal_type(sub) # N: Revealed type is "__main__.Sub" |
| reveal_type(sub.base_attr) # N: Revealed type is "builtins.int" |
| reveal_type(sub.middle_attr) # N: Revealed type is "builtins.str" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericsClassmethod] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar('T') |
| |
| @dataclass |
| class A(Generic[T]): |
| x: T |
| |
| @classmethod |
| def foo(cls) -> None: |
| reveal_type(cls) # N: Revealed type is "Type[__main__.A[T`1]]" |
| cls.x # E: Access to generic instance variables via class is ambiguous |
| |
| @classmethod |
| def other(cls, x: T) -> A[T]: ... |
| |
| reveal_type(A(0).other) # N: Revealed type is "def (x: builtins.int) -> __main__.A[builtins.int]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesForwardRefs] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| b: 'B' |
| |
| @dataclass |
| class B: |
| x: int |
| |
| reveal_type(A) # N: Revealed type is "def (b: __main__.B) -> __main__.A" |
| A(b=B(42)) |
| A(b=42) # E: Argument "b" to "A" has incompatible type "int"; expected "B" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| |
| [case testDataclassesInitVars] |
| from dataclasses import InitVar, dataclass |
| |
| @dataclass |
| class Application: |
| name: str |
| database_name: InitVar[str] |
| |
| reveal_type(Application) # N: Revealed type is "def (name: builtins.str, database_name: builtins.str) -> __main__.Application" |
| app = Application("example", 42) # E: Argument 2 to "Application" has incompatible type "int"; expected "str" |
| app = Application("example", "apps") |
| app.name |
| app.database_name # E: "Application" has no attribute "database_name" |
| |
| |
| @dataclass |
| class SpecializedApplication(Application): |
| rating: int |
| |
| reveal_type(SpecializedApplication) # N: Revealed type is "def (name: builtins.str, database_name: builtins.str, rating: builtins.int) -> __main__.SpecializedApplication" |
| app = SpecializedApplication("example", "apps", "five") # E: Argument 3 to "SpecializedApplication" has incompatible type "str"; expected "int" |
| app = SpecializedApplication("example", "apps", 5) |
| app.name |
| app.rating |
| app.database_name # E: "SpecializedApplication" has no attribute "database_name" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInitVarsAndDefer] |
| from dataclasses import InitVar, dataclass |
| |
| defer: Yes |
| |
| @dataclass |
| class Application: |
| name: str |
| database_name: InitVar[str] |
| |
| reveal_type(Application) # N: Revealed type is "def (name: builtins.str, database_name: builtins.str) -> __main__.Application" |
| app = Application("example", 42) # E: Argument 2 to "Application" has incompatible type "int"; expected "str" |
| app = Application("example", "apps") |
| app.name |
| app.database_name # E: "Application" has no attribute "database_name" |
| |
| class Yes: ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesNoInitInitVarInheritance] |
| from dataclasses import dataclass, field, InitVar |
| |
| @dataclass |
| class Super: |
| foo: InitVar = field(init=False) |
| |
| @dataclass |
| class Sub(Super): |
| bar: int |
| |
| sub = Sub(5) |
| sub.foo # E: "Sub" has no attribute "foo" |
| sub.bar |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFactory] |
| from typing import Type, TypeVar |
| from dataclasses import dataclass |
| |
| T = TypeVar('T', bound='A') |
| |
| @dataclass |
| class A: |
| @classmethod |
| def make(cls: Type[T]) -> T: |
| reveal_type(cls) # N: Revealed type is "Type[T`-1]" |
| reveal_type(cls()) # N: Revealed type is "T`-1" |
| return cls() |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInitVarOverride] |
| import dataclasses |
| |
| @dataclasses.dataclass |
| class A: |
| a: dataclasses.InitVar[int] |
| _a: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a): |
| self._a = a |
| |
| @dataclasses.dataclass(init=False) |
| class B(A): |
| b: dataclasses.InitVar[int] |
| _b: int = dataclasses.field(init=False) |
| |
| def __init__(self, b): |
| super().__init__(b+1) |
| self._b = b |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInitVarNoOverride] |
| import dataclasses |
| |
| @dataclasses.dataclass |
| class A: |
| a: dataclasses.InitVar[int] |
| _a: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a): |
| self._a = a |
| |
| @dataclasses.dataclass(init=True) |
| class B(A): |
| b: dataclasses.InitVar[int] |
| _b: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a, b): |
| self._a = a |
| self._b = b |
| |
| B(1, 2) |
| B(1, 'a') # E: Argument 2 to "B" has incompatible type "str"; expected "int" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInitVarPostInitOverride] |
| import dataclasses |
| |
| @dataclasses.dataclass |
| class A: |
| a: dataclasses.InitVar[int] |
| _a: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a: int) -> None: |
| self._a = a |
| |
| @dataclasses.dataclass |
| class B(A): |
| b: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a: int) -> None: |
| super().__post_init__(a) |
| self.b = a + 1 |
| |
| @dataclasses.dataclass(init=False) |
| class C(B): |
| c: int |
| |
| def __init__(self, a: int, c: int) -> None: |
| super().__init__(a) |
| self.c = c + self.b |
| |
| A(1) |
| B(1) |
| B(1, 2) # E: Too many arguments for "B" |
| C(1, 2) |
| C(1, 'a') # E: Argument 2 to "C" has incompatible type "str"; expected "int" |
| |
| [builtins fixtures/primitives.pyi] |
| |
| [case testDataclassesInitVarIncremental] |
| import a |
| |
| [file a.py] |
| import dataclasses |
| from b import A |
| |
| @dataclasses.dataclass |
| class B(A): |
| b: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a: int) -> None: |
| super().__post_init__(a) |
| self.b = a + 1 |
| |
| [file a.py.2] |
| import dataclasses |
| from b import A |
| |
| @dataclasses.dataclass |
| class B(A): |
| b: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a: int) -> None: |
| super().__post_init__(a) |
| self.b = a + 2 |
| |
| reveal_type(B) |
| |
| [file b.py] |
| import dataclasses |
| |
| @dataclasses.dataclass |
| class A: |
| a: dataclasses.InitVar[int] |
| _a: int = dataclasses.field(init=False) |
| |
| def __post_init__(self, a: int) -> None: |
| self._a = a |
| [out2] |
| tmp/a.py:12: note: Revealed type is "def (a: builtins.int) -> a.B" |
| |
| [builtins fixtures/primitives.pyi] |
| |
| |
| [case testNoComplainFieldNone] |
| # flags: --no-strict-optional |
| from dataclasses import dataclass, field |
| from typing import Optional |
| |
| @dataclass |
| class Foo: |
| bar: Optional[int] = field(default=None) |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| |
| [case testNoComplainFieldNoneStrict] |
| from dataclasses import dataclass, field |
| from typing import Optional |
| |
| @dataclass |
| class Foo: |
| bar: Optional[int] = field(default=None) |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| |
| [case testDisallowUntypedWorksForward] |
| # flags: --disallow-untyped-defs |
| from dataclasses import dataclass |
| from typing import List |
| |
| @dataclass |
| class B: |
| x: C |
| |
| class C(List[C]): |
| pass |
| |
| reveal_type(B) # N: Revealed type is "def (x: __main__.C) -> __main__.B" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDisallowUntypedWorksForwardBad] |
| # flags: --disallow-untyped-defs |
| from dataclasses import dataclass |
| |
| @dataclass |
| class B: |
| x: Undefined # E: Name "Undefined" is not defined |
| y = undefined() # E: Name "undefined" is not defined |
| |
| reveal_type(B) # N: Revealed type is "def (x: Any) -> __main__.B" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testMemberExprWorksAsField] |
| import dataclasses |
| |
| @dataclasses.dataclass |
| class A: |
| x: int = dataclasses.field(metadata={"doc": "foo"}) |
| y: str |
| |
| @dataclasses.dataclass |
| class B: |
| x: int = dataclasses.field(init=False, default=1) |
| y: str |
| |
| @dataclasses.dataclass |
| class C: |
| x: int = dataclasses.field(default=1) |
| y: str = dataclasses.field(metadata={"doc": "foo"}) # E: Attributes without a default cannot follow attributes with one |
| [builtins fixtures/dict.pyi] |
| |
| [case testDataclassOrderingDeferred] |
| from dataclasses import dataclass |
| |
| defer: Yes |
| |
| @dataclass(order=True) |
| class Application: |
| name: str |
| rating: int |
| |
| a = Application('', 0) |
| b = Application('', 0) |
| a < b |
| |
| class Yes: ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldDeferred] |
| from dataclasses import field, dataclass |
| |
| @dataclass |
| class C: |
| x: int = field(default=func()) |
| |
| def func() -> int: ... |
| C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldDeferredFrozen] |
| from dataclasses import field, dataclass |
| |
| @dataclass(frozen=True) |
| class C: |
| x: int = field(default=func()) |
| |
| def func() -> int: ... |
| c: C |
| c.x = 1 # E: Property "x" defined in "C" is read-only |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testTypeInDataclassDeferredStar] |
| import lib |
| [file lib.py] |
| from dataclasses import dataclass |
| MYPY = False |
| if MYPY: # Force deferral |
| from other import * |
| |
| @dataclass |
| class C: |
| total: int |
| |
| C() # E: Missing positional argument "total" in call to "C" |
| C('no') # E: Argument 1 to "C" has incompatible type "str"; expected "int" |
| [file other.py] |
| import lib |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDeferredDataclassInitSignature] |
| # flags: --no-strict-optional |
| from dataclasses import dataclass |
| from typing import Optional, Type |
| |
| @dataclass |
| class C: |
| x: Optional[int] = None |
| y: Type[Deferred] = Deferred |
| |
| @classmethod |
| def default(cls) -> C: |
| return cls(x=None, y=None) |
| |
| class Deferred: pass |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDeferredDataclassInitSignatureSubclass] |
| from dataclasses import dataclass |
| from typing import Optional |
| |
| @dataclass |
| class B: |
| x: Optional[C] |
| |
| @dataclass |
| class C(B): |
| y: str |
| |
| a = C(None, 'abc') |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaultsIncremental] |
| import a |
| |
| [file a.py] |
| from dataclasses import dataclass |
| from b import Person |
| |
| @dataclass |
| class Asdf(Person): |
| c: str = 'test' |
| |
| [file a.py.2] |
| from dataclasses import dataclass |
| from b import Person |
| |
| @dataclass |
| class Asdf(Person): |
| c: str = 'test' |
| |
| # asdf |
| |
| [file b.py] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Person: |
| b: int |
| a: str = 'test' |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesDefaultsMroOtherFile] |
| import a |
| |
| [file a.py] |
| from dataclasses import dataclass |
| from b import A1, A2 |
| |
| @dataclass |
| class Asdf(A1, A2): # E: Attributes without a default cannot follow attributes with one |
| pass |
| |
| [file b.py] |
| from dataclasses import dataclass |
| |
| # a bunch of blank lines to make sure the error doesn't accidentally line up... |
| |
| |
| |
| @dataclass |
| class A1: |
| a: int |
| |
| @dataclass |
| class A2: |
| b: str = 'test' |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesInheritingDuplicateField] |
| # see mypy issue #7792 |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| x: int = 0 |
| x: int = 0 # E: Name "x" already defined on line 6 |
| |
| @dataclass |
| class B(A): |
| pass |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInheritanceNoAnnotation] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| foo: int |
| |
| x = 0 |
| @dataclass |
| class B(A): |
| foo = x |
| |
| reveal_type(B) # N: Revealed type is "def (foo: builtins.int) -> __main__.B" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInheritanceNoAnnotation2] |
| from dataclasses import dataclass |
| |
| @dataclass(frozen=True) |
| class A: |
| foo: int |
| |
| @dataclass(frozen=True) |
| class B(A): |
| @property # E: Dataclass attribute may only be overridden by another attribute |
| def foo(self) -> int: pass |
| |
| reveal_type(B) # N: Revealed type is "def (foo: builtins.int) -> __main__.B" |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassHasAttributeWithFields] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| pass |
| |
| reveal_type(A.__dataclass_fields__) # N: Revealed type is "builtins.dict[builtins.str, dataclasses.Field[Any]]" |
| |
| [builtins fixtures/dict.pyi] |
| |
| [case testDataclassCallableFieldAccess] |
| from dataclasses import dataclass |
| from typing import Callable |
| |
| @dataclass |
| class A: |
| x: Callable[[int], int] |
| y: Callable[[int], int] = lambda i: i |
| |
| a = A(lambda i:i) |
| x: int = a.x(0) |
| y: str = a.y(0) # E: Incompatible types in assignment (expression has type "int", variable has type "str") |
| reveal_type(a.x) # N: Revealed type is "def (builtins.int) -> builtins.int" |
| reveal_type(a.y) # N: Revealed type is "def (builtins.int) -> builtins.int" |
| reveal_type(A.y) # N: Revealed type is "def (builtins.int) -> builtins.int" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassCallableFieldAssignment] |
| from dataclasses import dataclass |
| from typing import Callable |
| |
| @dataclass |
| class A: |
| x: Callable[[int], int] |
| |
| def x(i: int) -> int: |
| return i |
| def x2(s: str) -> str: |
| return s |
| |
| a = A(lambda i:i) |
| a.x = x |
| a.x = x2 # E: Incompatible types in assignment (expression has type "Callable[[str], str]", variable has type "Callable[[int], int]") |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldDoesNotFailOnKwargsUnpacking] |
| # https://github.com/python/mypy/issues/10879 |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Foo: |
| bar: float = field(**{"repr": False}) |
| [out] |
| main:6: error: Unpacking **kwargs in "field()" is not supported |
| main:6: error: No overload variant of "field" matches argument type "Dict[str, bool]" |
| main:6: note: Possible overload variants: |
| main:6: note: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T |
| main:6: note: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T |
| main:6: note: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldWithPositionalArguments] |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class C: |
| x: int = field(0) # E: "field()" does not accept positional arguments \ |
| # E: No overload variant of "field" matches argument type "int" \ |
| # N: Possible overload variants: \ |
| # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ |
| # N: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ |
| # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldWithTypedDictUnpacking] |
| from dataclasses import dataclass, field |
| from typing import TypedDict |
| |
| class FieldKwargs(TypedDict): |
| repr: bool |
| |
| field_kwargs: FieldKwargs = {"repr": False} |
| |
| @dataclass |
| class Foo: |
| bar: float = field(**field_kwargs) # E: Unpacking **kwargs in "field()" is not supported |
| |
| reveal_type(Foo(bar=1.5)) # N: Revealed type is "__main__.Foo" |
| [builtins fixtures/dataclasses.pyi] |
| [typing fixtures/typing-typeddict.pyi] |
| |
| [case testDataclassWithSlotsArg] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass(slots=True) |
| class Some: |
| x: int |
| |
| def __init__(self, x: int) -> None: |
| self.x = x |
| self.y = 0 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" |
| |
| def __post_init__(self) -> None: |
| self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithSlotsDef] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass(slots=False) |
| class Some: |
| __slots__ = ('x',) |
| x: int |
| |
| def __init__(self, x: int) -> None: |
| self.x = x |
| self.y = 0 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" |
| |
| def __post_init__(self) -> None: |
| self.y = 1 # E: Trying to assign name "y" that is not in "__slots__" of type "__main__.Some" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithSlotsDerivedFromNonSlot] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| class A: |
| pass |
| |
| @dataclass(slots=True) |
| class B(A): |
| x: int |
| |
| def __post_init__(self) -> None: |
| self.y = 42 |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithSlotsConflict] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass(slots=True) |
| class Some: # E: "Some" both defines "__slots__" and is used with "slots=True" |
| __slots__ = ('x',) |
| x: int |
| |
| @dataclass(slots=True) |
| class EmptyDef: # E: "EmptyDef" both defines "__slots__" and is used with "slots=True" |
| __slots__ = () |
| x: int |
| |
| slots = ('x',) |
| |
| @dataclass(slots=True) |
| class DynamicDef: # E: "DynamicDef" both defines "__slots__" and is used with "slots=True" |
| __slots__ = slots |
| x: int |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithSlotsArgBefore310] |
| # flags: --python-version 3.9 |
| from dataclasses import dataclass |
| |
| @dataclass(slots=True) # E: Keyword argument "slots" for "dataclass" is only valid in Python 3.10 and higher |
| class Some: |
| x: int |
| |
| # Possible conflict: |
| @dataclass(slots=True) # E: Keyword argument "slots" for "dataclass" is only valid in Python 3.10 and higher |
| class Other: |
| __slots__ = ('x',) |
| x: int |
| [builtins fixtures/dataclasses.pyi] |
| |
| |
| [case testDataclassWithSlotsRuntimeAttr] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass(slots=True) |
| class Some: |
| x: int |
| y: str |
| z: bool |
| |
| reveal_type(Some.__slots__) # N: Revealed type is "Tuple[builtins.str, builtins.str, builtins.str]" |
| |
| @dataclass(slots=True) |
| class Other: |
| x: int |
| y: str |
| |
| reveal_type(Other.__slots__) # N: Revealed type is "Tuple[builtins.str, builtins.str]" |
| |
| |
| @dataclass |
| class NoSlots: |
| x: int |
| y: str |
| |
| NoSlots.__slots__ # E: "Type[NoSlots]" has no attribute "__slots__" |
| [builtins fixtures/dataclasses.pyi] |
| |
| |
| [case testSlotsDefinitionWithTwoPasses1] |
| # flags: --python-version 3.10 |
| # https://github.com/python/mypy/issues/11821 |
| from typing import TypeVar, Protocol, Generic |
| from dataclasses import dataclass |
| |
| C = TypeVar("C", bound="Comparable") |
| |
| class Comparable(Protocol): |
| pass |
| |
| V = TypeVar("V", bound=Comparable) |
| |
| @dataclass(slots=True) |
| class Node(Generic[V]): # Error was here |
| data: V |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testSlotsDefinitionWithTwoPasses2] |
| # flags: --python-version 3.10 |
| from typing import TypeVar, Protocol, Generic |
| from dataclasses import dataclass |
| |
| C = TypeVar("C", bound="Comparable") |
| |
| class Comparable(Protocol): |
| pass |
| |
| V = TypeVar("V", bound=Comparable) |
| |
| @dataclass(slots=True) # Explicit slots are still not ok: |
| class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" |
| __slots__ = ('data',) |
| data: V |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testSlotsDefinitionWithTwoPasses3] |
| # flags: --python-version 3.10 |
| from typing import TypeVar, Protocol, Generic |
| from dataclasses import dataclass |
| |
| C = TypeVar("C", bound="Comparable") |
| |
| class Comparable(Protocol): |
| pass |
| |
| V = TypeVar("V", bound=Comparable) |
| |
| @dataclass(slots=True) # Explicit slots are still not ok, even empty ones: |
| class Node(Generic[V]): # E: "Node" both defines "__slots__" and is used with "slots=True" |
| __slots__ = () |
| data: V |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testSlotsDefinitionWithTwoPasses4] |
| # flags: --python-version 3.10 |
| import dataclasses as dtc |
| |
| PublishedMessagesVar = dict[int, 'PublishedMessages'] |
| |
| @dtc.dataclass(frozen=True, slots=True) |
| class PublishedMessages: |
| left: int |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesAnyInherit] |
| from dataclasses import dataclass |
| from typing import Any |
| B: Any |
| @dataclass |
| class A(B): |
| a: int |
| @dataclass |
| class C(B): |
| generated_args: int |
| generated_kwargs: int |
| |
| A(a=1, b=2) |
| A(1) |
| A(a="foo") # E: Argument "a" to "A" has incompatible type "str"; expected "int" |
| C(generated_args="foo", generated_kwargs="bar") # E: Argument "generated_args" to "C" has incompatible type "str"; expected "int" \ |
| # E: Argument "generated_kwargs" to "C" has incompatible type "str"; expected "int" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesCallableFrozen] |
| from dataclasses import dataclass |
| from typing import Any, Callable |
| @dataclass(frozen=True) |
| class A: |
| a: Callable[..., None] |
| |
| def func() -> None: |
| pass |
| |
| reveal_type(A.a) # N: Revealed type is "def (*Any, **Any)" |
| A(a=func).a() |
| A(a=func).a = func # E: Property "a" defined in "A" is read-only |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInFunctionDoesNotCrash] |
| from dataclasses import dataclass |
| |
| def foo() -> None: |
| @dataclass |
| class Foo: |
| foo: int |
| # This used to crash (see #8703) |
| # The return type of __call__ here needs to be something undefined |
| # In order to trigger the crash that existed prior to #12762 |
| def __call__(self) -> asdf: ... # E: Name "asdf" is not defined |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassesMultipleInheritanceWithNonDataclass] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| |
| @dataclass |
| class A: |
| prop_a: str |
| |
| @dataclass |
| class B: |
| prop_b: bool |
| |
| class Derived(A, B): |
| pass |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericInheritance2] |
| from dataclasses import dataclass |
| from typing import Any, Callable, Generic, TypeVar, List |
| |
| T = TypeVar("T") |
| S = TypeVar("S") |
| |
| @dataclass |
| class Parent(Generic[T]): |
| f: Callable[[T], Any] |
| |
| @dataclass |
| class Child(Parent[T]): ... |
| |
| class A: ... |
| def func(obj: A) -> bool: ... |
| |
| reveal_type(Child[A](func).f) # N: Revealed type is "def (__main__.A) -> Any" |
| |
| @dataclass |
| class Parent2(Generic[T]): |
| a: List[T] |
| |
| @dataclass |
| class Child2(Generic[T, S], Parent2[S]): |
| b: List[T] |
| |
| reveal_type(Child2([A()], [1]).a) # N: Revealed type is "builtins.list[__main__.A]" |
| reveal_type(Child2[int, A]([A()], [1]).b) # N: Revealed type is "builtins.list[builtins.int]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInheritOptionalType] |
| from dataclasses import dataclass |
| from typing import Any, Callable, Generic, TypeVar, List, Optional |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class Parent(Generic[T]): |
| x: Optional[str] |
| @dataclass |
| class Child(Parent): |
| y: Optional[int] |
| Child(x=1, y=1) # E: Argument "x" to "Child" has incompatible type "int"; expected "Optional[str]" |
| Child(x='', y='') # E: Argument "y" to "Child" has incompatible type "str"; expected "Optional[int]" |
| Child(x='', y=1) |
| Child(x=None, y=None) |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericInheritanceSpecialCase1] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar, List |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class Parent(Generic[T]): |
| x: List[T] |
| |
| @dataclass |
| class Child1(Parent["Child2"]): ... |
| |
| @dataclass |
| class Child2(Parent["Child1"]): ... |
| |
| def f(c: Child2) -> None: |
| reveal_type(Child1([c]).x) # N: Revealed type is "builtins.list[__main__.Child2]" |
| |
| def g(c: Child1) -> None: |
| reveal_type(Child2([c]).x) # N: Revealed type is "builtins.list[__main__.Child1]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericInheritanceSpecialCase2] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T") |
| |
| # A subclass might be analyzed before base in import cycles. They are |
| # defined here in reversed order to simulate this. |
| |
| @dataclass |
| class Child1(Parent["Child2"]): |
| x: int |
| |
| @dataclass |
| class Child2(Parent["Child1"]): |
| y: int |
| |
| @dataclass |
| class Parent(Generic[T]): |
| key: str |
| |
| Child1(x=1, key='') |
| Child2(y=1, key='') |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericWithBound] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T", bound="C") |
| |
| @dataclass |
| class C(Generic[T]): |
| x: int |
| |
| c: C[C] |
| d: C[str] # E: Type argument "str" of "C" must be a subtype of "C[Any]" |
| C(x=2) |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassGenericBoundToInvalidTypeVarDoesNotCrash] |
| import dataclasses |
| from typing import Generic, TypeVar |
| |
| T = TypeVar("T", bound="NotDefined") # E: Name "NotDefined" is not defined |
| |
| @dataclasses.dataclass |
| class C(Generic[T]): |
| x: float |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInitVarCannotBeSet] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class C: |
| x: InitVar[int] = 0 |
| y: InitVar[str] = '' |
| |
| def f(self) -> None: |
| # This works at runtime, but it seems like an abuse of the InitVar |
| # feature and thus we don't support it |
| self.x = 1 # E: "C" has no attribute "x" |
| self.y: str = 'x' # E: "C" has no attribute "y" |
| |
| c = C() |
| c2 = C(x=1) |
| c.x # E: "C" has no attribute "x" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassCheckTypeVarBounds] |
| from dataclasses import dataclass |
| from typing import ClassVar, Protocol, Dict, TypeVar, Generic |
| |
| class DataclassProtocol(Protocol): |
| __dataclass_fields__: ClassVar[Dict] |
| |
| T = TypeVar("T", bound=DataclassProtocol) |
| |
| @dataclass |
| class MyDataclass: |
| x: int = 1 |
| |
| class MyGeneric(Generic[T]): ... |
| class MyClass(MyGeneric[MyDataclass]): ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithMatchArgs] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| @dataclass |
| class One: |
| bar: int |
| baz: str |
| o: One |
| reveal_type(o.__match_args__) # N: Revealed type is "Tuple[Literal['bar'], Literal['baz']]" |
| @dataclass(match_args=True) |
| class Two: |
| bar: int |
| t: Two |
| reveal_type(t.__match_args__) # N: Revealed type is "Tuple[Literal['bar']]" |
| @dataclass |
| class Empty: |
| ... |
| e: Empty |
| reveal_type(e.__match_args__) # N: Revealed type is "Tuple[()]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithoutMatchArgs] |
| # flags: --python-version 3.10 |
| from dataclasses import dataclass |
| @dataclass(match_args=False) |
| class One: |
| bar: int |
| baz: str |
| o: One |
| reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \ |
| # N: Revealed type is "Any" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassWithMatchArgsOldVersion] |
| # flags: --python-version 3.9 |
| from dataclasses import dataclass |
| @dataclass(match_args=True) |
| class One: |
| bar: int |
| o: One |
| reveal_type(o.__match_args__) # E: "One" has no attribute "__match_args__" \ |
| # N: Revealed type is "Any" |
| @dataclass |
| class Two: |
| bar: int |
| t: Two |
| reveal_type(t.__match_args__) # E: "Two" has no attribute "__match_args__" \ |
| # N: Revealed type is "Any" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testFinalInDataclass] |
| from dataclasses import dataclass |
| from typing import Final |
| |
| @dataclass |
| class FirstClass: |
| FIRST_CONST: Final = 3 # OK |
| |
| @dataclass |
| class SecondClass: |
| SECOND_CONST: Final = FirstClass.FIRST_CONST # E: Need type argument for Final[...] with non-literal default in dataclass |
| |
| reveal_type(FirstClass().FIRST_CONST) # N: Revealed type is "Literal[3]?" |
| FirstClass().FIRST_CONST = 42 # E: Cannot assign to final attribute "FIRST_CONST" |
| reveal_type(SecondClass().SECOND_CONST) # N: Revealed type is "Literal[3]?" |
| SecondClass().SECOND_CONST = 42 # E: Cannot assign to final attribute "SECOND_CONST" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassFieldsProtocol] |
| # flags: --python-version 3.9 |
| from dataclasses import dataclass |
| from typing import Any, Protocol |
| |
| class ConfigProtocol(Protocol): |
| __dataclass_fields__: dict[str, Any] |
| |
| def takes_cp(cp: ConfigProtocol): ... |
| |
| @dataclass |
| class MyDataclass: |
| x: int = 3 |
| |
| takes_cp(MyDataclass) |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassTypeAnnotationAliasUpdated] |
| import a |
| [file a.py] |
| from dataclasses import dataclass |
| from b import B |
| |
| @dataclass |
| class D: |
| x: B |
| |
| reveal_type(D) # N: Revealed type is "def (x: builtins.list[b.C]) -> a.D" |
| [file b.py] |
| from typing import List |
| import a |
| class CC: ... |
| class C(CC): ... |
| B = List[C] |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassSelfType] |
| from dataclasses import dataclass |
| from typing import Self, TypeVar, Generic, Optional |
| |
| T = TypeVar("T") |
| |
| @dataclass |
| class LinkedList(Generic[T]): |
| value: T |
| next: Optional[Self] = None |
| |
| def meth(self) -> None: |
| reveal_type(self.next) # N: Revealed type is "Union[Self`0, None]" |
| |
| l_int: LinkedList[int] = LinkedList(1, LinkedList("no", None)) # E: Argument 1 to "LinkedList" has incompatible type "str"; expected "int" |
| |
| @dataclass |
| class SubLinkedList(LinkedList[int]): ... |
| |
| lst = SubLinkedList(1, LinkedList(2)) # E: Argument 2 to "SubLinkedList" has incompatible type "LinkedList[int]"; expected "Optional[SubLinkedList]" |
| reveal_type(lst.next) # N: Revealed type is "Union[__main__.SubLinkedList, None]" |
| reveal_type(SubLinkedList) # N: Revealed type is "def (value: builtins.int, next: Union[__main__.SubLinkedList, None] =) -> __main__.SubLinkedList" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testNoCrashOnNestedGenericCallable] |
| from dataclasses import dataclass |
| from typing import Generic, TypeVar, Callable |
| |
| T = TypeVar('T') |
| R = TypeVar('R') |
| X = TypeVar('X') |
| |
| @dataclass |
| class Box(Generic[T]): |
| inner: T |
| |
| @dataclass |
| class Cont(Generic[R]): |
| run: Box[Callable[[X], R]] |
| |
| def const_two(x: T) -> str: |
| return "two" |
| |
| c = Cont(Box(const_two)) |
| reveal_type(c) # N: Revealed type is "__main__.Cont[builtins.str]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testNoCrashOnSelfWithForwardRefGenericDataclass] |
| from typing import Generic, Sequence, TypeVar, Self |
| from dataclasses import dataclass |
| |
| _T = TypeVar('_T', bound="Foo") |
| |
| @dataclass |
| class Foo: |
| foo: int |
| |
| @dataclass |
| class Element(Generic[_T]): |
| elements: Sequence[Self] |
| |
| @dataclass |
| class Bar(Foo): ... |
| e: Element[Bar] |
| reveal_type(e.elements) # N: Revealed type is "typing.Sequence[__main__.Element[__main__.Bar]]" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testIfConditionsInDefinition] |
| # flags: --python-version 3.11 --always-true TRUTH |
| from dataclasses import dataclass |
| from typing import TYPE_CHECKING |
| |
| TRUTH = False # Is set to --always-true |
| |
| @dataclass |
| class Foo: |
| if TYPE_CHECKING: |
| present_1: int |
| else: |
| skipped_1: int |
| if True: # Mypy does not know if it is True or False, so the block is used |
| present_2: int |
| if False: # Mypy does not know if it is True or False, so the block is used |
| present_3: int |
| if not TRUTH: |
| skipped_2: int |
| elif 123: |
| present_4: int |
| elif TRUTH: |
| present_5: int |
| else: |
| skipped_3: int |
| |
| Foo( |
| present_1=1, |
| present_2=2, |
| present_3=3, |
| present_4=4, |
| present_5=5, |
| ) |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testReplace] |
| from dataclasses import dataclass, replace, InitVar |
| from typing import ClassVar |
| |
| @dataclass |
| class A: |
| x: int |
| q: InitVar[int] |
| q2: InitVar[int] = 0 |
| c: ClassVar[int] |
| |
| |
| a = A(x=42, q=7) |
| a2 = replace(a) # E: Missing named argument "q" for "replace" of "A" |
| a2 = replace(a, q=42) |
| a2 = replace(a, x=42, q=42) |
| a2 = replace(a, x=42, q=42, c=7) # E: Unexpected keyword argument "c" for "replace" of "A" |
| a2 = replace(a, x='42', q=42) # E: Argument "x" to "replace" of "A" has incompatible type "str"; expected "int" |
| a2 = replace(a, q='42') # E: Argument "q" to "replace" of "A" has incompatible type "str"; expected "int" |
| reveal_type(a2) # N: Revealed type is "__main__.A" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceUnion] |
| from typing import Generic, Union, TypeVar |
| from dataclasses import dataclass, replace, InitVar |
| |
| T = TypeVar('T') |
| |
| @dataclass |
| class A(Generic[T]): |
| x: T # exercises meet(T=int, int) = int |
| y: bool # exercises meet(bool, int) = bool |
| z: str # exercises meet(str, bytes) = Never |
| w: dict # exercises meet(dict, Never) = Never |
| init_var: InitVar[int] # exercises (non-optional, optional) = non-optional |
| |
| @dataclass |
| class B: |
| x: int |
| y: int |
| z: bytes |
| init_var: int |
| |
| |
| a_or_b: Union[A[int], B] |
| _ = replace(a_or_b, x=42, y=True, init_var=42) |
| _ = replace(a_or_b, x=42, y=True) # E: Missing named argument "init_var" for "replace" of "Union[A[int], B]" |
| _ = replace(a_or_b, x=42, y=True, z='42', init_var=42) # E: Argument "z" to "replace" of "Union[A[int], B]" has incompatible type "str"; expected "Never" |
| _ = replace(a_or_b, x=42, y=True, w={}, init_var=42) # E: Argument "w" to "replace" of "Union[A[int], B]" has incompatible type "Dict[Never, Never]"; expected "Never" |
| _ = replace(a_or_b, y=42, init_var=42) # E: Argument "y" to "replace" of "Union[A[int], B]" has incompatible type "int"; expected "bool" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceUnionOfTypeVar] |
| from typing import Generic, Union, TypeVar |
| from dataclasses import dataclass, replace |
| |
| @dataclass |
| class A: |
| x: int |
| y: int |
| z: str |
| w: dict |
| |
| class B: |
| pass |
| |
| TA = TypeVar('TA', bound=A) |
| TB = TypeVar('TB', bound=B) |
| |
| def f(b_or_t: Union[TA, TB, int]) -> None: |
| a2 = replace(b_or_t) # E: Value of type variable "_DataclassT" of "replace" cannot be "Union[TA, TB, int]" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceTypeVarBoundNotDataclass] |
| from dataclasses import dataclass, replace |
| from typing import Union, TypeVar |
| |
| TInt = TypeVar('TInt', bound=int) |
| TAny = TypeVar('TAny') |
| TNone = TypeVar('TNone', bound=None) |
| TUnion = TypeVar('TUnion', bound=Union[str, int]) |
| |
| def f1(t: TInt) -> None: |
| _ = replace(t, x=42) # E: Value of type variable "_DataclassT" of "replace" cannot be "TInt" |
| |
| def f2(t: TAny) -> TAny: |
| return replace(t, x='spam') # E: Value of type variable "_DataclassT" of "replace" cannot be "TAny" |
| |
| def f3(t: TNone) -> TNone: |
| return replace(t, x='spam') # E: Value of type variable "_DataclassT" of "replace" cannot be "TNone" |
| |
| def f4(t: TUnion) -> TUnion: |
| return replace(t, x='spam') # E: Value of type variable "_DataclassT" of "replace" cannot be "TUnion" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceTypeVarBound] |
| from dataclasses import dataclass, replace |
| from typing import TypeVar |
| |
| @dataclass |
| class A: |
| x: int |
| |
| @dataclass |
| class B(A): |
| pass |
| |
| TA = TypeVar('TA', bound=A) |
| |
| def f(t: TA) -> TA: |
| t2 = replace(t, x=42) |
| reveal_type(t2) # N: Revealed type is "TA`-1" |
| _ = replace(t, x='42') # E: Argument "x" to "replace" of "TA" has incompatible type "str"; expected "int" |
| return t2 |
| |
| f(A(x=42)) |
| f(B(x=42)) |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceAny] |
| from dataclasses import replace |
| from typing import Any |
| |
| a: Any |
| a2 = replace(a) |
| reveal_type(a2) # N: Revealed type is "Any" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceNotDataclass] |
| from dataclasses import replace |
| |
| replace(5) # E: Value of type variable "_DataclassT" of "replace" cannot be "int" |
| |
| class C: |
| pass |
| |
| replace(C()) # E: Value of type variable "_DataclassT" of "replace" cannot be "C" |
| |
| replace(None) # E: Value of type variable "_DataclassT" of "replace" cannot be "None" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceIsDataclass] |
| from dataclasses import is_dataclass, replace |
| |
| def f(x: object) -> None: |
| _ = replace(x) # E: Value of type variable "_DataclassT" of "replace" cannot be "object" |
| if is_dataclass(x): |
| _ = replace(x) # E: Value of type variable "_DataclassT" of "replace" cannot be "Union[DataclassInstance, Type[DataclassInstance]]" |
| if not isinstance(x, type): |
| _ = replace(x) |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testReplaceGeneric] |
| from dataclasses import dataclass, replace, InitVar |
| from typing import ClassVar, Generic, TypeVar |
| |
| T = TypeVar('T') |
| |
| @dataclass |
| class A(Generic[T]): |
| x: T |
| |
| a = A(x=42) |
| reveal_type(a) # N: Revealed type is "__main__.A[builtins.int]" |
| a2 = replace(a, x=42) |
| reveal_type(a2) # N: Revealed type is "__main__.A[builtins.int]" |
| a2 = replace(a, x='42') # E: Argument "x" to "replace" of "A[int]" has incompatible type "str"; expected "int" |
| reveal_type(a2) # N: Revealed type is "__main__.A[builtins.int]" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testPostInitNotMethod] |
| def __post_init__() -> None: |
| pass |
| |
| [case testPostInitCorrectSignature] |
| from typing import Any, Generic, TypeVar, Callable, Self |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Test1: |
| x: int |
| def __post_init__(self) -> None: ... |
| |
| @dataclass |
| class Test2: |
| x: int |
| y: InitVar[int] |
| z: str |
| def __post_init__(self, y: int) -> None: ... |
| |
| @dataclass |
| class Test3: |
| x: InitVar[int] |
| y: InitVar[str] |
| def __post_init__(self, x: int, y: str) -> None: ... |
| |
| @dataclass |
| class Test4: |
| x: int |
| y: InitVar[str] |
| z: InitVar[bool] = True |
| def __post_init__(self, y: str, z: bool) -> None: ... |
| |
| @dataclass |
| class Test5: |
| y: InitVar[str] = 'a' |
| z: InitVar[bool] = True |
| def __post_init__(self, y: str = 'a', z: bool = True) -> None: ... |
| |
| F = TypeVar('F', bound=Callable[..., Any]) |
| def identity(f: F) -> F: return f |
| |
| @dataclass |
| class Test6: |
| y: InitVar[str] |
| @identity # decorated method works |
| def __post_init__(self, y: str) -> None: ... |
| |
| T = TypeVar('T') |
| |
| @dataclass |
| class Test7(Generic[T]): |
| t: InitVar[T] |
| def __post_init__(self, t: T) -> None: ... |
| |
| @dataclass |
| class Test8: |
| s: InitVar[Self] |
| def __post_init__(self, s: Self) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitSubclassing] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Base: |
| a: str |
| x: InitVar[int] |
| def __post_init__(self, x: int) -> None: ... |
| |
| @dataclass |
| class Child(Base): |
| b: str |
| y: InitVar[str] |
| def __post_init__(self, x: int, y: str) -> None: ... |
| |
| @dataclass |
| class GrandChild(Child): |
| c: int |
| z: InitVar[str] = "a" |
| def __post_init__(self, x: int, y: str, z: str) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitNotADataclassCheck] |
| from dataclasses import dataclass, InitVar |
| |
| class Regular: |
| __post_init__ = 1 # can be whatever |
| |
| class Base: |
| x: InitVar[int] |
| def __post_init__(self) -> None: ... # can be whatever |
| |
| @dataclass |
| class Child(Base): |
| y: InitVar[str] |
| def __post_init__(self, y: str) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitMissingParam] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Child: |
| y: InitVar[str] |
| def __post_init__(self) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| main:6: error: Signature of "__post_init__" incompatible with supertype "dataclass" |
| main:6: note: Superclass: |
| main:6: note: def __post_init__(self: Child, y: str) -> None |
| main:6: note: Subclass: |
| main:6: note: def __post_init__(self: Child) -> None |
| |
| [case testPostInitWrongTypeAndName] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Test1: |
| y: InitVar[str] |
| def __post_init__(self, x: int) -> None: ... # E: Argument 2 of "__post_init__" is incompatible with supertype "dataclass"; supertype defines the argument type as "str" |
| |
| @dataclass |
| class Test2: |
| y: InitVar[str] = 'a' |
| def __post_init__(self, x: int) -> None: ... # E: Argument 2 of "__post_init__" is incompatible with supertype "dataclass"; supertype defines the argument type as "str" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitExtraParam] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Child: |
| y: InitVar[str] |
| def __post_init__(self, y: str, z: int) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| main:6: error: Signature of "__post_init__" incompatible with supertype "dataclass" |
| main:6: note: Superclass: |
| main:6: note: def __post_init__(self: Child, y: str) -> None |
| main:6: note: Subclass: |
| main:6: note: def __post_init__(self: Child, y: str, z: int) -> None |
| |
| [case testPostInitReturnType] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Child: |
| y: InitVar[str] |
| def __post_init__(self, y: str) -> int: ... # E: Return type "int" of "__post_init__" incompatible with return type "None" in supertype "dataclass" |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitDecoratedMethodError] |
| from dataclasses import dataclass, InitVar |
| from typing import Any, Callable, TypeVar |
| |
| F = TypeVar('F', bound=Callable[..., Any]) |
| def identity(f: F) -> F: return f |
| |
| @dataclass |
| class Klass: |
| y: InitVar[str] |
| @identity |
| def __post_init__(self) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| main:11: error: Signature of "__post_init__" incompatible with supertype "dataclass" |
| main:11: note: Superclass: |
| main:11: note: def __post_init__(self: Klass, y: str) -> None |
| main:11: note: Subclass: |
| main:11: note: def __post_init__(self: Klass) -> None |
| |
| [case testPostInitIsNotAFunction] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Test: |
| y: InitVar[str] |
| __post_init__ = 1 # E: "__post_init__" method must be an instance method |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPostInitClassMethod] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Test: |
| y: InitVar[str] |
| @classmethod |
| def __post_init__(cls) -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| main:7: error: Signature of "__post_init__" incompatible with supertype "dataclass" |
| main:7: note: Superclass: |
| main:7: note: def __post_init__(self: Test, y: str) -> None |
| main:7: note: Subclass: |
| main:7: note: @classmethod |
| main:7: note: def __post_init__(cls: Type[Test]) -> None |
| |
| [case testPostInitStaticMethod] |
| from dataclasses import dataclass, InitVar |
| |
| @dataclass |
| class Test: |
| y: InitVar[str] |
| @staticmethod |
| def __post_init__() -> None: ... |
| [builtins fixtures/dataclasses.pyi] |
| [out] |
| main:7: error: Signature of "__post_init__" incompatible with supertype "dataclass" |
| main:7: note: Superclass: |
| main:7: note: def __post_init__(self: Test, y: str) -> None |
| main:7: note: Subclass: |
| main:7: note: @staticmethod |
| main:7: note: def __post_init__() -> None |
| |
| [case testProtocolNoCrash] |
| from typing import Protocol, Union, ClassVar |
| from dataclasses import dataclass, field |
| |
| DEFAULT = 0 |
| |
| @dataclass |
| class Test(Protocol): |
| x: int |
| def reset(self) -> None: |
| self.x = DEFAULT |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testProtocolNoCrashOnJoining] |
| from dataclasses import dataclass |
| from typing import Protocol |
| |
| @dataclass |
| class MyDataclass(Protocol): ... |
| |
| a: MyDataclass |
| b = [a, a] # trigger joining the types |
| |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testPropertyAndFieldRedefinitionNoCrash] |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Foo: |
| @property |
| def c(self) -> int: |
| return 0 |
| |
| c: int # E: Name "c" already defined on line 5 |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDataclassInheritanceWorksWithExplicitOverrides] |
| # flags: --enable-error-code explicit-override |
| from dataclasses import dataclass |
| |
| @dataclass |
| class Base: |
| x: int |
| |
| @dataclass |
| class Child(Base): |
| y: int |
| [builtins fixtures/dataclasses.pyi] |
| |
| |
| [case testDataclassInheritanceWorksWithExplicitOverridesAndOrdering] |
| # flags: --enable-error-code explicit-override |
| from dataclasses import dataclass |
| |
| @dataclass(order=True) |
| class Base: |
| x: int |
| |
| @dataclass(order=True) |
| class Child(Base): |
| y: int |
| [builtins fixtures/dataclasses.pyi] |
| |
| [case testDunderReplacePresent] |
| # flags: --python-version 3.13 |
| from dataclasses import dataclass, field |
| |
| @dataclass |
| class Coords: |
| x: int |
| y: int |
| # non-init fields are not allowed with replace: |
| z: int = field(init=False) |
| |
| |
| replaced = Coords(2, 4).__replace__(x=2, y=5) |
| reveal_type(replaced) # N: Revealed type is "__main__.Coords" |
| |
| replaced = Coords(2, 4).__replace__(x=2) |
| reveal_type(replaced) # N: Revealed type is "__main__.Coords" |
| |
| Coords(2, 4).__replace__(x="asdf") # E: Argument "x" to "__replace__" of "Coords" has incompatible type "str"; expected "int" |
| Coords(2, 4).__replace__(23) # E: Too many positional arguments for "__replace__" of "Coords" |
| Coords(2, 4).__replace__(23, 25) # E: Too many positional arguments for "__replace__" of "Coords" |
| Coords(2, 4).__replace__(x=23, y=25, z=42) # E: Unexpected keyword argument "z" for "__replace__" of "Coords" |
| |
| from typing import Generic, TypeVar |
| T = TypeVar('T') |
| |
| @dataclass |
| class Gen(Generic[T]): |
| x: T |
| |
| replaced_2 = Gen(2).__replace__(x=2) |
| reveal_type(replaced_2) # N: Revealed type is "__main__.Gen[builtins.int]" |
| Gen(2).__replace__(x="not an int") # E: Argument "x" to "__replace__" of "Gen" has incompatible type "str"; expected "int" |
| |
| [builtins fixtures/tuple.pyi] |
| |
| [case testDunderReplaceCovariantOverride] |
| # flags: --python-version 3.13 --enable-error-code mutable-override |
| from dataclasses import dataclass |
| from typing import Optional |
| from typing_extensions import dataclass_transform |
| |
| @dataclass |
| class Base: |
| a: Optional[int] |
| |
| @dataclass |
| class Child(Base): |
| a: int # E: Covariant override of a mutable attribute (base class "Base" defined the type as "Optional[int]", expression has type "int") |
| |
| @dataclass |
| class Other(Base): |
| a: str # E: Incompatible types in assignment (expression has type "str", base class "Base" defined the type as "Optional[int]") |
| |
| @dataclass_transform(kw_only_default=True) |
| class DCMeta(type): ... |
| |
| class X(metaclass=DCMeta): |
| a: Optional[int] |
| |
| class Y(X): |
| a: int # E: Covariant override of a mutable attribute (base class "X" defined the type as "Optional[int]", expression has type "int") |
| [builtins fixtures/tuple.pyi] |
| |
| |
| [case testFrozenWithFinal] |
| from dataclasses import dataclass |
| from typing import Final |
| |
| @dataclass(frozen=True) |
| class My: |
| a: Final = 1 |
| b: Final[int] = 2 |
| |
| reveal_type(My.a) # N: Revealed type is "Literal[1]?" |
| reveal_type(My.b) # N: Revealed type is "builtins.int" |
| My.a = 1 # E: Cannot assign to final attribute "a" |
| My.b = 2 # E: Cannot assign to final attribute "b" |
| |
| m = My() |
| reveal_type(m.a) # N: Revealed type is "Literal[1]?" |
| reveal_type(m.b) # N: Revealed type is "builtins.int" |
| |
| m.a = 1 # E: Cannot assign to final attribute "a" |
| m.b = 2 # E: Cannot assign to final attribute "b" |
| [builtins fixtures/tuple.pyi] |
| |
| [case testNoCrashForDataclassNamedTupleCombination] |
| # flags: --python-version 3.13 |
| from dataclasses import dataclass |
| from typing import NamedTuple |
| |
| @dataclass |
| class A(NamedTuple): # E: A NamedTuple cannot be a dataclass |
| i: int |
| |
| class B1(NamedTuple): |
| i: int |
| @dataclass |
| class B2(B1): # E: A NamedTuple cannot be a dataclass |
| pass |
| |
| [builtins fixtures/tuple.pyi] |