Skip to content

Commit

Permalink
add support for unpacking maps with array keys
Browse files Browse the repository at this point in the history
Fixes #10
  • Loading branch information
vsergeev committed Sep 17, 2014
1 parent 290bdc6 commit 8052d14
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
10 changes: 7 additions & 3 deletions test_umsgpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@
# Complex Array
[ "complex array", [ True, 0x01, umsgpack.Ext(0x03, b"foo"), 0xff, { 1: False, 2: u"abc" }, b"\x80", [ 1, 2, 3], u"abc" ], b"\x98\xc3\x01\xc7\x03\x03\x66\x6f\x6f\xcc\xff\x82\x01\xc2\x02\xa3\x61\x62\x63\xc4\x01\x80\x93\x01\x02\x03\xa3\x61\x62\x63" ],
# Complex Map
[ "complex map", { 1 : [{1: 2, 3: 4}, {}], 2: 1, 3: [False, u"def"], 4: {0x100000000: u"a", 0xffffffff: u"b"}}, b"\x84\x01\x92\x82\x01\x02\x03\x04\x80\x02\x01\x03\x92\xc2\xa3\x64\x65\x66\x04\x82\xcf\x00\x00\x00\x01\x00\x00\x00\x00\xa1\x61\xce\xff\xff\xff\xff\xa1\x62" ]
[ "complex map", { 1 : [{1: 2, 3: 4}, {}], 2: 1, 3: [False, u"def"], 4: {0x100000000: u"a", 0xffffffff: u"b"}}, b"\x84\x01\x92\x82\x01\x02\x03\x04\x80\x02\x01\x03\x92\xc2\xa3\x64\x65\x66\x04\x82\xcf\x00\x00\x00\x01\x00\x00\x00\x00\xa1\x61\xce\xff\xff\xff\xff\xa1\x62" ],
# Map with Tuple Keys
[ "map with tuple keys", {(u"foo", False, 3) : True, (3e6, -5): u"def"}, b"\x82\x92\xcb\x41\x46\xe3\x60\x00\x00\x00\x00\xfb\xa3\x64\x65\x66\x93\xa3\x66\x6f\x6f\xc2\x03\xc3" ],
# Map with Complex Tuple Keys
[ "map with complex tuple keys", {(u"foo", (1,2,3), 3) : -5}, b"\x81\x93\xa3\x66\x6f\x6f\x93\x01\x02\x03\x03\xfb" ]
]

pack_exception_test_vectors = [
Expand Down Expand Up @@ -176,10 +180,10 @@
[ "insufficient data ext 8-bit", b"\xc7\x05\x05\x01\x02\x03", umsgpack.InsufficientDataException ],
[ "insufficient data ext 16-bit", b"\xc8\x01\x00\x05\x01\x02\x03", umsgpack.InsufficientDataException ],
[ "insufficient data ext 32-bit", b"\xc9\x00\x01\x00\x00\x05\x01\x02\x03", umsgpack.InsufficientDataException ],
# Unhashable key { 1 : False, [1,2,3] : True }
[ "unhashable key", b"\x82\x01\xc2\x93\x01\x02\x03\xc3", umsgpack.UnhashableKeyException ],
# Unhashable key { 1 : True, { 1 : 1 } : False }
[ "unhashable key", b"\x82\x01\xc3\x81\x01\x01\xc2", umsgpack.UnhashableKeyException ],
# Unhashable key { [ 1, 2, {} ] : True }
[ "unhashable key", b"\x81\x93\x01\x02\x80\xc3", umsgpack.UnhashableKeyException ],
# Key duplicate { 1 : True, 1 : False }
[ "duplicate key", b"\x82\x01\xc3\x01\xc2", umsgpack.DuplicateKeyException ],
# Reserved code (0xc1)
Expand Down
23 changes: 17 additions & 6 deletions umsgpack.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# u-msgpack-python v1.6 - vsergeev at gmail
# u-msgpack-python v1.8 - vsergeev at gmail
# https://github.com/vsergeev/u-msgpack-python
#
# u-msgpack-python is a lightweight MessagePack serializer and deserializer
Expand Down Expand Up @@ -31,7 +31,7 @@
# THE SOFTWARE.
#
"""
u-msgpack-python v1.6 - vsergeev at gmail
u-msgpack-python v1.8 - vsergeev at gmail
https://github.com/vsergeev/u-msgpack-python
u-msgpack-python is a lightweight MessagePack serializer and deserializer
Expand All @@ -44,7 +44,7 @@
License: MIT
"""

version = (1,6)
version = (1,8)
"Module version tuple"

import struct
Expand Down Expand Up @@ -531,6 +531,11 @@ def _unpack_array(code, read_fn):

return [_unpackb(read_fn) for i in range(length)]

def _deep_list_to_tuple(x):
if isinstance(x, list):
return tuple([_deep_list_to_tuple(e) for e in x])
return x

def _unpack_map(code, read_fn):
if (ord(code) & 0xf0) == 0x80:
length = (ord(code) & ~0xf0)
Expand All @@ -546,15 +551,21 @@ def _unpack_map(code, read_fn):
# Unpack key
k = _unpackb(read_fn)

if not isinstance(k, collections.Hashable):
raise UnhashableKeyException("encountered unhashable key type: %s" % str(type(k)))
if isinstance(k, list):
# Attempt to convert list into a hashable tuple
k = _deep_list_to_tuple(k)
elif not isinstance(k, collections.Hashable):
raise UnhashableKeyException("encountered unhashable key: %s, %s" % (str(k), str(type(k))))
elif k in d:
raise DuplicateKeyException("encountered duplicate key: %s, %s" % (str(k), str(type(k))))

# Unpack value
v = _unpackb(read_fn)

d[k] = v
try:
d[k] = v
except TypeError:
raise UnhashableKeyException("encountered unhashable key: %s" % str(k))
return d

########################################
Expand Down

0 comments on commit 8052d14

Please sign in to comment.