# ***************************************************************************** # # 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 # # ***************************************************************************** """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)