Skip to content

Commit b6a890c

Browse files
Types for rosidl_adapter (#828)
* type for rosidl_adapter Signed-off-by: Michael Carlstrom <rmc@carlstrom.com> * re-run CI Signed-off-by: Michael Carlstrom <rmc@carlstrom.com> * re-run CI Signed-off-by: Michael Carlstrom <rmc@carlstrom.com> * use ament_cmake_mypy instead Signed-off-by: Michael Carlstrom <rmc@carlstrom.com> --------- Signed-off-by: Michael Carlstrom <rmc@carlstrom.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent ecb5d12 commit b6a890c

29 files changed

+266
-179
lines changed

rosidl_adapter/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ ament_python_install_package(${PROJECT_NAME})
1010
if(BUILD_TESTING)
1111
find_package(ament_cmake_pytest REQUIRED)
1212
find_package(ament_lint_auto REQUIRED)
13+
find_package(ament_cmake_mypy REQUIRED)
1314
ament_lint_auto_find_test_dependencies()
1415
ament_add_pytest_test(pytest test)
1516
endif()

rosidl_adapter/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<exec_depend>python3-empy</exec_depend>
2727
<exec_depend>rosidl_cli</exec_depend>
2828

29+
<test_depend>ament_cmake_mypy</test_depend>
2930
<test_depend>ament_cmake_pytest</test_depend>
3031
<test_depend>ament_lint_common</test_depend>
3132
<test_depend>ament_lint_auto</test_depend>

rosidl_adapter/rosidl_adapter/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from pathlib import Path
1516

16-
def convert_to_idl(package_dir, package_name, interface_file, output_dir):
17+
18+
def convert_to_idl(package_dir: Path, package_name: str, interface_file: Path,
19+
output_dir: Path) -> Path:
1720
if interface_file.suffix == '.msg':
1821
from rosidl_adapter.msg import convert_msg_to_idl
1922
return convert_msg_to_idl(

rosidl_adapter/rosidl_adapter/__main__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@
1616

1717
from rosidl_adapter.main import main
1818

19-
sys.exit(main())
19+
main()
20+
sys.exit()

rosidl_adapter/rosidl_adapter/action/__init__.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from pathlib import Path
16+
1517
from rosidl_adapter.parser import parse_action_string
16-
from rosidl_adapter.resource import expand_template
18+
from rosidl_adapter.resource import ActionData, expand_template
1719

1820

19-
def convert_action_to_idl(package_dir, package_name, input_file, output_dir):
21+
def convert_action_to_idl(package_dir: Path, package_name: str, input_file: Path,
22+
output_dir: Path) -> Path:
2023
assert package_dir.is_absolute()
2124
assert not input_file.is_absolute()
2225
assert input_file.suffix == '.action'
@@ -30,7 +33,7 @@ def convert_action_to_idl(package_dir, package_name, input_file, output_dir):
3033
output_file = output_dir / input_file.with_suffix('.idl').name
3134
abs_output_file = output_file.absolute()
3235
print(f'Writing output file: {abs_output_file}')
33-
data = {
36+
data: ActionData = {
3437
'pkg_name': package_name,
3538
'relative_input_file': input_file.as_posix(),
3639
'action': action,

rosidl_adapter/rosidl_adapter/cli.py

+26-15
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
# limitations under the License.
1414

1515
import argparse
16-
import pathlib
16+
from pathlib import Path
1717
import sys
18+
from typing import Callable, List, Literal, TYPE_CHECKING
1819

1920
from catkin_pkg.package import package_exists_at
2021
from catkin_pkg.package import parse_package
@@ -27,7 +28,18 @@
2728
from rosidl_cli.command.translate.extensions import TranslateCommandExtension
2829

2930

30-
def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]):
31+
if TYPE_CHECKING:
32+
from typing_extensions import TypeAlias
33+
34+
ConversionFunctionType: TypeAlias = Callable[[Path, str, Path, Path], Path]
35+
36+
37+
def convert_files_to_idl(
38+
extension: Literal['.msg', '.srv', '.action'],
39+
conversion_function: 'ConversionFunctionType',
40+
argv: List[str] = sys.argv[1:]
41+
) -> None:
42+
3143
parser = argparse.ArgumentParser(
3244
description=f'Convert {extension} files to .idl')
3345
parser.add_argument(
@@ -36,7 +48,7 @@ def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]):
3648
args = parser.parse_args(argv)
3749

3850
for interface_file in args.interface_files:
39-
interface_file = pathlib.Path(interface_file)
51+
interface_file = Path(interface_file)
4052
package_dir = interface_file.parent.absolute()
4153
while (
4254
len(package_dir.parents) and
@@ -48,8 +60,7 @@ def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]):
4860
f"Could not find package for '{interface_file}'",
4961
file=sys.stderr)
5062
continue
51-
warnings = []
52-
pkg = parse_package(package_dir, warnings=warnings)
63+
pkg = parse_package(package_dir, warnings=[])
5364

5465
conversion_function(
5566
package_dir, pkg.name,
@@ -63,14 +74,14 @@ class TranslateToIDL(TranslateCommandExtension):
6374

6475
def translate(
6576
self,
66-
package_name,
67-
interface_files,
68-
include_paths,
69-
output_path
70-
):
77+
package_name: str,
78+
interface_files: List[str],
79+
include_paths: List[str],
80+
output_path: Path
81+
) -> List[str]:
7182
translated_interface_files = []
72-
for interface_file in interface_files:
73-
prefix, interface_file = interface_path_as_tuple(interface_file)
83+
for interface_file_str in interface_files:
84+
prefix, interface_file = interface_path_as_tuple(interface_file_str)
7485
output_dir = output_path / interface_file.parent
7586
translated_interface_file = self.conversion_function(
7687
prefix, package_name, interface_file, output_dir)
@@ -87,7 +98,7 @@ class TranslateMsgToIDL(TranslateToIDL):
8798
input_format = 'msg'
8899

89100
@property
90-
def conversion_function(self):
101+
def conversion_function(self) -> 'ConversionFunctionType':
91102
return convert_msg_to_idl
92103

93104

@@ -96,13 +107,13 @@ class TranslateSrvToIDL(TranslateToIDL):
96107
input_format = 'srv'
97108

98109
@property
99-
def conversion_function(self):
110+
def conversion_function(self) -> 'ConversionFunctionType':
100111
return convert_srv_to_idl
101112

102113

103114
class TranslateActionToIDL(TranslateToIDL):
104115
input_format = 'action'
105116

106117
@property
107-
def conversion_function(self):
118+
def conversion_function(self) -> 'ConversionFunctionType':
108119
return convert_action_to_idl

rosidl_adapter/rosidl_adapter/main.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717
import os
1818
import pathlib
1919
import sys
20+
from typing import List
2021

2122

2223
from rosidl_adapter import convert_to_idl
2324

2425

25-
def main(argv=sys.argv[1:]):
26+
def main(argv: List[str] = sys.argv[1:]) -> None:
2627
parser = argparse.ArgumentParser(
2728
description='Convert interface files to .idl')
2829
parser.add_argument(

rosidl_adapter/rosidl_adapter/msg/__init__.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from rosidl_adapter.parser import parse_message_string
16-
from rosidl_adapter.resource import expand_template
15+
from pathlib import Path
16+
from typing import Final, Optional, Union
1717

18+
from rosidl_adapter.parser import BaseType, parse_message_string, Type
19+
from rosidl_adapter.resource import expand_template, MsgData
1820

19-
def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
21+
22+
def convert_msg_to_idl(package_dir: Path, package_name: str, input_file: Path,
23+
output_dir: Path) -> Path:
2024
assert package_dir.is_absolute()
2125
assert not input_file.is_absolute()
2226
assert input_file.suffix == '.msg'
@@ -30,7 +34,7 @@ def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
3034
output_file = output_dir / input_file.with_suffix('.idl').name
3135
abs_output_file = output_file.absolute()
3236
print(f'Writing output file: {abs_output_file}')
33-
data = {
37+
data: MsgData = {
3438
'pkg_name': package_name,
3539
'relative_input_file': input_file.as_posix(),
3640
'msg': msg,
@@ -40,7 +44,7 @@ def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
4044
return output_file
4145

4246

43-
MSG_TYPE_TO_IDL = {
47+
MSG_TYPE_TO_IDL: Final = {
4448
'bool': 'boolean',
4549
'byte': 'octet',
4650
'char': 'uint8',
@@ -59,7 +63,7 @@ def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
5963
}
6064

6165

62-
def to_idl_literal(idl_type, value):
66+
def to_idl_literal(idl_type: str, value: str) -> str:
6367
if idl_type[-1] == ']' or idl_type.startswith('sequence<'):
6468
content = repr(tuple(value)).replace('\\', r'\\').replace('"', r'\"')
6569
return f'"{content}"'
@@ -73,24 +77,24 @@ def to_idl_literal(idl_type, value):
7377
return value
7478

7579

76-
def string_to_idl_string_literal(string):
80+
def string_to_idl_string_literal(string: str) -> str:
7781
"""Convert string to character literal as described in IDL 4.2 section 7.2.6.3 ."""
7882
estr = string.encode().decode('unicode_escape')
7983
estr = estr.replace('"', r'\"')
8084
return '"{0}"'.format(estr)
8185

8286

83-
def string_to_idl_wstring_literal(string):
87+
def string_to_idl_wstring_literal(string: str) -> str:
8488
return string_to_idl_string_literal(string)
8589

8690

87-
def get_include_file(base_type):
91+
def get_include_file(base_type: BaseType) -> Optional[str]:
8892
if base_type.is_primitive_type():
8993
return None
9094
return f'{base_type.pkg_name}/msg/{base_type.type}.idl'
9195

9296

93-
def get_idl_type(type_):
97+
def get_idl_type(type_: Union[str, Type]) -> str:
9498
if isinstance(type_, str):
9599
identifier = MSG_TYPE_TO_IDL[type_]
96100
elif type_.is_primitive_type():

0 commit comments

Comments
 (0)