2Tests basic handling of the dataclass factory.
5# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html
6# Also, see https://peps.python.org/pep-0557/
8from dataclasses import InitVar, dataclass, field
9from typing import Any, Callable, ClassVar, Generic, Protocol, TypeVar, assert_type
19 quantity_on_hand: int = 0
21 def total_cost(self) -> float:
22 return self.unit_price * self.quantity_on_hand
25v1 = InventoryItem("soap", 2.3)
28class InventoryItemInitProto(Protocol):
30 self, name: str, unit_price: float, quantity_on_hand: int = ...
34# Validate the type of the synthesized __init__ method.
35x1: InventoryItemInitProto = v1.__init__
37# Make sure the following additional methods were synthesized.
46assert_type(v1.name, str)
47assert_type(v1.unit_price, float)
48assert_type(v1.quantity_on_hand, int)
50v2 = InventoryItem("name") # E: missing unit_price
[missing-argument] No argument provided for required parameter `unit_price`
51v3 = InventoryItem("name", "price") # E: incorrect type for unit_price
[invalid-argument-type] Argument is incorrect: Expected `int | float`, found `Literal["price"]`
52v4 = InventoryItem("name", 3.1, 3, 4) # E: too many arguments
[too-many-positional-arguments] Too many positional arguments: expected 3, got 4
55# > TypeError will be raised if a field without a default value follows a
56# > field with a default value. This is true either when this occurs in a
57# > single class, or as a result of class inheritance.
60 a: int = 0 # E[DC1]: field with default should follow a field with no default.
61 b: int # E[DC1]: field with no default cannot follow field with default.
Tag 'DC1'
[dataclass-field-order] Required field `b` cannot be defined after fields with default values
66 a: int = field(default=1) # E[DC2]: field with default should follow a field with no default.
67 b: int # E[DC2]: field with no default cannot follow field with default.
Tag 'DC2'
[dataclass-field-order] Required field `b` cannot be defined after fields with default values
72 a: InitVar[int] = 0 # E[DC3]: field with default should follow a field with no default.
73 b: int # E[DC3]: field with no default cannot follow field with default.
Tag 'DC3'
[dataclass-field-order] Required field `b` cannot be defined after fields with default values
78 a: int = field(init=False)
83v6 = DC4(0, 1) # E: too many parameters
[too-many-positional-arguments] Too many positional arguments: expected 1, got 2
88 a: int = field(default_factory=str) # E: type mismatch
[invalid-assignment] Object of type `dataclasses.Field[str]` is not assignable to `int`
99 c: Callable[[str], int] = f
103assert_type(dc6.a, int)
104assert_type(DC6.a, int)
105assert_type(dc6.b, str)
106assert_type(dc6.c, Callable[[str], int])
114@dataclass(init=False)
118 def __init__(self, a: DC7, y: int):
119 self.__dict__ = a.__dict__
126# This should generate an error because there is an extra parameter
[too-many-positional-arguments] Too many positional arguments: expected 1, got 2
129# This should generate an error because there is one too few parameters
[missing-argument] No argument provided for required parameter `y` of bound method `__init__`
135 a: str = field(init=False, default="s")
145@dataclass(init=False)
150 def __init__(self, x: int):
152 self.x_squared = x * x
163 def __init__(self, x: int):
165 self.x_squared = x * x
171@dataclass(init=False)
177# This should generate an error because there is no matching
178# override __init__ method and no synthesized __init__.
[too-many-positional-arguments] Too many positional arguments to bound method `__init__`: expected 1, got 2
184 prop_1: str = field(init=False)
185 prop_2: str = field(default="hello")
186 prop_3: str = field(default_factory=lambda: "hello")
194dc15 = DC15(prop_2="test")
196assert_type(dc15.prop_1, str)
197assert_type(dc15.prop_2, str)
198assert_type(dc15.prop_3, str)
201class DataclassProto(Protocol):
202 __dataclass_fields__: ClassVar[dict[str, Any]]
205v7: DataclassProto = dc15
209class DC16(Generic[T]):
213assert_type(DC16(1), DC16[int])
216class DC17(DC16[str]):
220assert_type(DC17(""), DC17)
226 # This may generate a type checker error because an unannotated field
227 # will result in a runtime exception.