diff --git a/pytest.ini b/pytest.ini index d930b2104e..8adc48ee4c 100644 --- a/pytest.ini +++ b/pytest.ini @@ -51,3 +51,4 @@ markers = rmq_reconnect: rabbitmq reconnect tests rmq_shutdown: rabbitmq shutdown tests secure: Test platform and agents with secure platform options + rpc: Tests for RPC diff --git a/volttron/platform/vip/agent/subsystems/rpc.py b/volttron/platform/vip/agent/subsystems/rpc.py index 441b59b745..309844edc9 100644 --- a/volttron/platform/vip/agent/subsystems/rpc.py +++ b/volttron/platform/vip/agent/subsystems/rpc.py @@ -179,7 +179,8 @@ def _inspect(method): if p.default is not inspect.Parameter.empty: response['params'][p.name]['default'] = p.default if p.annotation is not inspect.Parameter.empty: - response['params'][p.name]['annotation'] = p.annotation + annotation = p.annotation.__name__ if type(p.annotation) is type else str(p.annotation) + response['params'][p.name]['annotation'] = annotation doc = inspect.getdoc(method) if doc: response['doc'] = doc @@ -195,8 +196,9 @@ def _inspect(method): 'file': source, 'line_number': lineno } - if signature.return_annotation is not inspect.Signature.empty: - response['return'] = signature.return_annotation + ret = signature.return_annotation + if ret is not inspect.Signature.empty: + response['return'] = ret.__name__ if type(ret) is type else str(ret) return response diff --git a/volttrontesting/subsystems/test_rpc_subsystem.py b/volttrontesting/subsystems/test_rpc_subsystem.py new file mode 100644 index 0000000000..5066cfc50f --- /dev/null +++ b/volttrontesting/subsystems/test_rpc_subsystem.py @@ -0,0 +1,51 @@ +import os +import pytest +import inspect +from volttron.platform.vip.agent import RPC +from volttron.platform.vip.agent import Agent +from typing import Optional, Union, List + +class _ExporterTestAgent(Agent): + def __init__(self, **kwargs): + super(_ExporterTestAgent, self).__init__(**kwargs) + + @RPC.export('test_method') + def test_method(self, param1: int, param2: Union[str, List[str]], *, param3: bool = True, + param4: Optional[Union[float, List[float]]] = None) -> dict: + """Doc String""" + return {'param1': param1, 'param2': param2, param3: param3, 'param4': param4} + + +@pytest.mark.rpc +def test_method_inspection(volttron_instance): + """ Tests RPC Method Inspection + + :param volttron_instance: + :return: + """ + + lineno = inspect.getsourcelines(_ExporterTestAgent.test_method)[1] + test_output = { + 'doc': 'Doc String', + 'params': {'param1': {'annotation': 'int', + 'kind': 'positional or keyword'}, + 'param2': {'annotation': 'typing.Union[str, typing.List[str]]', + 'kind': 'positional or keyword'}, + 'param3': {'annotation': 'bool', + 'default': True, + 'kind': 'keyword-only'}, + 'param4': {'annotation': 'typing.Union[float, typing.List[float], ' + 'NoneType]', + 'default': None, + 'kind': 'keyword-only'}}, + 'return': 'dict', + 'source': {'file': 'volttrontesting/subsystems/test_rpc_subsystem.py', # Must change if this file moves! + 'line_number': lineno}, + } + + new_agent1 = volttron_instance.build_agent(identity='test_inspect1', agent_class=_ExporterTestAgent) + new_agent2 = volttron_instance.build_agent(identity='test_inspect2') + + result = new_agent2.vip.rpc.call('test_inspect1', 'test_method.inspect').get() + + assert result == test_output