Add support for encoding namedtuples as tuples

This commit is contained in:
Dave Shawley 2021-11-05 07:20:10 -04:00
parent f5725ac6dd
commit 42bc4c9292
No known key found for this signature in database
GPG key ID: F41A8A99298F8EED
3 changed files with 25 additions and 0 deletions

View file

@ -9,6 +9,7 @@ Version History
- Add support for encoding :class:`ipaddress.IPv4Address` and :class:`ipaddress.IPv6Address`
- Add support for encoding :class:`pathlib.Path`
- Add support for encoding :class:`array.array`
- Add support for encoding :class:`collections.namedtuple` instances as tuples
- Add type annotations (see :ref:`type-info`)
- Return a "406 Not Acceptable" if the :http:header:`Accept` header values cannot be matched
and there is no default content type configured

View file

@ -506,6 +506,9 @@ class FormUrlEncodedTranscoder:
return ''.join(char_map[c] for c in datum)
elif isinstance(datum, type_info.SupportsIsoFormat):
str_repr = datum.isoformat()
# the following check is for namedtuples
elif isinstance(datum, tuple) and datum.__class__ is not tuple:
str_repr = str(tuple(datum))
else:
str_repr = str(datum)

View file

@ -1,5 +1,6 @@
import array
import base64
import collections
import dataclasses
import datetime
import decimal
@ -403,6 +404,13 @@ class JSONTranscoderTests(unittest.TestCase):
self.assertEqual(dumped,
'{"array":[%s]}' % (','.join(str(x) for x in a), ))
def test_that_namedtuples_are_handled_as_tuples(self):
Point = collections.namedtuple('Point', ['x', 'y'])
datum = Point(3, 4)
dumped = self.transcoder.dumps({'point': datum})
expected = json.dumps({'point': [x for x in datum]})
self.assertDictEqual(json.loads(expected), json.loads(dumped))
class ContentSettingsTests(unittest.TestCase):
def test_that_handler_listed_in_available_content_types(self):
@ -667,6 +675,12 @@ class MsgPackTranscoderTests(unittest.TestCase):
expected += pack_string(ch)
self.assertEqual(expected, self.transcoder.packb(a))
def test_that_namedtuples_are_handled_as_tuples(self):
Point = collections.namedtuple('Point', ['x', 'y'])
datum = Point(3, 4)
expected = struct.pack('>BBB', 0x90 | 2, 3, 4)
self.assertEqual(expected, self.transcoder.packb(datum))
class FormUrlEncodingTranscoderTests(unittest.TestCase):
transcoder: type_info.Transcoder
@ -851,3 +865,10 @@ class FormUrlEncodingTranscoderTests(unittest.TestCase):
_, expected = self.transcoder.to_bytes({'array': a.tolist()})
_, result = self.transcoder.to_bytes({'array': a})
self.assertEqual(expected, result)
def test_that_namedtuples_are_handled_as_tuples(self):
Point = collections.namedtuple('Point', ['x', 'y'])
datum = Point(3, 4)
_, expected = self.transcoder.to_bytes({'point': (3, 4)})
_, result = self.transcoder.to_bytes({'point': datum})
self.assertEqual(expected, result)