Open
Description
Feature request
Feature description
It would be useful if the python classes included type annotations.
For example:
Parent.msg
Child[] children
Child child
Child.msg
uint8 some_child_content
Would generate something like:
+from perception_msgs.msg import Child
class Parent(metaclass=Metaclass_Parent):
"""Message class 'Parent'."""
__slots__ = [
'_children',
'_child',
]
_fields_and_field_types = {
'children': 'sequence<perception_msgs/Child>',
'child': 'perception_msgs/Child',
}
SLOT_TYPES = (
rosidl_parser.definition.UnboundedSequence(rosidl_parser.definition.NamespacedType(['perception_msgs', 'msg'], 'Child')), # noqa: E501
rosidl_parser.definition.NamespacedType(['perception_msgs', 'msg'], 'Child'), # noqa: E501
)
- def __init__(self, **kwargs):
+ def __init__(self, children: Optional[List[Child]]=None, child: Optional[Child]=None):
- assert all('_' + key in self.__slots__ for key in kwargs.keys()), \
- 'Invalid arguments passed to constructor: %s' % \
- ', '.join(sorted(k for k in kwargs.keys() if '_' + k not in self.__slots__))
- self.children = kwargs.get('children', [])
- from perception_msgs.msg import Child
- self.child = kwargs.get('child', Child())
+ self.children = children or []
+ self.child = child or Child()
def __repr__(self):
typename = self.__class__.__module__.split('.')
typename.pop()
typename.append(self.__class__.__name__)
args = []
for s, t in zip(self.__slots__, self.SLOT_TYPES):
field = getattr(self, s)
fieldstr = repr(field)
# We use Python array type for fields that can be directly stored
# in them, and "normal" sequences for everything else. If it is
# a type that we store in an array, strip off the 'array' portion.
if (
isinstance(t, rosidl_parser.definition.AbstractSequence) and
isinstance(t.value_type, rosidl_parser.definition.BasicType) and
t.value_type.typename in ['float', 'double', 'int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64']
):
if len(field) == 0:
fieldstr = '[]'
else:
assert fieldstr.startswith('array(')
prefix = "array('X', "
suffix = ')'
fieldstr = fieldstr[len(prefix):-len(suffix)]
args.append(s[1:] + '=' + fieldstr)
return '%s(%s)' % ('.'.join(typename), ', '.join(args))
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
if self.children != other.children:
return False
if self.child != other.child:
return False
return True
@classmethod
def get_fields_and_field_types(cls):
from copy import copy
return copy(cls._fields_and_field_types)
@property
- def children(self):
+ def children(self) -> List[Child]:
"""Message field 'children'."""
return self._children
@children.setter
- def children(self, value):
+ def children(self, value: List[Child]):
if __debug__:
from perception_msgs.msg import Child
from collections.abc import Sequence
from collections.abc import Set
from collections import UserList
from collections import UserString
assert \
((isinstance(value, Sequence) or
isinstance(value, Set) or
isinstance(value, UserList)) and
not isinstance(value, str) and
not isinstance(value, UserString) and
all(isinstance(v, Child) for v in value) and
True), \
"The 'children' field must be a set or sequence and each value of type 'Child'"
self._children = value
@property
- def child(self):
+ def child(self) -> Child:
"""Message field 'child'."""
return self._child
@child.setter
- def child(self, value):
+ def child(self, value: Child):
if __debug__:
from perception_msgs.msg import Child
assert \
isinstance(value, Child), \
"The 'child' field must be a sub message of type 'Child'"
self._child = value
Implementation considerations
- There seems to be an issue with typing
@property
getters/setters. For me, usingpylance
the above syntax thinkschild
is of typeproperty
rather than typeChild
- Backwards compatibility requirements - do we need to support python < 3.8? I assume type annotations break old python.
- Another path....
from dataclasses import dataclass
gives us most of these features and more. Plus, it can be used with other libraries like dacite