Skip to content
2 changes: 1 addition & 1 deletion Pyro5/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ def dumps(self, data):
return msgpack.packb(data, use_bin_type=True, default=self.default)

def loadsCall(self, data):
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook)
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook, ext_hook=self.ext_hook)

def loads(self, data):
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook, ext_hook=self.ext_hook)
Expand Down
64 changes: 64 additions & 0 deletions tests/test_msgpack_ext_hook_loadsCall.py

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please integrate these tests in test_serialize.py ? Instead of introducing a new file for just these two.

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
Regression test: MsgpackSerializer.loadsCall must honor ext_hook so that
ExtType-encoded call arguments round-trip when a subclass overrides
ext_hook to handle custom codes. The sibling loads() has always passed
both hooks; loadsCall used to pass only object_hook.
"""
import unittest

import msgpack

import Pyro5.serializers as serializers


CUSTOM_EXT_CODE = 0x40


class Thing:
def __init__(self, value):
self.value = value


class CustomMsgpackSerializer(serializers.MsgpackSerializer):
def default(self, obj):
if isinstance(obj, Thing):
return msgpack.ExtType(CUSTOM_EXT_CODE, str(obj.value).encode("ascii"))
return super().default(obj)

def ext_hook(self, code, data):
if code == CUSTOM_EXT_CODE:
return Thing(int(data))
return super().ext_hook(code, data)


class TestMsgpackExtHookLoadsCall(unittest.TestCase):
def test_loadsCall_honors_ext_hook(self):
"""
Pack a call message whose first vararg is a custom-ExtType-encoded
object and verify loadsCall reconstructs it via the subclass's
ext_hook. Before the fix this returned msgpack.ExtType, not Thing.
"""
ser = CustomMsgpackSerializer()
data = ser.dumpsCall("obj-id", "method-name", (Thing(42),), {})
obj, method, vargs, kwargs = ser.loadsCall(data)
self.assertEqual(obj, "obj-id")
self.assertEqual(method, "method-name")
self.assertIsInstance(vargs[0], Thing)
self.assertEqual(vargs[0].value, 42)
self.assertEqual(kwargs, {})

def test_loads_already_honors_ext_hook(self):
"""
Symmetric sanity check on the working sibling path. Would have
passed before the fix too; included so future regressions on
either method surface symmetrically.
"""
ser = CustomMsgpackSerializer()
data = ser.dumps(Thing(7))
back = ser.loads(data)
self.assertIsInstance(back, Thing)
self.assertEqual(back.value, 7)


if __name__ == "__main__":
unittest.main()
Loading