From 81dfae7b1fe9c4d751accf7a05bbcdde572f4f0a Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Fri, 26 Feb 2021 17:39:13 -0300 Subject: [PATCH 1/6] Expose .msg/.srv/.action to .idl conversion via rosidl translate CLI Signed-off-by: Michel Hidalgo --- rosidl_adapter/package.xml | 1 + rosidl_adapter/rosidl_adapter/cli.py | 59 +++++++++++++++++++++++++++- rosidl_adapter/setup.cfg | 5 +++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 rosidl_adapter/setup.cfg diff --git a/rosidl_adapter/package.xml b/rosidl_adapter/package.xml index c546c3208..9f047bc0b 100644 --- a/rosidl_adapter/package.xml +++ b/rosidl_adapter/package.xml @@ -14,6 +14,7 @@ ament_cmake python3-empy + rosidl_cli ament_cmake_pytest ament_lint_common diff --git a/rosidl_adapter/rosidl_adapter/cli.py b/rosidl_adapter/rosidl_adapter/cli.py index dad3f0b39..5db46d4f5 100644 --- a/rosidl_adapter/rosidl_adapter/cli.py +++ b/rosidl_adapter/rosidl_adapter/cli.py @@ -1,4 +1,4 @@ -# Copyright 2018 Open Source Robotics Foundation, Inc. +# Copyright 2018-2021 Open Source Robotics Foundation, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,6 +19,9 @@ from catkin_pkg.package import package_exists_at from catkin_pkg.package import parse_package +from rosidl_cli.command.helpers import interface_path_as_tuple +from rosidl_cli.command.translate.extensions import TranslateCommandExtension + def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]): parser = argparse.ArgumentParser( @@ -48,3 +51,57 @@ def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]): package_dir, pkg.name, interface_file.absolute().relative_to(package_dir), interface_file.parent) + + +class TranslateToIDL(TranslateCommandExtension): + + output_format = 'idl' + + def translate( + self, + package_name, + interface_files, + include_paths, + output_path + ): + translated_interface_files = [] + for interface_file in interface_files: + prefix, interface_file = interface_path_as_tuple(interface_file) + output_dir = output_path / interface_file.parent + translated_interface_file = self.conversion_function( + prefix, package_name, interface_file, output_dir) + translated_interface_file = \ + translated_interface_file.relative_to(output_path) + translated_interface_files.append( + f'{output_path}:{translated_interface_file}' + ) + return translated_interface_files + + +class TranslateMsgToIDL(TranslateToIDL): + + input_format = 'msg' + + @property + def conversion_function(self): + from rosidl_adapter.msg import convert_msg_to_idl + return convert_msg_to_idl + + +class TranslateSrvToIDL(TranslateToIDL): + + input_format = 'srv' + + @property + def conversion_function(self): + from rosidl_adapter.srv import convert_srv_to_idl + return convert_srv_to_idl + + +class TranslateActionToIDL(TranslateToIDL): + input_format = 'action' + + @property + def conversion_function(self): + from rosidl_adapter.action import convert_action_to_idl + return convert_action_to_idl diff --git a/rosidl_adapter/setup.cfg b/rosidl_adapter/setup.cfg new file mode 100644 index 000000000..bfb5cb4b2 --- /dev/null +++ b/rosidl_adapter/setup.cfg @@ -0,0 +1,5 @@ +[options.entry_points] +rosidl_cli.command.translate.extensions = + msg2idl = rosidl_adapter.cli:TranslateMsgToIDL + srv2idl = rosidl_adapter.cli:TranslateSrvToIDL + action2idl = rosidl_adapter.cli:TranslateActionToIDL From 62bbb5e09c0854cda69e097d71010c0c33e7f715 Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Wed, 3 Mar 2021 17:31:22 -0300 Subject: [PATCH 2/6] Test rosidl translate extensions Signed-off-by: Michel Hidalgo --- rosidl_adapter/test/data/action/Test.action | 21 +++++ .../test/data/action/Test.expected.idl | 50 +++++++++++ .../test/data/msg/Test.expected.idl | 36 ++++++++ rosidl_adapter/test/data/msg/Test.msg | 13 +++ .../test/data/srv/Test.expected.idl | 41 +++++++++ rosidl_adapter/test/data/srv/Test.srv | 16 ++++ rosidl_adapter/test/test_cli_extensions.py | 85 +++++++++++++++++++ 7 files changed, 262 insertions(+) create mode 100644 rosidl_adapter/test/data/action/Test.action create mode 100644 rosidl_adapter/test/data/action/Test.expected.idl create mode 100644 rosidl_adapter/test/data/msg/Test.expected.idl create mode 100644 rosidl_adapter/test/data/msg/Test.msg create mode 100644 rosidl_adapter/test/data/srv/Test.expected.idl create mode 100644 rosidl_adapter/test/data/srv/Test.srv create mode 100644 rosidl_adapter/test/test_cli_extensions.py diff --git a/rosidl_adapter/test/data/action/Test.action b/rosidl_adapter/test/data/action/Test.action new file mode 100644 index 000000000..be9501b3a --- /dev/null +++ b/rosidl_adapter/test/data/action/Test.action @@ -0,0 +1,21 @@ +# goal definition +bool bool_value +byte byte_value +char char_value +float32 float32_value +float64 float64_value +int8 int8_value +uint8 uint8_value +int16 int16_value +uint16 uint16_value +int32 int32_value +uint32 uint32_value +int64 int64_value +uint64 uint64_value +string string_value +--- +# result definition +bool ok +--- +# feedback definition +int32[] sequence diff --git a/rosidl_adapter/test/data/action/Test.expected.idl b/rosidl_adapter/test/data/action/Test.expected.idl new file mode 100644 index 000000000..bb5c4e698 --- /dev/null +++ b/rosidl_adapter/test/data/action/Test.expected.idl @@ -0,0 +1,50 @@ +// generated from rosidl_adapter/resource/action.idl.em +// with input from test_msgs/action/Test.action +// generated code does not contain a copyright notice + + +module test_msgs { + module action { + @verbatim (language="comment", text= + " goal definition") + struct Test_Goal { + boolean bool_value; + + octet byte_value; + + uint8 char_value; + + float float32_value; + + double float64_value; + + int8 int8_value; + + uint8 uint8_value; + + int16 int16_value; + + uint16 uint16_value; + + int32 int32_value; + + uint32 uint32_value; + + int64 int64_value; + + uint64 uint64_value; + + string string_value; + }; + struct Test_Result { + @verbatim (language="comment", text= + " result definition") + boolean ok; + }; + struct Test_Feedback { + @verbatim (language="comment", text= + " feedback definition") + sequence sequence; + }; + }; +}; diff --git a/rosidl_adapter/test/data/msg/Test.expected.idl b/rosidl_adapter/test/data/msg/Test.expected.idl new file mode 100644 index 000000000..71694d374 --- /dev/null +++ b/rosidl_adapter/test/data/msg/Test.expected.idl @@ -0,0 +1,36 @@ +// generated from rosidl_adapter/resource/msg.idl.em +// with input from test_msgs/msg/Test.msg +// generated code does not contain a copyright notice + + +module test_msgs { + module msg { + struct Test { + boolean bool_value; + + octet byte_value; + + uint8 char_value; + + float float32_value; + + double float64_value; + + int8 int8_value; + + uint8 uint8_value; + + int16 int16_value; + + uint16 uint16_value; + + int32 int32_value; + + uint32 uint32_value; + + int64 int64_value; + + uint64 uint64_value; + }; + }; +}; diff --git a/rosidl_adapter/test/data/msg/Test.msg b/rosidl_adapter/test/data/msg/Test.msg new file mode 100644 index 000000000..eaf9b9ef3 --- /dev/null +++ b/rosidl_adapter/test/data/msg/Test.msg @@ -0,0 +1,13 @@ +bool bool_value +byte byte_value +char char_value +float32 float32_value +float64 float64_value +int8 int8_value +uint8 uint8_value +int16 int16_value +uint16 uint16_value +int32 int32_value +uint32 uint32_value +int64 int64_value +uint64 uint64_value diff --git a/rosidl_adapter/test/data/srv/Test.expected.idl b/rosidl_adapter/test/data/srv/Test.expected.idl new file mode 100644 index 000000000..dbb4dee01 --- /dev/null +++ b/rosidl_adapter/test/data/srv/Test.expected.idl @@ -0,0 +1,41 @@ +// generated from rosidl_adapter/resource/srv.idl.em +// with input from test_msgs/srv/Test.srv +// generated code does not contain a copyright notice + + +module test_msgs { + module srv { + struct Test_Request { + boolean bool_value; + + octet byte_value; + + uint8 char_value; + + float float32_value; + + double float64_value; + + int8 int8_value; + + uint8 uint8_value; + + int16 int16_value; + + uint16 uint16_value; + + int32 int32_value; + + uint32 uint32_value; + + int64 int64_value; + + uint64 uint64_value; + + string string_value; + }; + struct Test_Response { + boolean ok; + }; + }; +}; diff --git a/rosidl_adapter/test/data/srv/Test.srv b/rosidl_adapter/test/data/srv/Test.srv new file mode 100644 index 000000000..934567d7f --- /dev/null +++ b/rosidl_adapter/test/data/srv/Test.srv @@ -0,0 +1,16 @@ +bool bool_value +byte byte_value +char char_value +float32 float32_value +float64 float64_value +int8 int8_value +uint8 uint8_value +int16 int16_value +uint16 uint16_value +int32 int32_value +uint32 uint32_value +int64 int64_value +uint64 uint64_value +string string_value +--- +bool ok diff --git a/rosidl_adapter/test/test_cli_extensions.py b/rosidl_adapter/test/test_cli_extensions.py new file mode 100644 index 000000000..218d7bb41 --- /dev/null +++ b/rosidl_adapter/test/test_cli_extensions.py @@ -0,0 +1,85 @@ +# Copyright 2021 Open Source Robotics Foundation, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import filecmp +import pathlib + +from rosidl_cli.command.translate.api import translate + + +DATA_PATH = pathlib.Path(__file__).parent / 'data' + + +def test_translation_extensions(tmp_path, capsys): + # NOTE(hidmic): pytest and empy do not play along, + # the latter expects some proxy will stay in sys.stdout + # and the former insists in overwriting it + + with capsys.disabled(): # so do everything in one run + # Test .msg to .idl translation + idl_files = translate( + package_name='test_msgs', + interface_files=[ + f'{DATA_PATH}:msg/Test.msg'], + output_path=tmp_path, + output_format='idl', + translators=['msg2idl'] + ) + + assert len(idl_files) == 1 + idl_file = idl_files[0] + assert idl_file == f'{tmp_path}:msg/Test.idl' + assert filecmp.cmp( + tmp_path / 'msg' / 'Test.idl', + DATA_PATH / 'msg' / 'Test.expected.idl', + shallow=False + ) + + # Test .srv to .idl translation + idl_files = translate( + package_name='test_msgs', + interface_files=[ + f'{DATA_PATH}:srv/Test.srv'], + output_path=tmp_path, + output_format='idl', + translators=['srv2idl'] + ) + + assert len(idl_files) == 1 + idl_file = idl_files[0] + assert idl_file == f'{tmp_path}:srv/Test.idl' + assert filecmp.cmp( + tmp_path / 'srv' / 'Test.idl', + DATA_PATH / 'srv' / 'Test.expected.idl', + shallow=False + ) + + # Test .action to .idl translation + idl_files = translate( + package_name='test_msgs', + interface_files=[ + f'{DATA_PATH}:action/Test.action'], + output_path=tmp_path, + output_format='idl', + translators=['action2idl'] + ) + + assert len(idl_files) == 1 + idl_file = idl_files[0] + assert idl_file == f'{tmp_path}:action/Test.idl' + assert filecmp.cmp( + tmp_path / 'action' / 'Test.idl', + DATA_PATH / 'action' / 'Test.expected.idl', + shallow=False + ) From 014e2183a43c11cb9ef1635514e0d32ab030c5b7 Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Mon, 8 Mar 2021 15:09:06 -0300 Subject: [PATCH 3/6] Collapse BUILD_TESTING clauses Signed-off-by: Michel Hidalgo --- rosidl_adapter/CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/rosidl_adapter/CMakeLists.txt b/rosidl_adapter/CMakeLists.txt index 643682935..b14b5518b 100644 --- a/rosidl_adapter/CMakeLists.txt +++ b/rosidl_adapter/CMakeLists.txt @@ -8,8 +8,10 @@ find_package(ament_cmake_python REQUIRED) ament_python_install_package(${PROJECT_NAME}) if(BUILD_TESTING) + find_package(ament_cmake_pytest REQUIRED) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() + ament_add_pytest_test(pytest test) endif() ament_package( @@ -25,8 +27,3 @@ install(PROGRAMS scripts/msg2idl.py scripts/srv2idl.py DESTINATION lib/${PROJECT_NAME}) - -if(BUILD_TESTING) - find_package(ament_cmake_pytest REQUIRED) - ament_add_pytest_test(pytest test) -endif() From 74e0044bdabae5c6f25ce76c6f591423a26ef4ee Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Tue, 9 Mar 2021 11:35:53 -0300 Subject: [PATCH 4/6] Address peer review comments Signed-off-by: Michel Hidalgo --- rosidl_adapter/rosidl_adapter/cli.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rosidl_adapter/rosidl_adapter/cli.py b/rosidl_adapter/rosidl_adapter/cli.py index 5db46d4f5..72f10594c 100644 --- a/rosidl_adapter/rosidl_adapter/cli.py +++ b/rosidl_adapter/rosidl_adapter/cli.py @@ -1,4 +1,4 @@ -# Copyright 2018-2021 Open Source Robotics Foundation, Inc. +# Copyright 2018 Open Source Robotics Foundation, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,6 +19,10 @@ from catkin_pkg.package import package_exists_at from catkin_pkg.package import parse_package +from rosidl_adapter.action import convert_action_to_idl +from rosidl_adapter.msg import convert_msg_to_idl +from rosidl_adapter.srv import convert_srv_to_idl + from rosidl_cli.command.helpers import interface_path_as_tuple from rosidl_cli.command.translate.extensions import TranslateCommandExtension @@ -84,7 +88,6 @@ class TranslateMsgToIDL(TranslateToIDL): @property def conversion_function(self): - from rosidl_adapter.msg import convert_msg_to_idl return convert_msg_to_idl @@ -94,7 +97,6 @@ class TranslateSrvToIDL(TranslateToIDL): @property def conversion_function(self): - from rosidl_adapter.srv import convert_srv_to_idl return convert_srv_to_idl @@ -103,5 +105,4 @@ class TranslateActionToIDL(TranslateToIDL): @property def conversion_function(self): - from rosidl_adapter.action import convert_action_to_idl return convert_action_to_idl From 2775f03d810724e41bf4954c2d7f8e1818670ddb Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Tue, 9 Mar 2021 11:36:29 -0300 Subject: [PATCH 5/6] Interface file relative paths must be POSIX Signed-off-by: Michel Hidalgo --- rosidl_adapter/rosidl_adapter/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rosidl_adapter/rosidl_adapter/cli.py b/rosidl_adapter/rosidl_adapter/cli.py index 72f10594c..f1f5bb5eb 100644 --- a/rosidl_adapter/rosidl_adapter/cli.py +++ b/rosidl_adapter/rosidl_adapter/cli.py @@ -77,7 +77,7 @@ def translate( translated_interface_file = \ translated_interface_file.relative_to(output_path) translated_interface_files.append( - f'{output_path}:{translated_interface_file}' + f'{output_path}:{translated_interface_file.as_posix()}' ) return translated_interface_files From 928c1a42882af4afb4866dc719d98825901aa0ea Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Tue, 9 Mar 2021 15:42:42 -0300 Subject: [PATCH 6/6] Use POSIX paths in template comments. Signed-off-by: Michel Hidalgo --- rosidl_adapter/rosidl_adapter/action/__init__.py | 2 +- rosidl_adapter/rosidl_adapter/msg/__init__.py | 2 +- rosidl_adapter/rosidl_adapter/srv/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rosidl_adapter/rosidl_adapter/action/__init__.py b/rosidl_adapter/rosidl_adapter/action/__init__.py index d4b128079..6e8719b6c 100644 --- a/rosidl_adapter/rosidl_adapter/action/__init__.py +++ b/rosidl_adapter/rosidl_adapter/action/__init__.py @@ -32,7 +32,7 @@ def convert_action_to_idl(package_dir, package_name, input_file, output_dir): print(f'Writing output file: {abs_output_file}') data = { 'pkg_name': package_name, - 'relative_input_file': input_file, + 'relative_input_file': input_file.as_posix(), 'action': action, } diff --git a/rosidl_adapter/rosidl_adapter/msg/__init__.py b/rosidl_adapter/rosidl_adapter/msg/__init__.py index 1cd056ada..322bd7277 100644 --- a/rosidl_adapter/rosidl_adapter/msg/__init__.py +++ b/rosidl_adapter/rosidl_adapter/msg/__init__.py @@ -32,7 +32,7 @@ def convert_msg_to_idl(package_dir, package_name, input_file, output_dir): print(f'Writing output file: {abs_output_file}') data = { 'pkg_name': package_name, - 'relative_input_file': input_file, + 'relative_input_file': input_file.as_posix(), 'msg': msg, } diff --git a/rosidl_adapter/rosidl_adapter/srv/__init__.py b/rosidl_adapter/rosidl_adapter/srv/__init__.py index 41ae4e053..c57b7013f 100644 --- a/rosidl_adapter/rosidl_adapter/srv/__init__.py +++ b/rosidl_adapter/rosidl_adapter/srv/__init__.py @@ -32,7 +32,7 @@ def convert_srv_to_idl(package_dir, package_name, input_file, output_dir): print(f'Writing output file: {abs_output_file}') data = { 'pkg_name': package_name, - 'relative_input_file': input_file, + 'relative_input_file': input_file.as_posix(), 'srv': srv, }