bpo-32896: Fix error when subclassing a dataclass with a field that uses a default_factory (GH-6170) (GH-6171)
Fix the way that new annotations in a class are detected.
(cherry picked from commit 8f6eccdc64cab735c47620fea948e64b19f83684)
Co-authored-by: Eric V. Smith <ericvsmith@users.noreply.github.com>
diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py
index db03ec1..9b5aad2 100755
--- a/Lib/test/test_dataclasses.py
+++ b/Lib/test/test_dataclasses.py
@@ -1147,6 +1147,55 @@
C().x
self.assertEqual(factory.call_count, 2)
+ def test_default_factory_derived(self):
+ # See bpo-32896.
+ @dataclass
+ class Foo:
+ x: dict = field(default_factory=dict)
+
+ @dataclass
+ class Bar(Foo):
+ y: int = 1
+
+ self.assertEqual(Foo().x, {})
+ self.assertEqual(Bar().x, {})
+ self.assertEqual(Bar().y, 1)
+
+ @dataclass
+ class Baz(Foo):
+ pass
+ self.assertEqual(Baz().x, {})
+
+ def test_intermediate_non_dataclass(self):
+ # Test that an intermediate class that defines
+ # annotations does not define fields.
+
+ @dataclass
+ class A:
+ x: int
+
+ class B(A):
+ y: int
+
+ @dataclass
+ class C(B):
+ z: int
+
+ c = C(1, 3)
+ self.assertEqual((c.x, c.z), (1, 3))
+
+ # .y was not initialized.
+ with self.assertRaisesRegex(AttributeError,
+ 'object has no attribute'):
+ c.y
+
+ # And if we again derive a non-dataclass, no fields are added.
+ class D(C):
+ t: int
+ d = D(4, 5)
+ self.assertEqual((d.x, d.z), (4, 5))
+
+
def x_test_classvar_default_factory(self):
# XXX: it's an error for a ClassVar to have a factory function
@dataclass