diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 7a24f8a9e5ccee..ea2f2e4912c8f1 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1299,11 +1299,12 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields): # Clear existing `__weakref__` descriptor, it belongs to a previous type: cls_dict.pop('__weakref__', None) # gh-102069 + # Set the `__qualname__ accordingly + if (qualname := getattr(cls, '__qualname__', None)) is not None: + cls_dict['__qualname__'] = qualname + # And finally create the class. - qualname = getattr(cls, '__qualname__', None) newcls = type(cls)(cls.__name__, cls.__bases__, cls_dict) - if qualname is not None: - newcls.__qualname__ = qualname if is_frozen: # Need this for pickling frozen classes with slots. diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 2e6c49e29ce828..b69ce168127097 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -3367,6 +3367,24 @@ class A: self.assertFalse(hasattr(A, "__slots__")) self.assertTrue(hasattr(B, "__slots__")) + def test_slots_qualname(self): + # Test that __qualname__ is set correctly when using slots + @dataclass(slots=True) + class C: + x: int + + def __init_subclass__(cls): + expected = f'TestSlots.test_slots_qualname..{cls.__name__}' + self.assertEqual(cls.__qualname__, expected) + + self.assertEqual(C.__qualname__, 'TestSlots.test_slots_qualname..C') + + @dataclass(slots=True) + class D(C): + pass + + self.assertEqual(D.__qualname__, 'TestSlots.test_slots_qualname..D') + # Can't be local to test_frozen_pickle. @dataclass(frozen=True, slots=True) class FrozenSlotsClass: