[Python-checkins] bpo-46757: Add a test to verify dataclass's __post_init__ isn't being automatically added. (GH-31523)

ericvsmith webhook-mailer at python.org
Wed Feb 23 00:14:43 EST 2022


https://github.com/python/cpython/commit/288af845a32fd2a92e3b49738faf8f2de6a7bf7c
commit: 288af845a32fd2a92e3b49738faf8f2de6a7bf7c
branch: main
author: Eric V. Smith <ericvsmith at users.noreply.github.com>
committer: ericvsmith <ericvsmith at users.noreply.github.com>
date: 2022-02-23T00:14:35-05:00
summary:

bpo-46757: Add a test to verify dataclass's __post_init__ isn't being automatically added. (GH-31523)

files:
M Lib/test/test_dataclasses.py

diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py
index 69e76850830091..2f37ecdfca6b4d 100644
--- a/Lib/test/test_dataclasses.py
+++ b/Lib/test/test_dataclasses.py
@@ -1016,6 +1016,65 @@ def __post_init__(cls):
         self.assertEqual((c.x, c.y), (3, 4))
         self.assertTrue(C.flag)
 
+    def test_post_init_not_auto_added(self):
+        # See bpo-46757, which had proposed always adding __post_init__.  As
+        # Raymond Hettinger pointed out, that would be a breaking change.  So,
+        # add a test to make sure that the current behavior doesn't change.
+
+        @dataclass
+        class A0:
+            pass
+
+        @dataclass
+        class B0:
+            b_called: bool = False
+            def __post_init__(self):
+                self.b_called = True
+
+        @dataclass
+        class C0(A0, B0):
+            c_called: bool = False
+            def __post_init__(self):
+                super().__post_init__()
+                self.c_called = True
+
+        # Since A0 has no __post_init__, and one wasn't automatically added
+        # (because that's the rule: it's never added by @dataclass, it's only
+        # the class author that can add it), then B0.__post_init__ is called.
+        # Verify that.
+        c = C0()
+        self.assertTrue(c.b_called)
+        self.assertTrue(c.c_called)
+
+        ######################################
+        # Now, the same thing, except A1 defines __post_init__.
+        @dataclass
+        class A1:
+            def __post_init__(self):
+                pass
+
+        @dataclass
+        class B1:
+            b_called: bool = False
+            def __post_init__(self):
+                self.b_called = True
+
+        @dataclass
+        class C1(A1, B1):
+            c_called: bool = False
+            def __post_init__(self):
+                super().__post_init__()
+                self.c_called = True
+
+        # This time, B1.__post_init__ isn't being called.  This mimics what
+        # would happen if A1.__post_init__ had been automatically added,
+        # instead of manually added as we see here.  This test isn't really
+        # needed, but I'm including it just to demonstrate the changed
+        # behavior when A1 does define __post_init__.
+        c = C1()
+        self.assertFalse(c.b_called)
+        self.assertTrue(c.c_called)
+
     def test_class_var(self):
         # Make sure ClassVars are ignored in __init__, __repr__, etc.
         @dataclass



More information about the Python-checkins mailing list