Skip to content

Commit

Permalink
Enforce parameter types.
Browse files Browse the repository at this point in the history
This commit adds a Parameter.Type.check method which is used to enforce
the declared parameter type at runtime.
  • Loading branch information
nuclearsandwich committed Aug 10, 2018
1 parent 483bd2f commit 39698fb
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
33 changes: 32 additions & 1 deletion rclpy/rclpy/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,34 @@ class Type(Enum):
DOUBLE_ARRAY = ParameterType.PARAMETER_DOUBLE_ARRAY
STRING_ARRAY = ParameterType.PARAMETER_STRING_ARRAY

def check(self, parameter_value):
if Parameter.Type.NOT_SET == self:
return parameter_value is None
if Parameter.Type.BOOL == self:
return isinstance(parameter_value, bool)
if Parameter.Type.INTEGER == self:
return isinstance(parameter_value, int)
if Parameter.Type.DOUBLE == self:
return isinstance(parameter_value, float)
if Parameter.Type.STRING == self:
return isinstance(parameter_value, str)
if Parameter.Type.BYTE_ARRAY == self:
return isinstance(parameter_value, list) and \
all(isinstance(v, bytes) and len(v) == 1 for v in parameter_value)
if Parameter.Type.BOOL_ARRAY == self:
return isinstance(parameter_value, list) and \
all(isinstance(v, bool) for v in parameter_value)
if Parameter.Type.INTEGER_ARRAY == self:
return isinstance(parameter_value, list) and \
all(isinstance(v, int) for v in parameter_value)
if Parameter.Type.DOUBLE_ARRAY == self:
return isinstance(parameter_value, list) and \
all(isinstance(v, float) for v in parameter_value)
if Parameter.Type.STRING_ARRAY == self:
return isinstance(parameter_value, list) and \
all(isinstance(v, str) for v in parameter_value)
return False

@classmethod
def from_rcl_interface_parameter(cls, rcl_param):
value = None
Expand All @@ -55,10 +83,13 @@ def from_rcl_interface_parameter(cls, rcl_param):
value = rcl_param.value.string_array_value
return cls(rcl_param.name, type_, value)

def __init__(self, name, type_, value):
def __init__(self, name, type_, value=None):
if not isinstance(type_, Parameter.Type):
raise TypeError("type must be an instance of '{}'".format(repr(Parameter.Type)))

if not type_.check(value):
raise ValueError("Type '{}' and value '{}' do not agree".format(type_, value))

self._type = type_
self._name = name
self._value = value
Expand Down
4 changes: 4 additions & 0 deletions rclpy/test/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ def test_node_set_parameters(self):
self.assertEqual(self.node.get_parameter('bar').value, 'hello')
self.assertEqual(self.node.get_parameter('baz').value, 2.41)

def test_node_cannot_set_invalid_parameters(self):
with self.assertRaises(TypeError):
self.node.set_parameters([42])

def test_node_set_parameters_atomically(self):
result = self.node.set_parameters_atomically([
Parameter('foo', Parameter.Type.INTEGER, 42),
Expand Down
16 changes: 13 additions & 3 deletions rclpy/test/test_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def test_create_boolean_parameter(self):
self.assertEqual(p.value, True)

def test_create_bytes_parameter(self):
p = Parameter('myparam', Parameter.Type.BYTE_ARRAY, b'pvalue')
p = Parameter('myparam', Parameter.Type.BYTE_ARRAY, [b'p', b'v', b'a', b'l', b'u', b'e'])
self.assertEqual(p.name, 'myparam')
self.assertEqual(p.value, b'pvalue')
self.assertEqual(p.value, [b'p', b'v', b'a', b'l', b'u', b'e'])

def test_create_float_parameter(self):
p = Parameter('myparam', Parameter.Type.DOUBLE, 2.41)
Expand Down Expand Up @@ -60,8 +60,18 @@ def test_create_string_array_parameter(self):
p = Parameter('myparam', Parameter.Type.STRING_ARRAY, ['hello', 'world'])
self.assertEqual(p.value, ['hello', 'world'])

def test_create_not_set_parameter(self):
p = Parameter('myparam', Parameter.Type.NOT_SET)
self.assertIsNone(p.value)

def test_value_and_type_must_agree(self):
with self.assertRaises(ValueError):
Parameter('myparam', Parameter.Type.NOT_SET, 42)
with self.assertRaises(ValueError):
Parameter('myparam', Parameter.Type.BOOL_ARRAY, 42)

def test_error_on_illegal_value_type(self):
with self.assertRaises(AssertionError):
with self.assertRaises(TypeError):
Parameter('illegaltype', 'mytype', 'myvalue')


Expand Down

0 comments on commit 39698fb

Please sign in to comment.