Skip to content

Commit 20a49fa

Browse files
authored
[mypyc] Fix default_factory for inherited dataclass (#21785)
Closes mypyc/mypyc#1204, a `mypyc` issue. The issue likely unblocks `isort` from being compiled with `mypyc`, which is why I took an interest it. Full disclosure is that I used AI to write this, it provided this test and code just from the linked issue but it looks sensible to me. I did not use additional prompting. Like I said, fix looks sensible: we now call `dataclass_type` for each entry in the MRO, instead of once. I am aware the contributing guidelines say new contributors are not encourage to use LLMs but I hope the size of the PR and my track record as open source maintainer gives some flexibility here. I'm very aware that reviewing AI written PRs creates maintainer burden, but I'm committed to getting this over the finish line. To that end I: Tested locally with `pytest mypyc/test/test_run.py ` and that looked okay. Also tested that without the changes the added test would fail on `master`. Also tried to run CI on my local fork (DanielNoord#1), which succeeded. Feel free to push changes to the branch or cherry pick this into another branch. I am not necessarily interested in getting credits for the fix/PR, I'd just like to continue with my attempt to get `isort` compiled and for that I need this in a `mypy` release :)
1 parent d79a9e6 commit 20a49fa

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

mypyc/irbuild/classdef.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,6 @@ def find_attr_initializers(
760760
if cls.builtin_base:
761761
return set(), []
762762

763-
cls_type = dataclass_type(cdef)
764763
attrs_with_defaults: set[str] = set()
765764
default_assignments: list[tuple[AssignmentStmt, str]] = []
766765

@@ -774,10 +773,11 @@ def find_attr_initializers(
774773
info_ir = builder.mapper.type_to_ir.get(info)
775774
if info_ir is None:
776775
continue
776+
info_cls_type = dataclass_type(info.defn)
777777
for stmt in info.defn.defs.body:
778778
if not isinstance(stmt, AssignmentStmt):
779779
continue
780-
name = default_attr_name(stmt, info_ir, cls_type)
780+
name = default_attr_name(stmt, info_ir, info_cls_type)
781781
if name is None:
782782
continue
783783
attrs_with_defaults.add(name)

mypyc/test-data/run-python37.test

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,15 @@ class Person5:
7474
friends: Set[str] = field(default_factory=set)
7575
parents: FrozenSet[str] = frozenset()
7676

77+
@dataclass
78+
class HasFactoryDefault:
79+
x: dict[str, int] = field(default_factory=dict)
80+
81+
class InheritsDataclassInit(HasFactoryDefault):
82+
pass
83+
7784
[file other.py]
78-
from native import Person1, Person1b, Person2, Person3, Person4, Person5, testBool
85+
from native import Person1, Person1b, Person2, Person3, Person4, Person5, testBool, InheritsDataclassInit
7986
i1 = Person1(age = 5, name = 'robot')
8087
assert i1.age == 5
8188
assert i1.name == 'robot'
@@ -125,6 +132,9 @@ assert Person1.__annotations__ == {'age': int, 'name': str}
125132
assert Person2.__annotations__ == {'age': int, 'name': str}
126133
assert Person5.__annotations__ == {'weight': float, 'friends': set,
127134
'parents': frozenset}
135+
v = InheritsDataclassInit()
136+
assert isinstance(v.x, dict)
137+
assert v.x == {}
128138

129139
[file driver.py]
130140
import sys

0 commit comments

Comments
 (0)