Type hinting for ROS 2 python messages for

Has anyone figured out a way to get a language server like pyright to work with ros2 python messages? Normally if you have a class like this

class MyRosMessage:
    def __init__(x: float, y: float, z: float):
        ...
my_ros_message = MyRosMessage(x=1.0, y=2.0, z=3)

My LSP will warn me that z is an int when it should be a float.

However I noticed that the ROS2 implementation of Python ROS messages is as such:

class MyRosMessage:
    def __init__(kwargs**):
        ...
        self.x = kwargs.get('x', float())
        self.y = kwargs.get('y', float())
        self.z = kwargs.get('z', float())

    @x.setter
    def x(self, value):
        if __debug__:
            assert \
                isinstance(value, float), \
                "The 'x' field must be of type 'float'"
            assert not (value < -1.7976931348623157e+308 or value > 1.7976931348623157e+308) or math.isinf(value), \
                "The 'x' field must be a double in [-1.7976931348623157e+308, 1.7976931348623157e+308]"
        self._x = value

# This line will throw an assertion error. pyright will not warn you about this mistake.
my_ros_message = MyRosMessage(x=1.0, y=2.0, z=3)

Is there any way to make a language server understand the the code above will throw an exception before hand? Is there an easy way to modify the ROS2 message generation to include type hinting in the setter or something like such?

class MyRosMessage:
...

    @x.setter
    def x(self, value: float):
...

Check out GitHub - rospypi/rosidl_generator_mypy

This works at build time only so you’ll need to build any messages from source to get it to work.

3 Likes

I highly reccomend using rosidl_generator_mypy however this float accepting an int is a problem carried over from the pep 484 spec. There is currently no type hint to specify float but not int. There is lot of debate about this in the python typing scene.