Skip to content

Commit 355e6da

Browse files
cdce8pdmontagu
andauthored
Don't apply dataclass transform twice with plugin + mypy 1.1.1 (#5162)
* Don't apply dataclass transform twice with plugin + mypy 1.1.1 * Use single quotes * Add test and fix tuple annotation * Improvements and test fix --------- Co-authored-by: David Montague <[email protected]>
1 parent bf6b884 commit 355e6da

File tree

4 files changed

+23
-4
lines changed

4 files changed

+23
-4
lines changed

changes/5162-cdce8p.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix `InitVar` usage with pydantic dataclasses, mypy version `1.1.1` and the custom mypy plugin

pydantic/mypy.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@
8282

8383

8484
def parse_mypy_version(version: str) -> Tuple[int, ...]:
85-
return tuple(int(part) for part in version.split('+', 1)[0].split('.'))
85+
return tuple(map(int, version.partition('+')[0].split('.')))
8686

8787

8888
MYPY_VERSION_TUPLE = parse_mypy_version(mypy_version)
8989
BUILTINS_NAME = 'builtins' if MYPY_VERSION_TUPLE >= (0, 930) else '__builtins__'
9090

9191
# Increment version if plugin changes and mypy caches should be invalidated
92-
PLUGIN_VERSION = 1
92+
__version__ = 2
9393

9494

9595
def plugin(version: str) -> 'TypingType[Plugin]':
@@ -106,7 +106,6 @@ class PydanticPlugin(Plugin):
106106
def __init__(self, options: Options) -> None:
107107
self.plugin_config = PydanticPluginConfig(options)
108108
self._plugin_data = self.plugin_config.to_data()
109-
self._plugin_data['version'] = PLUGIN_VERSION
110109
super().__init__(options)
111110

112111
def get_base_class_hook(self, fullname: str) -> 'Optional[Callable[[ClassDefContext], None]]':
@@ -134,7 +133,11 @@ def get_method_hook(self, fullname: str) -> Optional[Callable[[MethodContext], T
134133
return None
135134

136135
def get_class_decorator_hook(self, fullname: str) -> Optional[Callable[[ClassDefContext], None]]:
137-
if fullname == DATACLASS_FULLNAME:
136+
"""Mark pydantic.dataclasses as dataclass.
137+
138+
Mypy version 1.1.1 added support for `@dataclass_transform` decorator.
139+
"""
140+
if fullname == DATACLASS_FULLNAME and MYPY_VERSION_TUPLE < (1, 1):
138141
return dataclasses.dataclass_class_maker_callback # type: ignore[return-value]
139142
return None
140143

tests/mypy/modules/plugin_success.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,16 @@ class FieldDefaultTestingModel(BaseModel):
224224
g: List[int] = Field(default_factory=_default_factory_list)
225225
h: str = Field(default_factory=_default_factory_str)
226226
i: str = Field(default_factory=lambda: 'test')
227+
228+
229+
# Include the import down here to reduce the effect on line numbers
230+
from dataclasses import InitVar # noqa E402
231+
232+
233+
@dataclass
234+
class MyDataClass:
235+
foo: InitVar[str]
236+
bar: str
237+
238+
239+
MyDataClass(foo='foo', bar='bar')

tests/mypy/outputs/plugin_success.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
122: error: Unexpected keyword argument "name" for "AddProject" [call-arg]
22
122: error: Unexpected keyword argument "slug" for "AddProject" [call-arg]
33
122: error: Unexpected keyword argument "description" for "AddProject" [call-arg]
4+
239: error: Unexpected keyword argument "foo" for "MyDataClass" [call-arg]
5+
239: error: Unexpected keyword argument "bar" for "MyDataClass" [call-arg]

0 commit comments

Comments
 (0)