diff options
author | Eric V. Smith <ericvsmith@users.noreply.github.com> | 2018-01-06 21:14:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-06 21:14:03 (GMT) |
commit | ed7d429ebb591f65cef558760fb4ebdc4fc8f8b0 (patch) | |
tree | 372d5745bb9d625b8d7a0be5a2bac802e40e5615 /Lib | |
parent | e7ba013d870012157f695ead7e3645c2828a7fc5 (diff) | |
download | cpython-ed7d429ebb591f65cef558760fb4ebdc4fc8f8b0.zip cpython-ed7d429ebb591f65cef558760fb4ebdc4fc8f8b0.tar.gz cpython-ed7d429ebb591f65cef558760fb4ebdc4fc8f8b0.tar.bz2 |
bpo-32278: Allow dataclasses.make_dataclass() to omit type information. (gh-5115)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/dataclasses.py | 20 | ||||
-rwxr-xr-x | Lib/test/test_dataclasses.py | 14 |
2 files changed, 28 insertions, 6 deletions
diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index b4786bf..c4e94b8 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -708,9 +708,10 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None): """Return a new dynamically created dataclass. - The dataclass name will be 'cls_name'. 'fields' is an interable - of either (name, type) or (name, type, Field) objects. Field - objects are created by calling 'field(name, type [, Field])'. + The dataclass name will be 'cls_name'. 'fields' is an iterable + of either (name), (name, type) or (name, type, Field) objects. If type is + omitted, use the string 'typing.Any'. Field objects are created by + calling 'field(name, type [, Field])'. C = make_class('C', [('a', int', ('b', int, Field(init=False))], bases=Base) @@ -730,12 +731,19 @@ def make_dataclass(cls_name, fields, *, bases=(), namespace=None): # Copy namespace since we're going to mutate it. namespace = namespace.copy() - anns = collections.OrderedDict((name, tp) for name, tp, *_ in fields) - namespace['__annotations__'] = anns + anns = collections.OrderedDict() for item in fields: - if len(item) == 3: + if isinstance(item, str): + name = item + tp = 'typing.Any' + elif len(item) == 2: + name, tp, = item + elif len(item) == 3: name, tp, spec = item namespace[name] = spec + anns[name] = tp + + namespace['__annotations__'] = anns cls = type(cls_name, bases, namespace) return dataclass(cls) diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index fca384d..c44c53d 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2033,6 +2033,20 @@ class TestCase(unittest.TestCase): self.assertEqual(C.y, 10) self.assertEqual(C.z, 20) + def test_helper_make_dataclass_no_types(self): + C = make_dataclass('Point', ['x', 'y', 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': 'typing.Any', + 'z': 'typing.Any'}) + + C = make_dataclass('Point', ['x', ('y', int), 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': int, + 'z': 'typing.Any'}) class TestDocString(unittest.TestCase): def assertDocStrEqual(self, a, b): |