summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorEric V. Smith <ericvsmith@users.noreply.github.com>2018-01-06 21:14:03 (GMT)
committerGitHub <noreply@github.com>2018-01-06 21:14:03 (GMT)
commited7d429ebb591f65cef558760fb4ebdc4fc8f8b0 (patch)
tree372d5745bb9d625b8d7a0be5a2bac802e40e5615 /Lib
parente7ba013d870012157f695ead7e3645c2828a7fc5 (diff)
downloadcpython-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.py20
-rwxr-xr-xLib/test/test_dataclasses.py14
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):