bpo-34363: dataclasses.asdict() and .astuple() now handle fields which are namedtuples. (GH-9151)

This commit is contained in:
Eric V. Smith 2018-09-14 11:32:16 -04:00 committed by GitHub
parent 73820a60cc
commit 9b9d97dd13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 118 additions and 2 deletions

View file

@ -1429,6 +1429,70 @@ class TestCase(unittest.TestCase):
self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)]))
self.assertIs(type(d), OrderedDict)
def test_helper_asdict_namedtuple(self):
T = namedtuple('T', 'a b c')
@dataclass
class C:
x: str
y: T
c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
d = asdict(c)
self.assertEqual(d, {'x': 'outer',
'y': T(1,
{'x': 'inner',
'y': T(11, 12, 13)},
2),
}
)
# Now with a dict_factory. OrderedDict is convenient, but
# since it compares to dicts, we also need to have separate
# assertIs tests.
d = asdict(c, dict_factory=OrderedDict)
self.assertEqual(d, {'x': 'outer',
'y': T(1,
{'x': 'inner',
'y': T(11, 12, 13)},
2),
}
)
# Make sure that the returned dicts are actuall OrderedDicts.
self.assertIs(type(d), OrderedDict)
self.assertIs(type(d['y'][1]), OrderedDict)
def test_helper_asdict_namedtuple_key(self):
# Ensure that a field that contains a dict which has a
# namedtuple as a key works with asdict().
@dataclass
class C:
f: dict
T = namedtuple('T', 'a')
c = C({T('an a'): 0})
self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}})
def test_helper_asdict_namedtuple_derived(self):
class T(namedtuple('Tbase', 'a')):
def my_a(self):
return self.a
@dataclass
class C:
f: T
t = T(6)
c = C(t)
d = asdict(c)
self.assertEqual(d, {'f': T(a=6)})
# Make sure that t has been copied, not used directly.
self.assertIsNot(d['f'], t)
self.assertEqual(d['f'].my_a(), 6)
def test_helper_astuple(self):
# Basic tests for astuple(), it should return a new tuple.
@dataclass
@ -1541,6 +1605,21 @@ class TestCase(unittest.TestCase):
self.assertEqual(t, NT(42, 2))
self.assertIs(type(t), NT)
def test_helper_astuple_namedtuple(self):
T = namedtuple('T', 'a b c')
@dataclass
class C:
x: str
y: T
c = C('outer', T(1, C('inner', T(11, 12, 13)), 2))
t = astuple(c)
self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2)))
# Now, using a tuple_factory. list is convenient here.
t = astuple(c, tuple_factory=list)
self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)])
def test_dynamic_class_creation(self):
cls_dict = {'__annotations__': {'x': int, 'y': int},
}