Skip to content

Commit

Permalink
Allow dynamic creation of generic dataclasses (GH-6319)
Browse files Browse the repository at this point in the history
  • Loading branch information
ilevkivskyi committed Mar 31, 2018
1 parent 233de02 commit 5a7092d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
4 changes: 3 additions & 1 deletion Lib/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,9 @@ class C(Base):
anns[name] = tp

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,
unsafe_hash=unsafe_hash, frozen=frozen)

Expand Down
19 changes: 18 additions & 1 deletion Lib/test/test_dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import inspect
import unittest
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 functools import total_ordering

Expand Down Expand Up @@ -1690,6 +1690,23 @@ def new_method(self):
c = Alias(10, 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):
@dataclass(frozen=True)
class C:
Expand Down

0 comments on commit 5a7092d

Please sign in to comment.