rework datatypes (setter should not check limits)
- use Datatype.validate for converting and checking limits (used also in properties) - Datatype.__call__ converts and validates, but without checking limits (used in setter) - Datatype.validate may be used to add missing optional struct elements from previous value (used in Dispatcher._setParameterValue) - remove problematic range check + use shorter formula for converting float to int in ScaledInteger (leftover from python2 compatibility) + improve error messages (strip very long repr(value)) Change-Id: Ib85736fe558ec3370ebce4e1c43f957e3bb0497c
This commit is contained in:
@@ -55,9 +55,11 @@ def test_FloatRange():
|
||||
assert dt.export_datatype() == {'type': 'double', 'min':-3.14, 'max':3.14}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
dt(9)
|
||||
dt.validate(9)
|
||||
with pytest.raises(ValueError):
|
||||
dt(-9)
|
||||
dt.validate(-9)
|
||||
dt(9) # convert, but do not check limits
|
||||
dt(-9) # convert, but do not check limits
|
||||
with pytest.raises(ValueError):
|
||||
dt('XX')
|
||||
with pytest.raises(ValueError):
|
||||
@@ -106,9 +108,11 @@ def test_IntRange():
|
||||
assert dt.export_datatype() == {'type': 'int', 'min':-3, 'max':3}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
dt(9)
|
||||
dt.validate(9)
|
||||
with pytest.raises(ValueError):
|
||||
dt(-9)
|
||||
dt.validate(-9)
|
||||
dt(9) # convert, but do not check limits
|
||||
dt(-9) # convert, but do not check limits
|
||||
with pytest.raises(ValueError):
|
||||
dt('XX')
|
||||
with pytest.raises(ValueError):
|
||||
@@ -142,9 +146,11 @@ def test_ScaledInteger():
|
||||
assert dt.export_datatype() == {'type': 'scaled', 'scale':0.01, 'min':-300, 'max':300}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
dt(9)
|
||||
dt.validate(9)
|
||||
with pytest.raises(ValueError):
|
||||
dt(-9)
|
||||
dt.validate(-9)
|
||||
dt(9) # convert, but do not check limits
|
||||
dt(-9) # convert, but do not check limits
|
||||
with pytest.raises(ValueError):
|
||||
dt('XX')
|
||||
with pytest.raises(ValueError):
|
||||
@@ -171,20 +177,23 @@ def test_ScaledInteger():
|
||||
'unit':'A'}
|
||||
assert dt.absolute_resolution == dt.scale
|
||||
|
||||
dt = ScaledInteger(0.003, 0, 1, unit='X', fmtstr='%.1f',
|
||||
dt = ScaledInteger(0.003, 0.4, 1, unit='X', fmtstr='%.1f',
|
||||
absolute_resolution=0.001, relative_resolution=1e-5)
|
||||
copytest(dt)
|
||||
assert dt.export_datatype() == {'type': 'scaled', 'scale':0.003, 'min':0, 'max':333,
|
||||
assert dt.export_datatype() == {'type': 'scaled', 'scale':0.003, 'min':133, 'max':333,
|
||||
'unit':'X', 'fmtstr':'%.1f',
|
||||
'absolute_resolution':0.001,
|
||||
'relative_resolution':1e-5}
|
||||
assert dt(0.4) == 0.399
|
||||
assert dt.format_value(0.4) == '0.4 X'
|
||||
assert dt.format_value(0.4, '') == '0.4'
|
||||
assert dt.format_value(0.4, 'Z') == '0.4 Z'
|
||||
assert dt(1.0029) == 0.999
|
||||
assert round(dt(0.7), 5) == 0.699
|
||||
assert dt.format_value(0.6) == '0.6 X'
|
||||
assert dt.format_value(0.6, '') == '0.6'
|
||||
assert dt.format_value(0.6, 'Z') == '0.6 Z'
|
||||
assert round(dt.validate(1.0004), 5) == 0.999 # rounded value within limit
|
||||
with pytest.raises(ValueError):
|
||||
dt(1.004)
|
||||
dt.validate(1.006) # rounded value outside limit
|
||||
assert round(dt.validate(0.398), 5) == 0.399 # rounded value within rounded limit
|
||||
with pytest.raises(ValueError):
|
||||
dt.validate(0.395) # rounded value outside limit
|
||||
|
||||
dt.setProperty('min', 1)
|
||||
dt.setProperty('max', 0)
|
||||
@@ -456,7 +465,7 @@ def test_StructOf():
|
||||
with pytest.raises(ValueError):
|
||||
dt([99, 'X'])
|
||||
with pytest.raises(ValueError):
|
||||
dt(dict(a_string='XXX', an_int=1811))
|
||||
dt.validate(dict(a_string='XXX', an_int=1811))
|
||||
|
||||
assert dt(dict(a_string='XXX', an_int=8)) == {'a_string': 'XXX',
|
||||
'an_int': 8}
|
||||
@@ -638,7 +647,7 @@ def test_get_datatype():
|
||||
(StringType(10, 10), StringType()),
|
||||
(ArrayOf(StringType(), 3, 5), ArrayOf(StringType(), 3, 6)),
|
||||
(TupleOf(StringType(), BoolType()), TupleOf(StringType(), IntRange())),
|
||||
(StructOf(a=FloatRange(-1,1)), StructOf(a=FloatRange(), b=BoolType(), optional=['b'])),
|
||||
(StructOf(a=FloatRange(-1,1), b=BoolType()), StructOf(a=FloatRange(), b=BoolType(), optional=['b'])),
|
||||
])
|
||||
def test_oneway_compatible(dt, contained_in):
|
||||
dt.compatible(contained_in)
|
||||
|
||||
@@ -31,7 +31,6 @@ from frappy.errors import ProgrammingError, ConfigError
|
||||
from frappy.modules import Communicator, Drivable, Readable, Module
|
||||
from frappy.params import Command, Parameter
|
||||
from frappy.rwhandler import ReadHandler, WriteHandler, nopoll
|
||||
from frappy.lib import generalConfig
|
||||
|
||||
|
||||
class DispatcherStub:
|
||||
@@ -235,7 +234,7 @@ def test_ModuleMagic():
|
||||
assert o2.parameters['a1'].datatype.unit == 'mm/s'
|
||||
cfg = Newclass2.configurables
|
||||
assert set(cfg.keys()) == {
|
||||
'export', 'group', 'description', 'disable_value_range_check', 'features',
|
||||
'export', 'group', 'description', 'features',
|
||||
'meaning', 'visibility', 'implementation', 'interface_classes', 'target', 'stop',
|
||||
'status', 'param1', 'param2', 'cmd', 'a2', 'pollinterval', 'slowinterval', 'b2',
|
||||
'cmd2', 'value', 'a1'}
|
||||
@@ -631,7 +630,7 @@ def test_problematic_value_range():
|
||||
obj = Mod('obj', logger, {'description': '', 'value':{'max': 10.1}}, srv) # pylint: disable=unused-variable
|
||||
|
||||
with pytest.raises(ConfigError):
|
||||
obj = Mod('obj', logger, {'description': ''}, srv)
|
||||
obj = Mod('obj', logger, {'description': '', 'value.max': 9.9}, srv)
|
||||
|
||||
class Mod2(Drivable):
|
||||
value = Parameter('', FloatRange(), default=0)
|
||||
@@ -640,17 +639,10 @@ def test_problematic_value_range():
|
||||
obj = Mod2('obj', logger, {'description': ''}, srv)
|
||||
obj = Mod2('obj', logger, {'description': '', 'target':{'min': 0, 'max': 10}}, srv)
|
||||
|
||||
with pytest.raises(ConfigError):
|
||||
obj = Mod('obj', logger, {
|
||||
'value':{'min': 0, 'max': 10},
|
||||
'target':{'min': 0, 'max': 10}, 'description': ''}, srv)
|
||||
|
||||
obj = Mod('obj', logger, {'disable_value_range_check': True,
|
||||
obj = Mod('obj', logger, {
|
||||
'value': {'min': 0, 'max': 10},
|
||||
'target': {'min': 0, 'max': 10}, 'description': ''}, srv)
|
||||
|
||||
generalConfig.defaults['disable_value_range_check'] = True
|
||||
|
||||
class Mod4(Drivable):
|
||||
value = Parameter('', FloatRange(0, 10), default=0)
|
||||
target = Parameter('', FloatRange(0, 10), default=0)
|
||||
|
||||
Reference in New Issue
Block a user