From 21376d799bef2756b4b3ca0fbae5203d23415afb Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Tue, 3 Feb 2026 20:53:01 -0800 Subject: [PATCH 1/6] rhel10 flake8 Signed-off-by: Michael Carlstrom --- rosidl_generator_py/resource/_idl.py.em | 11 +++++++++-- rosidl_generator_py/resource/_msg.py.em | 12 ++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/rosidl_generator_py/resource/_idl.py.em b/rosidl_generator_py/resource/_idl.py.em index 98fb0b13..e2e24720 100644 --- a/rosidl_generator_py/resource/_idl.py.em +++ b/rosidl_generator_py/resource/_idl.py.em @@ -5,15 +5,22 @@ from __future__ import annotations import collections.abc -from os import getenv +import os import typing import rosidl_pycommon.interface_base_classes +if typing.TYPE_CHECKING: + from ctypes import Structure + + class PyCapsule(Structure): + pass # don't need to define the full structure + + # This is being done at the module level and not on the instance level to avoid looking # for the same variable multiple times on each instance. This variable is not supposed to # change during runtime so it makes sense to only look for it once. -ros_python_check_fields = getenv('ROS_PYTHON_CHECK_FIELDS', default='') +ros_python_check_fields = os.getenv('ROS_PYTHON_CHECK_FIELDS', default='') @ @####################################################################### @# EmPy template for generating _.py files diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 98285ecb..9e4f9450 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -38,13 +38,6 @@ type_annotations_setter: dict[str, str] = {} type_annotations_getter: dict[str, str] = {} type_imports: set[str] = set() -# Types which always exist -# Done in one multi-line string to preserve order -type_imports.add( - """from ctypes import Structure - - class PyCapsule(Structure): - pass # don't need to define the full structure""") for member in message.structure.members: setter_type, getter_type = get_setter_and_getter_type(member, type_imports) type_annotations_setter[member.name] = setter_type @@ -66,11 +59,10 @@ suffix = '__'.join(message.structure.namespaced_type.namespaces[1:]) + '__' + co type_annotations_import_statements_copy = type_annotations_import_statements.copy() }@ - if typing.TYPE_CHECKING: -@[for type_import in type_imports]@ +@[for type_import in sorted(type_imports)]@ @[if type_import not in type_annotations_import_statements]@ - @(type_import) + @(type_import) # noqa: E402, I100 @{ type_annotations_import_statements.add(type_import) }@ From c7563c9886c72b5f1e85b4875d6f0f8a1efe5702 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Wed, 4 Feb 2026 08:38:38 -0800 Subject: [PATCH 2/6] Fix existing linter Signed-off-by: Michael Carlstrom --- rosidl_generator_py/CMakeLists.txt | 2 ++ rosidl_generator_py/action/Simple.action | 5 +++++ rosidl_generator_py/resource/_action.py.em | 2 +- rosidl_generator_py/resource/_msg.py.em | 12 +++++------- rosidl_generator_py/resource/_srv.py.em | 2 +- rosidl_generator_py/srv/Simple.srv | 3 +++ 6 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 rosidl_generator_py/action/Simple.action create mode 100644 rosidl_generator_py/srv/Simple.srv diff --git a/rosidl_generator_py/CMakeLists.txt b/rosidl_generator_py/CMakeLists.txt index e5ff834f..67cc2ef8 100644 --- a/rosidl_generator_py/CMakeLists.txt +++ b/rosidl_generator_py/CMakeLists.txt @@ -49,6 +49,8 @@ if(BUILD_TESTING) msg/BuiltinTypeSequencesIdl.idl msg/StringArrays.msg msg/Property.msg + srv/Simple.srv + action/Simple.action ADD_LINTER_TESTS SKIP_INSTALL ) diff --git a/rosidl_generator_py/action/Simple.action b/rosidl_generator_py/action/Simple.action new file mode 100644 index 00000000..1a6ee52f --- /dev/null +++ b/rosidl_generator_py/action/Simple.action @@ -0,0 +1,5 @@ +int8 a +--- +int8 b +--- +int8 c diff --git a/rosidl_generator_py/resource/_action.py.em b/rosidl_generator_py/resource/_action.py.em index 0a081993..923396fa 100644 --- a/rosidl_generator_py/resource/_action.py.em +++ b/rosidl_generator_py/resource/_action.py.em @@ -50,7 +50,7 @@ class Metaclass_@(action.namespaced_type.name)(rosidl_pycommon.interface_base_cl @@classmethod def __import_type_support__(cls) -> None: try: - from rosidl_generator_py import import_type_support + from rosidl_generator_py import import_type_support # type: ignore[attr-defined] module = import_type_support('@(package_name)') except ImportError: import logging diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 9e4f9450..4802cf44 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -56,20 +56,18 @@ for member in message.structure.members: }@ @{ suffix = '__'.join(message.structure.namespaced_type.namespaces[1:]) + '__' + convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name) -type_annotations_import_statements_copy = type_annotations_import_statements.copy() +new_typing_imports = sorted(type_imports - type_annotations_import_statements) }@ +@[if new_typing_imports]@ + if typing.TYPE_CHECKING: -@[for type_import in sorted(type_imports)]@ -@[if type_import not in type_annotations_import_statements]@ +@[ for type_import in new_typing_imports]@ @(type_import) # noqa: E402, I100 @{ type_annotations_import_statements.add(type_import) }@ -@[end if]@ -@[end for]@ -@[if type_annotations_import_statements == type_annotations_import_statements_copy]@ - pass +@[ end for]@ @[end if]@ @#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @# Collect necessary import statements for all members diff --git a/rosidl_generator_py/resource/_srv.py.em b/rosidl_generator_py/resource/_srv.py.em index 3320ff22..d20a467a 100644 --- a/rosidl_generator_py/resource/_srv.py.em +++ b/rosidl_generator_py/resource/_srv.py.em @@ -46,7 +46,7 @@ class Metaclass_@(service.namespaced_type.name)(rosidl_pycommon.interface_base_c @@classmethod def __import_type_support__(cls) -> None: try: - from rosidl_generator_py import import_type_support + from rosidl_generator_py import import_type_support # type: ignore[attr-defined] module = import_type_support('@(package_name)') except ImportError: import logging diff --git a/rosidl_generator_py/srv/Simple.srv b/rosidl_generator_py/srv/Simple.srv new file mode 100644 index 00000000..51357ab4 --- /dev/null +++ b/rosidl_generator_py/srv/Simple.srv @@ -0,0 +1,3 @@ +int8 a +--- +int8 b From 6a5a496dede34bc5603d6391b932436e278e57d7 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Wed, 4 Feb 2026 09:58:48 -0800 Subject: [PATCH 3/6] remove action and srv test Signed-off-by: Michael Carlstrom --- rosidl_generator_py/CMakeLists.txt | 2 -- rosidl_generator_py/action/Simple.action | 5 ----- rosidl_generator_py/srv/Simple.srv | 3 --- 3 files changed, 10 deletions(-) delete mode 100644 rosidl_generator_py/action/Simple.action delete mode 100644 rosidl_generator_py/srv/Simple.srv diff --git a/rosidl_generator_py/CMakeLists.txt b/rosidl_generator_py/CMakeLists.txt index 67cc2ef8..e5ff834f 100644 --- a/rosidl_generator_py/CMakeLists.txt +++ b/rosidl_generator_py/CMakeLists.txt @@ -49,8 +49,6 @@ if(BUILD_TESTING) msg/BuiltinTypeSequencesIdl.idl msg/StringArrays.msg msg/Property.msg - srv/Simple.srv - action/Simple.action ADD_LINTER_TESTS SKIP_INSTALL ) diff --git a/rosidl_generator_py/action/Simple.action b/rosidl_generator_py/action/Simple.action deleted file mode 100644 index 1a6ee52f..00000000 --- a/rosidl_generator_py/action/Simple.action +++ /dev/null @@ -1,5 +0,0 @@ -int8 a ---- -int8 b ---- -int8 c diff --git a/rosidl_generator_py/srv/Simple.srv b/rosidl_generator_py/srv/Simple.srv deleted file mode 100644 index 51357ab4..00000000 --- a/rosidl_generator_py/srv/Simple.srv +++ /dev/null @@ -1,3 +0,0 @@ -int8 a ---- -int8 b From 080b6cd8c120522b781a6942bb4748032e598f46 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Wed, 4 Feb 2026 21:28:51 -0800 Subject: [PATCH 4/6] switch to I300 Signed-off-by: Michael Carlstrom --- rosidl_generator_py/resource/_msg.py.em | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 4802cf44..902cace3 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -63,7 +63,7 @@ new_typing_imports = sorted(type_imports - type_annotations_import_statements) if typing.TYPE_CHECKING: @[ for type_import in new_typing_imports]@ - @(type_import) # noqa: E402, I100 + @(type_import) # noqa: E402, I300 @{ type_annotations_import_statements.add(type_import) }@ From c81b41f7e348c30ac13967a8941abc72a7a0e673 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Thu, 5 Feb 2026 07:59:18 -0800 Subject: [PATCH 5/6] Add I100 ignore Signed-off-by: Michael Carlstrom --- rosidl_generator_py/resource/_msg.py.em | 2 +- .../rosidl_generator_py/generate_py_impl.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 902cace3..80de5b02 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -63,7 +63,7 @@ new_typing_imports = sorted(type_imports - type_annotations_import_statements) if typing.TYPE_CHECKING: @[ for type_import in new_typing_imports]@ - @(type_import) # noqa: E402, I300 + @(type_import) # noqa: E402, I100, I300 @{ type_annotations_import_statements.add(type_import) }@ diff --git a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py index c0cf7c9b..5fe8e553 100644 --- a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py +++ b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py @@ -404,9 +404,9 @@ def get_setter_and_getter_type(member: Member, type_imports: set[str]) -> tuple[ type_.typename in SPECIAL_NESTED_BASIC_TYPES ): if isinstance(member.type, Array): - type_imports.add('import numpy.typing') + type_imports.add('from numpy.typing import NDArray') dtype = SPECIAL_NESTED_BASIC_TYPES[type_.typename]['dtype'] - type_annotation = f'numpy.typing.NDArray[{dtype}]' + type_annotation = f'NDArray[{dtype}]' elif isinstance(member.type, AbstractSequence): type_annotation = f'array.array[{python_type}]' @@ -422,13 +422,11 @@ def get_setter_and_getter_type(member: Member, type_imports: set[str]) -> tuple[ type_annotation = sequence_type elif isinstance(member.type, AbstractGenericString) and member.type.has_maximum_size(): - type_annotation = 'typing.Union[str, collections.UserString]' - - type_imports.add('import collections') + type_imports.add('from collections import UserString') + type_annotation = 'typing.Union[str, UserString]' elif isinstance(type_, BasicType) and type_.typename == 'char': - type_annotation = 'typing.Union[str, collection.UserString]' - - type_imports.add('import collections') + type_imports.add('from collections import UserString') + type_annotation = 'typing.Union[str, UserString]' elif isinstance(type_, BasicType) and type_.typename == 'octet': type_annotation = 'typing.Union[bytes, collections.abc.ByteString]' else: From f58389422d7518c2bb95e70008f25a96fa3e81c8 Mon Sep 17 00:00:00 2001 From: Michael Carlstrom Date: Thu, 5 Feb 2026 17:02:06 -0800 Subject: [PATCH 6/6] Fix more cases Signed-off-by: Michael Carlstrom --- rosidl_generator_py/resource/_idl.py.em | 9 +++++++++ rosidl_generator_py/resource/_msg.py.em | 2 +- rosidl_generator_py/resource/_srv.py.em | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rosidl_generator_py/resource/_idl.py.em b/rosidl_generator_py/resource/_idl.py.em index e2e24720..24d368dc 100644 --- a/rosidl_generator_py/resource/_idl.py.em +++ b/rosidl_generator_py/resource/_idl.py.em @@ -1,3 +1,12 @@ +@{ +import sys +module_name = f"_{interface_path.name.split('.', 1)[0].lower()}" +}@ +@[if module_name in sys.builtin_module_names]@ +# noqa: A005 +# Module @(module_name).py shadows a builtin + +@[end if]@ # generated from rosidl_generator_py/resource/_idl.py.em # with input from @(package_name):@(interface_path) # generated code does not contain a copyright notice diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 80de5b02..e882a5d9 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -63,7 +63,7 @@ new_typing_imports = sorted(type_imports - type_annotations_import_statements) if typing.TYPE_CHECKING: @[ for type_import in new_typing_imports]@ - @(type_import) # noqa: E402, I100, I300 + @(type_import) # noqa: E402, I100, I201, I300 @{ type_annotations_import_statements.add(type_import) }@ diff --git a/rosidl_generator_py/resource/_srv.py.em b/rosidl_generator_py/resource/_srv.py.em index d20a467a..26fe09ca 100644 --- a/rosidl_generator_py/resource/_srv.py.em +++ b/rosidl_generator_py/resource/_srv.py.em @@ -31,7 +31,7 @@ TYPE_ALIAS_IMPORT = 'from typing_extensions import TypeAlias' if typing.TYPE_CHECKING: - @(TYPE_ALIAS_IMPORT) + @(TYPE_ALIAS_IMPORT) # noqa: I100, I300 @[end if]@ @{ type_annotations_import_statements.add(TYPE_ALIAS_IMPORT)