From 03241069b9385590705dfc5399e5bb9f43317d83 Mon Sep 17 00:00:00 2001 From: Dan Shernicoff Date: Mon, 18 May 2026 13:50:20 -0700 Subject: [PATCH 1/4] Add `qualname` parameter to `dataclass.make_dataclass`. Added `qualname` parameter to `dataclasses.make_dataclass` in order to allow user to set `__qualname__` for the generated class. --- Doc/library/dataclasses.rst | 6 +++++- Lib/dataclasses.py | 8 +++++++- Lib/test/test_dataclasses/__init__.py | 7 +++++++ .../Library/2026-05-18-13-43-06.gh-issue-79413.OpTXbV.rst | 3 +++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-18-13-43-06.gh-issue-79413.OpTXbV.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index a09c28ad979158..24c58dbe26ad20 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -418,7 +418,7 @@ Module contents :func:`!astuple` raises :exc:`TypeError` if *obj* is not a dataclass instance. -.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None, decorator=dataclass) +.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None, qualname=None, decorator=dataclass) Creates a new dataclass with name *cls_name*, fields as defined in *fields*, base classes as given in *bases*, and initialized @@ -434,6 +434,10 @@ Module contents of the dataclass is set to that value. By default, it is set to the module name of the caller. + If *qualname* is defined, the :attr:`!__qualname__` attribute of the dataclass + is set to that value. + By default, it is set to the value passed to *cls_name*. + The *decorator* parameter is a callable that will be used to create the dataclass. It should take the class object as a first argument and the same keyword arguments as :deco:`dataclass`. By default, the :deco:`dataclass` diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index dbfabded2e47aa..035678d902adaf 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1644,7 +1644,7 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, - weakref_slot=False, module=None, decorator=dataclass): + weakref_slot=False, module=None, qualname=None, decorator=dataclass): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -1669,6 +1669,9 @@ class C(Base): If module parameter is defined, the '__module__' attribute of the dataclass is set to that value. + + If qualname parameter is defined, the '__qualname__' attribute of the dataclass is set + to that value. """ if namespace is None: @@ -1758,6 +1761,9 @@ def exec_body_callback(ns): if module is not None: cls.__module__ = module + if qualname: + cls.__qualname__ = qualname + # Apply the normal provided decorator. cls = decorator(cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen, diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index dcd6a3ef9abfab..5fa136bd42bb74 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -5289,6 +5289,13 @@ class A: self.assertEqual(len(fs), 1) self.assertEqual(fs[0].name, 'x') + def test_makedataclass_with_qualname(self): + A = make_dataclass("A", ['a'], qualname='ClassA') + self.assertEqual(A.__qualname__, 'ClassA') + + B = make_dataclass("B", ['b'], qualname='ClassB') + self.assertEqual(B.__qualname__, 'ClassB') + class TestZeroArgumentSuperWithSlots(unittest.TestCase): def test_zero_argument_super(self): diff --git a/Misc/NEWS.d/next/Library/2026-05-18-13-43-06.gh-issue-79413.OpTXbV.rst b/Misc/NEWS.d/next/Library/2026-05-18-13-43-06.gh-issue-79413.OpTXbV.rst new file mode 100644 index 00000000000000..8d62fda8b2b67f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-18-13-43-06.gh-issue-79413.OpTXbV.rst @@ -0,0 +1,3 @@ +Update :func:`dataclasses.make_dataclass` to add a *qualname* parameter. The +*qualname* parameter will be used to set the :attr:`!__qualname__` of the +created ``dataclass``. From 80cc3e8d39915ebf31d0e6b26f797fede863a8c3 Mon Sep 17 00:00:00 2001 From: Dan Shernicoff Date: Mon, 18 May 2026 14:30:33 -0700 Subject: [PATCH 2/4] PR feedback on documentation. - Added `versionadded:: next` for `qualname` parameter - Fixed formatting. --- Doc/library/dataclasses.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 24c58dbe26ad20..d77b309c5583dc 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -435,8 +435,7 @@ Module contents By default, it is set to the module name of the caller. If *qualname* is defined, the :attr:`!__qualname__` attribute of the dataclass - is set to that value. - By default, it is set to the value passed to *cls_name*. + is set to that value. By default, it is set to the value passed to *cls_name*. The *decorator* parameter is a callable that will be used to create the dataclass. It should take the class object as a first argument and the same keyword arguments @@ -468,6 +467,8 @@ Module contents .. versionadded:: 3.14 Added the *decorator* parameter. + .. versionadded:: next + Added the *qualname* parameter. .. function:: replace(obj, /, **changes) From e2db26a7ba04c670c42644e5beca27adc9d4f174 Mon Sep 17 00:00:00 2001 From: Dan Shernicoff Date: Mon, 18 May 2026 15:39:27 -0700 Subject: [PATCH 3/4] PR feedback on documentation. - Fix section on `qualname` parameter to link to `type.__qualname__`. --- Doc/library/dataclasses.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index d77b309c5583dc..954edc4506df1a 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -434,7 +434,7 @@ Module contents of the dataclass is set to that value. By default, it is set to the module name of the caller. - If *qualname* is defined, the :attr:`!__qualname__` attribute of the dataclass + If *qualname* is defined, the :attr:`~type.__qualname__` attribute of the dataclass is set to that value. By default, it is set to the value passed to *cls_name*. The *decorator* parameter is a callable that will be used to create the dataclass. From 6e529ab6e93c17715ce47c7b01d4eda99f65fc72 Mon Sep 17 00:00:00 2001 From: Dan Shernicoff Date: Mon, 18 May 2026 16:26:03 -0700 Subject: [PATCH 4/4] PR feedback on tests. - Add test case for `module.Class` for `qualname`. - Add test case for `qualname` not set. --- Lib/test/test_dataclasses/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 5fa136bd42bb74..2468e3e64dd621 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -5293,9 +5293,11 @@ def test_makedataclass_with_qualname(self): A = make_dataclass("A", ['a'], qualname='ClassA') self.assertEqual(A.__qualname__, 'ClassA') - B = make_dataclass("B", ['b'], qualname='ClassB') - self.assertEqual(B.__qualname__, 'ClassB') + B = make_dataclass("B", ['b'], qualname='module1.ClassB') + self.assertEqual(B.__qualname__, 'module1.ClassB') + C = make_dataclass("C", ['c']) + self.assertEqual(C.__qualname__, 'C') class TestZeroArgumentSuperWithSlots(unittest.TestCase): def test_zero_argument_super(self):