diff --git a/frappy/modulebase.py b/frappy/modulebase.py index 420e3d7..d572dcd 100644 --- a/frappy/modulebase.py +++ b/frappy/modulebase.py @@ -188,10 +188,8 @@ class HasAccessibles(HasProperties): if new_value is Done: # TODO: to be removed when all code using Done is updated return getattr(self, pname) new_value = value if new_value is None else validate(new_value) - except Exception as e: - if isinstance(e, SECoPError): - e.raising_methods.append(f'{self.name}.write_{pname}') - self.announceUpdate(pname, err=e) + except SECoPError as e: + e.raising_methods.append(f'{self.name}.write_{pname}') raise self.announceUpdate(pname, new_value, validate=False) return new_value @@ -516,13 +514,13 @@ class Module(HasAccessibles): with self.updateLock: pobj = self.parameters[pname] timestamp = timestamp or time.time() + changed = False if not err: try: if validate: value = pobj.datatype(value) except Exception as e: err = e - changed = False else: changed = pobj.value != value or pobj.readerror # store the value even in case of error diff --git a/test/test_modules.py b/test/test_modules.py index 5217cc8..9b865cd 100644 --- a/test/test_modules.py +++ b/test/test_modules.py @@ -28,7 +28,7 @@ from glob import glob import pytest from frappy.datatypes import BoolType, FloatRange, StringType, IntRange, ScaledInteger -from frappy.errors import ProgrammingError, ConfigError, RangeError +from frappy.errors import ProgrammingError, ConfigError, RangeError, HardwareError from frappy.modules import Communicator, Drivable, Readable, Module, Writable from frappy.params import Command, Parameter, Limit from frappy.rwhandler import ReadHandler, WriteHandler, nopoll @@ -941,3 +941,36 @@ def test_stop_doc(modcls): if (modcls.stop.description == Drivable.stop.description and modcls.stop.func != Drivable.stop.func): assert modcls.stop.func.__doc__ # stop method needs a doc string + + +def test_write_error(): + updates = {} + srv = ServerStub(updates) + + class Mod(Module): + par = Parameter('', FloatRange(), readonly=False, default=0) + + def read_par(self): + raise HardwareError('failure') + + def write_par(self, value): + if value < 0: + raise RangeError('outside range') + + a = Mod('a', LoggerStub(), {'description': 'test'}, srv) + + # behaviour on read errors: + with pytest.raises(HardwareError): + a.read_par() + assert updates == {'a': {('error', 'par'): 'failure'}} + updates.clear() + + # behaviour on normal write + a.write_par(1) + assert updates['a']['par'] == 1 + updates.clear() + + # behaviour when write failed + with pytest.raises(RangeError): + a.write_par(-1) + assert not updates # no error update!