Skip to content

Commit 4f5f80c

Browse files
Rosidl cli types with specs_set fix (#831)
* init Signed-off-by: Michael Carlstrom <[email protected]> * add type to fixture Signed-off-by: Michael Carlstrom <[email protected]> * remove import Signed-off-by: Michael Carlstrom <[email protected]> * add #type: ignore on yaml import Signed-off-by: Michael Carlstrom <[email protected]> * move # Signed-off-by: Michael Carlstrom <[email protected]> * Add ament_mypy dep Signed-off-by: Michael Carlstrom <[email protected]> * Add missing py.typed file Signed-off-by: Michael Carlstrom <[email protected]> * fix entry_points Signed-off-by: Michael Carlstrom <[email protected]> * Fix Unpack erros by removing kwargs Signed-off-by: Michael Carlstrom <[email protected]> * fix groups error Signed-off-by: Michael Carlstrom <[email protected]> * remove unused import Signed-off-by: Michael Carlstrom <[email protected]> * Use Union Tuple Signed-off-by: Michael Carlstrom <[email protected]> * Add missing specs_set default Signed-off-by: Michael Carlstrom <[email protected]> --------- Signed-off-by: Michael Carlstrom <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent a2706a5 commit 4f5f80c

File tree

22 files changed

+184
-112
lines changed

22 files changed

+184
-112
lines changed

rosidl_cli/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
<test_depend>ament_copyright</test_depend>
2424
<test_depend>ament_flake8</test_depend>
25+
<test_depend>ament_mypy</test_depend>
2526
<test_depend>ament_pep257</test_depend>
2627
<test_depend>ament_xmllint</test_depend>
2728
<test_depend>python3-pytest</test_depend>

rosidl_cli/py.typed

Whitespace-only changes.

rosidl_cli/rosidl_cli/cli.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414

1515
import argparse
1616
import signal
17+
from typing import Any, List, Union
1718

1819
from rosidl_cli.command.generate import GenerateCommand
1920
from rosidl_cli.command.translate import TranslateCommand
2021
from rosidl_cli.common import get_first_line_doc
2122

2223

23-
def add_subparsers(parser, cli_name, commands):
24+
def add_subparsers(
25+
parser: argparse.ArgumentParser,
26+
cli_name: str,
27+
commands: List[Union[GenerateCommand, TranslateCommand]]
28+
) -> argparse._SubParsersAction[argparse.ArgumentParser]:
2429
"""
2530
Create argparse subparser for each command.
2631
@@ -63,7 +68,7 @@ def add_subparsers(parser, cli_name, commands):
6368
return subparser
6469

6570

66-
def main():
71+
def main() -> Union[str, signal.Signals, Any]:
6772
script_name = 'rosidl'
6873
description = f'{script_name} is an extensible command-line tool ' \
6974
'for ROS interface generation.'
@@ -74,7 +79,8 @@ def main():
7479
formatter_class=argparse.RawDescriptionHelpFormatter
7580
)
7681

77-
commands = [GenerateCommand(), TranslateCommand()]
82+
commands: List[Union[GenerateCommand, TranslateCommand]] = \
83+
[GenerateCommand(), TranslateCommand()]
7884

7985
# add arguments for command extension(s)
8086
add_subparsers(

rosidl_cli/rosidl_cli/command/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import argparse
16+
1517

1618
class Command:
1719
"""
@@ -22,8 +24,8 @@ class Command:
2224
* `add_arguments`
2325
"""
2426

25-
def add_arguments(self, parser):
27+
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
2628
pass
2729

28-
def main(self, *, parser, args):
30+
def main(self, *, args: argparse.Namespace) -> None:
2931
raise NotImplementedError()

rosidl_cli/rosidl_cli/command/generate/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import argparse
1516
import pathlib
1617

1718
from rosidl_cli.command import Command
@@ -24,7 +25,7 @@ class GenerateCommand(Command):
2425

2526
name = 'generate'
2627

27-
def add_arguments(self, parser):
28+
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
2829
parser.add_argument(
2930
'-o', '--output-path', metavar='PATH',
3031
type=pathlib.Path, default=None,
@@ -50,7 +51,7 @@ def add_arguments(self, parser):
5051
"If prefixed by another path followed by a colon ':', "
5152
'path resolution is performed against such path.'))
5253

53-
def main(self, *, args):
54+
def main(self, *, args: argparse.Namespace) -> None:
5455
generate(
5556
package_name=args.package_name,
5657
interface_files=args.interface_files,

rosidl_cli/rosidl_cli/command/generate/api.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,22 @@
1414

1515
import os
1616
import pathlib
17+
from typing import List, Optional
1718

19+
from .extensions import GenerateCommandExtension
1820
from .extensions import load_type_extensions
1921
from .extensions import load_typesupport_extensions
2022

2123

2224
def generate(
2325
*,
24-
package_name,
25-
interface_files,
26-
include_paths=None,
27-
output_path=None,
28-
types=None,
29-
typesupports=None
30-
):
26+
package_name: str,
27+
interface_files: List[str],
28+
include_paths: Optional[List[str]] = None,
29+
output_path: Optional[pathlib.Path] = None,
30+
types: Optional[List[str]] = None,
31+
typesupports: Optional[List[str]] = None
32+
) -> List[List[str]]:
3133
"""
3234
Generate source code from interface definition files.
3335
@@ -60,7 +62,7 @@ def generate(
6062
:returns: list of lists of paths to generated source code files,
6163
one group per type or type support extension invoked
6264
"""
63-
extensions = []
65+
extensions: List[GenerateCommandExtension] = []
6466

6567
unspecific_generation = not types and not typesupports
6668

rosidl_cli/rosidl_cli/command/generate/extensions.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from pathlib import Path
16+
from typing import cast, List, Optional
17+
1518
from rosidl_cli.extensions import Extension
1619
from rosidl_cli.extensions import load_extensions
1720

@@ -26,11 +29,11 @@ class GenerateCommandExtension(Extension):
2629

2730
def generate(
2831
self,
29-
package_name,
30-
interface_files,
31-
include_paths,
32-
output_path
33-
):
32+
package_name: str,
33+
interface_files: List[str],
34+
include_paths: List[str],
35+
output_path: Path
36+
) -> List[str]:
3437
"""
3538
Generate source code.
3639
@@ -48,11 +51,17 @@ def generate(
4851
raise NotImplementedError()
4952

5053

51-
def load_type_extensions(**kwargs):
54+
def load_type_extensions(*, specs: Optional[List[str]],
55+
strict: bool) -> List[GenerateCommandExtension]:
5256
"""Load extensions for type representation source code generation."""
53-
return load_extensions('rosidl_cli.command.generate.type_extensions', **kwargs)
57+
extensions = load_extensions('rosidl_cli.command.generate.type_extensions', specs=specs,
58+
strict=strict)
59+
return cast(List[GenerateCommandExtension], extensions)
5460

5561

56-
def load_typesupport_extensions(**kwargs):
62+
def load_typesupport_extensions(*, specs: Optional[List[str]], strict: bool
63+
) -> List[GenerateCommandExtension]:
5764
"""Load extensions for type support source code generation."""
58-
return load_extensions('rosidl_cli.command.generate.typesupport_extensions', **kwargs)
65+
extensions = load_extensions('rosidl_cli.command.generate.typesupport_extensions',
66+
specs=specs, strict=strict)
67+
return cast(List[GenerateCommandExtension], extensions)

rosidl_cli/rosidl_cli/command/helpers.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
import os
1818
import pathlib
1919
import tempfile
20+
from typing import Generator, List, Tuple
2021

2122

22-
def package_name_from_interface_file_path(path):
23+
def package_name_from_interface_file_path(path: pathlib.Path) -> str:
2324
"""
2425
Derive ROS package name from a ROS interface definition file path.
2526
@@ -29,7 +30,7 @@ def package_name_from_interface_file_path(path):
2930
return pathlib.Path(os.path.abspath(path)).parents[1].name
3031

3132

32-
def dependencies_from_include_paths(include_paths):
33+
def dependencies_from_include_paths(include_paths: List[str]) -> List[str]:
3334
"""
3435
Collect dependencies' ROS interface definition files from include paths.
3536
@@ -45,7 +46,7 @@ def dependencies_from_include_paths(include_paths):
4546
})
4647

4748

48-
def interface_path_as_tuple(path):
49+
def interface_path_as_tuple(path: str) -> Tuple[pathlib.Path, pathlib.Path]:
4950
"""
5051
Express interface definition file path as an (absolute prefix, relative path) tuple.
5152
@@ -61,41 +62,43 @@ def interface_path_as_tuple(path):
6162
"""
6263
path_as_string = str(path)
6364
if ':' not in path_as_string:
64-
prefix = pathlib.Path.cwd()
65+
prefix_path = pathlib.Path.cwd()
6566
else:
6667
prefix, _, path = path_as_string.rpartition(':')
67-
prefix = pathlib.Path(os.path.abspath(prefix))
68-
path = pathlib.Path(path)
69-
if path.is_absolute():
68+
prefix_path = pathlib.Path(os.path.abspath(prefix))
69+
path_as_path = pathlib.Path(path)
70+
if path_as_path.is_absolute():
7071
raise ValueError('Interface definition file path '
71-
f"'{path}' cannot be absolute")
72-
return prefix, path
72+
f"'{path_as_path}' cannot be absolute")
73+
return prefix_path, path_as_path
7374

7475

75-
def idl_tuples_from_interface_files(interface_files):
76+
def idl_tuples_from_interface_files(
77+
interface_files: List[str]
78+
) -> List[str]:
7679
"""
7780
Express ROS interface definition file paths as IDL tuples.
7881
7982
An IDL tuple is a relative path prefixed by an absolute path against
8083
which to resolve it followed by a colon ':'. This function then applies
8184
the same logic as `interface_path_as_tuple`.
8285
"""
83-
idl_tuples = []
84-
for path in interface_files:
85-
prefix, path = interface_path_as_tuple(path)
86+
idl_tuples: List[str] = []
87+
for interface_path in interface_files:
88+
prefix, path = interface_path_as_tuple(interface_path)
8689
idl_tuples.append(f'{prefix}:{path.as_posix()}')
8790
return idl_tuples
8891

8992

9093
@contextlib.contextmanager
9194
def legacy_generator_arguments_file(
9295
*,
93-
package_name,
94-
interface_files,
95-
include_paths,
96-
templates_path,
97-
output_path
98-
):
96+
package_name: str,
97+
interface_files: List[str],
98+
include_paths: List[str],
99+
templates_path: str,
100+
output_path: str
101+
) -> Generator[str, None, None]:
99102
"""
100103
Generate a temporary rosidl generator arguments file.
101104
@@ -138,10 +141,10 @@ def legacy_generator_arguments_file(
138141

139142
def generate_visibility_control_file(
140143
*,
141-
package_name,
142-
template_path,
143-
output_path
144-
):
144+
package_name: str,
145+
template_path: str,
146+
output_path: str
147+
) -> None:
145148
"""
146149
Generate a visibility control file from a template.
147150

rosidl_cli/rosidl_cli/command/translate/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import argparse
1516
import pathlib
1617

18+
1719
from rosidl_cli.command import Command
1820

1921
from .api import translate
@@ -24,7 +26,7 @@ class TranslateCommand(Command):
2426

2527
name = 'translate'
2628

27-
def add_arguments(self, parser):
29+
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
2830
parser.add_argument(
2931
'-o', '--output-path', metavar='PATH',
3032
type=pathlib.Path, default=None,
@@ -64,7 +66,7 @@ def add_arguments(self, parser):
6466
'path resolution is performed against such path.')
6567
)
6668

67-
def main(self, *, args):
69+
def main(self, *, args: argparse.Namespace) -> None:
6870
translate(
6971
package_name=args.package_name,
7072
interface_files=args.interface_files,

rosidl_cli/rosidl_cli/command/translate/api.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,21 @@
1515
import collections
1616
import os
1717
import pathlib
18+
from typing import DefaultDict, Dict, List, Optional, Union
1819

1920
from .extensions import load_translate_extensions
2021

2122

2223
def translate(
2324
*,
24-
package_name,
25-
interface_files,
26-
output_format,
27-
input_format=None,
28-
include_paths=None,
29-
output_path=None,
30-
translators=None
31-
):
25+
package_name: str,
26+
interface_files: List[str],
27+
output_format: str,
28+
input_format: Optional[str] = None,
29+
include_paths: Optional[List[str]] = None,
30+
output_path: Optional[pathlib.Path] = None,
31+
translators: Optional[List[str]] = None
32+
) -> List[str]:
3233
"""
3334
Translate interface definition files from one format to another.
3435
@@ -64,7 +65,8 @@ def translate(
6465
raise RuntimeError('No translate extensions found')
6566

6667
if not input_format:
67-
interface_files_per_format = collections.defaultdict(list)
68+
interface_files_per_format: Union[DefaultDict[str, List[str]],
69+
Dict[str, List[str]]] = collections.defaultdict(list)
6870
for interface_file in interface_files:
6971
input_format = os.path.splitext(interface_file)[-1][1:]
7072
interface_files_per_format[input_format].append(interface_file)

0 commit comments

Comments
 (0)