fetched mlz version
- before some chamges in the gerrit pipline Change-Id: I33eb2d75f83345a7039d0fb709e66defefb1c3e0
This commit is contained in:
@ -26,12 +26,12 @@ import sys
|
||||
import threading
|
||||
import pytest
|
||||
|
||||
from secop.datatypes import BoolType, FloatRange, StringType, IntRange, ScaledInteger
|
||||
from secop.errors import ProgrammingError, ConfigError
|
||||
from secop.modules import Communicator, Drivable, Readable, Module
|
||||
from secop.params import Command, Parameter
|
||||
from secop.rwhandler import ReadHandler, WriteHandler, nopoll
|
||||
from secop.lib import generalConfig
|
||||
from frappy.datatypes import BoolType, FloatRange, StringType, IntRange, ScaledInteger
|
||||
from frappy.errors import ProgrammingError, ConfigError, RangeError
|
||||
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:
|
||||
@ -39,9 +39,9 @@ class DispatcherStub:
|
||||
# initial value from the timestamp. However, in the test below
|
||||
# the second update happens after the updates dict is cleared
|
||||
# -> we have to inhibit the 'omit unchanged update' feature
|
||||
omit_unchanged_within = 0
|
||||
|
||||
def __init__(self, updates):
|
||||
generalConfig.testinit(omit_unchanged_within=0)
|
||||
self.updates = updates
|
||||
|
||||
def announce_update(self, modulename, pname, pobj):
|
||||
@ -77,7 +77,7 @@ class DummyMultiEvent(threading.Event):
|
||||
|
||||
|
||||
def test_Communicator():
|
||||
o = Communicator('communicator', LoggerStub(), {'.description': ''}, ServerStub({}))
|
||||
o = Communicator('communicator', LoggerStub(), {'description': ''}, ServerStub({}))
|
||||
o.earlyInit()
|
||||
o.initModule()
|
||||
event = DummyMultiEvent()
|
||||
@ -151,8 +151,8 @@ def test_ModuleMagic():
|
||||
a1 = Parameter(datatype=FloatRange(unit='$/s'), readonly=False)
|
||||
# remark: it might be a programming error to override the datatype
|
||||
# and not overriding the read_* method. This is not checked!
|
||||
b2 = Parameter('<b2>', datatype=StringType(), default='empty',
|
||||
readonly=False, initwrite=True)
|
||||
b2 = Parameter('<b2>', datatype=StringType(), value='empty',
|
||||
readonly=False)
|
||||
|
||||
def write_a1(self, value):
|
||||
self._a1_written = value
|
||||
@ -177,8 +177,8 @@ def test_ModuleMagic():
|
||||
objects = []
|
||||
|
||||
for newclass, sortcheck in [(Newclass1, sortcheck1), (Newclass2, sortcheck2)]:
|
||||
o1 = newclass('o1', logger, {'.description':''}, srv)
|
||||
o2 = newclass('o2', logger, {'.description':''}, srv)
|
||||
o1 = newclass('o1', logger, {'description':''}, srv)
|
||||
o2 = newclass('o2', logger, {'description':''}, srv)
|
||||
for obj in [o1, o2]:
|
||||
objects.append(obj)
|
||||
for o in obj.accessibles.values():
|
||||
@ -187,12 +187,14 @@ def test_ModuleMagic():
|
||||
params_found.add(o)
|
||||
assert list(obj.accessibles) == sortcheck
|
||||
|
||||
updates.clear()
|
||||
# check for inital updates working properly
|
||||
o1 = Newclass1('o1', logger, {'.description':''}, srv)
|
||||
o1 = Newclass1('o1', logger, {'description':''}, srv)
|
||||
expectedBeforeStart = {'target': '', 'status': (Drivable.Status.IDLE, ''),
|
||||
'param1': False, 'param2': 1.0, 'a1': 0.0, 'a2': True, 'pollinterval': 5.0,
|
||||
'param1': False, 'param2': 1.0, 'a1': False, 'a2': True, 'pollinterval': 5.0,
|
||||
'value': 'first'}
|
||||
assert updates.pop('o1') == expectedBeforeStart
|
||||
for k, v in expectedBeforeStart.items():
|
||||
assert getattr(o1, k) == v
|
||||
o1.earlyInit()
|
||||
event = DummyMultiEvent()
|
||||
o1.initModule()
|
||||
@ -205,11 +207,11 @@ def test_ModuleMagic():
|
||||
assert updates.pop('o1') == expectedAfterStart
|
||||
|
||||
# check in addition if parameters are written
|
||||
o2 = Newclass2('o2', logger, {'.description':'', 'a1': 2.7}, srv)
|
||||
# no update for b2, as this has to be written
|
||||
expectedBeforeStart['a1'] = 2.7
|
||||
expectedBeforeStart['target'] = 0.0
|
||||
assert updates.pop('o2') == expectedBeforeStart
|
||||
assert not updates
|
||||
o2 = Newclass2('o2', logger, {'description':'', 'a1': {'value': 2.7}}, srv)
|
||||
expectedBeforeStart.update(a1=2.7, b2='empty', target=0, value=0)
|
||||
for k, v in expectedBeforeStart.items():
|
||||
assert getattr(o2, k) == v
|
||||
o2.earlyInit()
|
||||
event = DummyMultiEvent()
|
||||
o2.initModule()
|
||||
@ -224,10 +226,10 @@ def test_ModuleMagic():
|
||||
|
||||
assert not updates
|
||||
|
||||
o1 = Newclass1('o1', logger, {'.description':''}, srv)
|
||||
o2 = Newclass2('o2', logger, {'.description':''}, srv)
|
||||
o1 = Newclass1('o1', logger, {'description':''}, srv)
|
||||
o2 = Newclass2('o2', logger, {'description':''}, srv)
|
||||
assert o2.parameters['a1'].datatype.unit == 'deg/s'
|
||||
o2 = Newclass2('o2', logger, {'.description':'', 'value.unit':'mm', 'param2.unit':'mm'}, srv)
|
||||
o2 = Newclass2('o2', logger, {'description':'', 'value':{'unit':'mm'},'param2':{'unit':'mm'}}, srv)
|
||||
# check datatype is not shared
|
||||
assert o1.parameters['param2'].datatype.unit == 'Ohm'
|
||||
assert o2.parameters['param2'].datatype.unit == 'mm'
|
||||
@ -235,15 +237,15 @@ 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',
|
||||
'export', 'group', 'description', 'features',
|
||||
'meaning', 'visibility', 'implementation', 'interface_classes', 'target', 'stop',
|
||||
'status', 'param1', 'param2', 'cmd', 'a2', 'pollinterval', 'slowinterval', 'b2',
|
||||
'cmd2', 'value', 'a1'}
|
||||
'cmd2', 'value', 'a1', 'omit_unchanged_within'}
|
||||
assert set(cfg['value'].keys()) == {
|
||||
'group', 'export', 'relative_resolution',
|
||||
'visibility', 'unit', 'default', 'datatype', 'fmtstr',
|
||||
'visibility', 'unit', 'default', 'value', 'datatype', 'fmtstr',
|
||||
'absolute_resolution', 'max', 'min', 'readonly', 'constant',
|
||||
'description', 'needscfg'}
|
||||
'description', 'needscfg', 'update_unchanged'}
|
||||
|
||||
# check on the level of classes
|
||||
# this checks Newclass1 too, as it is inherited by Newclass2
|
||||
@ -374,13 +376,13 @@ def test_command_check():
|
||||
with pytest.raises(ProgrammingError):
|
||||
BadDatatype('o', logger, {
|
||||
'description': '',
|
||||
'cmd.argument': {'type': 'double', 'min': 1, 'max': 0},
|
||||
'cmd': {'argument': {'type': 'double', 'min': 1, 'max': 0}},
|
||||
}, srv)
|
||||
|
||||
with pytest.raises(ProgrammingError):
|
||||
BadDatatype('o', logger, {
|
||||
'description': '',
|
||||
'cmd.visibility': 'invalid',
|
||||
'cmd': {'visibility': 'invalid'},
|
||||
}, srv)
|
||||
|
||||
|
||||
@ -413,17 +415,15 @@ def test_mixin():
|
||||
|
||||
MixedDrivable('o', logger, {
|
||||
'description': '',
|
||||
'param1.description': 'param 1',
|
||||
'param1': 0,
|
||||
'param2.datatype': {"type": "double"},
|
||||
'param1': {'value': 0, 'description': 'param1'},
|
||||
'param2': {'datatype': {"type": "double"}},
|
||||
}, srv)
|
||||
|
||||
with pytest.raises(ConfigError):
|
||||
MixedReadable('o', logger, {
|
||||
'description': '',
|
||||
'param1.description': 'param 1',
|
||||
'param1': 0,
|
||||
'param2.datatype': {"type": "double"},
|
||||
'param1': {'value': 0, 'description': 'param1'},
|
||||
'param2': {'datatype': {"type": "double"}},
|
||||
}, srv)
|
||||
|
||||
|
||||
@ -434,7 +434,7 @@ def test_override():
|
||||
def stop(self):
|
||||
"""no decorator needed"""
|
||||
|
||||
assert Mod.value.default == 5
|
||||
assert Mod.value.value == 5
|
||||
assert Mod.stop.description == "no decorator needed"
|
||||
|
||||
class Mod2(Drivable):
|
||||
@ -455,7 +455,7 @@ def test_command_config():
|
||||
srv = ServerStub({})
|
||||
mod = Mod('o', logger, {
|
||||
'description': '',
|
||||
'convert.argument': {'type': 'bool'},
|
||||
'convert': {'argument': {'type': 'bool'}},
|
||||
}, srv)
|
||||
assert mod.commands['convert'].datatype.export_datatype() == {
|
||||
'type': 'command',
|
||||
@ -465,7 +465,7 @@ def test_command_config():
|
||||
|
||||
mod = Mod('o', logger, {
|
||||
'description': '',
|
||||
'convert.datatype': {'type': 'command', 'argument': {'type': 'bool'}, 'result': {'type': 'bool'}},
|
||||
'convert': {'datatype': {'type': 'command', 'argument': {'type': 'bool'}, 'result': {'type': 'bool'}}},
|
||||
}, srv)
|
||||
assert mod.commands['convert'].datatype.export_datatype() == {
|
||||
'type': 'command',
|
||||
@ -529,7 +529,7 @@ def test_generic_access():
|
||||
updates = {}
|
||||
srv = ServerStub(updates)
|
||||
|
||||
obj = Mod('obj', logger, {'description': '', 'param': 'initial value'}, srv)
|
||||
obj = Mod('obj', logger, {'description': '', 'param': {'value':'initial value'}}, srv)
|
||||
assert obj.param == 'initial value'
|
||||
assert obj.write_param('Cheese') == 'cheese'
|
||||
assert obj.write_unhandled('Cheese') == 'Cheese'
|
||||
@ -542,7 +542,7 @@ def test_generic_access():
|
||||
assert obj.read_unhandled()
|
||||
assert updates == {'obj': {'param': 'potato'}}
|
||||
updates.clear()
|
||||
assert updates == {}
|
||||
assert not updates
|
||||
|
||||
|
||||
def test_duplicate_handler_name():
|
||||
@ -590,7 +590,7 @@ def test_no_read_write():
|
||||
updates = {}
|
||||
srv = ServerStub(updates)
|
||||
|
||||
obj = Mod('obj', logger, {'description': '', 'param': 'cheese'}, srv)
|
||||
obj = Mod('obj', logger, {'description': '', 'param': {'value': 'cheese'}}, srv)
|
||||
assert obj.param == 'cheese'
|
||||
assert obj.read_param() == 'cheese'
|
||||
assert updates == {'obj': {'param': 'cheese'}}
|
||||
@ -630,32 +630,275 @@ def test_problematic_value_range():
|
||||
|
||||
srv = ServerStub({})
|
||||
|
||||
obj = Mod('obj', logger, {'description': '', 'value.max': 10.1}, srv) # pylint: disable=unused-variable
|
||||
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)
|
||||
target = Parameter('', FloatRange(), default=0)
|
||||
|
||||
obj = Mod2('obj', logger, {'description': ''}, srv)
|
||||
obj = Mod2('obj', logger, {'description': '', 'target.min': 0, 'target.max': 10}, srv)
|
||||
obj = Mod2('obj', logger, {'description': '', 'target':{'min': 0, 'max': 10}}, srv)
|
||||
|
||||
with pytest.raises(ConfigError):
|
||||
obj = Mod('obj', logger, {
|
||||
'value.min': 0, 'value.max': 10,
|
||||
'target.min': 0, 'target.max': 10, 'description': ''}, srv)
|
||||
|
||||
obj = Mod('obj', logger, {'disable_value_range_check': True,
|
||||
'value.min': 0, 'value.max': 10,
|
||||
'target.min': 0, 'target.max': 10, 'description': ''}, srv)
|
||||
|
||||
generalConfig.defaults['disable_value_range_check'] = True
|
||||
obj = Mod('obj', logger, {
|
||||
'value': {'min': 0, 'max': 10},
|
||||
'target': {'min': 0, 'max': 10}, 'description': ''}, srv)
|
||||
|
||||
class Mod4(Drivable):
|
||||
value = Parameter('', FloatRange(0, 10), default=0)
|
||||
target = Parameter('', FloatRange(0, 10), default=0)
|
||||
obj = Mod4('obj', logger, {
|
||||
'value.min': 0, 'value.max': 10,
|
||||
'target.min': 0, 'target.max': 10, 'description': ''}, srv)
|
||||
'value': {'min': 0, 'max': 10},
|
||||
'target': {'min': 0, 'max': 10}, 'description': ''}, srv)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('config, dynamicunit, finalunit, someunit', [
|
||||
({}, 'K', 'K', 'K'),
|
||||
({'value':{'unit': 'K'}}, 'C', 'C', 'C'),
|
||||
({'value':{'unit': 'K'}}, '', 'K', 'K'),
|
||||
({'value':{'unit': 'K'}, 'someparam':{'unit': 'A'}}, 'C', 'C', 'A'),
|
||||
])
|
||||
def test_deferred_main_unit(config, dynamicunit, finalunit, someunit):
|
||||
# this pattern is used in frappy_mlz.entangle.AnalogInput
|
||||
class Mod(Drivable):
|
||||
ramp = Parameter('', datatype=FloatRange(unit='$/min'))
|
||||
someparam = Parameter('', datatype=FloatRange(unit='$'))
|
||||
__main_unit = None
|
||||
|
||||
def applyMainUnit(self, mainunit):
|
||||
# called from __init__ method
|
||||
# replacement of '$' by main unit must be done later
|
||||
self.__main_unit = mainunit
|
||||
|
||||
def startModule(self, start_events):
|
||||
super().startModule(start_events)
|
||||
if dynamicunit:
|
||||
self.accessibles['value'].datatype.setProperty('unit', dynamicunit)
|
||||
self.__main_unit = dynamicunit
|
||||
if self.__main_unit:
|
||||
super().applyMainUnit(self.__main_unit)
|
||||
|
||||
srv = ServerStub({})
|
||||
m = Mod('m', logger, {'description': '', **config}, srv)
|
||||
m.startModule(None)
|
||||
assert m.parameters['value'].datatype.unit == finalunit
|
||||
assert m.parameters['target'].datatype.unit == finalunit
|
||||
assert m.parameters['ramp'].datatype.unit == finalunit + '/min'
|
||||
# when someparam.unit is configured, this differs from finalunit
|
||||
assert m.parameters['someparam'].datatype.unit == someunit
|
||||
|
||||
|
||||
def test_super_call():
|
||||
class Base(Readable):
|
||||
def read_status(self):
|
||||
return Readable.Status.IDLE, 'base'
|
||||
|
||||
class Mod(Base):
|
||||
def read_status(self):
|
||||
code, text = super().read_status()
|
||||
return code, text + ' (extended)'
|
||||
|
||||
class DispatcherStub1:
|
||||
def __init__(self, updates):
|
||||
self.updates = updates
|
||||
|
||||
def announce_update(self, modulename, pname, pobj):
|
||||
if pobj.readerror:
|
||||
raise pobj.readerror
|
||||
self.updates.append((modulename, pname, pobj.value))
|
||||
|
||||
class ServerStub1:
|
||||
def __init__(self, updates):
|
||||
self.dispatcher = DispatcherStub1(updates)
|
||||
|
||||
updates = []
|
||||
srv = ServerStub1(updates)
|
||||
b = Base('b', logger, {'description': ''}, srv)
|
||||
b.read_status()
|
||||
assert updates == [('b', 'status', ('IDLE', 'base'))]
|
||||
|
||||
updates.clear()
|
||||
m = Mod('m', logger, {'description': ''}, srv)
|
||||
m.read_status()
|
||||
# in the version before change 'allow super calls on read_/write_ methods'
|
||||
# updates would contain two items
|
||||
assert updates == [('m', 'status', ('IDLE', 'base (extended)'))]
|
||||
|
||||
assert type(m).__name__ == '_Mod'
|
||||
assert type(m).__mro__[1:5] == (Mod, Base, Readable, Module)
|
||||
|
||||
|
||||
def test_write_method_returns_none():
|
||||
class Mod(Module):
|
||||
a = Parameter('', FloatRange(), readonly=False)
|
||||
|
||||
def write_a(self, value):
|
||||
return None
|
||||
|
||||
mod = Mod('mod', LoggerStub(), {'description': ''}, ServerStub({}))
|
||||
mod.write_a(1.5)
|
||||
assert mod.a == 1.5
|
||||
|
||||
|
||||
@pytest.mark.parametrize('arg, value', [
|
||||
('always', 0),
|
||||
(0, 0),
|
||||
('never', 999999999),
|
||||
(999999999, 999999999),
|
||||
('default', 0.25),
|
||||
(1, 1),
|
||||
])
|
||||
def test_update_unchanged_ok(arg, value):
|
||||
srv = ServerStub({})
|
||||
generalConfig.testinit(omit_unchanged_within=0.25) # override value from DispatcherStub
|
||||
|
||||
class Mod1(Module):
|
||||
a = Parameter('', FloatRange(), default=0, update_unchanged=arg)
|
||||
|
||||
mod1 = Mod1('mod1', LoggerStub(), {'description': ''}, srv)
|
||||
par = mod1.parameters['a']
|
||||
assert par.omit_unchanged_within == value
|
||||
assert Mod1.a.omit_unchanged_within == 0
|
||||
|
||||
class Mod2(Module):
|
||||
a = Parameter('', FloatRange(), default=0)
|
||||
|
||||
mod2 = Mod2('mod2', LoggerStub(), {'description': '', 'a': {'update_unchanged': arg}}, srv)
|
||||
par = mod2.parameters['a']
|
||||
assert par.omit_unchanged_within == value
|
||||
assert Mod2.a.omit_unchanged_within == 0
|
||||
|
||||
|
||||
def test_omit_unchanged_within():
|
||||
srv = ServerStub({})
|
||||
generalConfig.testinit(omit_unchanged_within=0.25) # override call from DispatcherStub
|
||||
|
||||
class Mod(Module):
|
||||
a = Parameter('', FloatRange())
|
||||
|
||||
mod1 = Mod('mod1', LoggerStub(), {'description': ''}, srv)
|
||||
assert mod1.parameters['a'].omit_unchanged_within == 0.25
|
||||
|
||||
mod2 = Mod('mod2', LoggerStub(), {'description': '', 'omit_unchanged_within': 0.125}, srv)
|
||||
assert mod2.parameters['a'].omit_unchanged_within == 0.125
|
||||
|
||||
|
||||
stdlim = {
|
||||
'a_min': -1, 'a_max': 2,
|
||||
'b_min': 0,
|
||||
'c_max': 10,
|
||||
'd_limits': (-1, 1),
|
||||
}
|
||||
|
||||
|
||||
class Lim(Module):
|
||||
a = Parameter('', FloatRange(-10, 10), readonly=False, default=0)
|
||||
a_min = Parameter()
|
||||
a_max = Parameter()
|
||||
|
||||
b = Parameter('', FloatRange(0, None), readonly=False, default=0)
|
||||
b_min = Parameter()
|
||||
|
||||
c = Parameter('', IntRange(None, 100), readonly=False, default=0)
|
||||
c_max = Parameter()
|
||||
|
||||
d = Parameter('', FloatRange(-5, 5), readonly=False, default=0)
|
||||
d_limits = Parameter()
|
||||
|
||||
e = Parameter('', IntRange(0, 8), readonly=False, default=0)
|
||||
|
||||
def check_e(self, value):
|
||||
if value % 2:
|
||||
raise RangeError('e must not be odd')
|
||||
|
||||
|
||||
def test_limit_defaults():
|
||||
|
||||
srv = ServerStub({})
|
||||
|
||||
mod = Lim('mod', LoggerStub(), {'description': 'test'}, srv)
|
||||
|
||||
assert mod.a_min == -10
|
||||
assert mod.a_max == 10
|
||||
assert isinstance(mod.a_min, float)
|
||||
assert isinstance(mod.a_max, float)
|
||||
|
||||
assert mod.b_min == 0
|
||||
assert isinstance(mod.b_min, float)
|
||||
|
||||
assert mod.c_max == 100
|
||||
assert isinstance(mod.c_max, int)
|
||||
|
||||
assert mod.d_limits == (-5, 5)
|
||||
assert isinstance(mod.d_limits[0], float)
|
||||
assert isinstance(mod.d_limits[1], float)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('limits, pname, good, bad', [
|
||||
(stdlim, 'a', [-1, 2, 0], [-2, 3]),
|
||||
(stdlim, 'b', [0, 1e99], [-1, -1e99]),
|
||||
(stdlim, 'c', [-999, 0, 10], [11, 999]),
|
||||
(stdlim, 'd', [-1, 0.1, 1], [-1.001, 1.001]),
|
||||
({'a_min': 0, 'a_max': -1}, 'a', [], [0, -1]),
|
||||
(stdlim, 'e', [0, 2, 4, 6, 8], [-1, 1, 7, 9]),
|
||||
])
|
||||
def test_limits(limits, pname, good, bad):
|
||||
|
||||
srv = ServerStub({})
|
||||
|
||||
mod = Lim('mod', LoggerStub(), {'description': 'test'}, srv)
|
||||
mod.check_a = 0 # this should not harm. check_a is never called on the instance
|
||||
|
||||
for k, v in limits.items():
|
||||
setattr(mod, k, v)
|
||||
|
||||
for v in good:
|
||||
getattr(mod, 'write_' + pname)(v)
|
||||
for v in bad:
|
||||
with pytest.raises(RangeError):
|
||||
getattr(mod, 'write_' + pname)(v)
|
||||
|
||||
|
||||
def test_limit_inheritance():
|
||||
srv = ServerStub({})
|
||||
|
||||
class Base(Module):
|
||||
a = Parameter('', FloatRange(), readonly=False, default=0)
|
||||
|
||||
def check_a(self, value):
|
||||
if int(value * 4) != value * 4:
|
||||
raise ValueError('value is not a multiple of 0.25')
|
||||
|
||||
class Mixin:
|
||||
a_min = Parameter()
|
||||
a_max = Parameter()
|
||||
|
||||
class Mod(Mixin, Base):
|
||||
def check_a(self, value):
|
||||
if value == 0:
|
||||
raise ValueError('value must not be 0')
|
||||
|
||||
mod = Mod('mod', LoggerStub(), {'description': 'test', 'a_min': {'value': -1}, 'a_max': {'value': 1}}, srv)
|
||||
|
||||
for good in [-1, -0.75, 0.25, 1]:
|
||||
mod.write_a(good)
|
||||
|
||||
for bad in [-2, -0.1, 0, 0.9, 1.1]:
|
||||
with pytest.raises(ValueError):
|
||||
mod.write_a(bad)
|
||||
|
||||
class Mod2(Mixin, Base):
|
||||
def check_a(self, value):
|
||||
if value == 0:
|
||||
raise ValueError('value must not be 0')
|
||||
return True # indicates stop checking
|
||||
|
||||
mod2 = Mod2('mod2', LoggerStub(), {'description': 'test', 'a_min': {'value': -1}, 'a_max': {'value': 1}}, srv)
|
||||
|
||||
for good in [-2, -1, -0.75, 0.25, 1, 1.1]:
|
||||
mod2.write_a(good)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
mod2.write_a(0)
|
||||
|
Reference in New Issue
Block a user