diff --git a/rclpy/rclpy/endpoint_info.py b/rclpy/rclpy/endpoint_info.py index 90ec30aeb..936eb6880 100644 --- a/rclpy/rclpy/endpoint_info.py +++ b/rclpy/rclpy/endpoint_info.py @@ -48,7 +48,8 @@ class TopicEndpointInfo: '_topic_type_hash', '_endpoint_type', '_endpoint_gid', - '_qos_profile' + '_qos_profile', + '_buffer_backend_metadata' ] def __init__( @@ -59,8 +60,10 @@ def __init__( topic_type_hash: Union[TypeHash, TypeHashDictionary] = TypeHash(), endpoint_type: Union[EndpointTypeEnum, int] = EndpointTypeEnum.INVALID, endpoint_gid: list[int] = [], - qos_profile: Union[QoSProfile, '_rclpy._rmw_qos_profile_dict'] = + qos_profile: Union[QoSProfile, '_rclpy._rmw_qos_profile_dict'] = ( QoSPresetProfiles.UNKNOWN.value + ), + buffer_backend_metadata: dict[str, str] = {} ): self.node_name = node_name self.node_namespace = node_namespace @@ -69,6 +72,7 @@ def __init__( self.endpoint_type = endpoint_type self.endpoint_gid = endpoint_gid self.qos_profile = qos_profile + self.buffer_backend_metadata = buffer_backend_metadata @property def node_name(self) -> str: @@ -183,6 +187,21 @@ def qos_profile(self, value: Union[QoSProfile, '_rclpy._rmw_qos_profile_dict']) else: assert False + @property + def buffer_backend_metadata(self) -> dict[str, str]: + """ + Get field 'buffer_backend_metadata'. + + :returns: mapping from buffer backend name to backend metadata + """ + return self._buffer_backend_metadata + + @buffer_backend_metadata.setter + def buffer_backend_metadata(self, value: dict[str, str]) -> None: + assert isinstance(value, dict) + assert all(isinstance(k, str) and isinstance(v, str) for k, v in value.items()) + self._buffer_backend_metadata = value + def __eq__(self, other: object) -> bool: if not isinstance(other, TopicEndpointInfo): return False @@ -196,6 +215,11 @@ def __str__(self) -> str: history_depth_str = self.qos_profile.history.name else: history_depth_str = f'{self.qos_profile.history.name} ({self.qos_profile.depth})' + buffer_backend_str = ', '.join( + f'{backend}({metadata})' if metadata else backend + for backend, metadata in sorted(self.buffer_backend_metadata.items())) + if not buffer_backend_str: + buffer_backend_str = '' return '\n'.join([ f'Node name: {self.node_name}', f'Node namespace: {self.node_namespace}', @@ -203,6 +227,7 @@ def __str__(self) -> str: f'Topic type hash: {self.topic_type_hash}', f'Endpoint type: {self.endpoint_type.name}', f'GID: {gid}', + f'Buffer backends: {buffer_backend_str}', 'QoS profile:', f' Reliability: {self.qos_profile.reliability.name}', f' History (Depth): {history_depth_str}', diff --git a/rclpy/rclpy/impl/_rclpy_pybind11.pyi b/rclpy/rclpy/impl/_rclpy_pybind11.pyi index 6ea0a9a43..6d46eec27 100644 --- a/rclpy/rclpy/impl/_rclpy_pybind11.pyi +++ b/rclpy/rclpy/impl/_rclpy_pybind11.pyi @@ -801,6 +801,7 @@ class _TopicEndpointInfoDict(TypedDict): endpoint_type: int endpoint_gid: list[int] qos_profile: _rmw_qos_profile_dict + buffer_backend_metadata: dict[str, str] class _ServiceEndpointInfoDict(TypedDict): diff --git a/rclpy/src/rclpy/utils.cpp b/rclpy/src/rclpy/utils.cpp index 7d603123e..3cd5d7535 100644 --- a/rclpy/src/rclpy/utils.cpp +++ b/rclpy/src/rclpy/utils.cpp @@ -32,6 +32,7 @@ #include #include +#include #include "exceptions.hpp" #include "utils.hpp" @@ -313,6 +314,13 @@ _convert_to_py_topic_endpoint_info(const rmw_topic_endpoint_info_t * topic_endpo py_endpoint_info_dict["endpoint_gid"] = py_endpoint_gid; py_endpoint_info_dict["qos_profile"] = convert_to_qos_dict(&topic_endpoint_info->qos_profile); + py::dict py_buffer_backend_metadata; + for (const auto & backend_pair : + rmw::impl::cpp::parse_buffer_backend_metadata(topic_endpoint_info->buffer_backend_metadata)) + { + py_buffer_backend_metadata[py::str(backend_pair.first)] = py::str(backend_pair.second); + } + py_endpoint_info_dict["buffer_backend_metadata"] = py_buffer_backend_metadata; return py_endpoint_info_dict; } diff --git a/rclpy/test/test_topic_endpoint_info.py b/rclpy/test/test_topic_endpoint_info.py index af4dc352c..b99036249 100644 --- a/rclpy/test/test_topic_endpoint_info.py +++ b/rclpy/test/test_topic_endpoint_info.py @@ -88,6 +88,19 @@ def test_qos_profile_only_constructor(self) -> None: self.assertEqual(info_for_ref, info_from_ctor) self.assertEqual(test_qos_profile, info_from_ctor.qos_profile) + def test_buffer_backend_metadata_only_constructor(self) -> None: + test_buffer_backend_metadata = {'cpu': ''} + + info_for_ref = TopicEndpointInfo() + info_for_ref.buffer_backend_metadata = test_buffer_backend_metadata + + info_from_ctor = TopicEndpointInfo( + buffer_backend_metadata=test_buffer_backend_metadata) + + self.assertEqual(info_for_ref, info_from_ctor) + self.assertEqual( + test_buffer_backend_metadata, info_from_ctor.buffer_backend_metadata) + def test_print(self) -> None: actual_info_str = str(TopicEndpointInfo()) expected_info_str = 'Node name: \n' \ @@ -96,6 +109,7 @@ def test_print(self) -> None: 'Topic type hash: INVALID\n' \ 'Endpoint type: INVALID\n' \ 'GID: \n' \ + 'Buffer backends: \n' \ 'QoS profile:\n' \ ' Reliability: UNKNOWN\n' \ ' History (Depth): UNKNOWN\n' \