Add `get_keyword_types` to support argument conversion
martinezlc99 opened this issue · 4 comments
Issue
When using a custom Python library via RobotRemoteServer
, automatic type conversion seems to fail. All arguments are passed as str
. When using the same library nominally, automatic type conversion occurs as expected.
Actual Behavior
Multiply.py
import robot.api.deco
import robotremoteserver
class Multiply:
@robot.api.deco.keyword(name="Multiply Two Numbers", types={"x": float, "y": float})
def multiply(self, x: float, y: float):
"""multiply 'em"""
return x * y
if __name__ == "__main__":
robotremoteserver.RobotRemoteServer(Multiply())
multiply.robot
*** Settings ***
Documentation Test automatic type conversions
# Library Multiply
Library Remote 127.0.0.1:8270
*** Test Cases ***
Multiply Them With Type Conversion
[Documentation] Automatic type Conversion should occur
${product} = Multiply Two Numbers 1.5 2.5
Log ${sum}
Executing the test with fails with TypeError: can't multiply sequence by non-int of type 'str'
. Passing the arguments as named also fails.
Expected Behavior
Running the test as a normal Python library works as expected:
multiply.robot
*** Settings ***
Documentation Test automatic type conversions
Library Multiply
# Library Remote 127.0.0.1:8270
*** Test Cases ***
Multiply Them With Type Conversion
[Documentation] Automatic Type Conversion should occur
${product} = Multiply Two Numbers 1.5 2.5
Log ${sum}
Is this a known limitation? I could not find any relevant documentaion. If not, then this is probably a bug in the Remote
library I suspect. I am glad to open an issue there and look into a PR.
System info:
python -m robot --version
-> Robot Framework 6.0.2 (Python 3.10.6 on win32)
It seems RemoteServer doesn't support argument conversion. The Remote API would support get_keyword_types
, but the server doesn't have that method. Adding it ought to be pretty easy.
Thanks @pekkaklarck! Would you accept a PR for this? I dont mind trying to implement.
Certainly. The general approach ought to be:
- Check does the keyword have
robot_types
attribute set by the@keyword
decorator. If it does, use that. - If there's not
robot_types
, try getting type info usingtyping.get_type_info
. - If the above fails, get info from
__annotations__
. - Convert type info to strings for XML-RPC compatibility.
- If type is a
Union
, it needs to be returned as a tuple.
The hard part is Python 2 compatibility. It's been important that RemoteServer supports Python 2 especially when Robot Framework itself doesn't support it anymore, but it could be time to drop that support. That decision needs to be done separately and discussed with others. The #devel channel on our Slack is probably the best place.
Another issue is that parameterized types like list[int]
cannot be supported. The reason is that we cannot pass actual types over XML-RPC and Robot doesn't support strings like 'list[int]'
in type conversion. There's an issue about that, though, and I hope we add that support in RF 7.
We discussed this on Slack and noticed one more problem: XML-RPC supports only a limited set of types and the Remote library itself converts other types to strings. For example, if decimal.Decimal
is used as a type hint and we return that to Robot, it will convert the argument to a Decimal
, but Remote converts it to a string. That's actually better than converting it to a float
that would be supported by XML-RPC because precision would be lost, but that doesn't change the fact that the keyword won't get a Decimal
as an argument.
I don't see any other way to handle this issue than enhancing RemoteServer so that it does argument conversion itself. Because it gets values converted by the Remote library, we know the exact format and conversion ought to be pretty straightforward. Setting the conversion infrastructure in place is some work nevertheless and that requires a separate issue. This issue can concentrate on adding get_keyword_types
.