From d80b443f02e087dd289ffefd04179c675304d76d Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Sat, 6 Jan 2018 17:09:58 -0500 Subject: [PATCH] bpo-32279: Add additional params to make_dataclass(), pass through to dataclass(). (gh-5117) --- Lib/dataclasses.py | 10 +++++++--- Lib/test/test_dataclasses.py | 17 +++++++++++++++++ .../2018-01-06-16-50-11.bpo-32279.1xOpU8.rst | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-01-06-16-50-11.bpo-32279.1xOpU8.rst diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c4e94b8f667..62b7c5ed70a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -705,7 +705,8 @@ def _astuple_inner(obj, tuple_factory): return deepcopy(obj) -def make_dataclass(cls_name, fields, *, bases=(), namespace=None): +def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, + repr=True, eq=True, order=False, hash=None, frozen=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -723,6 +724,9 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None): b: int = field(init=False) For the bases and namespace paremeters, see the builtin type() function. + + The parameters init, repr, eq, order, hash, and frozen are passed to + dataclass(). """ if namespace is None: @@ -745,8 +749,8 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None): namespace['__annotations__'] = anns cls = type(cls_name, bases, namespace) - return dataclass(cls) - + return dataclass(cls, init=init, repr=repr, eq=eq, order=order, + hash=hash, frozen=frozen) def replace(obj, **changes): """Return a new object replacing specified fields with new values. diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index c44c53d039d..69819ea4507 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2033,6 +2033,23 @@ class TestCase(unittest.TestCase): self.assertEqual(C.y, 10) self.assertEqual(C.z, 20) + def test_helper_make_dataclass_other_params(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ], + init=False) + # Make sure we have a repr, but no init. + self.assertNotIn('__init__', vars(C)) + self.assertIn('__repr__', vars(C)) + + # Make sure random other params don't work. + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): + C = make_dataclass('C', + [], + xxinit=False) + def test_helper_make_dataclass_no_types(self): C = make_dataclass('Point', ['x', 'y', 'z']) c = C(1, 2, 3) diff --git a/Misc/NEWS.d/next/Library/2018-01-06-16-50-11.bpo-32279.1xOpU8.rst b/Misc/NEWS.d/next/Library/2018-01-06-16-50-11.bpo-32279.1xOpU8.rst new file mode 100644 index 00000000000..b7ef8c80f5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-06-16-50-11.bpo-32279.1xOpU8.rst @@ -0,0 +1,2 @@ +Add params to dataclasses.make_dataclasses(): init, repr, eq, order, hash, +and frozen. Pass them through to dataclass().