on Module, use one single callback list 'paramsCallback' instead of 'valueCallbacks', 'errorCallbacks'. Redesign the mechanism to avoid most of the closures. Change-Id: Ie7f68f6bf97ab3f3cd961faa20b0e77730e5b37d Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/33118 Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch> Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
156 lines
3.8 KiB
Python
156 lines
3.8 KiB
Python
# *****************************************************************************
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it under
|
|
# the terms of the GNU General Public License as published by the Free Software
|
|
# Foundation; either version 2 of the License, or (at your option) any later
|
|
# version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# this program; if not, write to the Free Software Foundation, Inc.,
|
|
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Module authors:
|
|
# Markus Zolliker <markus.zolliker@psi.ch>
|
|
#
|
|
# *****************************************************************************
|
|
"""test parameter callbacks"""
|
|
|
|
from test.test_modules import LoggerStub, ServerStub
|
|
import pytest
|
|
from frappy.core import Module, Parameter, FloatRange
|
|
from frappy.errors import WrongTypeError
|
|
|
|
|
|
WRONG_TYPE = WrongTypeError()
|
|
|
|
|
|
class Mod(Module):
|
|
a = Parameter('', FloatRange())
|
|
b = Parameter('', FloatRange())
|
|
c = Parameter('', FloatRange())
|
|
|
|
def read_a(self):
|
|
raise WRONG_TYPE
|
|
|
|
def read_b(self):
|
|
raise WRONG_TYPE
|
|
|
|
def read_c(self):
|
|
raise WRONG_TYPE
|
|
|
|
|
|
class Dbl(Module):
|
|
a = Parameter('', FloatRange())
|
|
b = Parameter('', FloatRange())
|
|
c = Parameter('', FloatRange())
|
|
_error_a = None
|
|
_value_b = None
|
|
_error_c = None
|
|
|
|
def update_a(self, value, err=None):
|
|
# treat error updates
|
|
try:
|
|
self.a = value * 2
|
|
except TypeError: # value is None -> err
|
|
self.announceUpdate('a', None, err)
|
|
|
|
def update_b(self, value):
|
|
self._value_b = value
|
|
# error updates are ignored
|
|
self.b = value * 2
|
|
|
|
|
|
def make(cls):
|
|
logger = LoggerStub()
|
|
srv = ServerStub({})
|
|
return cls('mod1', logger, {'description': ''}, srv)
|
|
|
|
|
|
def test_simple_callback():
|
|
mod1 = make(Mod)
|
|
result = []
|
|
|
|
def cbfunc(arg1, arg2, value):
|
|
result[:] = arg1, arg2, value
|
|
|
|
mod1.addCallback('a', cbfunc, 'ARG1', 'arg2')
|
|
|
|
mod1.a = 1.5
|
|
assert result == ['ARG1', 'arg2', 1.5]
|
|
|
|
result.clear()
|
|
|
|
with pytest.raises(WrongTypeError):
|
|
mod1.read_a()
|
|
|
|
assert not result # callback function is NOT called
|
|
|
|
|
|
def test_combi_callback():
|
|
mod1 = make(Mod)
|
|
result = []
|
|
|
|
def cbfunc(arg1, arg2, value, err=None):
|
|
result[:] = arg1, arg2, value, err
|
|
|
|
mod1.addCallback('a', cbfunc, 'ARG1', 'arg2')
|
|
|
|
mod1.a = 1.5
|
|
assert result == ['ARG1', 'arg2', 1.5, None]
|
|
|
|
result.clear()
|
|
|
|
with pytest.raises(WrongTypeError):
|
|
mod1.read_a()
|
|
|
|
assert result[:3] == ['ARG1', 'arg2', None] # callback function called with value None
|
|
assert isinstance(result[3], WrongTypeError)
|
|
|
|
|
|
def test_autoupdate():
|
|
mod1 = make(Mod)
|
|
mod2 = make(Dbl)
|
|
mod1.registerCallbacks(mod2, autoupdate=['c'])
|
|
|
|
result = {}
|
|
|
|
def cbfunc(pname, *args):
|
|
result[pname] = args
|
|
|
|
for param in 'a', 'b', 'c':
|
|
mod2.addCallback(param, cbfunc, param)
|
|
|
|
# test update_a without error
|
|
mod1.a = 5
|
|
assert mod2.a == 10
|
|
assert result.pop('a') == (10,)
|
|
|
|
# test update_a with error
|
|
with pytest.raises(WrongTypeError):
|
|
mod1.read_a()
|
|
|
|
assert result.pop('a') == (None, WRONG_TYPE)
|
|
|
|
# test that update_b is ignored in case of error
|
|
mod1.b = 3
|
|
assert mod2.b == 6 # no error
|
|
assert result.pop('b') == (6,)
|
|
|
|
with pytest.raises(WrongTypeError):
|
|
mod1.read_b()
|
|
assert 'b' not in result
|
|
|
|
# test autoupdate
|
|
mod1.c = 3
|
|
assert mod2.c == 3
|
|
assert result['c'] == (3,)
|
|
|
|
with pytest.raises(WrongTypeError):
|
|
mod1.read_c()
|
|
assert result['c'] == (None, WRONG_TYPE)
|