mirror of https://github.com/python/cpython
bpo-32278: Allow dataclasses.make_dataclass() to omit type information. (gh-5115)
This commit is contained in:
parent
e7ba013d87
commit
ed7d429ebb
|
@ -708,9 +708,10 @@ def _astuple_inner(obj, tuple_factory):
|
||||||
def make_dataclass(cls_name, fields, *, bases=(), namespace=None):
|
def make_dataclass(cls_name, fields, *, bases=(), namespace=None):
|
||||||
"""Return a new dynamically created dataclass.
|
"""Return a new dynamically created dataclass.
|
||||||
|
|
||||||
The dataclass name will be 'cls_name'. 'fields' is an interable
|
The dataclass name will be 'cls_name'. 'fields' is an iterable
|
||||||
of either (name, type) or (name, type, Field) objects. Field
|
of either (name), (name, type) or (name, type, Field) objects. If type is
|
||||||
objects are created by calling 'field(name, type [, Field])'.
|
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)
|
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.
|
# Copy namespace since we're going to mutate it.
|
||||||
namespace = namespace.copy()
|
namespace = namespace.copy()
|
||||||
|
|
||||||
anns = collections.OrderedDict((name, tp) for name, tp, *_ in fields)
|
anns = collections.OrderedDict()
|
||||||
namespace['__annotations__'] = anns
|
|
||||||
for item in fields:
|
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
|
name, tp, spec = item
|
||||||
namespace[name] = spec
|
namespace[name] = spec
|
||||||
|
anns[name] = tp
|
||||||
|
|
||||||
|
namespace['__annotations__'] = anns
|
||||||
cls = type(cls_name, bases, namespace)
|
cls = type(cls_name, bases, namespace)
|
||||||
return dataclass(cls)
|
return dataclass(cls)
|
||||||
|
|
||||||
|
|
|
@ -2033,6 +2033,20 @@ class TestCase(unittest.TestCase):
|
||||||
self.assertEqual(C.y, 10)
|
self.assertEqual(C.y, 10)
|
||||||
self.assertEqual(C.z, 20)
|
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):
|
class TestDocString(unittest.TestCase):
|
||||||
def assertDocStrEqual(self, a, b):
|
def assertDocStrEqual(self, a, b):
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Make type information optional on dataclasses.make_dataclass(). If omitted,
|
||||||
|
the string 'typing.Any' is used.
|
Loading…
Reference in New Issue