MsgPackTranscoder: Add support for UUID and datetimes.

This commit is contained in:
Dave Shawley 2016-01-16 09:24:34 -05:00
parent 7d2237745e
commit ba3d7cfc84
2 changed files with 47 additions and 1 deletions

View file

@ -192,6 +192,8 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
+-------------------------------+-------------------------------+
| :class:`collections.Mapping` | `map family`_ |
+-------------------------------+-------------------------------+
| :class:`uuid.UUID` | Converted to String |
+-------------------------------+-------------------------------+
.. _nil byte: https://github.com/msgpack/msgpack/blob/
0b8f5ac67cdd130f4d4d4fe6afb839b989fdb86a/spec.md#formats-nil
@ -218,6 +220,15 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
if isinstance(datum, self.PACKABLE_TYPES):
return datum
if isinstance(datum, uuid.UUID):
datum = str(datum)
if hasattr(datum, 'isoformat'):
datum = datum.isoformat()
if isinstance(datum, bytes):
datum = datum.decode('utf-8')
if isinstance(datum, str):
return datum

View file

@ -3,6 +3,7 @@ import datetime
import json
import os
import pickle
import struct
import sys
import unittest
import uuid
@ -32,6 +33,21 @@ class Context(object):
pass
def pack_string(obj):
"""Optimally pack a string according to msgpack format"""
payload = str(obj).encode('ASCII')
l = len(payload)
if l < (2 ** 5):
prefix = struct.pack('B', 0b10100000 | l)
elif l < (2 ** 8):
prefix = struct.pack('BB', 0xD9, l)
elif l < (2 ** 16):
prefix = struct.pack('>BH', 0xDA, l)
else:
prefix = struct.pack('>BI', 0xDB, l)
return prefix + payload
class SendResponseTests(testing.AsyncHTTPTestCase):
def get_app(self):
@ -202,7 +218,7 @@ class MsgPackTranscoderTests(unittest.TestCase):
def test_that_strings_are_dumped_as_strings(self):
dumped = self.transcoder.packb(u'foo')
self.assertEqual(self.transcoder.unpackb(dumped), 'foo')
self.assertEqual(dumped, b'\xA3foo')
self.assertEqual(dumped, pack_string('foo'))
def test_that_none_is_packed_as_nil_byte(self):
self.assertEqual(self.transcoder.packb(None), b'\xC0')
@ -248,3 +264,22 @@ class MsgPackTranscoderTests(unittest.TestCase):
def test_that_unhandled_objects_raise_type_error(self):
with self.assertRaises(TypeError):
self.transcoder.packb(object())
def test_that_uuids_are_dumped_as_strings(self):
uid = uuid.uuid4()
dumped = self.transcoder.packb(uid)
self.assertEqual(self.transcoder.unpackb(dumped), str(uid))
self.assertEqual(dumped, pack_string(uid))
def test_that_datetimes_are_dumped_in_isoformat(self):
now = datetime.datetime.now()
dumped = self.transcoder.packb(now)
self.assertEqual(self.transcoder.unpackb(dumped), now.isoformat())
self.assertEqual(dumped, pack_string(now.isoformat()))
def test_that_tzaware_datetimes_include_tzoffset(self):
now = datetime.datetime.now().replace(tzinfo=UTC())
self.assertTrue(now.isoformat().endswith('+00:00'))
dumped = self.transcoder.packb(now)
self.assertEqual(self.transcoder.unpackb(dumped), now.isoformat())
self.assertEqual(dumped, pack_string(now.isoformat()))