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/_idl.py.em b/rosidl_generator_py/resource/_idl.py.em index 98fb0b13..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 @@ -5,15 +14,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..e882a5d9 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 @@ -63,21 +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 type_imports]@ -@[if type_import not in type_annotations_import_statements]@ - @(type_import) +@[ for type_import in new_typing_imports]@ + @(type_import) # noqa: E402, I100, I201, I300 @{ 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..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) @@ -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/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: