← Back to index

dataclasses_transform_class.py

True Positive
False Positive
False Negative
Optional (detected)
Warning or Info
TP: 5
FP: 0
FN: 1
Optional: 0 / 0
1"""
2Tests the dataclass_transform mechanism when it is applied to a base class.
3"""
4
5# Specification: https://typing.readthedocs.io/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator
6
7from typing import Any, Generic, TypeVar, dataclass_transform
8
9T = TypeVar("T")
12class ModelField:
13 def __init__(self, *, init: bool = True, default: Any | None = None) -> None:
14 ...
17def model_field(
18 *, init: bool = True, default: Any | None = None, alias: str | None = None
19) -> Any:
20 ...
23@dataclass_transform(
24 kw_only_default=True,
25 field_specifiers=(ModelField, model_field),
26)
27class ModelBase:
28 not_a_field: str
30 def __init_subclass__(
31 cls,
32 *,
33 frozen: bool = False,
34 kw_only: bool = True,
35 order: bool = True,
36 ) -> None:
37 ...
39 def __init__(self, not_a_field: str) -> None:
40 self.not_a_field = not_a_field
43class Customer1(ModelBase, frozen=True):
44 id: int = model_field()
45 name: str = model_field()
46 name2: str = model_field(alias="other_name", default="None")
49# This should generate an error because a non-frozen dataclass cannot
50# derive from a frozen one.
51class Customer1Subclass(Customer1): # E
Expected a ty diagnostic for this line
52 salary: float = model_field()
55class Customer2(ModelBase, order=True):
56 id: int
57 name: str = model_field(default="None")
60c1_1 = Customer1(id=3, name="Sue", other_name="Susan")
62# This should generate an error because the class is frozen.
63c1_1.id = 4 # E
[invalid-assignment] Property `id` defined in `Customer1` is read-only
65# This should generate an error because the class is kw_only.
66c1_2 = Customer1(3, "Sue") # E
[missing-argument] No arguments provided for required parameters `id`, `name` [too-many-positional-arguments] Too many positional arguments: expected 0, got 2
68c1_3 = Customer1(id=3, name="John")
70# This should generate an error because comparison methods are
71# not synthesized.
72v1 = c1_1 < c1_2 # E
[unsupported-operator] Operator `<` is not supported between two objects of type `Customer1`
74c2_1 = Customer2(id=0, name="John")
76c2_2 = Customer2(id=1)
78v2 = c2_1 < c2_2
80# This should generate an error because Customer2 supports
81# keyword-only parameters for its constructor.
82c2_3 = Customer2(0, "John") # E
[missing-argument] No argument provided for required parameter `id` [too-many-positional-arguments] Too many positional arguments: expected 0, got 2
85@dataclass_transform(
86 kw_only_default=True,
87 field_specifiers=(ModelField, model_field),
88)
89class GenericModelBase(Generic[T]):
90 not_a_field: T
92 def __init_subclass__(
93 cls,
94 *,
95 frozen: bool = False,
96 kw_only: bool = True,
97 order: bool = True,
98 ) -> None:
99 ...
102class GenericCustomer(GenericModelBase[int]):
103 id: int = model_field()
106gc_1 = GenericCustomer(id=3)
109@dataclass_transform(frozen_default=True)
110class ModelBaseFrozen:
111 not_a_field: str
114class Customer3(ModelBaseFrozen):
115 id: int
116 name: str
119c3_1 = Customer3(id=2, name="hi")
121# This should generate an error because Customer3 is frozen.
122c3_1.id = 4 # E
[invalid-assignment] Property `id` defined in `Customer3` is read-only