Skip to content

Commit 5a7092d

Browse files
authored
Allow dynamic creation of generic dataclasses (GH-6319)
1 parent 233de02 commit 5a7092d

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

Lib/dataclasses.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,9 @@ class C(Base):
10041004
anns[name] = tp
10051005

10061006
namespace['__annotations__'] = anns
1007-
cls = type(cls_name, bases, namespace)
1007+
# We use `types.new_class()` instead of simply `type()` to allow dynamic creation
1008+
# of generic dataclassses.
1009+
cls = types.new_class(cls_name, bases, {}, lambda ns: ns.update(namespace))
10081010
return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
10091011
unsafe_hash=unsafe_hash, frozen=frozen)
10101012

Lib/test/test_dataclasses.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import inspect
99
import unittest
1010
from unittest.mock import Mock
11-
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar
11+
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
1212
from collections import deque, OrderedDict, namedtuple
1313
from functools import total_ordering
1414

@@ -1690,6 +1690,23 @@ def new_method(self):
16901690
c = Alias(10, 1.0)
16911691
self.assertEqual(c.new_method(), 1.0)
16921692

1693+
def test_generic_dynamic(self):
1694+
T = TypeVar('T')
1695+
1696+
@dataclass
1697+
class Parent(Generic[T]):
1698+
x: T
1699+
Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)],
1700+
bases=(Parent[int], Generic[T]), namespace={'other': 42})
1701+
self.assertIs(Child[int](1, 2).z, None)
1702+
self.assertEqual(Child[int](1, 2, 3).z, 3)
1703+
self.assertEqual(Child[int](1, 2, 3).other, 42)
1704+
# Check that type aliases work correctly.
1705+
Alias = Child[T]
1706+
self.assertEqual(Alias[int](1, 2).x, 1)
1707+
# Check MRO resolution.
1708+
self.assertEqual(Child.__mro__, (Child, Parent, Generic, object))
1709+
16931710
def test_helper_replace(self):
16941711
@dataclass(frozen=True)
16951712
class C:

0 commit comments

Comments
 (0)