Skip to content

Commit

Permalink
Fix creation of binary method
Browse files Browse the repository at this point in the history
  • Loading branch information
BenediktBurger committed Jun 12, 2024
1 parent 8e3d82e commit f1967fe
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
12 changes: 10 additions & 2 deletions pyleco/utils/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,16 @@ def _generate_binary_capable_method(

@wraps(method)
def modified_method(*args, **kwargs) -> ReturnValue: # type: ignore
if args:
args = list(args)
if args[-1] is None:
args[-1] = self.current_message.payload[1:]
else:
args.append(self.current_message.payload[1:])
else:
kwargs["additional_payload"] = self.current_message.payload[1:]
return_value = method(
*args, additional_payload=self.current_message.payload[1:], **kwargs
*args, **kwargs
)
return returner(return_value=return_value) # type: ignore
else:
Expand Down Expand Up @@ -193,7 +201,7 @@ def register_binary_rpc_method(
"""Register a method which accepts binary input and/or returns binary values.
:param accept_binary_input: the method must accept the additional payload as an
`additional_payload` parameter.
`additional_payload=None` parameter (default value must be present as `None`!).
:param return_binary_output: the method must return a tuple of a JSON-able python object
(e.g. `None`) and of a list of bytes objects, to be sent as additional payload.
"""
Expand Down
61 changes: 46 additions & 15 deletions tests/utils/test_message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,51 +498,82 @@ def test_handle_json_not_request(self, handler: MessageHandler):
assert error.message == INVALID_REQUEST.message


class Test_process_json_message_with_binary:
data = {"jsonrpc": "2.0", "method": "do_binary", "id": 8}
class Test_process_json_message_with_created_binary:
payload_in: list[bytes]
payload_out: list[bytes]

@pytest.fixture(
params=(
# normally created binary method
{"method": "do_binary", "params": [5]}, # with a list
{"method": "do_binary", "params": {"data": 5}}, # a dictionary
# manually created binary method
{"method": "do_binary_manually", "params": [5]},
{"method": "do_binary_manually", "params": {"data": 5}},
),
ids=(
"created, list",
"created, dict",
"manual, list",
"manual, dict",
),
)
def data(self, request):
"""Create a request with a list and a dict of other parameters."""
d = {"jsonrpc": "2.0", "id": 8}
d.update(request.param)
return d

@pytest.fixture
def handler_b(self, handler: MessageHandler):
test_class = self
class SpecialHandler(MessageHandler):
def do_binary(self) -> None:
def do_binary_manually(self, data: int) -> int:
test_class.payload_in = self.current_message.payload[1:]
self.additional_response_payload = test_class.payload_out
return data

def do_binary(
self, data: int, additional_payload: Optional[list[bytes]] = None
) -> tuple[int, list[bytes]]:
test_class.payload_in = additional_payload # type: ignore
return data, test_class.payload_out

handler = SpecialHandler(name=handler_name.split(".")[1], context=FakeContext()) # type: ignore
handler.namespace = handler_name.split(".")[0]
handler.stop_event = SimpleEvent()
handler.timeout = 0.1

handler.register_rpc_method(handler.do_binary)
handler.register_rpc_method(handler.do_binary_manually)
handler.register_binary_rpc_method(
handler.do_binary, accept_binary_input=True, return_binary_output=True
)
return handler

def test_message_stored(self, handler_b: MessageHandler):
m_in = Message("abc", data=self.data, message_type=MessageTypes.JSON)
def test_message_stored(self, handler_b: MessageHandler, data):
m_in = Message("abc", data=data, message_type=MessageTypes.JSON)
handler_b.process_json_message(m_in)
assert handler_b.current_message == m_in

def test_empty_additional_payload(self, handler_b: MessageHandler):
m_in = Message("abc", data=self.data, message_type=MessageTypes.JSON)
def test_empty_additional_payload(self, handler_b: MessageHandler, data):
m_in = Message("abc", data=data, message_type=MessageTypes.JSON)
handler_b.process_json_message(m_in)
assert handler_b.additional_response_payload is None

def test_binary_payload_available(self, handler_b: MessageHandler):
def test_binary_payload_available(self, handler_b: MessageHandler, data):
m_in = Message(
"abc", data=self.data, message_type=MessageTypes.JSON, additional_payload=[b"def"]
"abc", data=data, message_type=MessageTypes.JSON, additional_payload=[b"def"]
)
self.payload_out = []
handler_b.process_json_message(m_in)
assert self.payload_in == [b"def"]

def test_binary_payload_sent(self, handler_b: MessageHandler):
m_in = Message("abc", data=self.data, message_type=MessageTypes.JSON)
def test_binary_payload_sent(self, handler_b: MessageHandler, data):
m_in = Message("abc", data=data, message_type=MessageTypes.JSON)
self.payload_out = [b"ghi"]
response = handler_b.process_json_message(m_in)
assert response.payload[1:] == [b"ghi"]
assert response.data == {"jsonrpc": "2.0", "id": 8, "result": None}
assert response.data == {"jsonrpc": "2.0", "id": 8, "result": 5}


def test_handle_binary_return_value(handler: MessageHandler):
Expand All @@ -565,9 +596,9 @@ def modified_binary_method(self, handler: MessageHandler, binary_method, request
handler.current_message = Message(
"rec", "send", data=b"", additional_payload=[b"0", b"1", b"2", b"3"]
)
self._accept_binary_input = abi = request.param
self._accept_binary_input = request.param
mod = handler._generate_binary_capable_method(
binary_method, accept_binary_input=abi, return_binary_output=True
binary_method, accept_binary_input=self._accept_binary_input, return_binary_output=True
)
self.handler = handler
return mod
Expand Down

0 comments on commit f1967fe

Please sign in to comment.