mirror of
https://github.com/python/cpython.git
synced 2025-10-07 15:42:02 +00:00
Allow dynamic creation of generic dataclasses (GH-6319) (GH-6320)
(cherry picked from commit 5a7092de12
)
Co-authored-by: Ivan Levkivskyi <levkivskyi@gmail.com>
This commit is contained in:
parent
9e96e7b24e
commit
d063ad8962
2 changed files with 21 additions and 2 deletions
|
@ -1004,7 +1004,9 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True,
|
||||||
anns[name] = tp
|
anns[name] = tp
|
||||||
|
|
||||||
namespace['__annotations__'] = anns
|
namespace['__annotations__'] = anns
|
||||||
cls = type(cls_name, bases, namespace)
|
# We use `types.new_class()` instead of simply `type()` to allow dynamic creation
|
||||||
|
# of generic dataclassses.
|
||||||
|
cls = types.new_class(cls_name, bases, {}, lambda ns: ns.update(namespace))
|
||||||
return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
|
return dataclass(cls, init=init, repr=repr, eq=eq, order=order,
|
||||||
unsafe_hash=unsafe_hash, frozen=frozen)
|
unsafe_hash=unsafe_hash, frozen=frozen)
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import pickle
|
||||||
import inspect
|
import inspect
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar
|
from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional
|
||||||
from collections import deque, OrderedDict, namedtuple
|
from collections import deque, OrderedDict, namedtuple
|
||||||
from functools import total_ordering
|
from functools import total_ordering
|
||||||
|
|
||||||
|
@ -1690,6 +1690,23 @@ class TestCase(unittest.TestCase):
|
||||||
c = Alias(10, 1.0)
|
c = Alias(10, 1.0)
|
||||||
self.assertEqual(c.new_method(), 1.0)
|
self.assertEqual(c.new_method(), 1.0)
|
||||||
|
|
||||||
|
def test_generic_dynamic(self):
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Parent(Generic[T]):
|
||||||
|
x: T
|
||||||
|
Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)],
|
||||||
|
bases=(Parent[int], Generic[T]), namespace={'other': 42})
|
||||||
|
self.assertIs(Child[int](1, 2).z, None)
|
||||||
|
self.assertEqual(Child[int](1, 2, 3).z, 3)
|
||||||
|
self.assertEqual(Child[int](1, 2, 3).other, 42)
|
||||||
|
# Check that type aliases work correctly.
|
||||||
|
Alias = Child[T]
|
||||||
|
self.assertEqual(Alias[int](1, 2).x, 1)
|
||||||
|
# Check MRO resolution.
|
||||||
|
self.assertEqual(Child.__mro__, (Child, Parent, Generic, object))
|
||||||
|
|
||||||
def test_helper_replace(self):
|
def test_helper_replace(self):
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class C:
|
class C:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue