From 184b236a27ca1f4ebeb39aa18a3624bd4fc22837 Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Tue, 21 Aug 2018 16:46:14 +0100 Subject: [PATCH 01/10] Add field exception, raised when the entered field does not exist on a device, and update comments to reflect addition. --- pytac/element.py | 10 ++++++++++ pytac/model.py | 21 +++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/pytac/element.py b/pytac/element.py index 47401473..c950f9b8 100644 --- a/pytac/element.py +++ b/pytac/element.py @@ -1,6 +1,7 @@ """Module containing the element class.""" import pytac from pytac.device import DeviceException +from pytac.model import FieldException class Element(object): @@ -161,6 +162,7 @@ def get_value(self, field, handle=pytac.RB, units=pytac.ENG, Raises: DeviceException: if there is no device on the given field. + FieldException: if the element does not have the specified field. """ try: model = self._models[model] @@ -170,6 +172,8 @@ def get_value(self, field, handle=pytac.RB, units=pytac.ENG, except KeyError: raise DeviceException('No model type {} on element {}'.format(model, self)) + except FieldException: + raise FieldException('No field {} on element {}'.format(field, self)) def set_value(self, field, value, handle=pytac.SP, units=pytac.ENG, model=pytac.LIVE): @@ -187,6 +191,7 @@ def set_value(self, field, value, handle=pytac.SP, units=pytac.ENG, Raises: DeviceException: if arguments are incorrect. + FieldException: if the element does not have the specified field. """ if handle != pytac.SP: raise DeviceException('Must write using {}'.format(pytac.SP)) @@ -197,6 +202,8 @@ def set_value(self, field, value, handle=pytac.SP, units=pytac.ENG, except KeyError: raise DeviceException('No model type {} on element {}'.format(model, self)) + except FieldException: + raise FieldException('No field {} on element {}'.format(field, self)) def get_pv_name(self, field, handle): """Get a PV name on a device. @@ -210,9 +217,12 @@ def get_pv_name(self, field, handle): Raises: DeviceException: if there is no device for this field. + FieldException: if the element does not have the specified field. """ try: return self._models[pytac.LIVE].get_pv_name(field, handle) except KeyError: raise DeviceException('{} has no device for field {}'.format(self, field)) + except FieldException: + raise FieldException('No field {} on element {}'.format(field, self)) diff --git a/pytac/model.py b/pytac/model.py index 5b9f720f..a01fa6fc 100644 --- a/pytac/model.py +++ b/pytac/model.py @@ -2,6 +2,11 @@ import pytac +class FieldException(Exception): + '''Exception associated with invalid field requests.''' + pass + + class Model(object): """Abstract base classes for element models. @@ -116,8 +121,14 @@ def get_value(self, field, handle): Returns: float: The value of the PV. + + Raises: + FieldException: if the device does not have the specified field. """ - return self._devices[field].get_value(handle) + try: + return self._devices[field].get_value(handle) + except KeyError: + raise FieldException('No field {} on device {}'.format(field, self)) def set_value(self, field, value): """Set the value of a readback or setpoint PV for a field from the @@ -126,5 +137,11 @@ def set_value(self, field, value): Args: field (str): field for the requested value. value (float): The value to set on the PV. + + Raises: + FieldException: if the device does not have the specified field. """ - self._devices[field].set_value(value) + try: + self._devices[field].set_value(value) + except KeyError: + raise FieldException('No field {} on device {}'.format(field, self)) From 13511eae0f56c3d7593271bd83a6263a2107d1cc Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Tue, 21 Aug 2018 17:53:05 +0100 Subject: [PATCH 02/10] Add handle exception, raised when an invalid handle is used. --- pytac/device.py | 12 +++++++++--- pytac/element.py | 11 +++++++---- pytac/model.py | 3 ++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/pytac/device.py b/pytac/device.py index 5a81d77c..39bf849a 100644 --- a/pytac/device.py +++ b/pytac/device.py @@ -8,6 +8,12 @@ import pytac +class HandleException(Exception): + """Exception associated with requests with invalid handles. + """ + pass + + class DeviceException(Exception): """Exception associated with Device misconfiguration or invalid requests. """ @@ -73,7 +79,7 @@ def set_value(self, value): DeviceException: if no setpoint PV exists. """ if self.sp_pv is None: - raise DeviceException("""Device {0} has no setpoint PV.""" + raise HandleException("""Device {0} has no setpoint PV.""" .format(self.name)) self._cs.put(self.sp_pv, value) @@ -96,7 +102,7 @@ def get_value(self, handle): elif handle == pytac.SP and self.sp_pv: return self._cs.get(self.sp_pv) - raise DeviceException("""Device {0} has no {1} PV.""" + raise HandleException("""Device {0} has no {1} PV.""" .format(self.name, handle)) def get_pv_name(self, handle): @@ -116,7 +122,7 @@ def get_pv_name(self, handle): elif handle == pytac.SP and self.sp_pv: return self.sp_pv - raise DeviceException("""Device {0} has no {1} PV.""" + raise HandleException("""Device {0} has no {1} PV.""" .format(self.name, handle)) def get_cs(self): diff --git a/pytac/element.py b/pytac/element.py index c950f9b8..5c4bff0a 100644 --- a/pytac/element.py +++ b/pytac/element.py @@ -1,6 +1,6 @@ """Module containing the element class.""" import pytac -from pytac.device import DeviceException +from pytac.device import DeviceException, HandleException from pytac.model import FieldException @@ -194,14 +194,17 @@ def set_value(self, field, value, handle=pytac.SP, units=pytac.ENG, FieldException: if the element does not have the specified field. """ if handle != pytac.SP: - raise DeviceException('Must write using {}'.format(pytac.SP)) + raise HandleException('Must write using {}'.format(pytac.SP)) try: model = self._models[model] - value = self._uc[field].convert(value, origin=units, target=model.units) - model.set_value(field, value) except KeyError: raise DeviceException('No model type {} on element {}'.format(model, self)) + try: + value = self._uc[field].convert(value, origin=units, target=model.units) + model.set_value(field, value) + except KeyError: + raise FieldException('No field {} on element {}'.format(model, self)) except FieldException: raise FieldException('No field {} on element {}'.format(field, self)) diff --git a/pytac/model.py b/pytac/model.py index a01fa6fc..48574c06 100644 --- a/pytac/model.py +++ b/pytac/model.py @@ -3,7 +3,8 @@ class FieldException(Exception): - '''Exception associated with invalid field requests.''' + """Exception associated with invalid field requests. + """ pass From f5d8e8ff29239cb122b5bfcae5d0fbfaf414ea5f Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Tue, 21 Aug 2018 17:54:39 +0100 Subject: [PATCH 03/10] Update test_element to work with new handles and create separate get and set tests. --- test/test_element.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/test_element.py b/test/test_element.py index 93b09dad..79145431 100644 --- a/test/test_element.py +++ b/test/test_element.py @@ -106,16 +106,22 @@ def test_set_value_phys(test_element): (DUMMY_VALUE_2 / 2)) -def test_set_value_incorrect_field(test_element): +def test_set_exceptions(test_element): + with pytest.raises(pytac.model.FieldException): + test_element.set_value('unknown_field', 40.0, 'setpoint') + with pytest.raises(pytac.device.HandleException): + test_element.set_value('y', 40.0, 'unknown_handle') with pytest.raises(pytac.device.DeviceException): - test_element.set_value('non_existent', 40.0) + test_element.set_value('y', 40.0, 'setpoint', model='unknown_model') -def test_get_pv_exceptions(test_element): +def test_get_exceptions(test_element): + with pytest.raises(pytac.model.FieldException): + test_element.get_value('unknown_field', 'setpoint') + with pytest.raises(pytac.device.HandleException): + test_element.get_value('y', 'unknown_handle') with pytest.raises(pytac.device.DeviceException): - test_element.get_value('setpoint', 'unknown_field') - with pytest.raises(pytac.device.DeviceException): - test_element.get_value('unknown_handle', 'y') + test_element.get_value('y', 'setpoint', model='unknown_model') def test_identity_conversion(): From 4b568d78bb106cff16d20f442793fef890b7d029 Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 09:13:19 +0100 Subject: [PATCH 04/10] Correct DeviceException to HandleException in comments where relevant. --- pytac/device.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytac/device.py b/pytac/device.py index 39bf849a..42486e32 100644 --- a/pytac/device.py +++ b/pytac/device.py @@ -76,7 +76,7 @@ def set_value(self, value): value (float): The value to set on the PV. Raises: - DeviceException: if no setpoint PV exists. + HandleException: if no setpoint PV exists. """ if self.sp_pv is None: raise HandleException("""Device {0} has no setpoint PV.""" @@ -94,7 +94,7 @@ def get_value(self, handle): float: The value of the PV. Raises: - DeviceException: if the requested PV doesn't exist. + HandleException: if the requested PV doesn't exist. """ print('getting {}'.format('handle')) if handle == pytac.RB and self.rb_pv: @@ -115,7 +115,7 @@ def get_pv_name(self, handle): str: A readback or setpoint PV. Raises: - DeviceException: if the PV doesn't exist. + HandleException: if the PV doesn't exist. """ if handle == pytac.RB and self.rb_pv: return self.rb_pv From 5fc940e905e995cbc8a548547c4f1520a88b7ae0 Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 09:17:55 +0100 Subject: [PATCH 05/10] Update test files inline with changes to exceptions raised in the code. --- test/test_device.py | 4 ++-- test/test_machine.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_device.py b/test/test_device.py index 9924a3c2..91dcd5cf 100644 --- a/test/test_device.py +++ b/test/test_device.py @@ -21,13 +21,13 @@ def test_set_device_value(): def test_device_invalid_sp_raise_exception(): device2 = create_device(PREFIX, RB_PV, None) - with pytest.raises(pytac.device.DeviceException): + with pytest.raises(pytac.device.HandleException): device2.set_value(40) def test_get_device_value(): device = create_device() - with pytest.raises(pytac.device.DeviceException): + with pytest.raises(pytac.device.HandleException): device.get_value('non_existent') diff --git a/test/test_machine.py b/test/test_machine.py index 83d96b12..7e7849f4 100644 --- a/test/test_machine.py +++ b/test/test_machine.py @@ -63,7 +63,7 @@ def test_load_bpms(ring_mode, n_bpms): 'y_fofb_disabled', 'y_sofb_disabled') ) assert re.match('SR.*BPM.*X', bpm.get_pv_name('x', pytac.RB)) - with pytest.raises(pytac.device.DeviceException): + with pytest.raises(pytac.device.HandleException): bpm.get_pv_name('x', pytac.SP) assert len(bpms) == n_bpms assert bpms[0].cell == 1 From 34a30a29d5f0bd6b29c0f7476fdb1e91d8aad877 Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 09:23:01 +0100 Subject: [PATCH 06/10] Fix trailing whitespace after try: in element.py. --- pytac/element.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytac/element.py b/pytac/element.py index 5c4bff0a..df85ab03 100644 --- a/pytac/element.py +++ b/pytac/element.py @@ -200,7 +200,7 @@ def set_value(self, field, value, handle=pytac.SP, units=pytac.ENG, except KeyError: raise DeviceException('No model type {} on element {}'.format(model, self)) - try: + try: value = self._uc[field].convert(value, origin=units, target=model.units) model.set_value(field, value) except KeyError: From 676de767cce7513312e5f70ac52df1b86949886f Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 15:39:08 +0100 Subject: [PATCH 07/10] Resolve merge conflict. --- pytac/device.py | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/pytac/device.py b/pytac/device.py index 2516e80c..44d3d483 100644 --- a/pytac/device.py +++ b/pytac/device.py @@ -79,14 +79,9 @@ def set_value(self, value): HandleException: if no setpoint PV exists. """ if self.sp_pv is None: -<<<<<<< HEAD - raise HandleException("""Device {0} has no setpoint PV.""" - .format(self.name)) -======= - raise DeviceException( + raise HandleException( "Device {0} has no setpoint PV.".format(self.name) ) ->>>>>>> 106930cd6a2dd86a1533bf73d03c4ef14bd72e49 self._cs.put(self.sp_pv, value) def get_value(self, handle): @@ -108,14 +103,9 @@ def get_value(self, handle): elif handle == pytac.SP and self.sp_pv: return self._cs.get(self.sp_pv) -<<<<<<< HEAD - raise HandleException("""Device {0} has no {1} PV.""" - .format(self.name, handle)) -======= - raise DeviceException( + raise HandleException( "Device {0} has no {1} PV.".format(self.name, handle) ) ->>>>>>> 106930cd6a2dd86a1533bf73d03c4ef14bd72e49 def get_pv_name(self, handle): """Get a PV name on a specified handle. @@ -134,14 +124,9 @@ def get_pv_name(self, handle): elif handle == pytac.SP and self.sp_pv: return self.sp_pv -<<<<<<< HEAD - raise HandleException("""Device {0} has no {1} PV.""" - .format(self.name, handle)) -======= - raise DeviceException( + raise HandleException( "Device {0} has no {1} PV.".format(self.name, handle) ) ->>>>>>> 106930cd6a2dd86a1533bf73d03c4ef14bd72e49 def get_cs(self): """The control system object used to get and set the value of a PV. From 1bf0728f17dbace0915f8ae9715425a2912b5b10 Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 16:07:20 +0100 Subject: [PATCH 08/10] Move all exceptions to thier own files and update their call accordingly. --- pytac/device.py | 13 +------------ pytac/element.py | 3 +-- pytac/lattice.py | 5 +---- pytac/model.py | 8 +------- pytac/units.py | 7 +------ test/test_device.py | 4 ++-- test/test_element.py | 12 ++++++------ test/test_lattice.py | 4 ++-- test/test_machine.py | 4 ++-- test/test_units.py | 3 ++- 10 files changed, 19 insertions(+), 44 deletions(-) diff --git a/pytac/device.py b/pytac/device.py index 44d3d483..631988e7 100644 --- a/pytac/device.py +++ b/pytac/device.py @@ -6,18 +6,7 @@ magnets and a skew quadrupole. """ import pytac - - -class HandleException(Exception): - """Exception associated with requests with invalid handles. - """ - pass - - -class DeviceException(Exception): - """Exception associated with Device misconfiguration or invalid requests. - """ - pass +from pytac.exceptions import HandleException class Device(object): diff --git a/pytac/element.py b/pytac/element.py index df85ab03..8b4342d9 100644 --- a/pytac/element.py +++ b/pytac/element.py @@ -1,7 +1,6 @@ """Module containing the element class.""" import pytac -from pytac.device import DeviceException, HandleException -from pytac.model import FieldException +from pytac.exceptions import FieldException, HandleException, DeviceException class Element(object): diff --git a/pytac/lattice.py b/pytac/lattice.py index 021e524b..f0585369 100644 --- a/pytac/lattice.py +++ b/pytac/lattice.py @@ -2,10 +2,7 @@ machine. """ import numpy - - -class LatticeException(Exception): - pass +from pytac.exceptions import LatticeException class Lattice(object): diff --git a/pytac/model.py b/pytac/model.py index 48574c06..5839720e 100644 --- a/pytac/model.py +++ b/pytac/model.py @@ -1,12 +1,6 @@ """Module containing pytac model classes.""" import pytac - - -class FieldException(Exception): - """Exception associated with invalid field requests. - """ - pass - +from pytac.exceptions import FieldException class Model(object): """Abstract base classes for element models. diff --git a/pytac/units.py b/pytac/units.py index 6ce60ac5..a70e6f4c 100644 --- a/pytac/units.py +++ b/pytac/units.py @@ -1,15 +1,10 @@ """Classes for use in unit conversion.""" import pytac import numpy +from pytac.exceptions import UnitsException from scipy.interpolate import PchipInterpolator -class UnitsException(Exception): - """Conversion not understood - """ - pass - - def unit_function(value): """Default value for the pre and post functions used in unit conversion. diff --git a/test/test_device.py b/test/test_device.py index 12c379a7..8bfb3370 100644 --- a/test/test_device.py +++ b/test/test_device.py @@ -22,13 +22,13 @@ def test_set_device_value(): def test_device_invalid_sp_raise_exception(): device2 = create_device(PREFIX, RB_PV, None) - with pytest.raises(pytac.device.HandleException): + with pytest.raises(pytac.exceptions.HandleException): device2.set_value(40) def test_get_device_value(): device = create_device() - with pytest.raises(pytac.device.HandleException): + with pytest.raises(pytac.exceptions.HandleException): device.get_value('non_existent') diff --git a/test/test_element.py b/test/test_element.py index 79145431..897d9eb8 100644 --- a/test/test_element.py +++ b/test/test_element.py @@ -107,20 +107,20 @@ def test_set_value_phys(test_element): def test_set_exceptions(test_element): - with pytest.raises(pytac.model.FieldException): + with pytest.raises(pytac.exceptions.FieldException): test_element.set_value('unknown_field', 40.0, 'setpoint') - with pytest.raises(pytac.device.HandleException): + with pytest.raises(pytac.exceptions.HandleException): test_element.set_value('y', 40.0, 'unknown_handle') - with pytest.raises(pytac.device.DeviceException): + with pytest.raises(pytac.exceptions.DeviceException): test_element.set_value('y', 40.0, 'setpoint', model='unknown_model') def test_get_exceptions(test_element): - with pytest.raises(pytac.model.FieldException): + with pytest.raises(pytac.exceptions.FieldException): test_element.get_value('unknown_field', 'setpoint') - with pytest.raises(pytac.device.HandleException): + with pytest.raises(pytac.exceptions.HandleException): test_element.get_value('y', 'unknown_handle') - with pytest.raises(pytac.device.DeviceException): + with pytest.raises(pytac.exceptions.DeviceException): test_element.get_value('y', 'setpoint', model='unknown_model') diff --git a/test/test_lattice.py b/test/test_lattice.py index 576fa9b1..950c97af 100644 --- a/test/test_lattice.py +++ b/test/test_lattice.py @@ -129,7 +129,7 @@ def test_set_values(simple_element_and_lattice): def test_set_values_raise_exception_if_number_of_values_does_not_match(simple_element_and_lattice): element, lattice = simple_element_and_lattice - with pytest.raises(pytac.lattice.LatticeException): + with pytest.raises(pytac.exceptions.LatticeException): lattice.set_values('family', 'x', [1, 2]) @@ -149,7 +149,7 @@ def test_s_position(simple_element_and_lattice): def test_get_s_throws_exception_if_element_not_in_lattice(): lat = pytac.lattice.Lattice(LATTICE, mock.MagicMock(), 1) element = pytac.element.Element(1, 1.0, 'Quad') - with pytest.raises(pytac.lattice.LatticeException): + with pytest.raises(pytac.exceptions.LatticeException): lat.get_s(element) diff --git a/test/test_machine.py b/test/test_machine.py index 71df2787..d37ecc3e 100644 --- a/test/test_machine.py +++ b/test/test_machine.py @@ -67,7 +67,7 @@ def test_load_bpms(ring_mode, n_bpms): for bpm in bpms: assert set(bpm.get_fields()) == bpm_fields assert re.match('SR.*BPM.*X', bpm.get_pv_name('x', pytac.RB)) - with pytest.raises(pytac.device.HandleException): + with pytest.raises(pytac.exceptions.HandleException): bpm.get_pv_name('x', pytac.SP) assert len(bpms) == n_bpms assert bpms[0].cell == 1 @@ -184,7 +184,7 @@ def test_quad_unitconv(): def test_quad_unitconv_raise_exception(): uc = pytac.units.PchipUnitConv([50.0, 100.0, 180.0], [-4.95, -9.85, -17.56]) - with pytest.raises(pytac.units.UnitsException): + with pytest.raises(pytac.exceptions.UnitsException): uc.phys_to_eng(-0.7) diff --git a/test/test_units.py b/test/test_units.py index 35782ffd..9bad8a84 100644 --- a/test/test_units.py +++ b/test/test_units.py @@ -1,6 +1,7 @@ import pytest import pytac -from pytac.units import UnitConv, PolyUnitConv, PchipUnitConv, UnitsException +from pytac.units import UnitConv, PolyUnitConv, PchipUnitConv +from pytac.exceptions import UnitsException import numpy From 978e6c06714315616253f254f0431ec6f0cc98dc Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 16:31:17 +0100 Subject: [PATCH 09/10] Add exceptions file to repository. --- pytac/exceptions.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 pytac/exceptions.py diff --git a/pytac/exceptions.py b/pytac/exceptions.py new file mode 100644 index 00000000..9e5dccd1 --- /dev/null +++ b/pytac/exceptions.py @@ -0,0 +1,24 @@ +"""Module containing all the exceptions used in pytac.""" + +class FieldException(Exception): + """Exception associated with invalid field requests. + """ + pass + +class HandleException(Exception): + """Exception associated with requests with invalid handles. + """ + pass + +class DeviceException(Exception): + """Exception associated with Device misconfiguration or invalid requests. + """ + pass + +class UnitsException(Exception): + """Conversion not understood + """ + pass + +class LatticeException(Exception): + pass From 934e26ff7dd07c4a2b933a2a640ee12a2f9b0e4b Mon Sep 17 00:00:00 2001 From: T-Nicholls Date: Wed, 22 Aug 2018 17:07:51 +0100 Subject: [PATCH 10/10] Correct two files to be inline with pep8 standards. --- pytac/exceptions.py | 5 +++++ pytac/model.py | 1 + 2 files changed, 6 insertions(+) diff --git a/pytac/exceptions.py b/pytac/exceptions.py index 9e5dccd1..60f67e8b 100644 --- a/pytac/exceptions.py +++ b/pytac/exceptions.py @@ -1,24 +1,29 @@ """Module containing all the exceptions used in pytac.""" + class FieldException(Exception): """Exception associated with invalid field requests. """ pass + class HandleException(Exception): """Exception associated with requests with invalid handles. """ pass + class DeviceException(Exception): """Exception associated with Device misconfiguration or invalid requests. """ pass + class UnitsException(Exception): """Conversion not understood """ pass + class LatticeException(Exception): pass diff --git a/pytac/model.py b/pytac/model.py index 5839720e..475f433e 100644 --- a/pytac/model.py +++ b/pytac/model.py @@ -2,6 +2,7 @@ import pytac from pytac.exceptions import FieldException + class Model(object): """Abstract base classes for element models.