Skip to content

Commit 6d28910

Browse files
fix: preserve str subclass map keys in fallback unpacker
Only intern exact str keys so decoding hooks can return str subclasses when strict_map_key=False, matching the C extension. Add a regression test for key identity and strict_map_key validation.
1 parent 8a88e3d commit 6d28910

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

‎msgpack/fallback.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ def _unpack(self, execute=EX_CONSTRUCT):
550550
key = self._unpack(EX_CONSTRUCT)
551551
if self._strict_map_key and type(key) not in (str, bytes):
552552
raise ValueError("%s is not allowed for map key" % str(type(key)))
553-
if isinstance(key, str):
553+
if type(key) is str:
554554
key = sys.intern(key)
555555
ret[key] = self._unpack(EX_CONSTRUCT)
556556
if self._object_hook is not None:

‎test/test_obj.py‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from pytest import raises
44

5-
from msgpack import packb, unpackb
5+
from msgpack import ExtType, packb, unpackb
66

77

88
def _decode_complex(obj):
@@ -92,3 +92,19 @@ def test_an_exception_in_objecthook2():
9292
with raises(DecodeError):
9393
packed = packb({1: [{"__complex__": True, "real": 1, "imag": 2}]})
9494
unpackb(packed, list_hook=bad_complex_decoder, use_list=1, strict_map_key=False)
95+
96+
97+
def test_str_subclass_map_key_from_ext_hook():
98+
class Key(str):
99+
pass
100+
101+
key = Key("name")
102+
packed = packb({ExtType(1, b"name"): 42})
103+
options = {"ext_hook": lambda code, data: key}
104+
105+
result = unpackb(packed, strict_map_key=False, **options)
106+
assert result == {key: 42}
107+
assert next(iter(result)) is key
108+
109+
with raises(ValueError):
110+
unpackb(packed, strict_map_key=True, **options)

0 commit comments

Comments
 (0)