[ESI] Better single-argument handling for FunctionPort (#8782)

Previously, if one has a function with only a single `BitsType` argument, there was no way that this code could provide a correct argument to be serialized, given that only `kwargs` would be accepted - which is a dict, and not serializeable by `BitsType`.

Modified argument handling abit s.t.
1. users have to provide either kwargs or positional
2. if positional arguments are provided, and only a single is present, it is unpacked, ensuring that the validation and serialization code doesn't recieve a tuple, but instead the underlying value.
This commit is contained in:
Morten Borup Petersen 2025-07-29 08:39:23 +02:00 committed by GitHub
parent d9545ff5a0
commit 82bd22bda3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 17 additions and 4 deletions

View File

@ -448,14 +448,27 @@ class FunctionPort(BundlePort):
self.cpp_port.connect()
self.connected = True
def call(self, **kwargs: Any) -> Future:
def call(self, *args: Any, **kwargs: Any) -> Future:
"""Call the function with the given argument and returns a future of the
result."""
valid, reason = self.arg_type.is_valid(kwargs)
# Accept either positional or keyword arguments, but not both.
if len(args) > 0 and len(kwargs) > 0:
raise ValueError("cannot use both positional and keyword arguments")
# Handle arguments: for single positional arg, unwrap it from tuple
if len(args) == 1:
selected = args[0]
elif len(args) > 1:
selected = args
else:
selected = kwargs
valid, reason = self.arg_type.is_valid(selected)
if not valid:
raise ValueError(
f"'{kwargs}' cannot be converted to '{self.arg_type}': {reason}")
arg_bytes: bytearray = self.arg_type.serialize(kwargs)
f"'{selected}' cannot be converted to '{self.arg_type}': {reason}")
arg_bytes: bytearray = self.arg_type.serialize(selected)
cpp_future = self.cpp_port.call(arg_bytes)
return MessageFuture(self.result_type, cpp_future)