gh-142214: Fix two regressions in dataclasses (#142223)

This commit is contained in:
Jelle Zijlstra 2025-12-04 20:04:42 -08:00 committed by GitHub
parent 128d31637e
commit 53ec7c8fc0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 4 deletions

View file

@ -550,7 +550,12 @@ def __annotate__(format, /):
new_annotations = {}
for k in annotation_fields:
# gh-142214: The annotation may be missing in unusual dynamic cases.
# If so, just skip it.
try:
new_annotations[k] = cls_annotations[k]
except KeyError:
pass
if return_type is not MISSING:
if format == Format.STRING:
@ -1399,7 +1404,8 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields):
f.type = ann
# Fix the class reference in the __annotate__ method
init_annotate = newcls.__init__.__annotate__
init = newcls.__init__
if init_annotate := getattr(init, "__annotate__", None):
if getattr(init_annotate, "__generated_by_dataclasses__", False):
_update_func_cell_for__class__(init_annotate, cls, newcls)

View file

@ -927,6 +927,20 @@ class C:
validate_class(C)
def test_incomplete_annotations(self):
# gh-142214
@dataclass
class C:
"doc" # needed because otherwise we fetch the annotations at the wrong time
x: int
C.__annotate__ = lambda _: {}
self.assertEqual(
annotationlib.get_annotations(C.__init__),
{"return": None}
)
def test_missing_default(self):
# Test that MISSING works the same as a default not being
# specified.
@ -2578,6 +2592,20 @@ def __init__(self, x: int) -> None:
self.assertFalse(hasattr(E.__init__.__annotate__, "__generated_by_dataclasses__"))
def test_slots_true_init_false(self):
# Test that slots=True and init=False work together and
# that __annotate__ is not added to __init__.
@dataclass(slots=True, init=False)
class F:
x: int
f = F()
f.x = 10
self.assertEqual(f.x, 10)
self.assertFalse(hasattr(F.__init__, "__annotate__"))
def test_init_false_forwardref(self):
# Test forward references in fields not required for __init__ annotations.

View file

@ -0,0 +1,12 @@
Fix two regressions in :mod:`dataclasses` in Python 3.14.1 related to
annotations.
* An exception is no longer raised if ``slots=True`` is used and the
``__init__`` method does not have an ``__annotate__`` attribute
(likely because ``init=False`` was used).
* An exception is no longer raised if annotations are requested on the
``__init__`` method and one of the fields is not present in the class
annotations. This can occur in certain dynamic scenarios.
Patch by Jelle Zijlstra.