From 2f8da4ca3f0c6e4a5af4affee930717b63d6ae20 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sun, 19 Jul 2026 00:32:34 +0100 Subject: [PATCH] Fix settings paths for tests, change EPICS_TOP type --- common_tests/DAQmx.py | 2 +- common_tests/danfysik.py | 41 +++--- common_tests/eurotherm.py | 15 +-- common_tests/fermichopper.py | 58 ++++----- common_tests/instron_base.py | 30 ++--- common_tests/kepco.py | 10 +- common_tests/moxa12XX.py | 12 +- common_tests/oscillating_collimators.py | 2 +- common_tests/riken_changeover.py | 56 ++++---- common_tests/tpgx00.py | 6 +- common_tests/tpgx6x.py | 52 ++++---- common_tests/tti_common.py | 2 +- run_tests.py | 41 +++--- run_utils.py | 40 +++--- test_config/good_for_refl/galil01.cmd | 24 ++++ test_config/good_for_refl/galil02.cmd | 24 ++++ test_config/good_for_refl/galil03.cmd | 24 ++++ tests/CAENv895.py | 8 +- tests/DAQmx.py | 9 +- tests/DAQmx_monster.py | 9 +- tests/axis.py | 29 +++-- tests/cryosms.py | 22 ++-- tests/cybaman.py | 69 +++++----- tests/danfysik_calibrated.py | 20 +-- tests/danfysik_common_calib.py | 4 +- tests/danfysik_local_calib.py | 6 +- tests/dma4500m.py | 10 +- tests/egxcolim.py | 9 +- tests/eurotherm_eibisynch.py | 2 +- tests/eurotherm_modbus.py | 2 +- tests/eurotherm_modbus_needlevalve.py | 2 +- tests/fermi_chopper_lifter.py | 5 +- tests/fermichopper_merlin.py | 8 +- tests/galil.py | 26 ++-- tests/galilmul.py | 16 +-- tests/gem_jaws_manager.py | 17 +-- tests/heliox.py | 28 ++-- tests/helium_recovery_plc.py | 51 ++++---- tests/indfurn.py | 8 +- tests/inhibitr.py | 10 +- tests/instetc.py | 10 +- tests/itc503.py | 8 +- tests/jaws.py | 93 +++++++------- tests/jaws_split.py | 2 + tests/jsco4180.py | 30 ++--- tests/keithley_2001.py | 61 +++++---- tests/kepco_no_rem.py | 6 +- tests/kepco_rem.py | 2 +- tests/kynctm3k.py | 38 +++--- tests/lakeshore340.py | 28 ++-- tests/lakeshore460.py | 37 +++--- tests/larmor_bench_fins.py | 5 +- tests/lksh218.py | 15 ++- tests/lsicorr.py | 17 ++- tests/mecfrf.py | 12 +- tests/mercuryitc.py | 130 +++++++++---------- tests/mercuryitc_FLOW_SPC.py | 112 ++++++++-------- tests/mercuryitc_VTI_SPC.py | 32 ++--- tests/mezflipr_v1.py | 34 +++-- tests/mezflipr_v2.py | 30 +++-- tests/mk3chopper.py | 4 +- tests/mkspr4kb.py | 66 +++++----- tests/motion_setpoints.py | 84 ++++++------ tests/moxa1210.py | 20 +-- tests/moxa1240.py | 12 +- tests/moxa1242.py | 22 ++-- tests/moxa1262.py | 6 +- tests/neocera.py | 6 +- tests/ngpspsu.py | 2 +- tests/nimrod_jaws_manager.py | 9 +- tests/oscillating_collimator_let.py | 7 +- tests/polaris_jaws_manager.py | 11 +- tests/readascii.py | 34 ++--- tests/refl.py | 140 ++++++++++---------- tests/refl_init.py | 22 ++-- tests/refl_trunc.py | 22 ++-- tests/rikenfe_plc.py | 8 +- tests/rkndio.py | 8 +- tests/samplechanger.py | 32 ++--- tests/sampos.py | 12 +- tests/sans2d_apertures_guides.py | 25 +--- tests/sans2d_vacuum.py | 13 +- tests/sans2d_vacuum_collision_avoidance.py | 37 +++--- tests/sans2d_vacuum_tank.py | 36 ++---- tests/separator.py | 18 ++- tests/simple.py | 54 ++++---- tests/skf_mb350_chopper.py | 2 +- tests/sp2xx.py | 7 +- tests/spinflipper.py | 9 +- tests/tdk_lambda_genesys.py | 11 +- tests/tekafg3XXX.py | 2 +- tests/tizr.py | 13 +- tests/triton.py | 16 +-- tests/zfcntrl.py | 136 +++++++++----------- tests/zfhifi.py | 19 +-- tests/zfmagfld.py | 81 ++++++------ utils/calibration_utils.py | 4 +- utils/channel_access.py | 142 +++++++++++---------- utils/device_launcher.py | 10 +- utils/emulator_exceptions.py | 4 +- utils/emulator_launcher.py | 124 +++++++++--------- utils/formatters.py | 2 +- utils/free_ports.py | 17 +-- utils/ioc_launcher.py | 135 +++++++++----------- utils/log_file.py | 11 +- utils/testing.py | 32 ++--- 106 files changed, 1480 insertions(+), 1518 deletions(-) create mode 100644 test_config/good_for_refl/galil01.cmd create mode 100644 test_config/good_for_refl/galil02.cmd create mode 100644 test_config/good_for_refl/galil03.cmd diff --git a/common_tests/DAQmx.py b/common_tests/DAQmx.py index 5f5557fd..2dec6e01 100644 --- a/common_tests/DAQmx.py +++ b/common_tests/DAQmx.py @@ -8,7 +8,7 @@ ICPCONFIGNAME = "DAQMX" -class DAQmxTests(object): +class DAQmxTests: """ General tests for the DAQmx. """ diff --git a/common_tests/danfysik.py b/common_tests/danfysik.py index b90fb949..1638de50 100644 --- a/common_tests/danfysik.py +++ b/common_tests/danfysik.py @@ -30,7 +30,7 @@ HAS_TRIPPED = {True: "Tripped", False: "OK"} -class DanfysikBase(object): +class DanfysikBase: """ Tests for danfysik. """ @@ -87,70 +87,69 @@ def _deactivate_interlocks(self): """ Most danfysiks have interlocks deactivated on startup anyway """ - pass @parameterized.expand(parameterized_list(["VOLT", "CURR"])) @skip_if_recsim("Can not test disconnection in rec sim") def test_GIVEN_device_not_connected_WHEN_pv_checked_THEN_pv_in_alarm(self, _, pv): for id_prefix in self.id_prefixes: self.ca.assert_that_pv_alarm_is_not( - "{}{}".format(id_prefix, pv), ChannelAccess.Alarms.INVALID, timeout=30 + f"{id_prefix}{pv}", ChannelAccess.Alarms.INVALID, timeout=30 ) with self._lewis.backdoor_simulate_disconnected_device(): for id_prefix in self.id_prefixes: self.ca.assert_that_pv_alarm_is( - "{}{}".format(id_prefix, pv), ChannelAccess.Alarms.INVALID, timeout=30 + f"{id_prefix}{pv}", ChannelAccess.Alarms.INVALID, timeout=30 ) for id_prefix in self.id_prefixes: self.ca.assert_that_pv_alarm_is_not( - "{}{}".format(id_prefix, pv), ChannelAccess.Alarms.INVALID, timeout=30 + f"{id_prefix}{pv}", ChannelAccess.Alarms.INVALID, timeout=30 ) def test_WHEN_polarity_setpoint_is_set_THEN_readback_updates_with_set_value(self): for id_prefix in self.id_prefixes: for pol in POLARITIES: - self.ca.assert_setting_setpoint_sets_readback(pol, "{}POL".format(id_prefix)) + self.ca.assert_setting_setpoint_sets_readback(pol, f"{id_prefix}POL") def test_WHEN_polarity_setpoint_is_set_with_number_THEN_readback_updates_with_set_value(self): for id_prefix in self.id_prefixes: for pol_num, pol in enumerate(POLARITIES): self.ca.assert_setting_setpoint_sets_readback( - pol_num, "{}POL".format(id_prefix), "{}POL:SP".format(id_prefix), pol + pol_num, f"{id_prefix}POL", f"{id_prefix}POL:SP", pol ) @skip_if_recsim("Recsim is not set up properly for this test to work") def test_WHEN_power_setpoint_is_set_THEN_readback_updates_with_set_value(self): for id_prefix in self.id_prefixes: for state in POWER_STATES: - self.ca.assert_setting_setpoint_sets_readback(state, "{}POWER".format(id_prefix)) + self.ca.assert_setting_setpoint_sets_readback(state, f"{id_prefix}POWER") @skip_if_recsim("Recsim is not set up properly for this test to work") - def test_WHEN_power_setpoint_is_set_THEN_readback_updates_with_set_value(self): + def test_WHEN_power_setpoint_is_set_THEN_readback_updates_with_set_value_sp(self): for id_prefix in self.id_prefixes: for state_num, state in enumerate(POWER_STATES): self.ca.assert_setting_setpoint_sets_readback( - state_num, "{}POWER".format(id_prefix), "{}POWER:SP".format(id_prefix), state + state_num, f"{id_prefix}POWER", f"{id_prefix}POWER:SP", state ) def test_WHEN_current_setpoint_is_set_THEN_current_readback_updates_to_set_value(self): for id_prefix in self.id_prefixes: for curr in TEST_CURRENTS: - self.ca.set_pv_value("{}CURR:SP".format(id_prefix), curr) + self.ca.set_pv_value(f"{id_prefix}CURR:SP", curr) expected_value = ( curr * self.current_readback_factor if IOCRegister.uses_rec_sim else curr ) self.ca.assert_that_pv_is_number( - "{}CURR".format(id_prefix), expected_value, tolerance=0.5 + f"{id_prefix}CURR", expected_value, tolerance=0.5 ) # Tolerance 0.5 because readback is integer @skip_if_devsim("In dev sim this test fails as the simulated records are not used") def test_GIVEN_emulator_not_in_use_WHEN_voltage_is_read_THEN_value_is_as_expected(self): expected_value = 12 for id_prefix in self.id_prefixes: - self.ca.set_pv_value("{}SIM:VOLT".format(id_prefix), expected_value) - self.ca.assert_that_pv_is("{}VOLT".format(id_prefix), expected_value) + self.ca.set_pv_value(f"{id_prefix}SIM:VOLT", expected_value) + self.ca.assert_that_pv_is(f"{id_prefix}VOLT", expected_value) @skip_if_recsim("Recsim is unable to simulate comms being uninitialized") def test_GIVEN_power_supply_comms_become_uninitialized_THEN_ioc_recovers(self): @@ -161,7 +160,7 @@ def test_GIVEN_power_supply_comms_become_uninitialized_THEN_ioc_recovers(self): for id_prefix in self.id_prefixes: # Should be able to re-initialize comms and read the new voltage self.ca.assert_that_pv_is_number( - "{}VOLT".format(id_prefix), volt, tolerance=0.5, timeout=30 + f"{id_prefix}VOLT", volt, tolerance=0.5, timeout=30 ) finally: @@ -171,7 +170,7 @@ def test_GIVEN_power_supply_comms_become_uninitialized_THEN_ioc_recovers(self): def test_GIVEN_no_interlocks_active_WHEN_getting_overall_interlock_status_THEN_it_is_ok(self): self._deactivate_interlocks() for id_prefix in self.id_prefixes: - self.ca.assert_that_pv_is("{}ILK".format(id_prefix), HAS_TRIPPED[False]) + self.ca.assert_that_pv_is(f"{id_prefix}ILK", HAS_TRIPPED[False]) @skip_if_recsim( "In rec sim this test fails as recsim does not set any of the related values " @@ -179,11 +178,11 @@ def test_GIVEN_no_interlocks_active_WHEN_getting_overall_interlock_status_THEN_i ) def test_WHEN_reset_is_sent_THEN_readbacks_and_power_are_off(self): for id_prefix in self.id_prefixes: - self.ca.set_pv_value("{}CURR:SP".format(id_prefix), 5) - self.ca.set_pv_value("{}RESET".format(id_prefix), 1) - self.ca.assert_that_pv_is("{}POWER".format(id_prefix), "Off") - self.ca.assert_that_pv_is("{}CURR".format(id_prefix), 0) - self.ca.assert_that_pv_is("{}VOLT".format(id_prefix), 0) + self.ca.set_pv_value(f"{id_prefix}CURR:SP", 5) + self.ca.set_pv_value(f"{id_prefix}RESET", 1) + self.ca.assert_that_pv_is(f"{id_prefix}POWER", "Off") + self.ca.assert_that_pv_is(f"{id_prefix}CURR", 0) + self.ca.assert_that_pv_is(f"{id_prefix}VOLT", 0) def test_GIVEN_power_on_and_zero_sp_WHEN_enabling_auto_onoff_THEN_device_is_powered_off(self): self.set_autoonoff(False) diff --git a/common_tests/eurotherm.py b/common_tests/eurotherm.py index f301652c..df677c44 100644 --- a/common_tests/eurotherm.py +++ b/common_tests/eurotherm.py @@ -1,9 +1,8 @@ import abc -import os +import contextlib import time import typing import unittest -from typing import ContextManager from parameterized import parameterized @@ -49,7 +48,7 @@ def get_emulator_device(self) -> str: pass @abc.abstractmethod - def _get_temperature_setter_wrapper(self) -> ContextManager: + def _get_temperature_setter_wrapper(self) -> contextlib.AbstractContextManager: pass @abc.abstractmethod @@ -57,7 +56,7 @@ def get_scaling(self) -> str: pass def get_prefix(self) -> str: - return "{}:A01".format(self.get_device()) + return f"{self.get_device()}:A01" def setUp(self): self._setup_lewis_and_channel_access() @@ -274,12 +273,10 @@ def _assert_units(self, units): def _assert_using_mock_table_location(self): for pv in ["A01:TEMP", "A01:TEMP:SP:CONV", "A01:TEMP:SP:RBV:CONV"]: - self.ca.assert_that_pv_is( - "{}.TDIR".format(pv), r"eurotherm2k/master/example_temp_sensor" - ) + self.ca.assert_that_pv_is(f"{pv}.TDIR", r"eurotherm2k/master/example_temp_sensor") self.ca.assert_that_pv_is_path( - "{}.BDIR".format(pv), - os.path.join(EPICS_TOP, "support").replace("\\", "/"), + f"{pv}.BDIR", + (EPICS_TOP / "support").as_posix(), ) def test_WHEN_calibration_file_is_in_units_of_K_THEN_egu_of_temperature_pvs_is_K( diff --git a/common_tests/fermichopper.py b/common_tests/fermichopper.py index 5d268395..8b12bb2d 100644 --- a/common_tests/fermichopper.py +++ b/common_tests/fermichopper.py @@ -13,7 +13,7 @@ ) -class ErrorStrings(object): +class ErrorStrings: """ Error messages that we expect to appear in the IOC log in various situations. """ @@ -34,22 +34,11 @@ class ErrorStrings(object): CONTROLLER_OVERSPEED = "Controller reports speed limit exceeded" -class FermichopperBase(object, metaclass=ABCMeta): +class FermichopperBase(metaclass=ABCMeta): """ Tests for the Fermi Chopper IOC. """ - valid_commands = ["0001", "0002", "0003", "0004", "0005"] - - # Values that will be tested in the parametrized tests. - test_chopper_speeds = [100, 350, 600] - test_delay_durations = [0, 2.5, 18] - test_gatewidth_values = [0, 0.5, 5] - test_temperature_values = [20.0, 25.0, 37.5, 47.5] - test_current_values = [0, 1.37, 2.22] - test_voltage_values = [0, 282.9, 333.3] - test_autozero_values = [-5.0, -2.22, 0, 1.23, 5] - @abstractmethod def _get_device_prefix(self): pass @@ -70,6 +59,17 @@ def setUp(self): if not IOCRegister.uses_rec_sim: self._lewis.backdoor_run_function_on_device("reset") + self.valid_commands = ["0001", "0002", "0003", "0004", "0005"] + + # Values that will be tested in the parametrized tests. + self.test_chopper_speeds = [100, 350, 600] + self.test_delay_durations = [0, 2.5, 18] + self.test_gatewidth_values = [0, 0.5, 5] + self.test_temperature_values = [20.0, 25.0, 37.5, 47.5] + self.test_current_values = [0, 1.37, 2.22] + self.test_voltage_values = [0, 282.9, 333.3] + self.test_autozero_values = [-5.0, -2.22, 0, 1.23, 5] + def is_device_broken(self): if IOCRegister.uses_rec_sim: return False # In recsim, assume device is always ok @@ -105,7 +105,7 @@ def test_WHEN_speed_setpoint_is_set_THEN_readback_updates(self): @skip_if_recsim("Recsim does not handle this") def test_WHEN_speed_setpoint_is_set_via_gui_pv_THEN_readback_updates(self): for speed in self.test_chopper_speeds: - self.ca.set_pv_value("SPEED:SP:GUI", "{} Hz".format(speed)) + self.ca.set_pv_value("SPEED:SP:GUI", f"{speed} Hz") self.ca.assert_that_pv_is("SPEED:SP", speed) self.ca.assert_that_pv_alarm_is("SPEED:SP", self.ca.Alarms.NONE) self.ca.assert_that_pv_is("SPEED:SP:RBV", speed) @@ -132,14 +132,12 @@ def test_WHEN_autozero_voltages_are_set_via_backdoor_THEN_pvs_update(self): for number, boundary, value in itertools.product( [1, 2], ["upper", "lower"], self.test_autozero_values ): - self._lewis.backdoor_set_on_device( - "autozero_{n}_{b}".format(n=number, b=boundary), value - ) + self._lewis.backdoor_set_on_device(f"autozero_{number}_{boundary}", value) self.ca.assert_that_pv_is_number( - "AUTOZERO:{n}:{b}".format(n=number, b=boundary.upper()), value, tolerance=0.05 + f"AUTOZERO:{number}:{boundary.upper()}", value, tolerance=0.05 ) self.ca.assert_that_pv_alarm_is( - "AUTOZERO:{n}:{b}".format(n=number, b=boundary.upper()), self.ca.Alarms.NONE + f"AUTOZERO:{number}:{boundary.upper()}", self.ca.Alarms.NONE ) @skip_if_recsim("In rec sim this test fails") @@ -256,28 +254,26 @@ def test_GIVEN_autozero_voltages_are_out_of_range_WHEN_chopper_is_moving_THEN_ra self._ioc, in_time=2, must_contain=ErrorStrings.CONTROLLER_AUTOZERO_OUT_OF_RANGE ): # Set autozero voltage too high - self._lewis.backdoor_set_on_device( - "autozero_{n}_{p}".format(n=number, p=position), 3.2 - ) + self._lewis.backdoor_set_on_device(f"autozero_{number}_{position}", 3.2) # Assert self.ca.assert_that_pv_is("AUTOZERO:RANGECHECK", 1) # Reset relevant autozero voltage back to zero - self._lewis.backdoor_set_on_device("autozero_{n}_{p}".format(n=number, p=position), 0) + self._lewis.backdoor_set_on_device(f"autozero_{number}_{position}", 0) self.ca.assert_that_pv_is_number( - "AUTOZERO:{n}:{p}".format(n=number, p=position.upper()), 0, tolerance=0.1 + f"AUTOZERO:{number}:{position.upper()}", 0, tolerance=0.1 ) @contextmanager def _lie_about(self, lie): if IOCRegister.uses_rec_sim: - raise IOError("Can't use lewis backdoor in recsim!") + raise OSError("Can't use lewis backdoor in recsim!") - self._lewis.backdoor_set_on_device("is_lying_about_{}".format(lie), True) + self._lewis.backdoor_set_on_device(f"is_lying_about_{lie}", True) try: yield finally: - self._lewis.backdoor_set_on_device("is_lying_about_{}".format(lie), False) + self._lewis.backdoor_set_on_device(f"is_lying_about_{lie}", False) def _lie_about_delay_setpoint_readback(self): return self._lie_about("delay_sp_rbv") @@ -440,16 +436,14 @@ def test_GIVEN_autozero_voltages_are_out_of_range_WHEN_chopper_is_moving_THEN_sw self._ioc, in_time=2, must_contain=ErrorStrings.SOFTWARE_AUTOZERO_OUT_OF_RANGE ): # Set autozero voltage too high and set device moving - self._lewis.backdoor_set_on_device( - "autozero_{n}_{p}".format(n=number, p=position), 3.2 - ) + self._lewis.backdoor_set_on_device(f"autozero_{number}_{position}", 3.2) self._lewis.backdoor_set_on_device("speed", 7) # Assert that "switch drive on and stop" was sent self.ca.assert_that_pv_is("LASTCOMMAND", "0001") # Reset relevant autozero voltage back to zero - self._lewis.backdoor_set_on_device("autozero_{n}_{p}".format(n=number, p=position), 0) + self._lewis.backdoor_set_on_device(f"autozero_{number}_{position}", 0) self.ca.assert_that_pv_is_number( - "AUTOZERO:{n}:{p}".format(n=number, p=position.upper()), 0, tolerance=0.1 + f"AUTOZERO:{number}:{position.upper()}", 0, tolerance=0.1 ) diff --git a/common_tests/instron_base.py b/common_tests/instron_base.py index 8aea92a0..17f3d76a 100644 --- a/common_tests/instron_base.py +++ b/common_tests/instron_base.py @@ -26,7 +26,7 @@ CHANNELS = {"Position": 1, "Stress": 2, "Strain": 3} -class InstronBase(object, metaclass=abc.ABCMeta): +class InstronBase(metaclass=abc.ABCMeta): """ Tests for the Instron IOC. """ @@ -36,7 +36,7 @@ def get_prefix(self): pass def add_prefix(self, prefix, root): - return "{0}:{1}".format(prefix, root) + return f"{prefix}:{root}" def wave_prefixed(self, val): return self.add_prefix("WAVE", val) @@ -137,9 +137,7 @@ def test_WHEN_the_rig_has_error_THEN_the_status_is_emergency_stop_pushed(self): self._lewis.backdoor_set_on_device("status", code_val) - self.ca.assert_that_pv_is( - "STAT:DISP", error, msg="code set {0} = {code_val}".format(code, code_val=code_val) - ) + self.ca.assert_that_pv_is("STAT:DISP", error, msg=f"code set {code} = {code_val}") self.ca.assert_that_pv_alarm_is("STAT:DISP", ChannelAccess.Alarms.MAJOR) def test_WHEN_the_rig_is_initialized_THEN_it_is_not_going(self): @@ -156,12 +154,12 @@ def test_that_the_rig_is_not_normally_in_control_mode(self): def test_WHEN_init_sequence_run_THEN_waveform_ramp_is_set_the_status_is_ok(self): for chan in POS_STRESS_STRAIN: - self.ca.set_pv_value("{0}:RAMP:WFTYP:SP".format(chan), 0) + self.ca.set_pv_value(f"{chan}:RAMP:WFTYP:SP", 0) self.ca.set_pv_value("INIT", 1) for chan in POS_STRESS_STRAIN: - self.ca.assert_that_pv_is("{0}:RAMP:WFTYP".format(chan), RAMP_WAVEFORM_TYPES[3]) + self.ca.assert_that_pv_is(f"{chan}:RAMP:WFTYP", RAMP_WAVEFORM_TYPES[3]) @skip_if_recsim("In rec sim this test fails") def test_WHEN_arbitrary_command_Q22_is_sent_THEN_the_response_is_a_status_code(self): @@ -188,7 +186,7 @@ def test_WHEN_control_channel_setpoint_is_requested_THEN_it_is_one_of_the_allowe def test_WHEN_the_control_channel_is_set_THEN_the_readback_contains_the_value_that_was_just_set( self, ): - for channel in CHANNELS.keys(): + for channel in CHANNELS: # change channel function contains the relevant assertions. self._change_channel(channel) @@ -488,10 +486,8 @@ def test_WHEN_waveform_type_abs_set_on_axes_THEN_all_axes_are_set(self): def _set_and_check(set_value, return_value): self.ca.set_pv_value("AXES:RAMP:WFTYP:SP", set_value) for chan in POS_STRESS_STRAIN: - self.ca.assert_that_pv_is("{0}:RAMP:WFTYP".format(chan), return_value) - self.ca.assert_that_pv_alarm_is( - "{0}:RAMP:WFTYP".format(chan), ChannelAccess.Alarms.NONE - ) + self.ca.assert_that_pv_is(f"{chan}:RAMP:WFTYP", return_value) + self.ca.assert_that_pv_alarm_is(f"{chan}:RAMP:WFTYP", ChannelAccess.Alarms.NONE) for set_value, return_value in enumerate(RAMP_WAVEFORM_TYPES): _set_and_check(set_value, return_value) @@ -509,7 +505,7 @@ def test_WHEN_channel_fails_check_THEN_channel_mbbi_record_is_invalid_and_has_ta self.ca.assert_that_pv_is("" + chan_name + ":TYPE:CHECK", "FAIL") self.ca.assert_that_pv_is( - "CHANNEL:SP.{}ST".format(index_as_name), "{0} - disabled".format(channel_as_name) + f"CHANNEL:SP.{index_as_name}ST", f"{channel_as_name} - disabled" ) self.ca.set_pv_value("CHANNEL:SP", index) @@ -530,10 +526,8 @@ def test_WHEN_channel_succeeds_check_THEN_channel_mbbi_record_is_invalid_and_has self.ca.assert_that_pv_is("" + chan_name + ":TYPE:CHECK", "PASS", timeout=30) - self.ca.assert_that_pv_is("CHANNEL:SP.{}ST".format(index_as_name), channel_as_name) - self.ca.assert_that_pv_is( - "CHANNEL:SP.{}SV".format(index_as_name), ChannelAccess.Alarms.NONE - ) + self.ca.assert_that_pv_is(f"CHANNEL:SP.{index_as_name}ST", channel_as_name) + self.ca.assert_that_pv_is(f"CHANNEL:SP.{index_as_name}SV", ChannelAccess.Alarms.NONE) self.ca.set_pv_value("CHANNEL:SP", index) self.ca.assert_that_pv_alarm_is("CHANNEL:SP", ChannelAccess.Alarms.NONE) @@ -679,7 +673,7 @@ def test_GIVEN_multiple_channels_WHEN_waveform_amplitude_is_set_THEN_the_device_ ] for i in range(len(conversion_factors)): - self.assertNotEqual(0, conversion_factors[i], "Factor {} was zero".format(i)) + self.assertNotEqual(0, conversion_factors[i], f"Factor {i} was zero") expected_values = [ input_values[i] / conversion_factors[i] for i in range(NUMBER_OF_CHANNELS) diff --git a/common_tests/kepco.py b/common_tests/kepco.py index f29a1854..160407f7 100644 --- a/common_tests/kepco.py +++ b/common_tests/kepco.py @@ -14,17 +14,17 @@ TEST_MODES = [TestModes.RECSIM, TestModes.DEVSIM] -class OutputMode(object): +class OutputMode: VOLTAGE = "VOLTAGE" CURRENT = "CURRENT" -class Status(object): +class Status: ON = "ON" OFF = "OFF" -class UnitFlags(object): +class UnitFlags: VOLTAGE = 0 CURRENT = 1 ON = 1 @@ -50,7 +50,7 @@ class UnitFlags(object): MAX_CURRENT = 1000 -class KepcoTests(object): +class KepcoTests: """ Tests for the KEPCO. """ @@ -73,7 +73,7 @@ def _write_current(self, expected_current): def _set_IDN(self, expected_idn_no_firmware, expected_firmware): self._lewis.backdoor_set_on_device("idn_no_firmware", expected_idn_no_firmware) self._lewis.backdoor_set_on_device("firmware", expected_firmware) - expected_idn = "{}{}".format(expected_idn_no_firmware, str(expected_firmware))[ + expected_idn = f"{expected_idn_no_firmware}{expected_firmware!s}"[ :39 ] # EPICS limited to 40 chars self._ioc.set_simulated_value("SIM:IDN", expected_idn) diff --git a/common_tests/moxa12XX.py b/common_tests/moxa12XX.py index 385f8ff6..2bcd788a 100644 --- a/common_tests/moxa12XX.py +++ b/common_tests/moxa12XX.py @@ -5,7 +5,7 @@ from utils.testing import get_running_lewis_and_ioc -class Moxa12XXBase(object, metaclass=ABCMeta): +class Moxa12XXBase(metaclass=ABCMeta): """ Tests for a moxa ioLogik e1240. (8x DC Voltage/Current measurements) """ @@ -97,7 +97,7 @@ def test_WHEN_an_AI_input_is_changed_THEN_that_channel_readback_updates(self): expected_value = self.SCALING_FACTOR * test_value self.ca.assert_that_pv_is_number( - "CH{:01d}:{PV}".format(channel, PV=self.get_PV_name()), + f"CH{channel:01d}:{self.get_PV_name()}", expected_value, tolerance=0.1 * abs(expected_value), ) @@ -116,13 +116,13 @@ def test_WHEN_device_voltage_is_within_user_limits_THEN_PV_shows_no_alarm(self): ) self.ca.assert_that_pv_is_number( - "CH{:01d}:{PV}".format(channel, PV=self.get_PV_name()), + f"CH{channel:01d}:{self.get_PV_name()}", expected_value, tolerance=0.1 * abs(expected_value), ) self.ca.assert_that_pv_alarm_is( - "CH{:01d}:{PV}".format(channel, PV=self.get_PV_name()), self.ca.Alarms.NONE + f"CH{channel:01d}:{self.get_PV_name()}", self.ca.Alarms.NONE ) def test_WHEN_device_voltage_is_outside_user_limits_THEN_PV_shows_major_alarm(self): @@ -139,13 +139,13 @@ def test_WHEN_device_voltage_is_outside_user_limits_THEN_PV_shows_major_alarm(se ) self.ca.assert_that_pv_is_number( - "CH{:01d}:{PV}".format(channel, PV=self.get_PV_name()), + f"CH{channel:01d}:{self.get_PV_name()}", expected_value, tolerance=0.1 * abs(expected_value), ) self.ca.assert_that_pv_alarm_is( - "CH{:01d}:{PV}".format(channel, PV=self.get_PV_name()), self.ca.Alarms.MAJOR + f"CH{channel:01d}:{self.get_PV_name()}", self.ca.Alarms.MAJOR ) def test_WHEN_a_channel_is_aliased_THEN_a_PV_with_that_alias_exists(self): diff --git a/common_tests/oscillating_collimators.py b/common_tests/oscillating_collimators.py index d9e1ba12..0e8d00c9 100644 --- a/common_tests/oscillating_collimators.py +++ b/common_tests/oscillating_collimators.py @@ -14,7 +14,7 @@ def _custom_name_func(testcase_func, param_num, param): return "{}_ang_{}_freq_{}_rad_{}".format(testcase_func.__name__, *param.args[0]) -class OscillatingCollimatorBase(object): +class OscillatingCollimatorBase: def test_WHEN_angle_set_negative_THEN_angle_is_zero(self): self.ca.set_pv_value(ANGLE, -1.0) self.ca.assert_that_pv_is_number(ANGLE, 0.0) diff --git a/common_tests/riken_changeover.py b/common_tests/riken_changeover.py index 9b8556ca..678cd01e 100644 --- a/common_tests/riken_changeover.py +++ b/common_tests/riken_changeover.py @@ -8,7 +8,7 @@ from contextlib2 import ExitStack # PY2 -class RikenChangeover(object, metaclass=ABCMeta): +class RikenChangeover(metaclass=ABCMeta): """ Tests for a riken changeover. @@ -37,17 +37,17 @@ def get_prefix(self): return "" def _set_input_pv(self, ok_to_run_psus): - self.ca.set_pv_value("{}:SIM".format(self.get_input_pv()), 1 if ok_to_run_psus else 0) - self.ca.assert_that_pv_is("{}:SIM".format(self.get_input_pv()), 1 if ok_to_run_psus else 0) - self.ca.assert_that_pv_alarm_is("{}".format(self.get_input_pv()), self.ca.Alarms.NONE) - self.ca.assert_that_pv_is("{}".format(self.get_input_pv()), 1 if ok_to_run_psus else 0) + self.ca.set_pv_value(f"{self.get_input_pv()}:SIM", 1 if ok_to_run_psus else 0) + self.ca.assert_that_pv_is(f"{self.get_input_pv()}:SIM", 1 if ok_to_run_psus else 0) + self.ca.assert_that_pv_alarm_is(f"{self.get_input_pv()}", self.ca.Alarms.NONE) + self.ca.assert_that_pv_is(f"{self.get_input_pv()}", 1 if ok_to_run_psus else 0) def _set_power_supply_state(self, supply, on): - self.ca.set_pv_value("{}:POWER:SP".format(supply), 1 if on else 0) - self.ca.assert_that_pv_is("{}:POWER".format(supply), "On" if on else "Off") + self.ca.set_pv_value(f"{supply}:POWER:SP", 1 if on else 0) + self.ca.assert_that_pv_is(f"{supply}:POWER", "On" if on else "Off") def _assert_power_supply_disabled(self, supply, disabled): - self.ca.assert_that_pv_is_number("{}:POWER:SP.DISP".format(supply), 1 if disabled else 0) + self.ca.assert_that_pv_is_number(f"{supply}:POWER:SP.DISP", 1 if disabled else 0) def _set_all_power_supply_states(self, on): for supply in self.get_power_supplies(): @@ -58,11 +58,11 @@ def _assert_all_power_supplies_disabled(self, disabled): self._assert_power_supply_disabled(supply, disabled) def _assert_necessary_pvs_exist(self): - self.ca.assert_that_pv_exists("{}:PSUS:DISABLE".format(self.get_coord_prefix())) + self.ca.assert_that_pv_exists(f"{self.get_coord_prefix()}:PSUS:DISABLE") self.ca.assert_that_pv_exists(self.get_input_pv()) self.ca.assert_that_pv_exists(self.get_acknowledgement_pv()) for id in self.get_power_supplies(): - self.ca.assert_that_pv_exists("{}:POWER".format(id)) + self.ca.assert_that_pv_exists(f"{id}:POWER") def setUp(self): self.ca = ChannelAccess(device_prefix=self.get_prefix(), default_timeout=10) @@ -81,7 +81,7 @@ def test_GIVEN_value_on_input_ioc_changes_THEN_coord_psus_disable_pv_updates_wit def _set_and_check(ok_to_run_psus): self._set_input_pv(ok_to_run_psus) self.ca.assert_that_pv_is( - "{}:PSUS:DISABLE".format(self.get_coord_prefix()), + f"{self.get_coord_prefix()}:PSUS:DISABLE", "ENABLED" if ok_to_run_psus else "DISABLED", ) @@ -101,14 +101,14 @@ def _set_and_check_disabled_status(ok_to_run_psus): def test_WHEN_any_power_supply_is_on_THEN_power_all_pv_is_high(self): self._set_all_power_supply_states(False) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 0) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 0) for psu in self.get_power_supplies(): self._set_power_supply_state(psu, True) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 1) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 1) self._set_power_supply_state(psu, False) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 0) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 0) def test_GIVEN_power_supplies_on_WHEN_value_on_input_ioc_changes_THEN_power_supplies_are_not_disabled_until_they_are_switched_off( self, @@ -133,14 +133,12 @@ def test_GIVEN_plc_cancels_changeover_before_psus_are_all_switched_off_WHEN_psus def test_GIVEN_a_power_supply_is_in_alarm_THEN_the_power_any_pv_is_also_in_alarm(self): for supply in self.get_power_supplies(): - with self.ca.put_simulated_record_into_alarm( - "{}:POWER".format(supply), self.ca.Alarms.INVALID - ): + with self.ca.put_simulated_record_into_alarm(f"{supply}:POWER", self.ca.Alarms.INVALID): self.ca.assert_that_pv_alarm_is( - "{}:PSUS:POWER".format(self.get_coord_prefix()), self.ca.Alarms.INVALID + f"{self.get_coord_prefix()}:PSUS:POWER", self.ca.Alarms.INVALID ) self.ca.assert_that_pv_alarm_is( - "{}:PSUS:POWER".format(self.get_coord_prefix()), self.ca.Alarms.NONE + f"{self.get_coord_prefix()}:PSUS:POWER", self.ca.Alarms.NONE ) def test_GIVEN_all_power_supply_are_in_alarm_THEN_the_power_any_pv_is_also_in_alarm(self): @@ -148,25 +146,23 @@ def test_GIVEN_all_power_supply_are_in_alarm_THEN_the_power_any_pv_is_also_in_al for supply in self.get_power_supplies(): stack.enter_context( self.ca.put_simulated_record_into_alarm( - "{}:POWER".format(supply), self.ca.Alarms.INVALID + f"{supply}:POWER", self.ca.Alarms.INVALID ) ) self.ca.assert_that_pv_alarm_is( - "{}:PSUS:POWER".format(self.get_coord_prefix()), self.ca.Alarms.INVALID + f"{self.get_coord_prefix()}:PSUS:POWER", self.ca.Alarms.INVALID ) self.ca.assert_that_pv_alarm_is( - "{}:PSUS:POWER".format(self.get_coord_prefix()), self.ca.Alarms.NONE + f"{self.get_coord_prefix()}:PSUS:POWER", self.ca.Alarms.NONE ) def test_GIVEN_a_power_supply_is_in_alarm_THEN_the_power_any_pv_reports_that_psus_are_active( self, ): for supply in self.get_power_supplies(): - with self.ca.put_simulated_record_into_alarm( - "{}:POWER".format(supply), self.ca.Alarms.INVALID - ): - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 1) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 0) + with self.ca.put_simulated_record_into_alarm(f"{supply}:POWER", self.ca.Alarms.INVALID): + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 1) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 0) def test_GIVEN_all_power_supply_are_in_alarm_THEN_the_power_any_pv_reports_that_psus_are_active( self, @@ -175,11 +171,11 @@ def test_GIVEN_all_power_supply_are_in_alarm_THEN_the_power_any_pv_reports_that_ for supply in self.get_power_supplies(): stack.enter_context( self.ca.put_simulated_record_into_alarm( - "{}:POWER".format(supply), self.ca.Alarms.INVALID + f"{supply}:POWER", self.ca.Alarms.INVALID ) ) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 1) - self.ca.assert_that_pv_is_number("{}:PSUS:POWER".format(self.get_coord_prefix()), 0) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 1) + self.ca.assert_that_pv_is_number(f"{self.get_coord_prefix()}:PSUS:POWER", 0) def test_GIVEN_changeover_initiated_WHEN_power_supplies_off_THEN_acknowledgement_pv_true(self): self._set_all_power_supply_states(False) diff --git a/common_tests/tpgx00.py b/common_tests/tpgx00.py index 5bce2b6f..a4045214 100644 --- a/common_tests/tpgx00.py +++ b/common_tests/tpgx00.py @@ -73,7 +73,7 @@ def tearDown(self): self._connect_emulator() def _set_pressure(self, expected_pressure, channel): - prop = "pressure_{}".format(channel.lower()) + prop = f"pressure_{channel.lower()}" pv = "SIM:PRESSURE" self._lewis.backdoor_set_on_device(prop, expected_pressure) self._ioc.set_simulated_value(pv, expected_pressure) @@ -141,7 +141,7 @@ def test_that_GIVEN_a_connected_emulator_WHEN_units_are_set_THEN_unit_is_the_sam def test_that_GIVEN_a_connected_emulator_and_pressure_value_WHEN_set_pressure_is_set_THEN_the_ioc_is_updated( self, _, expected_pressure, channel ): - pv = "PRESSURE_{}".format(channel) + pv = f"PRESSURE_{channel}" self._set_pressure(expected_pressure, channel) self.ca.assert_that_pv_is(pv, expected_pressure) @@ -150,7 +150,7 @@ def test_that_GIVEN_a_connected_emulator_and_pressure_value_WHEN_set_pressure_is def test_that_GIVEN_a_disconnected_emulator_WHEN_getting_pressure_THEN_INVALID_alarm_shows( self, _, channel ): - pv = "PRESSURE_{}".format(channel) + pv = f"PRESSURE_{channel}" self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.NONE) with self._disconnect_device(): self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.INVALID) diff --git a/common_tests/tpgx6x.py b/common_tests/tpgx6x.py index 527e3621..0cb19108 100644 --- a/common_tests/tpgx6x.py +++ b/common_tests/tpgx6x.py @@ -4,19 +4,19 @@ from utils.testing import get_running_lewis_and_ioc -class UnitFlags(object): +class UnitFlags: MBAR = 0 TORR = 1 PA = 2 -class UnitStrings(object): +class UnitStrings: MBAR = "mbar" TORR = "Torr" PA = "Pa" -class ErrorFlags(object): +class ErrorFlags: NO_ERROR = 0 UNDER_RANGE = 1 OVER_RANGE = 2 @@ -26,7 +26,7 @@ class ErrorFlags(object): IDENTIFICATION_ERROR = 6 -class ErrorStrings(object): +class ErrorStrings: NO_ERROR = "No Error" UNDER_RANGE = "Underrange" OVER_RANGE = "Overrange" @@ -36,7 +36,7 @@ class ErrorStrings(object): IDENTIFICATION_ERROR = "Identification Error" -class TpgBase(object, metaclass=abc.ABCMeta): +class TpgBase(metaclass=abc.ABCMeta): @abc.abstractmethod def get_prefix(self): pass @@ -54,14 +54,14 @@ def setUp(self): self.channels = 2 def _set_pressure(self, expected_pressure, channel): - pv = "SIM:{0:d}:PRESSURE".format(channel) - prop = "pressure%d" % channel + pv = f"SIM:{channel:d}:PRESSURE" + prop = f"pressure{channel}" self._lewis.backdoor_set_on_device(prop, expected_pressure) self._ioc.set_simulated_value(pv, expected_pressure) def _set_error(self, expected_error, channel): - pv = "SIM:{0:d}:ERROR".format(channel) - prop = "error%d" % channel + pv = f"SIM:{channel:d}:ERROR" + prop = f"error{channel}" self._lewis.backdoor_set_on_device(prop, expected_error) self._ioc.set_simulated_value(pv, expected_error) @@ -74,23 +74,23 @@ def test_GIVEN_pressure_set_WHEN_read_THEN_pressure_is_as_expected(self): expected_pressure = 1.23 self._set_pressure(expected_pressure, channel) - self.ca.assert_that_pv_is("{}:PRESSURE".format(channel), expected_pressure) - self.ca.assert_that_pv_alarm_is("{}:PRESSURE".format(channel), self.ca.Alarms.NONE) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), "No Error") + self.ca.assert_that_pv_is(f"{channel}:PRESSURE", expected_pressure) + self.ca.assert_that_pv_alarm_is(f"{channel}:PRESSURE", self.ca.Alarms.NONE) + self.ca.assert_that_pv_is(f"{channel}:ERROR", "No Error") def test_GIVEN_negative_pressure_set_WHEN_read_THEN_pressure_is_as_expected(self): for channel in range(1, self.channels + 1): expected_pressure = -123.34 self._set_pressure(expected_pressure, channel) - self.ca.assert_that_pv_is("{}:PRESSURE".format(channel), expected_pressure) + self.ca.assert_that_pv_is(f"{channel}:PRESSURE", expected_pressure) def test_GIVEN_pressure_with_no_decimal_places_set_WHEN_read_THEN_pressure_is_as_expected(self): for channel in range(1, self.channels + 1): expected_pressure = 7 self._set_pressure(expected_pressure, channel) - self.ca.assert_that_pv_is("{}:PRESSURE".format(channel), expected_pressure) + self.ca.assert_that_pv_is(f"{channel}:PRESSURE", expected_pressure) def test_GIVEN_pressure_under_range_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -99,8 +99,8 @@ def test_GIVEN_pressure_under_range_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MINOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_pressure_over_range_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -109,8 +109,8 @@ def test_GIVEN_pressure_over_range_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MINOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_pressure_sensor_error_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -119,8 +119,8 @@ def test_GIVEN_pressure_sensor_error_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MAJOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_pressure_sensor_off_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -129,8 +129,8 @@ def test_GIVEN_pressure_sensor_off_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MAJOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_pressure_no_sensor_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -139,8 +139,8 @@ def test_GIVEN_pressure_no_sensor_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MAJOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_pressure_identification_error_set_WHEN_read_THEN_error(self): for channel in range(1, self.channels + 1): @@ -149,8 +149,8 @@ def test_GIVEN_pressure_identification_error_set_WHEN_read_THEN_error(self): expected_alarm = self.ca.Alarms.MAJOR self._set_error(expected_error, channel) - self.ca.assert_that_pv_is("{}:ERROR".format(channel), expected_error_str) - self.ca.assert_that_pv_alarm_is("{}:ERROR".format(channel), expected_alarm) + self.ca.assert_that_pv_is(f"{channel}:ERROR", expected_error_str) + self.ca.assert_that_pv_alarm_is(f"{channel}:ERROR", expected_alarm) def test_GIVEN_units_set_WHEN_read_THEN_units_are_as_expected(self): expected_units = UnitFlags.PA diff --git a/common_tests/tti_common.py b/common_tests/tti_common.py index 56396014..d320cbc2 100644 --- a/common_tests/tti_common.py +++ b/common_tests/tti_common.py @@ -5,7 +5,7 @@ from utils.testing import skip_if_recsim -class TtiCommon(object, metaclass=abc.ABCMeta): +class TtiCommon(metaclass=abc.ABCMeta): @abc.abstractmethod def get_off_state_name(self): pass diff --git a/run_tests.py b/run_tests.py index caea511b..d66ed421 100644 --- a/run_tests.py +++ b/run_tests.py @@ -10,7 +10,6 @@ import sys import traceback import unittest -from typing import List import xmlrunner from genie_python.utilities import cleanup_subprocs_on_process_exit @@ -37,12 +36,12 @@ def clean_environment(): Cleans up the test environment between tests. """ autosave_directory = os.path.join(var_dir, "autosave") - files = glob.glob("{}/*SIM/*".format(autosave_directory)) + files = glob.glob(f"{autosave_directory}/*SIM/*") for autosave_file in files: try: os.remove(autosave_file) - except Exception as e: - print("Failed to delete {}: {}".format(autosave_file, e)) + except OSError as e: + print(f"Failed to delete {autosave_file}: {e}") def check_and_do_pre_ioc_launch_hook(ioc): @@ -59,7 +58,7 @@ def do_nothing(*args): if callable(pre_ioc_launch_hook): pre_ioc_launch_hook() else: - raise ValueError("Pre IOC launch hook not callable, so nothing has been done for it.") + raise TypeError("Pre IOC launch hook not callable, so nothing has been done for it.") def make_device_launchers_from_module(test_module, mode): @@ -78,7 +77,7 @@ def make_device_launchers_from_module(test_module, mode): iocs = test_module.IOCS except AttributeError: raise AttributeError( - "Expected module '{}' to contain an IOCS attribute".format(test_module.__name__) + f"Expected module '{test_module.__name__}' to contain an IOCS attribute" ) if len(iocs) < 1: @@ -94,7 +93,7 @@ def make_device_launchers_from_module(test_module, mode): "IOC entry must have a 'directory' attribute which should give the path to the IOC" ) - print("Testing module {} in {} mode.".format(test_module.__name__, TestModes.name(mode))) + print(f"Testing module {test_module.__name__} in {TestModes.name(mode)} mode.") device_launchers = [] device_directories = set() @@ -125,8 +124,8 @@ def make_device_launchers_from_module(test_module, mode): ) elif "emulators" in ioc and mode != TestModes.RECSIM: emulator_launcher_class = ioc.get("emulators_launcher_class", MultiLewisLauncher) - test_emulator_data: List[TestEmulatorData] = ioc.get("emulators", []) - emulator_list: List[Emulator] = [] + test_emulator_data: list[TestEmulatorData] = ioc.get("emulators", []) + emulator_list: list[Emulator] = [] for test_emulator in test_emulator_data: emulator_list.append( Emulator( @@ -267,10 +266,10 @@ def report_test_coverage_for_devices(tested_directories): """ # get names of iocs from ioc folder iocs = [] - for dir in os.listdir(IOCS_DIR): - if os.path.isdir(os.path.join(IOCS_DIR, dir)): - iocs.append(dir) - iocs = set(ioc.lower() for ioc in iocs) + for item in IOCS_DIR.iterdir(): + if item.is_dir(): + iocs.append(item.name) + iocs = {ioc.lower() for ioc in iocs} tested_iocs = [] for dir in tested_directories: @@ -315,9 +314,9 @@ def __init__(self, failing_module_name, msg): # strictly we should use and pass (*args, **kwargs) but we only call # this directly ourselves and not from a test suite. # We create a function based on fail_with_msg() to get a better test summary. - func_name = "{}_module_failed_to_load".format(failing_module_name) + func_name = f"{failing_module_name}_module_failed_to_load" setattr(self, func_name, self.fail_with_msg) - super(ReportFailLoadTestsuiteTestCase, self).__init__(func_name) + super().__init__(func_name) self.msg = msg def fail_with_msg(self): @@ -371,8 +370,8 @@ def run_tests( except KeyboardInterrupt: print("\nCleaning up...") sys.exit(0) - except Exception: - msg = "ERROR: while attempting to load test suite: {}".format(traceback.format_exc()) + except Exception: # noqa: BLE001 + msg = f"ERROR: while attempting to load test suite: {traceback.format_exc()}" result = runner.run(ReportFailLoadTestsuiteTestCase(module_name, msg)).wasSuccessful() return result @@ -474,7 +473,7 @@ def run_tests( arguments.tests_path = os.path.join(arguments.test_and_emulator, "tests") emulator_path = arguments.test_and_emulator else: - emulator_path = DEVICE_EMULATOR_PATH + emulator_path = str(DEVICE_EMULATOR_PATH) if os.path.dirname(arguments.tests_path): full_path = os.path.abspath(arguments.tests_path) @@ -529,7 +528,9 @@ def run_tests( # cygserver to cache this # we start it before cleanup_subprocs_on_process_exit() so it will # remain running as it takes a while to start and is safe to leave running - subprocess.run([os.path.join(EPICS_TOP, "tools", "master", "start_cygserver.bat")], shell=True) + subprocess.run( + [os.path.join(EPICS_TOP, "tools", "master", "start_cygserver.bat")], shell=True, check=False + ) # make sure we close any subprocesses we create when we exit cleanup_subprocs_on_process_exit() @@ -546,7 +547,7 @@ def run_tests( success = load_and_run_tests( tests, failfast, report_coverage, ask_before_running_tests, tests_mode ) - except Exception: + except Exception: # noqa: BLE001 print("---\n---\n---\nERROR: when loading the tests: ") traceback.print_exc() print("---\n---\n---\n") diff --git a/run_utils.py b/run_utils.py index 1501f6a5..1f881d16 100644 --- a/run_utils.py +++ b/run_utils.py @@ -1,15 +1,15 @@ import glob import importlib import os +from collections.abc import Generator from contextlib import contextmanager from types import ModuleType -from typing import Generator, List, Optional, Set from utils.build_architectures import BuildArchitectures from utils.test_modes import TestModes -def package_contents(package_path: str, filter_files: str) -> Set[str]: +def package_contents(package_path: str, filter_files: str) -> set[str]: """ Finds all the files in a package. @@ -17,13 +17,11 @@ def package_contents(package_path: str, filter_files: str) -> Set[str]: :param filter_files: glob format expression to filter files by :return: a set containing all the module names """ - return set( - [ - os.path.splitext(module)[0] - for module in glob.glob(filter_files, root_dir=package_path) - if module.endswith(".py") and not module.startswith("__init__") - ] - ) + return { + os.path.splitext(module)[0] + for module in glob.glob(filter_files, root_dir=package_path) + if module.endswith(".py") and not module.startswith("__init__") + } @contextmanager @@ -34,7 +32,7 @@ def modified_environment(**kwargs: str) -> Generator[None, None, None]: :param kwargs: the settings to apply """ # Copying old values - old_env = {name: os.environ.get(name, "") for name in kwargs.keys()} + old_env = {name: os.environ.get(name, "") for name in kwargs} # Apply new settings and then yield os.environ.update(kwargs) @@ -44,7 +42,7 @@ def modified_environment(**kwargs: str) -> Generator[None, None, None]: os.environ.update(old_env) -class ModuleTests(object): +class ModuleTests: """ Object which contains information about tests in a module to be run. @@ -58,7 +56,7 @@ class ModuleTests(object): def __init__(self, name: str) -> None: self.__name = name - self.tests: Optional[List[str]] = None + self.tests: list[str] | None = None self.__file = self.__get_file_reference() self.__modes = self.__get_modes() self.__architectures = self.__get_architectures() @@ -69,7 +67,7 @@ def name(self) -> str: return self.__name @property - def modes(self) -> Set[TestModes]: + def modes(self) -> set[TestModes]: """Returns the modes to run the tests in.""" return self.__modes @@ -79,20 +77,20 @@ def file(self) -> ModuleType: return self.__file @property - def architectures(self) -> Set[BuildArchitectures]: + def architectures(self) -> set[BuildArchitectures]: """Returns the architectures the test can be run in.""" return self.__architectures def __get_file_reference(self) -> ModuleType: - module = load_module("tests.{}".format(self.__name)) + module = load_module(f"tests.{self.__name}") return module - def __get_modes(self) -> Set[TestModes]: + def __get_modes(self) -> set[TestModes]: if not self.__file: self.__get_file_reference() return check_test_modes(self.__file) - def __get_architectures(self) -> Set[BuildArchitectures]: + def __get_architectures(self) -> set[BuildArchitectures]: if not self.__file: self.__get_file_reference() return check_build_architectures(self.__file) @@ -110,7 +108,7 @@ def load_module(name: str) -> ModuleType: ) -def check_test_modes(module: ModuleType) -> Set[TestModes]: +def check_test_modes(module: ModuleType) -> set[TestModes]: """ Checks for RECSIM and DEVSIM test modes. @@ -121,13 +119,13 @@ def check_test_modes(module: ModuleType) -> Set[TestModes]: modes = set(module.TEST_MODES) except AttributeError: raise ValueError( - "Expected test module {} to contain a TEST_MODES attribute".format(module.__name__) + f"Expected test module {module.__name__} to contain a TEST_MODES attribute" ) return modes -def check_build_architectures(module: ModuleType) -> Set[BuildArchitectures]: +def check_build_architectures(module: ModuleType) -> set[BuildArchitectures]: """ Checks for which build architectures the test can run in. If not specified, default to both 64 and 32 bit allowed. @@ -138,6 +136,6 @@ def check_build_architectures(module: ModuleType) -> Set[BuildArchitectures]: try: architectures = set(module.BUILD_ARCHITECTURES) except AttributeError: - architectures = set([BuildArchitectures._64BIT, BuildArchitectures._32BIT]) + architectures = {BuildArchitectures._64BIT, BuildArchitectures._32BIT} return architectures diff --git a/test_config/good_for_refl/galil01.cmd b/test_config/good_for_refl/galil01.cmd new file mode 100644 index 00000000..e5d7fc96 --- /dev/null +++ b/test_config/good_for_refl/galil01.cmd @@ -0,0 +1,24 @@ +## configure galil crate 1 + +## passed parameters +## GCID - galil crate software index. Numbering starts at 0 - will always be 0 if there is one to one galil crate <-> galil IOC mapping +## GALILADDR - address of this galil + +## see README_galil_cmd.txt for usage of commands below + +GalilCreateController("Galil", "127.0.0.1", 20) + +GalilCreateAxis("Galil","A",0,"",1) +GalilCreateAxis("Galil","B",0,"",1) +GalilCreateAxis("Galil","C",0,"",1) +GalilCreateAxis("Galil","D",0,"",1) +GalilCreateAxis("Galil","E",0,"",1) +GalilCreateAxis("Galil","F",0,"",1) +GalilCreateAxis("Galil","G",0,"",1) +GalilCreateAxis("Galil","H",0,"",1) + +$(IFNEWGALIL=#) GalilCreateCSAxes("Galil") + +GalilStartController("Galil","$(GALIL)/gmc/galil_Default_Header.gmc;$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc;$(GALIL)/gmc/galil_Default_Footer.gmc",0,0,3) + +$(IFNEWGALIL=#) GalilCreateProfile("Galil", 2000) diff --git a/test_config/good_for_refl/galil02.cmd b/test_config/good_for_refl/galil02.cmd new file mode 100644 index 00000000..6e294338 --- /dev/null +++ b/test_config/good_for_refl/galil02.cmd @@ -0,0 +1,24 @@ +## configure galil crate 2 + +## passed parameters +## GCID - galil crate software index. Numbering starts at 0 - will always be 0 if there is one to one galil crate <-> galil IOC mapping +## GALILADDR - address of this galil + +## see README_galil_cmd.txt for usage of commands below + +GalilCreateController("Galil", "127.0.0.1", 20) + +GalilCreateAxis("Galil","A",0,"",1) +GalilCreateAxis("Galil","B",0,"",1) +GalilCreateAxis("Galil","C",0,"",1) +GalilCreateAxis("Galil","D",0,"",1) +GalilCreateAxis("Galil","E",0,"",1) +GalilCreateAxis("Galil","F",0,"",1) +GalilCreateAxis("Galil","G",0,"",1) +GalilCreateAxis("Galil","H",0,"",1) + +$(IFNEWGALIL=#) GalilCreateCSAxes("Galil") + +GalilStartController("Galil","$(GALIL)/gmc/galil_Default_Header.gmc;$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc;$(GALIL)/gmc/galil_Default_Footer.gmc",0,0,3) + +$(IFNEWGALIL=#) GalilCreateProfile("Galil", 2000) diff --git a/test_config/good_for_refl/galil03.cmd b/test_config/good_for_refl/galil03.cmd new file mode 100644 index 00000000..423335f9 --- /dev/null +++ b/test_config/good_for_refl/galil03.cmd @@ -0,0 +1,24 @@ +## configure galil crate 3 + +## passed parameters +## GCID - galil crate software index. Numbering starts at 0 - will always be 0 if there is one to one galil crate <-> galil IOC mapping +## GALILADDR - address of this galil + +## see README_galil_cmd.txt for usage of commands below + +GalilCreateController("Galil", "127.0.0.1", 20) + +GalilCreateAxis("Galil","A",0,"",1) +GalilCreateAxis("Galil","B",0,"",1) +GalilCreateAxis("Galil","C",0,"",1) +GalilCreateAxis("Galil","D",0,"",1) +GalilCreateAxis("Galil","E",0,"",1) +GalilCreateAxis("Galil","F",0,"",1) +GalilCreateAxis("Galil","G",0,"",1) +GalilCreateAxis("Galil","H",0,"",1) + +$(IFNEWGALIL=#) GalilCreateCSAxes("Galil") + +GalilStartController("Galil","$(GALIL)/gmc/galil_Default_Header.gmc;$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc!$(GALIL)/gmc/galil_Home_Dummy_Do_Nothing.gmc!$(GALIL)/gmc/galil_Home_No_Home.gmc;$(GALIL)/gmc/galil_Default_Footer.gmc",0,0,3) + +$(IFNEWGALIL=#) GalilCreateProfile("Galil", 2000) diff --git a/tests/CAENv895.py b/tests/CAENv895.py index a0b15164..7876f8f7 100644 --- a/tests/CAENv895.py +++ b/tests/CAENv895.py @@ -1,5 +1,3 @@ -from __future__ import division - import os import unittest @@ -89,10 +87,10 @@ def test_GIVEN_ioc_WHEN_startup_complete_THEN_defaults_loaded(self): self.ca.assert_that_pv_is("CR0:C0:CH3:THOLD:SP", 75) self.ca.assert_that_pv_is("CR0:C1:CH0:ENABLE:SP", "YES") self.ca_np.assert_that_pv_is( - "AS:{}:vmeconfigMenu:currName".format(DEVICE_PREFIX), "ioctestdefaults" + f"AS:{DEVICE_PREFIX}:vmeconfigMenu:currName", "ioctestdefaults" ) - self.ca_np.assert_that_pv_is("AS:{}:vmeconfigMenu:status".format(DEVICE_PREFIX), "Success") - self.ca_np.assert_that_pv_is("AS:{}:vmeconfigMenu:busy".format(DEVICE_PREFIX), "Done") + self.ca_np.assert_that_pv_is(f"AS:{DEVICE_PREFIX}:vmeconfigMenu:status", "Success") + self.ca_np.assert_that_pv_is(f"AS:{DEVICE_PREFIX}:vmeconfigMenu:busy", "Done") def test_GIVEN_output_widths_WHEN_output_widths_set_THEN_width_read_back(self): # GIVEN diff --git a/tests/DAQmx.py b/tests/DAQmx.py index 95325c3b..cdc40f96 100644 --- a/tests/DAQmx.py +++ b/tests/DAQmx.py @@ -1,4 +1,3 @@ -import os import unittest from common_tests.DAQmx import DEVICE_PREFIX, ICPCONFIGNAME, DAQmxTests @@ -11,9 +10,9 @@ { "name": DEVICE_PREFIX, "icpconfigname": ICPCONFIGNAME, - "directory": os.path.join( - EPICS_TOP, "support", "DAQmxBase", "master", "iocBoot", "iocDAQmx" - ), + "directory": ( + EPICS_TOP / "support" / "DAQmxBase" / "master" / "iocBoot" / "iocDAQmx" + ).as_posix(), "emulator": DEVICE_PREFIX, "emulator_launcher_class": DAQMxEmulatorLauncher, "pv_for_existence": "ACQUIRE", @@ -34,7 +33,7 @@ def test_WHEN_acquire_called_THEN_data_gathered_and_is_changing(self): self.ca.set_pv_value("ACQUIRE", 1) def non_zero_data(data): - return all([d != 0.0 for d in data]) + return all(d != 0.0 for d in data) self.ca.assert_that_pv_value_causes_func_to_return_true("DATA", non_zero_data) self.ca.assert_that_pv_value_is_changing("DATA", 1) diff --git a/tests/DAQmx_monster.py b/tests/DAQmx_monster.py index 9dc039ed..c7a6a21b 100644 --- a/tests/DAQmx_monster.py +++ b/tests/DAQmx_monster.py @@ -1,4 +1,3 @@ -import os import unittest from common_tests.DAQmx import DEVICE_PREFIX, ICPCONFIGNAME, DAQmxTests @@ -11,9 +10,9 @@ { "name": DEVICE_PREFIX, "icpconfigname": ICPCONFIGNAME, - "directory": os.path.join( - EPICS_TOP, "support", "DAQmxBase", "master", "iocBoot", "iocDAQmx" - ), + "directory": ( + EPICS_TOP / "support" / "DAQmxBase" / "master" / "iocBoot" / "iocDAQmx" + ).as_posix(), "emulator": DEVICE_PREFIX, "emulator_launcher_class": DAQMxEmulatorLauncher, "pv_for_existence": "ACQUIRE", @@ -34,5 +33,3 @@ class DAQmxMonsterTests(DAQmxTests, unittest.TestCase): """ Test all DAQMx tests using monster mode. """ - - pass diff --git a/tests/axis.py b/tests/axis.py index 07d856cb..4e9f4b6d 100644 --- a/tests/axis.py +++ b/tests/axis.py @@ -1,13 +1,15 @@ import unittest from utils.channel_access import ChannelAccess -from utils.ioc_launcher import get_default_ioc_dir +from utils.ioc_launcher import EPICS_TOP, get_default_ioc_dir from utils.test_modes import TestModes GALIL_ADDR = "127.0.0.11" GALIL_PREFIX = "GALIL_01" +test_path = EPICS_TOP / "support" / "motorExtensions" / "master" / "settings" / "jaws_manager" + IOCS = [ { "name": GALIL_PREFIX, @@ -17,6 +19,7 @@ "macros": { "GALILADDR": GALIL_ADDR, "MTRCTRL": "1", + "GALILCONFIGDIR": test_path.as_posix(), }, } ] @@ -64,25 +67,25 @@ def test_GIVEN_both_retry_deadband_and_setpoint_deadband_are_explicitly_set_WHEN def test_GIVEN_neither_retry_not_setpoint_deadbands_set_and_mres_bigger_than_eres_WHEN_checking_tolerance_WHEN_checking_tolerance_THEN_mres_times_ten_is_used( self, ): - MRES = 456 - ERES = 123 - self.ca.set_pv_value("MTR0101.MRES", MRES, sleep_after_set=0) - self.ca.set_pv_value("MTR0101.ERES", ERES, sleep_after_set=0) + mres = 456 + eres = 123 + self.ca.set_pv_value("MTR0101.MRES", mres, sleep_after_set=0) + self.ca.set_pv_value("MTR0101.ERES", eres, sleep_after_set=0) # RDBD can not be less than MRES, if it is the same as MRES that means unset - self.ca.set_pv_value("MTR0101.RDBD", MRES, sleep_after_set=0) + self.ca.set_pv_value("MTR0101.RDBD", mres, sleep_after_set=0) self.ca.set_pv_value("MTR0101.SPDB", 0, sleep_after_set=0) - self.ca.assert_that_pv_is("MTR0101:IN_POSITION:TOLERANCE", MRES * 10) + self.ca.assert_that_pv_is("MTR0101:IN_POSITION:TOLERANCE", mres * 10) def test_GIVEN_neither_retry_not_setpoint_deadbands_set_and_mres_smaller_than_eres_WHEN_checking_tolerance_WHEN_checking_tolerance_THEN_eres_times_ten_is_used( self, ): - MRES = 456 - ERES = 789 - self.ca.set_pv_value("MTR0101.MRES", MRES, sleep_after_set=0) - self.ca.set_pv_value("MTR0101.ERES", ERES, sleep_after_set=0) + mres = 456 + eres = 789 + self.ca.set_pv_value("MTR0101.MRES", mres, sleep_after_set=0) + self.ca.set_pv_value("MTR0101.ERES", eres, sleep_after_set=0) # RDBD can not be less than MRES, if it is the same as MRES that means unset - self.ca.set_pv_value("MTR0101.RDBD", MRES, sleep_after_set=0) + self.ca.set_pv_value("MTR0101.RDBD", mres, sleep_after_set=0) self.ca.set_pv_value("MTR0101.SPDB", 0, sleep_after_set=0) - self.ca.assert_that_pv_is("MTR0101:IN_POSITION:TOLERANCE", ERES * 10) + self.ca.assert_that_pv_is("MTR0101:IN_POSITION:TOLERANCE", eres * 10) diff --git a/tests/cryosms.py b/tests/cryosms.py index d3126e75..d37c0960 100644 --- a/tests/cryosms.py +++ b/tests/cryosms.py @@ -7,7 +7,7 @@ from utils.channel_access import ChannelAccess from utils.emulator_launcher import EmulatorLauncher -from utils.ioc_launcher import BaseLauncher, IOCRegister, get_default_ioc_dir +from utils.ioc_launcher import EPICS_TOP, BaseLauncher, IOCRegister, get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc, parameterized_list, skip_if_recsim @@ -34,7 +34,9 @@ def local_cryosms_pv(pv): "MAX_VOLT": 9.9, "WRITE_UNIT": "TESLA", "DISPLAY_UNIT": "TESLA", - "RAMP_FILE": r"C:\\Instrument\\Apps\\EPICS\\support\\cryosms\\master\\ramps\\test.txt", + "RAMP_FILE": ( + EPICS_TOP / "support" / "cryosms" / "master" / "ramps" / "test.txt" + ).as_posix(), "MID_TOLERANCE": 0.1, "TARGET_TOLERANCE": 0.01, "ALLOW_PERSIST": "Yes", @@ -141,19 +143,19 @@ def test_GIVEN_certain_macros_WHEN_IOC_loads_THEN_correct_values_initialised(sel "RAMP:LEADS.DISP": "0", } failed_pvs = [] - for pv in expected_values: + for pv, value in expected_values.items(): try: - if type(expected_values[pv]) in [int, float]: + if type(value) in [int, float]: self.ca.assert_that_pv_is_within_range( - pv, expected_values[pv] - 0.01, expected_values[pv] + 0.01, timeout=5 + pv, value - 0.01, value + 0.01, timeout=5 ) else: - self.ca.assert_that_pv_is(pv, expected_values[pv], timeout=5) - except Exception as e: + self.ca.assert_that_pv_is(pv, value, timeout=5) + except Exception as e: # noqa: BLE001 if hasattr(e, "message"): failed_pvs.append(f"{pv} {e.message}") # pyright: ignore else: - failed_pvs.append(f"{pv} {repr(e)}") + failed_pvs.append(f"{pv} {e!r}") if failed_pvs: self.fail("The following PVs generated errors:\n{}".format("\n".join(failed_pvs))) @@ -193,9 +195,7 @@ def test_GIVEN_psu_at_field_strength_A_WHEN_told_to_ramp_to_B_THEN_correct_rates output = self.ca.get_pv_value("OUTPUT") else: self.fail( - "Output failed to reach mid-point, was {0}G but expected {1}G".format( - output, mid_point - ) + f"Output failed to reach mid-point, was {output}G but expected {mid_point}G" ) self.ca.assert_that_pv_is("RAMP:STAT", "HOLDING ON TARGET", timeout=120) self.ca.assert_that_pv_is_within_range("OUTPUT", end_point - 0.01, end_point + 0.01) diff --git a/tests/cybaman.py b/tests/cybaman.py index b8254fab..a01223b5 100644 --- a/tests/cybaman.py +++ b/tests/cybaman.py @@ -29,20 +29,19 @@ class CybamanTests(unittest.TestCase): Tests for the cybaman IOC. """ - AXES = ["A", "B", "C"] - test_positions = [-200, -1.23, 0, 180.0] - def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc(EMULATOR_DEVICE, DEVICE_PREFIX) self.ca = ChannelAccess(default_timeout=20, device_prefix=DEVICE_PREFIX) self.ca.assert_that_pv_exists("INITIALIZE", timeout=30) + self.AXES = ["A", "B", "C"] + self.test_positions = [-200, -1.23, 0, 180.0] self._lewis.backdoor_set_on_device("connected", True) # Check that all the relevant PVs are up. for axis in self.AXES: self.ca.assert_that_pv_exists(axis) - self.ca.assert_that_pv_exists("{}:SP".format(axis)) + self.ca.assert_that_pv_exists(f"{axis}:SP") # Initialize the device, do this in setup to avoid doing it in every test self.ca.set_pv_value("INITIALIZE", 1) @@ -57,18 +56,16 @@ def test_WHEN_position_setpoints_are_set_via_backdoor_THEN_positions_move_toward ): for axis in self.AXES: for pos in self.test_positions: - self._lewis.backdoor_set_on_device("{}_setpoint".format(axis.lower()), pos) - self.ca.assert_that_pv_is_number("{}".format(axis), pos, tolerance=0.01) + self._lewis.backdoor_set_on_device(f"{axis.lower()}_setpoint", pos) + self.ca.assert_that_pv_is_number(f"{axis}", pos, tolerance=0.01) @skip_if_recsim("Uses lewis backdoor command") def test_GIVEN_home_position_is_set_WHEN_home_pv_is_set_THEN_position_moves_towards_home(self): for axis in self.AXES: for pos in self.test_positions: - self._lewis.backdoor_set_on_device( - "home_position_axis_{}".format(axis.lower()), pos - ) - self.ca.set_pv_value("{}:HOME".format(axis), 1) - self.ca.assert_that_pv_is_number("{}".format(axis), pos, tolerance=0.01) + self._lewis.backdoor_set_on_device(f"home_position_axis_{axis.lower()}", pos) + self.ca.set_pv_value(f"{axis}:HOME", 1) + self.ca.assert_that_pv_is_number(f"{axis}", pos, tolerance=0.01) @skip_if_recsim("Uses lewis backdoor command") def test_GIVEN_a_device_in_some_other_state_WHEN_reset_command_is_sent_THEN_device_is_reset_to_original_state( @@ -85,16 +82,16 @@ def test_GIVEN_a_device_in_some_other_state_WHEN_reset_command_is_sent_THEN_devi original = {} for axis in self.AXES: - original[axis] = float(self.ca.get_pv_value("{}".format(axis.upper()))) + original[axis] = float(self.ca.get_pv_value(f"{axis.upper()}")) # Set both value and setpoint to avoid the device moving back towards the setpoint self._lewis.backdoor_set_on_device( - "{}_setpoint".format(axis.lower()), original[axis] + modifier + f"{axis.lower()}_setpoint", original[axis] + modifier ) - self._lewis.backdoor_set_on_device("{}".format(axis.lower()), original[axis] + modifier) + self._lewis.backdoor_set_on_device(f"{axis.lower()}", original[axis] + modifier) self.ca.assert_that_pv_is_number( - "{}".format(axis.upper()), original[axis] + modifier, tolerance=0.001 + f"{axis.upper()}", original[axis] + modifier, tolerance=0.001 ) # Reset cybaman @@ -102,17 +99,15 @@ def test_GIVEN_a_device_in_some_other_state_WHEN_reset_command_is_sent_THEN_devi # Check that a, b and c values are now at original values for axis in self.AXES: - self.ca.assert_that_pv_is_number( - "{}".format(axis.upper()), original[axis], tolerance=0.001 - ) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", original[axis], tolerance=0.001) def test_GIVEN_a_device_in_initialized_state_WHEN_setpoints_are_sent_THEN_device_goes_to_setpoint( self, ): for axis in self.AXES: for pos in self.test_positions: - self.ca.set_pv_value("{}:SP".format(axis.upper()), pos) - self.ca.assert_that_pv_is_number("{}".format(axis.upper()), pos) + self.ca.set_pv_value(f"{axis.upper()}:SP", pos) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", pos) @skip_if_recsim("Uses lewis backdoor command") def test_GIVEN_a_device_with_a_setpoint_less_than_minus_150_WHEN_homed_THEN_setpoint_is_set_to_minus_150_before_home( @@ -120,20 +115,20 @@ def test_GIVEN_a_device_with_a_setpoint_less_than_minus_150_WHEN_homed_THEN_setp ): for axis in self.AXES: # Ensure home position is known - self._lewis.backdoor_set_on_device("home_position_axis_{}".format(axis.lower()), 100) + self._lewis.backdoor_set_on_device(f"home_position_axis_{axis.lower()}", 100) # Ensure setpoint and readback are less than -150 - self.ca.set_pv_value("{}:SP".format(axis.upper()), -155) - self.ca.assert_that_pv_is_number("{}".format(axis.upper()), -155, tolerance=0.01) + self.ca.set_pv_value(f"{axis.upper()}:SP", -155) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", -155, tolerance=0.01) # Tell axis to home - self.ca.set_pv_value("{}:HOME".format(axis.upper()), 1) + self.ca.set_pv_value(f"{axis.upper()}:HOME", 1) # Ensure that setpoint is updated to -150 before home - self.ca.assert_that_pv_is_number("{}:SP".format(axis.upper()), -150, tolerance=0.01) + self.ca.assert_that_pv_is_number(f"{axis.upper()}:SP", -150, tolerance=0.01) # Let device actually reach home position - self.ca.assert_that_pv_is_number("{}".format(axis.upper()), 100) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", 100) @skip_if_recsim("Uses lewis backdoor command") def test_GIVEN_a_device_with_a_setpoint_more_than_minus_150_WHEN_homed_THEN_setpoint_is_not_set_before_home( @@ -141,20 +136,20 @@ def test_GIVEN_a_device_with_a_setpoint_more_than_minus_150_WHEN_homed_THEN_setp ): for axis in self.AXES: # Ensure home position is known - self._lewis.backdoor_set_on_device("home_position_axis_{}".format(axis.lower()), 100) + self._lewis.backdoor_set_on_device(f"home_position_axis_{axis.lower()}", 100) # Ensure setpoint and readback are more than -150 - self.ca.set_pv_value("{}:SP".format(axis.upper()), -145) - self.ca.assert_that_pv_is_number("{}".format(axis.upper()), -145, tolerance=0.01) + self.ca.set_pv_value(f"{axis.upper()}:SP", -145) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", -145, tolerance=0.01) # Tell axis to home - self.ca.set_pv_value("{}:HOME".format(axis.upper()), 1) + self.ca.set_pv_value(f"{axis.upper()}:HOME", 1) # Ensure that setpoint has not been updated - self.ca.assert_that_pv_is_number("{}:SP".format(axis.upper()), -145, tolerance=0.01) + self.ca.assert_that_pv_is_number(f"{axis.upper()}:SP", -145, tolerance=0.01) # Let device actually reach home position - self.ca.assert_that_pv_is_number("{}".format(axis.upper()), 100) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", 100) def test_GIVEN_a_device_at_a_specific_position_WHEN_setpoint_is_updated_THEN_tm_val_is_calculated_correctly( self, @@ -193,10 +188,8 @@ def test_GIVEN_a_device_at_a_specific_position_WHEN_setpoint_is_updated_THEN_tm_ for case in test_cases: # Ensure original position is what it's meant to be for axis, setpoint in zip(self.AXES, case["old_pos"]): - self.ca.set_pv_value("{}:SP".format(axis.upper()), setpoint) - self.ca.assert_that_pv_is_number( - "{}".format(axis.upper()), setpoint, tolerance=0.01 - ) + self.ca.set_pv_value(f"{axis.upper()}:SP", setpoint) + self.ca.assert_that_pv_is_number(f"{axis.upper()}", setpoint, tolerance=0.01) # Change the relevant axis to a new setpoint self.ca.set_pv_value( @@ -233,8 +226,8 @@ def test_GIVEN_one_axis_is_homed_WHEN_another_axis_has_its_setpoint_set_THEN_the ): # Put all setpoints to zero for axis in self.AXES: - self.ca.set_pv_value("{}:SP".format(axis.upper()), 0) - self.ca.assert_that_pv_is("{}".format(axis.upper()), 0) + self.ca.set_pv_value(f"{axis.upper()}:SP", 0) + self.ca.assert_that_pv_is(f"{axis.upper()}", 0) self.ca.set_pv_value("A:HOME", 1) # Wait for homing to start diff --git a/tests/danfysik_calibrated.py b/tests/danfysik_calibrated.py index f75680a6..55d43931 100644 --- a/tests/danfysik_calibrated.py +++ b/tests/danfysik_calibrated.py @@ -40,7 +40,7 @@ class DanfysikCalibratedTests(DanfysikCommon, unittest.TestCase): """ def setUp(self): - super(DanfysikCalibratedTests, self).setUp() + super().setUp() self.current_readback_factor = read_scale_factor self.ca.set_pv_value("FIELD:SP", 0) self._lewis.backdoor_run_function_on_device("set_current_read_factor", [read_scale_factor]) @@ -53,10 +53,10 @@ def test_GIVEN_asymmetric_read_and_write_WHEN_setting_current_THEN_current_rbv_a ): expected = 100 for id_prefix in self.id_prefixes: - self.ca.set_pv_value("{}CURR:SP".format(id_prefix), expected) + self.ca.set_pv_value(f"{id_prefix}CURR:SP", expected) - self.ca.assert_that_pv_is_number("{}CURR".format(id_prefix), expected) - self.ca.assert_that_pv_is_number("{}CURR:SP:RBV".format(id_prefix), expected) + self.ca.assert_that_pv_is_number(f"{id_prefix}CURR", expected) + self.ca.assert_that_pv_is_number(f"{id_prefix}CURR:SP:RBV", expected) def test_GIVEN_asymmetric_read_and_write_WHEN_setting_field_THEN_rbv_and_sp_rbv_and_percent_are_correct( self, @@ -65,17 +65,17 @@ def test_GIVEN_asymmetric_read_and_write_WHEN_setting_field_THEN_rbv_and_sp_rbv_ expected = 10000 expected_percent = 100.0 / max_raw_setpoint * expected for id_prefix in self.id_prefixes: - self.ca.set_pv_value("{}FIELD:SP".format(id_prefix), expected) + self.ca.set_pv_value(f"{id_prefix}FIELD:SP", expected) - self.ca.assert_that_pv_is_number("{}FIELD".format(id_prefix), expected) - self.ca.assert_that_pv_is_number("{}FIELD:SP:RBV".format(id_prefix), expected) - self.ca.assert_that_pv_is_number("{}RAW:PERCENT".format(id_prefix), expected_percent) + self.ca.assert_that_pv_is_number(f"{id_prefix}FIELD", expected) + self.ca.assert_that_pv_is_number(f"{id_prefix}FIELD:SP:RBV", expected) + self.ca.assert_that_pv_is_number(f"{id_prefix}RAW:PERCENT", expected_percent) def test_GIVEN_asymmetric_read_and_write_WHEN_setting_field_THEN_curr_is_correct(self): # default scaling field:raw is 1:1 field_to_set = 10000 expected = field_to_set / write_scale_factor for id_prefix in self.id_prefixes: - self.ca.set_pv_value("{}FIELD:SP".format(id_prefix), field_to_set) + self.ca.set_pv_value(f"{id_prefix}FIELD:SP", field_to_set) - self.ca.assert_that_pv_is_number("{}CURR".format(id_prefix), expected) + self.ca.assert_that_pv_is_number(f"{id_prefix}CURR", expected) diff --git a/tests/danfysik_common_calib.py b/tests/danfysik_common_calib.py index 939111bb..9f9aefa2 100644 --- a/tests/danfysik_common_calib.py +++ b/tests/danfysik_common_calib.py @@ -36,8 +36,8 @@ class DanfysikCommonCalibTests(DanfysikBase, unittest.TestCase): def test_GIVEN_local_calib_macro_set_to_no_THEN_calib_base_dir_is_common_dir(self): for pv in ["FIELD:CALIB", "FIELD:SP:CALIB"]: - self.ca.assert_that_pv_is("{}.TDIR".format(pv), r"magnets") - self.ca.assert_that_pv_is("{}.BDIR".format(pv), r"C:/Instrument/Settings/config/common") + self.ca.assert_that_pv_is(f"{pv}.TDIR", r"magnets") + self.ca.assert_that_pv_is(f"{pv}.BDIR", r"C:/Instrument/Settings/config/common") def test_GIVEN_a_requested_current_which_is_too_big_WHEN_calibrated_THEN_current_setpoint_sent_to_danfysik_is_not_bigger_than_max( self, diff --git a/tests/danfysik_local_calib.py b/tests/danfysik_local_calib.py index cdcd3863..09bfa3aa 100644 --- a/tests/danfysik_local_calib.py +++ b/tests/danfysik_local_calib.py @@ -29,7 +29,5 @@ def test_GIVEN_local_calib_macro_set_to_no_THEN_calib_base_dir_is_common_dir(sel g.set_instrument(None) inst = os.environ.get("INSTRUMENT", g.adv.get_instrument()) for pv in ["FIELD:CALIB", "FIELD:SP:CALIB"]: - self.ca.assert_that_pv_is("{}.TDIR".format(pv), r"calib/magnets") - self.ca.assert_that_pv_is( - "{}.BDIR".format(pv), r"C:/Instrument/Settings/config/{}".format(inst) - ) + self.ca.assert_that_pv_is(f"{pv}.TDIR", r"calib/magnets") + self.ca.assert_that_pv_is(f"{pv}.BDIR", rf"C:/Instrument/Settings/config/{inst}") diff --git a/tests/dma4500m.py b/tests/dma4500m.py index 93bf3330..bf99699e 100644 --- a/tests/dma4500m.py +++ b/tests/dma4500m.py @@ -31,9 +31,6 @@ class DMA4500MTests(unittest.TestCase): Tests for the DMA4500M density meter """ - PVS_ENABLED_OUTSIDE_MEASUREMENT = ["TEMPERATURE:SP", "START"] - PVS_DISABLED_DURING_MEASUREMENT = ["TEMPERATURE:SP", "START", "AUTOMEASURE"] - def _reset_ioc(self): self.ca.set_pv_value("MEASUREMENT", "ready") self.ca.set_pv_value("TEMPERATURE", 0) @@ -47,15 +44,14 @@ def _assert_pvs_disabled(self, pvs, disabled): for pv in pvs: self.ca.process_pv(pv) if disabled: - self.ca.assert_that_pv_is("{0}.STAT".format(pv), "DISABLE") + self.ca.assert_that_pv_is(f"{pv}.STAT", "DISABLE") else: - self.ca.assert_that_pv_is_not("{0}.STAT".format(pv), "DISABLE") + self.ca.assert_that_pv_is_not(f"{pv}.STAT", "DISABLE") def _start_instant_measurement(self): self._start_measurement(0) def _start_measurement(self, measurement_time=10): - measurement_time = measurement_time self._lewis.backdoor_set_on_device("measurement_time", measurement_time * LEWIS_SPEED) self.ca.set_pv_value("START", 1) @@ -67,6 +63,8 @@ def _disable_automeasure(self): self.ca.set_pv_value("AUTOMEASURE:ENABLED", 0) def setUp(self): + self.PVS_ENABLED_OUTSIDE_MEASUREMENT = ["TEMPERATURE:SP", "START"] + self.PVS_DISABLED_DURING_MEASUREMENT = ["TEMPERATURE:SP", "START", "AUTOMEASURE"] self._lewis, self._ioc = get_running_lewis_and_ioc(_EMULATOR_NAME, DEVICE_PREFIX) self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX, default_timeout=15) self._lewis.backdoor_run_function_on_device("reset") diff --git a/tests/egxcolim.py b/tests/egxcolim.py index d7d61c01..7c142a62 100644 --- a/tests/egxcolim.py +++ b/tests/egxcolim.py @@ -24,10 +24,9 @@ class EgxcolimTests(unittest.TestCase): Tests for the egxcolim IOC. """ - directions = ["NORTH", "SOUTH"] - axes = ["X"] - def setUp(self): + self.directions = ["NORTH", "SOUTH"] + self.axes = ["X"] self._ioc = IOCRegister.get_running(DEVICE_PREFIX) self.ca = ChannelAccess(20, device_prefix=DEVICE_PREFIX) @@ -39,6 +38,4 @@ def test_WHEN_ioc_is_started_THEN_ioc_is_not_disabled(self): def test_WHEN_setpoint_is_set_THEN_readback_updates(self): for direction in self.directions: for axis in self.axes: - self.ca.assert_setting_setpoint_sets_readback( - 123, "{direction}:{axis}".format(direction=direction, axis=axis) - ) + self.ca.assert_setting_setpoint_sets_readback(123, f"{direction}:{axis}") diff --git a/tests/eurotherm_eibisynch.py b/tests/eurotherm_eibisynch.py index 6f6232e0..f9a3d662 100644 --- a/tests/eurotherm_eibisynch.py +++ b/tests/eurotherm_eibisynch.py @@ -42,7 +42,7 @@ class EurothermTests(EurothermBaseTests, unittest.TestCase): def setUp(self): - super(EurothermTests, self).setUp() + super().setUp() self._lewis.backdoor_run_function_on_device("set_scaling", ["01", 1.0]) self._lewis.backdoor_run_function_on_device("set_delay_time", [0.0]) self._lewis: LewisLauncher diff --git a/tests/eurotherm_modbus.py b/tests/eurotherm_modbus.py index 0f54a031..7848a31a 100644 --- a/tests/eurotherm_modbus.py +++ b/tests/eurotherm_modbus.py @@ -50,7 +50,7 @@ class EurothermModbusTests(EurothermBaseTests, unittest.TestCase): def setUp(self): - super(EurothermModbusTests, self).setUp() + super().setUp() self._lewis.backdoor_run_function_on_device( "set_scaling", [sensors[0], 1.0 / float(SCALING)] ) diff --git a/tests/eurotherm_modbus_needlevalve.py b/tests/eurotherm_modbus_needlevalve.py index a32afe4f..628ff1c3 100644 --- a/tests/eurotherm_modbus_needlevalve.py +++ b/tests/eurotherm_modbus_needlevalve.py @@ -65,7 +65,7 @@ class EurothermModbusNeedleValveTests(EurothermBaseTests, unittest.TestCase): def setUp(self): - super(EurothermModbusNeedleValveTests, self).setUp() + super().setUp() self._lewis.backdoor_run_function_on_device( "set_scaling", [SENSORS[0], 1.0 / float(SCALING)] ) diff --git a/tests/fermi_chopper_lifter.py b/tests/fermi_chopper_lifter.py index 06963547..97a69e5f 100644 --- a/tests/fermi_chopper_lifter.py +++ b/tests/fermi_chopper_lifter.py @@ -16,7 +16,8 @@ "motorExtensions", "master", "settings", - "emma_chopper_lifter", + "EMMA-A", + "galil", ) ) @@ -27,7 +28,7 @@ "pv_for_existence": "AXIS1", "macros": { "MTRCTRL": "01", - "GALILADDR01": GALIL_ADDR, + "GALILADDR": GALIL_ADDR, "GALILCONFIGDIR": test_path.replace("\\", "/"), }, }, diff --git a/tests/fermichopper_merlin.py b/tests/fermichopper_merlin.py index 82bef427..a89af36e 100644 --- a/tests/fermichopper_merlin.py +++ b/tests/fermichopper_merlin.py @@ -59,11 +59,11 @@ def test_WHEN_chopper_parameters_are_set_THEN_status_updates(self): self.ca.assert_that_pv_is("STATUS.B3", "0") self.ca.set_pv_value("COMMAND:SP", command_number) - self.ca.assert_that_pv_is("LASTCOMMAND", "000{}".format(command_number)) + self.ca.assert_that_pv_is("LASTCOMMAND", f"000{command_number}") - self.ca.assert_that_pv_is("STATUS.B6", "{}".format(b6)) - self.ca.assert_that_pv_is("STATUS.B8", "{}".format(b8)) - self.ca.assert_that_pv_is("STATUS.B9", "{}".format(b9)) + self.ca.assert_that_pv_is("STATUS.B6", f"{b6}") + self.ca.assert_that_pv_is("STATUS.B8", f"{b8}") + self.ca.assert_that_pv_is("STATUS.B9", f"{b9}") @skip_if_recsim("Uses lewis backdoor") def test_WHEN_electronics_temperature_is_too_high_THEN_over_temperature_is_true(self): diff --git a/tests/galil.py b/tests/galil.py index b7ef063f..5874df28 100644 --- a/tests/galil.py +++ b/tests/galil.py @@ -20,7 +20,7 @@ "pv_for_existence": "AXIS1", "macros": { "MTRCTRL": "01", - "GALILADDR1": "127.0.0.11", + "GALILADDR": "127.0.0.11", "GALILCONFIGDIR": test_config_path.replace("\\", "/"), }, }, @@ -88,16 +88,16 @@ class GalilTests(unittest.TestCase): num_motors = 8 def zero_motors(self): - for motor in ["{:02d}".format(mtr) for mtr in range(1, self.num_motors + 1)]: - self.pv.set_pv_value("MOT:MTR{}{}".format(self.controller, motor), 0) - self.pv.assert_that_pv_is("MOT:MTR{}{}".format(self.controller, motor), 0) - self.pv.assert_that_pv_is("MOT:MTR{}{}.RBV".format(self.controller, motor), 0) + for motor in [f"{mtr:02d}" for mtr in range(1, self.num_motors + 1)]: + self.pv.set_pv_value(f"MOT:MTR{self.controller}{motor}", 0) + self.pv.assert_that_pv_is(f"MOT:MTR{self.controller}{motor}", 0) + self.pv.assert_that_pv_is(f"MOT:MTR{self.controller}{motor}.RBV", 0) def stop_motors(self): - for motor in ["{:02d}".format(mtr) for mtr in range(1, self.num_motors + 1)]: - self.pv.set_pv_value("MOT:MTR{}{}.STOP".format(self.controller, motor), 1) - self.pv.assert_that_pv_is("MOT:MTR{}{}.DMOV".format(self.controller, motor), 1) - self.pv.assert_that_pv_is("MOT:MTR{}{}.MOVN".format(self.controller, motor), 0) + for motor in [f"{mtr:02d}" for mtr in range(1, self.num_motors + 1)]: + self.pv.set_pv_value(f"MOT:MTR{self.controller}{motor}.STOP", 1) + self.pv.assert_that_pv_is(f"MOT:MTR{self.controller}{motor}.DMOV", 1) + self.pv.assert_that_pv_is(f"MOT:MTR{self.controller}{motor}.MOVN", 0) def setUp(self): self._ioc = IOCRegister.get_running(DEVICE_PREFIX) @@ -118,12 +118,12 @@ def test_GIVEN_ioc_started_THEN_pvs_for_all_motors_exist(self): """ check for real motors """ - for motor in ["{:02d}".format(mtr) for mtr in range(1, self.num_motors + 1)]: - self.pv.assert_that_pv_exists("MOT:MTR{}{}".format(self.controller, motor)) + for motor in [f"{mtr:02d}" for mtr in range(1, self.num_motors + 1)]: + self.pv.assert_that_pv_exists(f"MOT:MTR{self.controller}{motor}") def test_GIVEN_ioc_started_THEN_axes_for_all_motors_exist(self): for motor in range(1, 8 + 1): - self.pv.assert_that_pv_exists("GALIL_01:AXIS{}".format(motor)) + self.pv.assert_that_pv_exists(f"GALIL_01:AXIS{motor}") def test_GIVEN_motor_requested_to_move_THEN_motor_moves(self): self.zero_motors() @@ -179,7 +179,7 @@ def setup_motors(self, ueip: Literal["Yes", "No"]): self.pv.set_pv_value(key.format(self.controller), value) self.pv.assert_that_pv_is(key.format(self.controller), value) - for motor in ["{:02d}".format(mtr) for mtr in range(1, self.num_motors + 1)]: + for motor in [f"{mtr:02d}" for mtr in range(1, self.num_motors + 1)]: for key, value in MOTOR_SETUP.items(): if isinstance(value, str): value = value.format(ueip=ueip) diff --git a/tests/galilmul.py b/tests/galilmul.py index 9030143a..fc2e6d47 100644 --- a/tests/galilmul.py +++ b/tests/galilmul.py @@ -36,22 +36,22 @@ def setUp(self): def test_GIVEN_ioc_started_THEN_pvs_for_all_motors_exist(self): for controller in ("01", "02"): - for motor in ["{:02d}".format(mtr) for mtr in range(1, 8 + 1)]: - self.ca.assert_that_pv_exists("MOT:MTR{}{}".format(controller, motor)) + for motor in [f"{mtr:02d}" for mtr in range(1, 8 + 1)]: + self.ca.assert_that_pv_exists(f"MOT:MTR{controller}{motor}") def test_GIVEN_ioc_started_THEN_axes_for_all_motors_exist(self): for controller in (1, 2): for motor in range(1, 8 + 1): - self.ca.assert_that_pv_exists("GALILMUL_01:{}:AXIS{}".format(controller, motor)) + self.ca.assert_that_pv_exists(f"GALILMUL_01:{controller}:AXIS{motor}") def test_GIVEN_axis_moved_THEN_other_axes_do_not_move(self): # This is to check that axes are independent, i.e. they're not accidentally using the same underlying driver # Set all motors to zero for controller in ("01", "02"): - for motor in ["{:02d}".format(mtr) for mtr in range(1, 8 + 1)]: - self.ca.set_pv_value("MOT:MTR{}{}".format(controller, motor), 0) - self.ca.assert_that_pv_is("MOT:MTR{}{}".format(controller, motor), 0) + for motor in [f"{mtr:02d}" for mtr in range(1, 8 + 1)]: + self.ca.set_pv_value(f"MOT:MTR{controller}{motor}", 0) + self.ca.assert_that_pv_is(f"MOT:MTR{controller}{motor}", 0) # Move motor 0101 self.ca.set_pv_value("MOT:MTR0101", 20) @@ -59,7 +59,7 @@ def test_GIVEN_axis_moved_THEN_other_axes_do_not_move(self): # Check all other motors are still at zero for controller in ("01", "02"): - for motor in ["{:02d}".format(mtr) for mtr in range(1, 8 + 1)]: + for motor in [f"{mtr:02d}" for mtr in range(1, 8 + 1)]: if controller == "01" and motor == "01": continue - self.ca.assert_that_pv_is("MOT:MTR{}{}".format(controller, motor), 0) + self.ca.assert_that_pv_is(f"MOT:MTR{controller}{motor}", 0) diff --git a/tests/gem_jaws_manager.py b/tests/gem_jaws_manager.py index bc7d3f0a..3409db37 100644 --- a/tests/gem_jaws_manager.py +++ b/tests/gem_jaws_manager.py @@ -1,10 +1,9 @@ -import os import unittest from parameterized.parameterized import parameterized from common_tests.jaws_manager_utils import MOD_GAP, JawsManagerBase -from utils.ioc_launcher import get_default_ioc_dir +from utils.ioc_launcher import EPICS_TOP, get_default_ioc_dir # IP address of device from utils.test_modes import TestModes @@ -12,23 +11,19 @@ GALIL_ADDR = "127.0.0.11" -test_path = os.path.realpath( - os.path.join( - os.getenv("EPICS_KIT_ROOT"), "support", "motorExtensions", "master", "settings", "gem_jaws" - ) -) +test_path = EPICS_TOP / "support" / "motorExtensions" / "master" / "settings" / "GEM" / "galil" # Create 3 Galils IOCS = [ { - "name": "GALIL_0{}".format(i), + "name": f"GALIL_0{i}", "directory": get_default_ioc_dir("GALIL", i), "custom_prefix": "MOT", - "pv_for_existence": "MTR0{}01".format(i), + "pv_for_existence": f"MTR0{i}01", "macros": { "GALILADDR": GALIL_ADDR, - "MTRCTRL": "0{}".format(i), - "GALILCONFIGDIR": test_path.replace("\\", "/"), + "MTRCTRL": f"0{i}", + "GALILCONFIGDIR": test_path.as_posix(), }, } for i in range(1, 4) diff --git a/tests/heliox.py b/tests/heliox.py index 366a9139..23b00e13 100644 --- a/tests/heliox.py +++ b/tests/heliox.py @@ -2,6 +2,7 @@ import unittest from contextlib import contextmanager +from genie_python.genie import PVValue from parameterized import parameterized from utils.channel_access import ChannelAccess @@ -90,7 +91,7 @@ def test_WHEN_individual_channel_temperature_is_set_THEN_readback_updates( self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_temperature", [chan, temperature] ) - self.ca.assert_that_pv_is_number("{}:TEMP".format(chan), temperature, tolerance=0.005) + self.ca.assert_that_pv_is_number(f"{chan}:TEMP", temperature, tolerance=0.005) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_TEMPERATURES))) @skip_if_recsim("Lewis Backdoor not available in recsim") @@ -100,9 +101,7 @@ def test_WHEN_individual_channel_temperature_setpoint_is_set_THEN_readback_updat self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_temperature_sp", [chan, temperature] ) - self.ca.assert_that_pv_is_number( - "{}:TEMP:SP:RBV".format(chan), temperature, tolerance=0.005 - ) + self.ca.assert_that_pv_is_number(f"{chan}:TEMP:SP:RBV", temperature, tolerance=0.005) @parameterized.expand(parameterized_list(CHANNELS_WITH_STABILITY)) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -111,9 +110,7 @@ def test_WHEN_channel_statbility_is_set_via_backdoor_THEN_readback_updates(self, self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_stability", [chan, stability] ) - self.ca.assert_that_pv_is( - "{}:STABILITY".format(chan), "Stable" if stability else "Unstable" - ) + self.ca.assert_that_pv_is(f"{chan}:STABILITY", "Stable" if stability else "Unstable") @parameterized.expand(parameterized_list(CHANNELS_WITH_HEATER_AUTO)) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -122,7 +119,7 @@ def test_WHEN_channel_heater_auto_is_set_via_backdoor_THEN_readback_updates(self self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_heater_auto", [chan, heater_auto] ) - self.ca.assert_that_pv_is("{}:HEATER:AUTO".format(chan), "On" if heater_auto else "Off") + self.ca.assert_that_pv_is(f"{chan}:HEATER:AUTO", "On" if heater_auto else "Off") @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_HEATER_PERCENTAGES))) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -132,7 +129,7 @@ def test_WHEN_individual_channel_heater_percentage_is_set_THEN_readback_updates( self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_heater_percent", [chan, percent] ) - self.ca.assert_that_pv_is_number("{}:HEATER:PERCENT".format(chan), percent, tolerance=0.005) + self.ca.assert_that_pv_is_number(f"{chan}:HEATER:PERCENT", percent, tolerance=0.005) @skip_if_recsim("Cannot properly simulate disconnected device in recsim") def test_WHEN_device_disconnected_THEN_temperature_goes_into_alarm(self): @@ -208,18 +205,25 @@ def test_GIVEN_helium_3_pot_is_empty_WHEN_drifting_THEN_drift_rate_correct(self, "drift_rate", value / 100 ) # Emulator runs at 100x speed in framework - with self._simulate_helium_3_pot_empty(): # Will cause temperature to drift upwards continuously + with ( + self._simulate_helium_3_pot_empty() + ): # Will cause temperature to drift upwards continuously self.ca.assert_that_pv_is_number( "REGEN:_CALCULATE_TEMP_DRIFT.VALB", value, timeout=(DRIFT_BUFFER_SIZE + 10), tolerance=0.05, ) + + def _comparator(initial: PVValue, final: PVValue) -> bool: + assert isinstance(initial, float), "initial must be a float" + assert isinstance(final, float), "final must be a float" + return abs(initial - final) < 0.05 and abs(value - final) < 0.05 + self.ca.assert_that_pv_value_over_time_satisfies_comparator( "REGEN:_CALCULATE_TEMP_DRIFT.VALB", wait=DRIFT_BUFFER_SIZE, - comparator=lambda initial, final: abs(initial - final) < 0.05 - and abs(value - final) < 0.05, + comparator=_comparator, ) self.ca.assert_that_pv_is("REGEN:TEMP_DRIFT_RATE", 1) diff --git a/tests/helium_recovery_plc.py b/tests/helium_recovery_plc.py index 9282f4a7..ee8be682 100644 --- a/tests/helium_recovery_plc.py +++ b/tests/helium_recovery_plc.py @@ -1,5 +1,4 @@ import itertools -import os import unittest from parameterized import parameterized @@ -18,7 +17,7 @@ DEVICE_PREFIX = "FINS_01" IOC_NAME = "FINS" -TEST_PATH = os.path.join(EPICS_TOP, "ioc", "master", IOC_NAME, "exampleSettings", "HELIUM_RECOVERY") +TEST_PATH = EPICS_TOP / "ioc" / "master" / IOC_NAME / "exampleSettings" / "HELIUM_RECOVERY" IOC_PREFIX = "HA:HLM" @@ -28,7 +27,7 @@ "directory": get_default_ioc_dir("FINS"), "custom_prefix": IOC_PREFIX, "macros": { - "FINSCONFIGDIR": TEST_PATH.replace("\\", "/"), + "FINSCONFIGDIR": TEST_PATH.as_posix(), "PLC_IP": "127.0.0.1", "PLC_NODE": 58, }, @@ -257,7 +256,7 @@ def test_WHEN_int16_no_calc_set_backdoor_THEN_ioc_read_correctly(self, _, pv_nam self._lewis.backdoor_run_function_on_device("set_memory", (pv_name, test_value)) if pv_name != "HEARTBEAT": - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_after_processing_is(pv_name, test_value) @@ -266,10 +265,10 @@ def test_WHEN_int16_no_calc_set_backdoor_THEN_ioc_read_correctly(self, _, pv_nam ) @skip_if_devsim("sim pvs not available in devsim") def test_WHEN_int16_no_calc_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name, test_value): - self.ca.set_pv_value("SIM:{}".format(pv_name), test_value) + self.ca.set_pv_value(f"SIM:{pv_name}", test_value) if pv_name != "HEARTBEAT": - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_after_processing_is(pv_name, test_value) @@ -284,7 +283,7 @@ def test_WHEN_int16_no_calc_set_negative_value_backdoor_THEN_ioc_read_correctly( self.skipTest("HEARTBEAT does not have support for negative values") self._lewis.backdoor_run_function_on_device("set_memory", (pv_name, -test_value)) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_after_processing_is(pv_name, -test_value) @parameterized.expand( @@ -297,22 +296,22 @@ def test_WHEN_int16_no_calc_set_negative_value_sim_pv_THEN_ioc_read_correctly( if pv_name == "HEARTBEAT": self.skipTest("HEARTBEAT does not have support for negative values") - self.ca.set_pv_value("SIM:{}".format(pv_name), -test_value) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.set_pv_value(f"SIM:{pv_name}", -test_value) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_after_processing_is(pv_name, -test_value) @parameterized.expand(parameterized_list(zip(INT16_PV_NAMES, INT16_TEST_VALUES))) @skip_if_recsim("lewis backdoor not supported in recsim") def test_WHEN_int16_value_set_backdoor_THEN_ioc_read_correctly(self, _, pv_name, test_value): self._lewis.backdoor_run_function_on_device("set_memory", (pv_name, test_value)) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_is(pv_name, test_value / 10) @parameterized.expand(parameterized_list(zip(INT16_PV_NAMES, INT16_TEST_VALUES))) @skip_if_devsim("sim pvs not available in devsim") def test_WHEN_int16_value_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name, test_value): - self.ca.set_pv_value("SIM:{}".format(pv_name), test_value) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.set_pv_value(f"SIM:{pv_name}", test_value) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_is(pv_name, test_value / 10) @parameterized.expand(parameterized_list(zip(INT16_PV_NAMES, INT16_TEST_VALUES))) @@ -321,7 +320,7 @@ def test_WHEN_int16_value_set_negative_value_backdoor_THEN_ioc_read_correctly( self, _, pv_name, test_value ): self._lewis.backdoor_run_function_on_device("set_memory", (pv_name, -test_value)) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_is(pv_name, -test_value / 10) @parameterized.expand(parameterized_list(zip(INT16_PV_NAMES, INT16_TEST_VALUES))) @@ -329,8 +328,8 @@ def test_WHEN_int16_value_set_negative_value_backdoor_THEN_ioc_read_correctly( def test_WHEN_int16_value_set_negative_value_sim_pv_THEN_ioc_read_correctly( self, _, pv_name, test_value ): - self.ca.set_pv_value("SIM:{}".format(pv_name), -test_value) - self.ca.process_pv("{}:_RAW".format(pv_name)) + self.ca.set_pv_value(f"SIM:{pv_name}", -test_value) + self.ca.process_pv(f"{pv_name}:_RAW") self.ca.assert_that_pv_is(pv_name, -test_value / 10) @parameterized.expand(parameterized_list(zip(DWORD_PV_NAMES, DWORD_TEST_VALUES))) @@ -342,7 +341,7 @@ def test_WHEN_int32_value_set_backdoor_THEN_ioc_read_correctly(self, _, pv_name, @parameterized.expand(parameterized_list(zip(DWORD_PV_NAMES, DWORD_TEST_VALUES))) @skip_if_devsim("sim pvs not available in devsim") def test_WHEN_int32_value_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name, test_value): - self.ca.set_pv_value("SIM:{}".format(pv_name), test_value) + self.ca.set_pv_value(f"SIM:{pv_name}", test_value) self.ca.assert_that_pv_after_processing_is(pv_name, test_value) @parameterized.expand(parameterized_list(zip(ANALOGUE_IN_PV_NAMES, ANALOGUE_TEST_VALUES))) @@ -354,7 +353,7 @@ def test_WHEN_analogue_value_set_backdoor_THEN_ioc_read_correctly(self, _, pv_na @parameterized.expand(parameterized_list(zip(ANALOGUE_IN_PV_NAMES, ANALOGUE_TEST_VALUES))) @skip_if_devsim("sim pvs not available in devsim") def test_WHEN_analogue_value_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name, test_value): - self.ca.set_pv_value("SIM:{}".format(pv_name), test_value) + self.ca.set_pv_value(f"SIM:{pv_name}", test_value) self.ca.assert_that_pv_after_processing_is_number(pv_name, test_value, 0.001) @parameterized.expand(parameterized_list(AUTO_MANUAL_PV_NAMES)) @@ -373,10 +372,10 @@ def test_WHEN_auto_manual_set_backdoor_THEN_ioc_read_correctly(self, _, pv_name) def test_WHEN_auto_manual_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name): self.ca.assert_that_pv_after_processing_is(pv_name, "MANUAL") - self.ca.set_pv_value("SIM:{}".format(pv_name), 1) + self.ca.set_pv_value(f"SIM:{pv_name}", 1) self.ca.assert_that_pv_after_processing_is(pv_name, "AUTOMATIC") - self.ca.set_pv_value("SIM:{}".format(pv_name), 0) + self.ca.set_pv_value(f"SIM:{pv_name}", 0) self.ca.assert_that_pv_after_processing_is(pv_name, "MANUAL") @skip_if_recsim("lewis backdoor not available in recsim") @@ -498,7 +497,7 @@ def test_WHEN_valve_status_set_backdoor_THEN_ioc_read_correctly(self, _, pv_name @skip_if_devsim("sim pvs not available in devsim") def test_WHEN_valve_status_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_name, test_value): index_test_value = VALVE_STATUS_VALUES.index(test_value) - self.ca.set_pv_value("SIM:{}".format(pv_name), index_test_value) + self.ca.set_pv_value(f"SIM:{pv_name}", index_test_value) self.ca.assert_that_pv_after_processing_is(pv_name, test_value) # Liquefier alarms are tested separately because in the memory map they are unsigned integers. The C driver does @@ -514,8 +513,8 @@ def test_WHEN_liquefier_alarm_set_backdoor_THEN_ioc_read_correctly(self, _, pv_n mbbi_direct_pv = HeliumRecoveryPLCTests._get_liquefier_hardware_pv(alarm_index) test_value = HeliumRecoveryPLCTests._get_alarm_test_value(mbbi_direct_pv, alarm_index) - raw_pv = "{}:_RAW".format(mbbi_direct_pv) - full_pv_name = "{}:ALARM".format(pv_name) + raw_pv = f"{mbbi_direct_pv}:_RAW" + full_pv_name = f"{pv_name}:ALARM" self.ca.process_pv(raw_pv) self.ca.assert_that_pv_is(full_pv_name, "OK") @@ -535,17 +534,17 @@ def test_WHEN_liquefier_alarm_set_sim_pv_THEN_ioc_read_correctly(self, _, pv_nam mbbi_direct_pv = HeliumRecoveryPLCTests._get_liquefier_hardware_pv(alarm_index) test_value = HeliumRecoveryPLCTests._get_alarm_test_value(mbbi_direct_pv, alarm_index) - raw_pv = "{}:_RAW".format(mbbi_direct_pv) - full_pv_name = "{}:ALARM".format(pv_name) + raw_pv = f"{mbbi_direct_pv}:_RAW" + full_pv_name = f"{pv_name}:ALARM" self.ca.process_pv(raw_pv) self.ca.assert_that_pv_is(full_pv_name, "OK") - self.ca.set_pv_value("SIM:{}".format(mbbi_direct_pv), test_value) + self.ca.set_pv_value(f"SIM:{mbbi_direct_pv}", test_value) self.ca.process_pv(raw_pv) self.ca.assert_that_pv_is(full_pv_name, "IN ALARM") - self.ca.set_pv_value("SIM:{}".format(mbbi_direct_pv), 0) + self.ca.set_pv_value(f"SIM:{mbbi_direct_pv}", 0) self.ca.process_pv(raw_pv) self.ca.assert_that_pv_is(full_pv_name, "OK") diff --git a/tests/indfurn.py b/tests/indfurn.py index 67bce376..c73e8466 100644 --- a/tests/indfurn.py +++ b/tests/indfurn.py @@ -260,18 +260,18 @@ def test_GIVEN_sample_holder_material_is_set_THEN_sample_holder_material_can_be_ def test_GIVEN_thermocouple_1_fault_on_device_THEN_read_successfully(self): self._lewis.backdoor_set_on_device("thermocouple_1_fault", 0) for fault_pv in FAULTS: - self.ca.assert_that_pv_is("TC1FAULTS:{}".format(fault_pv), "OK") + self.ca.assert_that_pv_is(f"TC1FAULTS:{fault_pv}", "OK") for fault_pv, fault_number in FAULTS.items(): self._lewis.backdoor_set_on_device("thermocouple_1_fault", fault_number) - self.ca.assert_that_pv_is("TC1FAULTS:{}".format(fault_pv), "FAULT") + self.ca.assert_that_pv_is(f"TC1FAULTS:{fault_pv}", "FAULT") @skip_if_recsim("Can't use lewis backdoor in recsim") def test_GIVEN_thermocouple_2_fault_on_device_THEN_read_successfully(self): self._lewis.backdoor_set_on_device("thermocouple_2_fault", 0) for fault_pv in FAULTS: - self.ca.assert_that_pv_is("TC2FAULTS:{}".format(fault_pv), "OK") + self.ca.assert_that_pv_is(f"TC2FAULTS:{fault_pv}", "OK") for fault_pv, fault_number in FAULTS.items(): self._lewis.backdoor_set_on_device("thermocouple_2_fault", fault_number) - self.ca.assert_that_pv_is("TC2FAULTS:{}".format(fault_pv), "FAULT") + self.ca.assert_that_pv_is(f"TC2FAULTS:{fault_pv}", "FAULT") diff --git a/tests/inhibitr.py b/tests/inhibitr.py index 3b0e38f2..73785a5d 100644 --- a/tests/inhibitr.py +++ b/tests/inhibitr.py @@ -15,8 +15,8 @@ IOC_PREFIX = "INHIBITR_01" DEVICE_PREFIX = g.my_pv_prefix -SIMPLE_VALUE_ONE = "{}SIMPLE:VALUE1:SP".format(DEVICE_PREFIX) -SIMPLE_VALUE_TWO = "{}SIMPLE:VALUE2:SP".format(DEVICE_PREFIX) +SIMPLE_VALUE_ONE = f"{DEVICE_PREFIX}SIMPLE:VALUE1:SP" +SIMPLE_VALUE_TWO = f"{DEVICE_PREFIX}SIMPLE:VALUE2:SP" IOCS = [ { @@ -30,7 +30,9 @@ }, { "name": "SIMPLE", - "directory": os.path.join(EPICS_TOP, "ISIS", "SimpleIoc", "master", "iocBoot", "iocsimple"), + "directory": ( + EPICS_TOP / "ISIS" / "SimpleIoc" / "master" / "iocBoot" / "iocsimple" + ).as_posix(), "macros": {}, }, ] @@ -63,7 +65,7 @@ def reset_values_to_zero(self): def test_GIVEN_both_inputs_are_zero_WHEN_setting_either_input_THEN_this_is_allowed(self): for val in self.values: - self.ca.assert_that_pv_is("{}.DISP".format(val), "0") + self.ca.assert_that_pv_is(f"{val}.DISP", "0") @unstable_test() def test_GIVEN_one_input_is_one_WHEN_setting_other_value_to_one_THEN_this_is_not_allowed(self): diff --git a/tests/instetc.py b/tests/instetc.py index fe2a867e..5e589632 100644 --- a/tests/instetc.py +++ b/tests/instetc.py @@ -39,9 +39,9 @@ def test_GIVEN_loaded_WHEN_set_and_read_user_integer_THEN_integer_is_set( ): for var_index in range(NUM_USER_VARS + 1): self.ca.assert_setting_setpoint_sets_readback( - value, readback_pv="USER:{}{}".format(test_type, var_index) + value, readback_pv=f"USER:{test_type}{var_index}" ) - self.ca.assert_that_pv_does_not_exist("USER:I{}".format(NUM_USER_VARS + 1)) + self.ca.assert_that_pv_does_not_exist(f"USER:I{NUM_USER_VARS + 1}") def test_GIVEN_loaded_WHEN_get_max_user_record_THEN_max_is_returned(self): self.ca.assert_that_pv_is("USER:MAX", NUM_USER_VARS) @@ -53,7 +53,7 @@ def test_GIVEN_loaded_WHEN_set_and_read_button_THEN_running_set(self): for var_index in range(NUM_USER_BUTTONS + 1): self.ca.assert_setting_setpoint_sets_readback( "Running", - readback_pv="USER:BUTTON{}:SP".format(var_index), - set_point_pv="USER:BUTTON{}:SP".format(var_index), + readback_pv=f"USER:BUTTON{var_index}:SP", + set_point_pv=f"USER:BUTTON{var_index}:SP", ) - self.ca.assert_that_pv_does_not_exist("USER:BUTTON{}".format(NUM_USER_VARS + 1)) + self.ca.assert_that_pv_does_not_exist(f"USER:BUTTON{NUM_USER_VARS + 1}") diff --git a/tests/itc503.py b/tests/itc503.py index b622e606..6f44ca93 100644 --- a/tests/itc503.py +++ b/tests/itc503.py @@ -76,8 +76,8 @@ def _make_device_scan_faster(self): if self.ca.get_pv_value("FAN1.SCAN") != ".1 second": for i in range(1, 8 + 1): # Ensure all DLY links are 0 in both FAN records - self.ca.set_pv_value("FAN1.DLY{}".format(i), 0) - self.ca.set_pv_value("FAN2.DLY{}".format(i), 0) + self.ca.set_pv_value(f"FAN1.DLY{i}", 0) + self.ca.set_pv_value(f"FAN2.DLY{i}", 0) # Set the scan rate to .1 second (setting string does not work, have to use numeric value) self.ca.set_pv_value("FAN1.SCAN", 9) @@ -87,7 +87,7 @@ def test_WHEN_ioc_is_started_THEN_it_is_not_disabled(self): @parameterized.expand((pv, val) for pv, val in itertools.product(["P", "I", "D"], TEST_VALUES)) def test_WHEN_setting_pid_settings_THEN_can_be_read_back(self, pv, val): - self.ca.set_pv_value("{}:SP".format(pv), val) + self.ca.set_pv_value(f"{pv}:SP", val) self.ca.assert_that_pv_is_number(pv, val, tolerance=0.1) # Only comes back to 1dp @parameterized.expand(val for val in parameterized_list(TEST_VALUES)) @@ -153,7 +153,7 @@ def test_WHEN_heater_voltage_is_set_THEN_heater_voltage_updates(self, _, val): @skip_if_recsim("Comes back via record redirection which recsim can't handle easily") def test_WHEN_control_command_sent_THEN_remote_unlocked_set(self, _, control_pv, set_value): self.ca.set_pv_value("CTRL", "Locked") - self.ca.set_pv_value("{}:SP".format(control_pv), set_value) + self.ca.set_pv_value(f"{control_pv}:SP", set_value) self.ca.assert_that_pv_is("CTRL", "Local and remote") self.ca.set_pv_value("CTRL", "Locked") diff --git a/tests/jaws.py b/tests/jaws.py index 7c1c1472..b9153678 100644 --- a/tests/jaws.py +++ b/tests/jaws.py @@ -29,6 +29,7 @@ "pv_for_existence": "AXIS1", "macros": { "MTRCTRL": "01", + "GALILADDR": "127.0.0.1", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, }, @@ -37,7 +38,7 @@ TEST_MODES = [TestModes.DEVSIM] -class JawsTestsBase(object): +class JawsTestsBase: """ Base class for jaws tests """ @@ -47,12 +48,12 @@ def setUp(self): self._ioc = IOCRegister.get_running("jaws") self.ca = ChannelAccess(default_timeout=30) for mtr in self.UNDERLYING_MTRS.values(): - self.ca.set_pv_value("{}.DISP".format(mtr), 0) - self.ca.set_pv_value("{}.VMAX".format(mtr), 100) - self.ca.set_pv_value("{}.VELO".format(mtr), 100) + self.ca.set_pv_value(f"{mtr}.DISP", 0) + self.ca.set_pv_value(f"{mtr}.VMAX", 100) + self.ca.set_pv_value(f"{mtr}.VELO", 100) - self.ca.set_pv_value("{}:ABLE:SP".format(JAWS_BASE_PV), 0) - self.ca.set_pv_value("{}:LOCK:SP".format(JAWS_BASE_PV), 0) + self.ca.set_pv_value(f"{JAWS_BASE_PV}:ABLE:SP", 0) + self.ca.set_pv_value(f"{JAWS_BASE_PV}:LOCK:SP", 0) self.ca.set_pv_value("MOT:JAWS1:HGAP:SP", 0) self.ca.set_pv_value("MOT:JAWS1:VGAP:SP", 0) @@ -63,23 +64,23 @@ def setUp(self): def test_GIVEN_ioc_started_THEN_underlying_mtr_fields_can_be_read(self, _, direction): underlying_mtr = self.UNDERLYING_MTRS[direction] - expected = self.ca.get_pv_value("{}.VELO".format(underlying_mtr)) - jaw_blade_pv = "{}:J{}".format(JAWS_BASE_PV, direction) + expected = self.ca.get_pv_value(f"{underlying_mtr}.VELO") + jaw_blade_pv = f"{JAWS_BASE_PV}:J{direction}" - actual = self.ca.get_pv_value("{}:MTR.VELO".format(jaw_blade_pv)) + actual = self.ca.get_pv_value(f"{jaw_blade_pv}:MTR.VELO") self.assertEqual(expected, actual) @parameterized.expand(parameterized_list(TEST_POSITIONS)) def test_WHEN_jaw_blade_setpoint_changed_THEN_jaw_blade_moves(self, _, value): for direction in DIRECTIONS: - rbv_pv = "{}:J{}".format(JAWS_BASE_PV, direction) - sp_pv = "{}:J{}:SP".format(JAWS_BASE_PV, direction) + rbv_pv = f"{JAWS_BASE_PV}:J{direction}" + sp_pv = f"{JAWS_BASE_PV}:J{direction}:SP" self.ca.assert_setting_setpoint_sets_readback(value, rbv_pv, sp_pv) def test_GIVEN_jaws_closed_at_centre_WHEN_vgap_opened_THEN_north_and_south_jaws_move(self): - n_pv = "{}:JN".format(JAWS_BASE_PV) - s_pv = "{}:JS".format(JAWS_BASE_PV) + n_pv = f"{JAWS_BASE_PV}:JN" + s_pv = f"{JAWS_BASE_PV}:JS" # GIVEN self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:VCENT", 0) @@ -90,8 +91,8 @@ def test_GIVEN_jaws_closed_at_centre_WHEN_vgap_opened_THEN_north_and_south_jaws_ self.ca.assert_that_pv_is(s_pv, -0.5) def test_GIVEN_jaws_closed_at_centre_WHEN_hgap_opened_THEN_east_and_west_jaws_move(self): - e_pv = "{}:JE".format(JAWS_BASE_PV) - w_pv = "{}:JW".format(JAWS_BASE_PV) + e_pv = f"{JAWS_BASE_PV}:JE" + w_pv = f"{JAWS_BASE_PV}:JW" # GIVEN self.ca.assert_that_pv_is("MOT:JAWS1:HGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:HCENT", 0) @@ -103,9 +104,9 @@ def test_GIVEN_jaws_closed_at_centre_WHEN_hgap_opened_THEN_east_and_west_jaws_mo self.ca.assert_that_pv_is(w_pv, -0.5) def test_GIVEN_jaws_closed_at_centre_WHEN_JN_moves_THEN_vcent_moves(self): - n_pv = "{}:JN".format(JAWS_BASE_PV) - n_pv_sp = "{}:JN:SP".format(JAWS_BASE_PV) - s_pv = "{}:JS".format(JAWS_BASE_PV) + n_pv = f"{JAWS_BASE_PV}:JN" + n_pv_sp = f"{JAWS_BASE_PV}:JN:SP" + s_pv = f"{JAWS_BASE_PV}:JS" # GIVEN self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:VCENT", 0) @@ -124,11 +125,11 @@ def test_GIVEN_jaws_closed_at_centre_WHEN_JN_moves_THEN_vcent_moves(self): def test_GIVEN_jaws_closed_at_centre_WHEN_north_low_moved_THEN_vcent_not_move(self): testval = 1 - n_pv = "{}:JN".format(JAWS_BASE_PV) - n_pv_sp = "{}:JN:SP".format(JAWS_BASE_PV) - n_pv_low_sp = "{}:JN:MTR".format(JAWS_BASE_PV) - n_pv_low = "{}:JN:MTR.RBV".format(JAWS_BASE_PV) - s_pv = "{}:JS".format(JAWS_BASE_PV) + n_pv = f"{JAWS_BASE_PV}:JN" + n_pv_sp = f"{JAWS_BASE_PV}:JN:SP" + n_pv_low_sp = f"{JAWS_BASE_PV}:JN:MTR" + n_pv_low = f"{JAWS_BASE_PV}:JN:MTR.RBV" + s_pv = f"{JAWS_BASE_PV}:JS" self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:VCENT", 0) self.ca.assert_that_pv_is(n_pv_low, 0) @@ -147,11 +148,11 @@ def test_GIVEN_jaws_closed_at_centre_WHEN_north_low_moved_THEN_vcent_not_move(se self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", testval) def test_GIVEN_jaws_offset_WHEN_gap_set_THEN_centre_maintained(self): - n_pv = "{}:JN".format(JAWS_BASE_PV) - n_pv_sp = "{}:JN:SP".format(JAWS_BASE_PV) - n_pv_low_sp = "{}:JN:MTR".format(JAWS_BASE_PV) - n_pv_low = "{}:JN:MTR.RBV".format(JAWS_BASE_PV) - s_pv = "{}:JS".format(JAWS_BASE_PV) + n_pv = f"{JAWS_BASE_PV}:JN" + n_pv_sp = f"{JAWS_BASE_PV}:JN:SP" + n_pv_low_sp = f"{JAWS_BASE_PV}:JN:MTR" + n_pv_low = f"{JAWS_BASE_PV}:JN:MTR.RBV" + s_pv = f"{JAWS_BASE_PV}:JS" self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:VCENT", 0) self.ca.assert_that_pv_is(n_pv_low, 0) @@ -171,11 +172,11 @@ def test_GIVEN_jaws_offset_WHEN_gap_set_THEN_centre_maintained(self): self.ca.assert_that_pv_is("MOT:JAWS1:VCENT:SP", 0) def test_GIVEN_jaws_offset_WHEN_centre_set_THEN_gap_maintained(self): - n_pv = "{}:JN".format(JAWS_BASE_PV) - n_pv_sp = "{}:JN:SP".format(JAWS_BASE_PV) - n_pv_low_sp = "{}:JN:MTR".format(JAWS_BASE_PV) - n_pv_low = "{}:JN:MTR.RBV".format(JAWS_BASE_PV) - s_pv = "{}:JS".format(JAWS_BASE_PV) + n_pv = f"{JAWS_BASE_PV}:JN" + n_pv_sp = f"{JAWS_BASE_PV}:JN:SP" + n_pv_low_sp = f"{JAWS_BASE_PV}:JN:MTR" + n_pv_low = f"{JAWS_BASE_PV}:JN:MTR.RBV" + s_pv = f"{JAWS_BASE_PV}:JS" self.ca.assert_that_pv_is("MOT:JAWS1:VGAP", 0) self.ca.assert_that_pv_is("MOT:JAWS1:VCENT", 0) self.ca.assert_that_pv_is(n_pv_low, 0) @@ -200,10 +201,10 @@ def test_GIVEN_jaws_offset_WHEN_centre_set_THEN_gap_maintained(self): def test_GIVEN_all_jaws_have_state_set_THEN_overall_state_is_set(self, key, expected): enabled_val = 0 for mtr in self.UNDERLYING_MTRS.values(): - mtr_status_pv = "{}_{}".format(mtr, key) + mtr_status_pv = f"{mtr}_{key}" self.ca.set_pv_value(mtr_status_pv, enabled_val) - jaws_status_readback_pv = "{}:{}".format(JAWS_BASE_PV, key.upper()) + jaws_status_readback_pv = f"{JAWS_BASE_PV}:{key.upper()}" actual = self.ca.get_pv_value(jaws_status_readback_pv) self.assertEqual(expected, actual) @@ -212,10 +213,10 @@ def test_GIVEN_all_jaws_have_state_set_THEN_overall_state_is_set(self, key, expe def test_GIVEN_no_jaws_have_state_set_THEN_overall_state_is_not_set(self, key, expected): disabled_val = 1 for mtr in self.UNDERLYING_MTRS.values(): - mtr_status_pv = "{}_{}".format(mtr, key) + mtr_status_pv = f"{mtr}_{key}" self.ca.set_pv_value(mtr_status_pv, disabled_val) - jaws_status_readback_pv = "{}:{}".format(JAWS_BASE_PV, key.upper()) + jaws_status_readback_pv = f"{JAWS_BASE_PV}:{key.upper()}" actual = self.ca.get_pv_value(jaws_status_readback_pv) self.assertEqual(expected, actual) @@ -225,21 +226,21 @@ def test_GIVEN_some_jaws_have_state_set_THEN_overall_state_is_unknown(self, key, disabled_val = 0 enabled_val = 1 for mtr in list(self.UNDERLYING_MTRS.values())[:2]: - mtr_status_pv = "{}_{}".format(mtr, key) + mtr_status_pv = f"{mtr}_{key}" self.ca.set_pv_value(mtr_status_pv, enabled_val) for mtr in list(self.UNDERLYING_MTRS.values())[2:]: - mtr_status_pv = "{}_{}".format(mtr, key) + mtr_status_pv = f"{mtr}_{key}" self.ca.set_pv_value(mtr_status_pv, disabled_val) - jaws_status_readback_pv = "{}:{}".format(JAWS_BASE_PV, key.upper()) + jaws_status_readback_pv = f"{JAWS_BASE_PV}:{key.upper()}" actual = self.ca.get_pv_value(jaws_status_readback_pv) self.assertEqual(expected, actual) @parameterized.expand(parameterized_list(DIRECTIONS)) def test_GIVEN_underlying_mtr_adel_value_THEN_jaws_ADEL_field_mirrored(self, _, direction): - motor_adel_pv = "{}.ADEL".format(self.UNDERLYING_MTRS[direction]) - jaw_adel_pv = "{}:J{}.ADEL".format(JAWS_BASE_PV, direction) + motor_adel_pv = f"{self.UNDERLYING_MTRS[direction]}.ADEL" + jaw_adel_pv = f"{JAWS_BASE_PV}:J{direction}.ADEL" self.ca.set_pv_value(motor_adel_pv, 0.0) self.ca.assert_that_pv_is(motor_adel_pv, 0.0) @@ -257,7 +258,7 @@ def test_GIVEN_underlying_mtr_adel_THEN_jaws_centre_and_gap_adel_mirrored( self, axis, underlying_mtr_direction ): underlying_mtr = self.UNDERLYING_MTRS[underlying_mtr_direction] - motor_pv = "{}.ADEL".format(underlying_mtr) + motor_pv = f"{underlying_mtr}.ADEL" test_values = [1e-4, 1.2, 12.3] for test_value in test_values: @@ -265,10 +266,8 @@ def test_GIVEN_underlying_mtr_adel_THEN_jaws_centre_and_gap_adel_mirrored( self.ca.assert_that_pv_is_number(motor_pv, test_value) - self.ca.assert_that_pv_is_number( - "{}:{}CENT.ADEL".format(JAWS_BASE_PV, axis), test_value - ) - self.ca.assert_that_pv_is_number("{}:{}GAP.ADEL".format(JAWS_BASE_PV, axis), test_value) + self.ca.assert_that_pv_is_number(f"{JAWS_BASE_PV}:{axis}CENT.ADEL", test_value) + self.ca.assert_that_pv_is_number(f"{JAWS_BASE_PV}:{axis}GAP.ADEL", test_value) class JawsTests(JawsTestsBase, unittest.TestCase): diff --git a/tests/jaws_split.py b/tests/jaws_split.py index a7e813c2..cc616780 100644 --- a/tests/jaws_split.py +++ b/tests/jaws_split.py @@ -23,6 +23,7 @@ "pv_for_existence": "AXIS1", "macros": { "MTRCTRL": "01", + "GALILADDR": "127.0.0.1", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, }, @@ -32,6 +33,7 @@ "pv_for_existence": "AXIS1", "macros": { "MTRCTRL": "02", + "GALILADDR": "127.0.0.1", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, }, diff --git a/tests/jsco4180.py b/tests/jsco4180.py index 5e33027f..22a752c6 100644 --- a/tests/jsco4180.py +++ b/tests/jsco4180.py @@ -58,13 +58,13 @@ def setUp(self): def test_GIVEN_wrong_component_on_device_WHEN_running_THEN_retry_run_and_updates_component( self, ): - expected_value_A = 30 - expected_value_B = 15 - expected_value_C = 55 + expected_value_a = 30 + expected_value_b = 15 + expected_value_c = 55 - self.ca.set_pv_value("COMP:A:SP", expected_value_A) - self.ca.set_pv_value("COMP:B:SP", expected_value_B) - self.ca.set_pv_value("COMP:C:SP", expected_value_C) + self.ca.set_pv_value("COMP:A:SP", expected_value_a) + self.ca.set_pv_value("COMP:B:SP", expected_value_b) + self.ca.set_pv_value("COMP:C:SP", expected_value_c) self.ca.set_pv_value("START:SP", 1) @@ -75,9 +75,9 @@ def test_GIVEN_wrong_component_on_device_WHEN_running_THEN_retry_run_and_updates self._lewis.backdoor_set_on_device("component_B", 10) self._lewis.backdoor_set_on_device("component_C", 14) - self.ca.assert_that_pv_is("COMP:A", expected_value_A, timeout=30) - self.ca.assert_that_pv_is("COMP:B", expected_value_B, timeout=30) - self.ca.assert_that_pv_is("COMP:C", expected_value_C, timeout=30) + self.ca.assert_that_pv_is("COMP:A", expected_value_a, timeout=30) + self.ca.assert_that_pv_is("COMP:B", expected_value_b, timeout=30) + self.ca.assert_that_pv_is("COMP:C", expected_value_c, timeout=30) # there was a previous problem where if setpoint and readback differed a sleep and resend was started, # but the old state machine did not look to see if a new sp was issued while it was asleep and so then @@ -285,21 +285,19 @@ def test_GIVEN_an_ioc_WHEN_get_current_pressure_THEN_current_pressure_returned(s self.ca.assert_that_pv_is("PRESSURE", expected_value) - @parameterized.expand( - [("component_{}".format(suffix), suffix) for suffix in ["A", "B", "C", "D"]] - ) + @parameterized.expand([(f"component_{suffix}", suffix) for suffix in ["A", "B", "C", "D"]]) def test_GIVEN_an_ioc_WHEN_get_component_THEN_correct_component_returned( self, component, suffix ): expected_value = 10.0 self._lewis.backdoor_set_on_device(component, expected_value) - self.ca.assert_that_pv_is("COMP:{}".format(suffix), expected_value) + self.ca.assert_that_pv_is(f"COMP:{suffix}", expected_value) - @parameterized.expand([("COMP:{}".format(suffix), suffix) for suffix in ["A", "B", "C"]]) + @parameterized.expand([(f"COMP:{suffix}", suffix) for suffix in ["A", "B", "C"]]) def test_GIVEN_an_ioc_WHEN_set_component_THEN_correct_component_set(self, component, suffix): expected_value = 100.0 - self.ca.set_pv_value("COMP:{}:SP".format(suffix), expected_value) + self.ca.set_pv_value(f"COMP:{suffix}:SP", expected_value) if component == "COMP:A": self.ca.set_pv_value("COMP:B:SP", 0) self.ca.set_pv_value("COMP:C:SP", 0) @@ -324,7 +322,7 @@ def test_GIVEN_ioc_in_hardware_error_state_WHEN_get_error_THEN_hardware_error_re self.ca.assert_that_pv_is("ERROR", expected_value) - def test_GIVEN_ioc_in_error_state_WHEN_reset_error_THEN_error_reset(self): + def test_GIVEN_ioc_not_in_error_state_WHEN_reset_error_THEN_error_reset(self): expected_value = "No error" self._lewis.backdoor_set_on_device("error", ERROR_STATE_NO_ERROR) self.ca.set_pv_value("ERROR:SP", "Reset") diff --git a/tests/keithley_2001.py b/tests/keithley_2001.py index c91405a3..1891a31e 100644 --- a/tests/keithley_2001.py +++ b/tests/keithley_2001.py @@ -50,13 +50,13 @@ def _reset_ioc(ca): def _reset_channels(ca): for channel in CHANNEL_LIST: - pv = "CHAN:{:02d}:ACTIVE".format(channel) + pv = f"CHAN:{channel:02d}:ACTIVE" ca.assert_setting_setpoint_sets_readback("INACTIVE", pv, set_point_pv=pv) def _reset_units(ca): for channel in CHANNEL_LIST: - pv = "CHAN:{:02d}:UNIT:RAW.AA".format(channel) + pv = f"CHAN:{channel:02d}:UNIT:RAW.AA" ca.assert_setting_setpoint_sets_readback("", pv, set_point_pv=pv) @@ -83,7 +83,7 @@ def _setup_channel_to_test(ca, lewis, channel, value=None): def _set_active_channel(ca, channel): - pv = "CHAN:{0:02d}:ACTIVE".format(channel) + pv = f"CHAN:{channel:02d}:ACTIVE" ca.assert_setting_setpoint_sets_readback("ACTIVE", pv, set_point_pv=pv) @@ -93,6 +93,8 @@ def _connect_device(lewis): @setup_tests class InitTests(unittest.TestCase): + ca: ChannelAccess + def test_that_GIVEN_a_reset_IOC_THEN_it_is_set_up(self): # Given: self.ca.set_pv_value("RESET:FLAG", 1) @@ -145,10 +147,13 @@ def test_that_GIVEN_a_fresh_IOC_THEN_the_status_register_has_been_reset(self): @setup_tests class SingleShotTests(unittest.TestCase): + ca: ChannelAccess + def _simulate_readings(self, channel, value, unit): if IOCRegister.uses_rec_sim: - simulated_reading = ["{:.7E}{}".format(value, unit), "{0:02d}INTCHAN".format(channel)] - self.ca.set_pv_value("READINGS", simulated_reading) + simulated_reading = [f"{value:.7E}{unit}", f"{channel:02d}INTCHAN"] + # type hint in genie python cachannel not allowing list[str] + self.ca.set_pv_value("READINGS", simulated_reading) # pyright: ignore else: self._lewis.backdoor_run_function_on_device( "set_channel_value_via_the_backdoor", [channel, value, unit] @@ -164,10 +169,10 @@ def test_that_GIVEN_one_channels_set_to_active_THEN_the_voltage_value_for_that_c self._simulate_readings(channel, expected_value, "VDC") # Then: - self.ca.assert_that_pv_is("CHAN:{0:02d}:READ".format(channel), expected_value) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:READ", expected_value) @parameterized.expand(parameterized_list([1, 5, 10])) - def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_that_channel_are_read( + def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_that_channel_are_read_vdc( self, _, channel ): # Given: @@ -177,10 +182,10 @@ def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_tha # Then: expected_unit = "VDC" - self.ca.assert_that_pv_is("CHAN:{0:02d}:UNIT".format(channel), expected_unit) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:UNIT", expected_unit) @parameterized.expand(parameterized_list([1, 5, 10])) - def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_that_channel_are_read( + def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_that_channel_are_read_mvdc( self, _, channel ): # Given: @@ -190,18 +195,20 @@ def test_that_GIVEN_one_channel_set_to_active_THEN_the_measurement_units_for_tha # Then: expected_unit = "mVDC" - self.ca.assert_that_pv_is("CHAN:{0:02d}:UNIT".format(channel), expected_unit) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:UNIT", expected_unit) @setup_tests class ScanningSetupTests(unittest.TestCase): + ca: ChannelAccess + def test_that_GIVEN_two_active_channels_WHEN_scanning_on_two_channels_THEN_the_buffer_size_is_set_to_two( self, ): # Given: channels = (1, 2) for channel in channels: - self.ca.set_pv_value("CHAN:{:02d}:ACTIVE".format(channel), 1) + self.ca.set_pv_value(f"CHAN:{channel:02d}:ACTIVE", 1) # Then: self.ca.assert_that_pv_after_processing_is("BUFF:SIZE", len(channels)) @@ -212,7 +219,7 @@ def test_that_GIVEN_two_active_channels_WHEN_scanning_on_two_channels_THEN_the_m # Given: channels = (1, 2) for channel in channels: - self.ca.set_pv_value("CHAN:{:02d}:ACTIVE".format(channel), 1) + self.ca.set_pv_value(f"CHAN:{channel:02d}:ACTIVE", 1) # Then: self.ca.assert_that_pv_after_processing_is("SCAN:MEAS:COUNT", len(channels)) @@ -222,7 +229,7 @@ def test_that_GIVEN_two_active_channels_THEN_the_buffer_is_cleared(self): # Given: channels = (1, 2) for channel in channels: - self.ca.set_pv_value("CHAN:{:02d}:ACTIVE".format(channel), 1) + self.ca.set_pv_value(f"CHAN:{channel:02d}:ACTIVE", 1) # Then: number_of_times_buffer_has_been_cleared = int( @@ -238,8 +245,8 @@ def test_that_GIVEN_IOC_with_active_channels_THEN_the_IOC_creates_the_correct_st ): # Given: for channel in active_channels: - self.ca.set_pv_value("CHAN:{:02d}:ACTIVE".format(channel), 1) - self.ca.assert_that_pv_is("CHAN:{:02d}:ACTIVE".format(channel), "ACTIVE") + self.ca.set_pv_value(f"CHAN:{channel:02d}:ACTIVE", 1) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:ACTIVE", "ACTIVE") # Then: expected_channel_string = ",".join([str(i) for i in active_channels]) @@ -248,13 +255,13 @@ def test_that_GIVEN_IOC_with_active_channels_THEN_the_IOC_creates_the_correct_st @setup_tests class ScanningTests(unittest.TestCase): + ca: ChannelAccess + def _simulate_readings(self, values, channels, unit): if IOCRegister.uses_rec_sim: simulated_readings = [] for value, channel in zip(values, channels): - simulated_readings.extend( - ["{:.7E}{}".format(value, unit), "{0:02d}INTCHAN".format(channel)] - ) + simulated_readings.extend([f"{value:.7E}{unit}", f"{channel:02d}INTCHAN"]) self.ca.set_pv_value("READINGS", simulated_readings) else: for value, channel in zip(values, channels): @@ -273,7 +280,7 @@ def test_that_GIVEN_two_or_more_active_channels_THEN_the_readings_values_are_rea # Then: for expected_value, channel in zip(expected_values, channels): - self.ca.assert_that_pv_is("CHAN:{0:02d}:READ".format(channel), expected_value) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:READ", expected_value) @parameterized.expand(parameterized_list([[1, 2], [1, 2, 3, 4], [1, 5, 10]])) def test_that_GIVEN_two_or_more_active_channels_THEN_VDC_is_parsed_into_the_unit_records( @@ -287,7 +294,7 @@ def test_that_GIVEN_two_or_more_active_channels_THEN_VDC_is_parsed_into_the_unit # Then: expected_unit = "VDC" for expected_value, channel in zip(expected_values, channels): - self.ca.assert_that_pv_is("CHAN:{0:02d}:UNIT".format(channel), expected_unit) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:UNIT", expected_unit) @parameterized.expand(parameterized_list([[1, 2], [1, 2, 3, 4], [1, 5, 10]])) def test_that_GIVEN_two_or_more_active_channels_THEN_mVDC_is_parsed_into_the_unit_records( @@ -301,11 +308,13 @@ def test_that_GIVEN_two_or_more_active_channels_THEN_mVDC_is_parsed_into_the_uni # Then: expected_unit = "mVDC" for expected_value, channel in zip(expected_values, channels): - self.ca.assert_that_pv_is("CHAN:{0:02d}:UNIT".format(channel), expected_unit) + self.ca.assert_that_pv_is(f"CHAN:{channel:02d}:UNIT", expected_unit) @setup_tests class ErrorTests(unittest.TestCase): + ca: ChannelAccess + def _simulate_error(self, error_code, error_message): if IOCRegister.uses_rec_sim: self.ca.set_pv_value("SIM:ERROR:RAW", [str(error_code), error_message]) @@ -392,6 +401,8 @@ def test_that_GIVEN_a_device_not_scanning_on_any_channels_with_an_error_THEN_the @setup_tests class DisconnectedTests(unittest.TestCase): + ca: ChannelAccess + def _disconnect_device(self): self._lewis.backdoor_run_function_on_device("disconnect") @@ -420,12 +431,12 @@ def test_that_GIVEN_a_disconnected_device_set_to_scan_on_three_channels_WHEN_it_ # When/Then: map( self.ca.assert_that_pv_alarm_is, - ["CHAN:0{}:UNIT".format(i) for i in range(1, 3 + 1)], + [f"CHAN:0{i}:UNIT" for i in range(1, 3 + 1)], [self.ca.Alarms.INVALID] * 3, ) map( self.ca.assert_that_pv_alarm_is, - ["CHAN:0{}:READ".format(i) for i in range(1, 3 + 1)], + [f"CHAN:0{i}:READ" for i in range(1, 3 + 1)], [self.ca.Alarms.INVALID] * 3, ) @@ -441,7 +452,7 @@ def test_that_GIVEN_a_device_set_to_scan_on_one_channels_WHEN_disconnected_THEN_ self._lewis.backdoor_run_function_on_device( "set_channel_value_via_the_backdoor", [channel, value, "VDC"] ) - self.ca.assert_that_pv_is("CHAN:0{}:READ".format(channel), value) + self.ca.assert_that_pv_is(f"CHAN:0{channel}:READ", value) # When: self._disconnect_device() @@ -454,6 +465,8 @@ def test_that_GIVEN_a_device_set_to_scan_on_one_channels_WHEN_disconnected_THEN_ @setup_tests class IOCResetTests(unittest.TestCase): + ca: ChannelAccess + @skip_if_recsim("Can't replicate resetting the device in RECSIM") def test_that_GIVEN_a_device_WHEN_reset_THEN_the_IOC_has_been_reinitalized(self): # Given: diff --git a/tests/kepco_no_rem.py b/tests/kepco_no_rem.py index da3a5ca6..9e8e0cd7 100644 --- a/tests/kepco_no_rem.py +++ b/tests/kepco_no_rem.py @@ -36,7 +36,7 @@ class KepcoNoRemTests(KepcoTests, unittest.TestCase): """ def setUp(self): - super(KepcoNoRemTests, self).setUp() + super().setUp() self._set_IDN(IDN_NO_REM[0], IDN_NO_REM[1]) def lewis_set_and_assert_list(self, lewis_vars_and_vals): @@ -56,9 +56,9 @@ def assert_lewis_set_counts_set_correctly(self, lewis_vars_and_vals, set_func): try: self._lewis.assert_that_emulator_value_is(var, set_func(val), cast=int) except AssertionError as e: - error_message_calls += "\n{}\n{}".format(var, e.message) + error_message_calls += f"\n{var}\n{e.message}" if error_message_calls != "": - raise AssertionError("Failed to call sets:{}".format(error_message_calls)) + raise AssertionError(f"Failed to call sets:{error_message_calls}") @parameterized.expand( parameterized_list( diff --git a/tests/kepco_rem.py b/tests/kepco_rem.py index 99bf0586..2f958d15 100644 --- a/tests/kepco_rem.py +++ b/tests/kepco_rem.py @@ -34,7 +34,7 @@ class KepcoRemTests(KepcoTests, unittest.TestCase): """ def setUp(self): - super(KepcoRemTests, self).setUp() + super().setUp() self._set_IDN(IDN_REM[0], IDN_REM[1]) @parameterized.expand( diff --git a/tests/kynctm3k.py b/tests/kynctm3k.py index 77ad53d6..5ca4ea3e 100644 --- a/tests/kynctm3k.py +++ b/tests/kynctm3k.py @@ -27,22 +27,20 @@ class Kynctm3KTests(unittest.TestCase): Tests for the Keyence TM-3001P IOC. """ - # Defines the OUT channels which are on/off for each program - program_modes = { - "all_off": ["off"] * 16, - "all_out_of_range": ["out_of_range"] * 16, - "first_on_rest_out_of_range": ["on"] + ["out_of_range"] * 15, - "first_on_rest_off": ["on"] + ["off"] * 15, - "all_on": ["on"] * 16, - "even_on_odd_out_of_range": ["out_of_range", "on"] * 8, - "even_on_odd_off": ["off", "on"] * 8, - } - - init_OUT_VALUES = ["off"] * 16 - def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc(EMULATOR_NAME, DEVICE_PREFIX) self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX) + # Defines the OUT channels which are on/off for each program + self.program_modes = { + "all_off": ["off"] * 16, + "all_out_of_range": ["out_of_range"] * 16, + "first_on_rest_out_of_range": ["on"] + ["out_of_range"] * 15, + "first_on_rest_off": ["on"] + ["off"] * 15, + "all_on": ["on"] * 16, + "even_on_odd_out_of_range": ["out_of_range", "on"] * 8, + "even_on_odd_off": ["off", "on"] * 8, + } + self.init_OUT_VALUES = ["off"] * 16 self._lewis.backdoor_run_function_on_device("reset_device") @@ -82,7 +80,7 @@ def test_GIVEN_input_program_WHEN_measurement_value_is_requested_THEN_appropriat self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel_to_test, expected_value in enumerate(expected_values): - pv = "MEAS:OUT:{:02d}".format(channel_to_test + 1) + pv = f"MEAS:OUT:{channel_to_test + 1:02d}" if expected_value in ("off", "out_of_range"): continue else: @@ -102,7 +100,7 @@ def test_GIVEN_input_program_WHEN_all_OUT_values_are_out_of_range_THEN_disconnec self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel in range(1, 17): - pv = "MEAS:OUT:{:02d}".format(channel) + pv = f"MEAS:OUT:{channel:02d}" self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.MAJOR) @skip_if_recsim("Backdoor behaviour too complex for RECSIM") @@ -117,7 +115,7 @@ def test_GIVEN_input_program_WHEN_some_measurement_values_are_out_of_range_THEN_ self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel_to_test, expected_value in enumerate(expected_values): - pv = "MEAS:OUT:{:02d}".format(channel_to_test + 1) + pv = f"MEAS:OUT:{channel_to_test + 1:02d}" if expected_value == "out_of_range": self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.MAJOR) elif type(expected_value) is float: @@ -136,7 +134,7 @@ def test_GIVEN_input_program_WHEN_all_OUT_measurements_turned_off_THEN_all_pv_al self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel in range(1, 17): - pv = "MEAS:OUT:{:02d}".format(channel) + pv = f"MEAS:OUT:{channel:02d}" self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.INVALID) @skip_if_recsim("Backdoor behaviour too complex for RECSIM") @@ -149,7 +147,7 @@ def test_GIVEN_input_program_WHEN_some_OUT_measurements_are_turned_off_THEN_thos self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel_to_test, expected_value in enumerate(expected_values): - pv = "MEAS:OUT:{:02d}".format(channel_to_test + 1) + pv = f"MEAS:OUT:{channel_to_test + 1:02d}" if expected_value == "off": self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.INVALID) elif type(expected_value) is float: @@ -169,7 +167,7 @@ def test_GIVEN_a_truncated_output_string_THEN_all_pv_alarms_are_raised(self): self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel in range(1, 17): - pv = "MEAS:OUT:{:02d}".format(channel) + pv = f"MEAS:OUT:{channel:02d}" self.ca.assert_that_pv_alarm_is(pv, self.ca.Alarms.INVALID) @skip_if_recsim("Backdoor behaviour too complex for RECSIM") @@ -181,7 +179,7 @@ def test_GIVEN_emulator_is_in_auto_send_state_THEN_auto_send_is_unset_and_pvs_re self._lewis.backdoor_set_on_device("OUT_values", expected_values) for channel_to_test, expected_value in enumerate(expected_values): - pv = "MEAS:OUT:{:02d}".format(channel_to_test + 1) + pv = f"MEAS:OUT:{channel_to_test + 1:02d}" self._lewis.backdoor_set_on_device("auto_send", True) diff --git a/tests/lakeshore340.py b/tests/lakeshore340.py index 41f008e4..137980b1 100644 --- a/tests/lakeshore340.py +++ b/tests/lakeshore340.py @@ -83,7 +83,7 @@ THRESHOLD_TEMP_PV = "THRESHOLDS:TEMP" THRESHOLDS_ERROR_PV = "THRESHOLDS:ERROR" THRESHOLDS_DELAY_CHANGE_PV = "THRESHOLDS:DELAY_CHANGE" -THRESHOLD_FILES_DIR = EPICS_TOP + "/support/lakeshore340/master/excitation_thresholds/" +THRESHOLD_FILES_DIR = EPICS_TOP / "support" / "lakeshore340" / "master" / "excitation_thresholds" class Lakeshore340Tests(unittest.TestCase): @@ -101,14 +101,14 @@ def test_WHEN_device_is_started_THEN_it_is_not_disabled(self): @parameterized.expand(parameterized_list(itertools.product(SENSORS, TEST_TEMPERATURES))) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_temperature_set_via_backdoor_THEN_it_can_be_read_back(self, _, sensor, value): - self._lewis.backdoor_set_on_device("temp_{}".format(sensor.lower()), value) - self.ca.assert_that_pv_is_number("{}:TEMP".format(sensor.upper()), value) + self._lewis.backdoor_set_on_device(f"temp_{sensor.lower()}", value) + self.ca.assert_that_pv_is_number(f"{sensor.upper()}:TEMP", value) @parameterized.expand(parameterized_list(itertools.product(SENSORS, TEST_TEMPERATURES))) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_measurement_set_via_backdoor_THEN_it_can_be_read_back(self, _, sensor, value): - self._lewis.backdoor_set_on_device("measurement_{}".format(sensor.lower()), value) - self.ca.assert_that_pv_is_number("{}:RDG".format(sensor.upper()), value) + self._lewis.backdoor_set_on_device(f"measurement_{sensor.lower()}", value) + self.ca.assert_that_pv_is_number(f"{sensor.upper()}:RDG", value) @parameterized.expand(parameterized_list(TEST_TEMPERATURES)) def test_WHEN_tset_is_changed_THEN_readback_updates(self, _, val): @@ -124,7 +124,7 @@ def test_WHEN_pid_settings_changed_THEN_can_be_read_back(self, _, setting, value self.ca.assert_setting_setpoint_sets_readback(value, setting) @parameterized.expand(parameterized_list(PID_MODES)) - def test_WHEN_pid_settings_changed_THEN_can_be_read_back(self, _, mode): + def test_WHEN_pid_settings_changed_THEN_mode_be_read_back(self, _, mode): self.ca.assert_setting_setpoint_sets_readback(mode, "PIDMODE") @parameterized.expand(parameterized_list(LOOP_STATES)) @@ -156,7 +156,9 @@ def test_WHEN_excitation_set_by_backdoor_THEN_can_be_read_back(self, _, excitati self.ca.assert_that_pv_is("EXCITATIONA", excitation) def test_WHEN_use_valid_file_THEN_threshold_file_is_none(self): - self.ca.assert_that_pv_is_path(THRESHOLD_FILE_PV, THRESHOLD_FILES_DIR + THRESHOLDS_FILE) + self.ca.assert_that_pv_is_path( + THRESHOLD_FILE_PV, (THRESHOLD_FILES_DIR / THRESHOLDS_FILE).as_posix() + ) self.ca.assert_that_pv_is(THRESHOLDS_ERROR_PV, "No Error") self.ca.assert_that_pv_is("THRESHOLDS:USE", "YES") @@ -173,7 +175,9 @@ def test_WHEN_initialise_with_incorrect_macro_THEN_pv_is_in_alarm(self): {"EXCITATION_THRESHOLD_FILE": filename, "USE_EXCITATION_THRESHOLD_FILE": "YES"}, pv_to_wait_for=THRESHOLD_FILE_PV, ): - self.ca.assert_that_pv_is_path(THRESHOLD_FILE_PV, THRESHOLD_FILES_DIR + filename) + self.ca.assert_that_pv_is_path( + THRESHOLD_FILE_PV, (THRESHOLD_FILES_DIR / filename).as_posix() + ) self.ca.set_pv_value(THRESHOLD_FILE_PROC, 1) self.ca.assert_that_pv_is("THRESHOLDS:USE", "YES") self.ca.assert_that_pv_is(THRESHOLDS_ERROR_PV, "File Not Found") @@ -184,7 +188,9 @@ def test_WHEN_initialise_with_invalid_file_THEN_pv_is_in_alarm(self): {"EXCITATION_THRESHOLD_FILE": filename, "USE_EXCITATION_THRESHOLD_FILE": "YES"}, pv_to_wait_for=THRESHOLD_FILE_PV, ): - self.ca.assert_that_pv_is_path(THRESHOLD_FILE_PV, THRESHOLD_FILES_DIR + filename) + self.ca.assert_that_pv_is_path( + THRESHOLD_FILE_PV, (THRESHOLD_FILES_DIR / filename).as_posix() + ) self.ca.set_pv_value(THRESHOLD_FILE_PROC, 1) self.ca.assert_that_pv_is("THRESHOLDS:USE", "YES") self.ca.assert_that_pv_is(THRESHOLDS_ERROR_PV, "Invalid Lines In File") @@ -264,7 +270,9 @@ def test_GIVEN_not_using_excitations_OR_invalid_file_WHEN_set_temp_sp_THEN_thres with self._ioc.start_with_macros( {"EXCITATION_THRESHOLD_FILE": filename}, pv_to_wait_for=THRESHOLD_FILE_PV ): - self.ca.assert_that_pv_is_path(THRESHOLD_FILE_PV, THRESHOLD_FILES_DIR + filename) + self.ca.assert_that_pv_is_path( + THRESHOLD_FILE_PV, (THRESHOLD_FILES_DIR / filename).as_posix() + ) for temp_sp, temp, excitation in [ (5.2, 3.1, "30 nA"), (16.4, 18.2, "100 nA"), diff --git a/tests/lakeshore460.py b/tests/lakeshore460.py index 8088b51e..2290feef 100644 --- a/tests/lakeshore460.py +++ b/tests/lakeshore460.py @@ -28,7 +28,7 @@ TEST_MODES = [TestModes.DEVSIM, TestModes.RECSIM] -class UnitStrings(object): +class UnitStrings: GAUSS = "G" TESLA = "T" ON = "ON" @@ -41,7 +41,7 @@ class UnitStrings(object): CHANNEL_OFF = "OFF" -class UnitFlags(object): +class UnitFlags: GAUSS = 0 TESLA = 1 OFF = 0 @@ -85,7 +85,7 @@ def test_GIVEN_magnetic_field_reading_set_WHEN_read_THEN_magnetic_field_reading_ self._lewis.backdoor_command( ["device", "set_channel_param", chan, "field_reading", str(set_field_reading)] ) - self.ca.assert_that_pv_is("{}:FIELD:RAW".format(chan), set_field_reading) + self.ca.assert_that_pv_is(f"{chan}:FIELD:RAW", set_field_reading) @skip_if_recsim("In rec sim this test fails") def test_GIVEN_prms_set_peak_WHEN_read_THEN_prms_is_peak(self): @@ -93,13 +93,11 @@ def test_GIVEN_prms_set_peak_WHEN_read_THEN_prms_is_peak(self): set_prms = UnitFlags.PEAK expected_prms = UnitStrings.PEAK self.ca.assert_setting_setpoint_sets_readback( - set_prms, "{}:PRMS".format(chan), expected_value=expected_prms, timeout=15 + set_prms, f"{chan}:PRMS", expected_value=expected_prms, timeout=15 ) def test_GIVEN_source_set_WHEN_read_THEN_source_is_set_value(self): - for key in vectors: - set_value = key - expected_value = vectors[key] + for set_value, expected_value in vectors.items(): self.ca.assert_setting_setpoint_sets_readback( set_value, "SOURCE", expected_value=expected_value ) @@ -113,7 +111,7 @@ def test_GIVEN_output_mode_set_to_value_WHEN_read_THEN_output_mode_is_value( ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:MODE".format(chan), expected_value=unit_string + unit_flag, f"{chan}:MODE", expected_value=unit_string ) @skip_if_recsim("In rec sim this test fails") @@ -122,7 +120,7 @@ def test_GIVEN_prms_set_rms_WHEN_read_THEN_prms_is_rms(self): set_prms = UnitFlags.RMS expected_prms = UnitStrings.RMS self.ca.assert_setting_setpoint_sets_readback( - set_prms, "{}:PRMS".format(chan), expected_value=expected_prms, timeout=15 + set_prms, f"{chan}:PRMS", expected_value=expected_prms, timeout=15 ) @parameterized.expand( @@ -134,7 +132,7 @@ def test_GIVEN_display_filter_set_to_val_WHEN_read_THEN_display_filter_is_set_va ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:FILTER".format(chan), expected_value=unit_string + unit_flag, f"{chan}:FILTER", expected_value=unit_string ) @parameterized.expand( @@ -146,7 +144,7 @@ def test_GIVEN_rel_mode_status_set_to_val_WHEN_read_THEN_rel_mode_status_is_set_ ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:RELMODE".format(chan), expected_value=unit_string + unit_flag, f"{chan}:RELMODE", expected_value=unit_string ) @parameterized.expand(parameterized_list([10.4, 20, 3])) @@ -155,7 +153,7 @@ def test_GIVEN_rel_mode_setpoint_set_to_val_WHEN_read_THEN_rel_mode_setpoint_is_ self, _, value ): for chan in channels: - self.ca.assert_setting_setpoint_sets_readback(value, "{}:RELMODESET".format(chan)) + self.ca.assert_setting_setpoint_sets_readback(value, f"{chan}:RELMODESET") @parameterized.expand( [("ON", UnitFlags.ON, UnitStrings.ON), ("OFF", UnitFlags.OFF, UnitStrings.OFF)] @@ -166,7 +164,7 @@ def test_GIVEN_auto_mode_status_set_to_value_WHEN_read_THEN_auto_mode_status_is_ ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:AUTO".format(chan), expected_value=unit_string + unit_flag, f"{chan}:AUTO", expected_value=unit_string ) @parameterized.expand( @@ -178,7 +176,7 @@ def test_GIVEN_max_hold_status_set_to_value_WHEN_read_THEN_max_hold_status_is_se ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:MAXHOLD".format(chan), expected_value=unit_string + unit_flag, f"{chan}:MAXHOLD", expected_value=unit_string ) @parameterized.expand( @@ -193,7 +191,7 @@ def test_GIVEN_channel_status_set_on_WHEN_read_THEN_channel_status_is_set_value( ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - unit_flag, "{}:STATUS".format(chan), expected_value=unit_string + unit_flag, f"{chan}:STATUS", expected_value=unit_string ) @parameterized.expand([("11_alarm_major", 11, "MAJOR"), ("4_no_alarm", 4, "NO_ALARM")]) @@ -203,7 +201,7 @@ def test_GIVEN_filter_windows_set_WHEN_read_THEN_alarm_is_as_expected( ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - filter_windows, "{}:FWIN".format(chan), expected_alarm=exp_alarm + filter_windows, f"{chan}:FWIN", expected_alarm=exp_alarm ) @parameterized.expand([("65_alarm_major", 65, "MAJOR"), ("10_no_alarm", 10, "NO_ALARM")]) @@ -213,15 +211,14 @@ def test_GIVEN_filter_points_set_WHEN_read_THEN_alarm_is_major( ): for chan in channels: self.ca.assert_setting_setpoint_sets_readback( - filter_points, "{}:FNUM".format(chan), expected_alarm=exp_alarm + filter_points, f"{chan}:FNUM", expected_alarm=exp_alarm ) @skip_if_recsim("In rec sim this test fails") def test_GIVEN_range_set_WHEN_read_THEN_range_is_set_value(self): for chan in channels: - for key in ranges: + for key, value in ranges.items(): set_range = key - expected_range = ranges[key] self.ca.assert_setting_setpoint_sets_readback( - set_range, "{}:RANGE".format(chan), expected_value=expected_range + set_range, f"{chan}:RANGE", expected_value=value ) diff --git a/tests/larmor_bench_fins.py b/tests/larmor_bench_fins.py index a8146ccb..d47c11c9 100644 --- a/tests/larmor_bench_fins.py +++ b/tests/larmor_bench_fins.py @@ -1,4 +1,3 @@ -import os import unittest from utils.channel_access import ChannelAccess @@ -8,14 +7,14 @@ DEVICE_PREFIX = "FINS_01" ioc_name = "FINS" -test_path = os.path.join(EPICS_TOP, "ioc", "master", ioc_name, "exampleSettings", "LARMOR_bench") +test_path = EPICS_TOP / "ioc" / "master" / ioc_name / "exampleSettings" / "LARMOR_bench" IOCS = [ { "name": DEVICE_PREFIX, "directory": get_default_ioc_dir(ioc_name), "pv_for_existence": "BENCH:FLOW1", - "macros": {"FINSCONFIGDIR": test_path.replace("\\", "/"), "PLCIP": "127.0.0.1"}, + "macros": {"FINSCONFIGDIR": test_path.as_posix(), "PLCIP": "127.0.0.1"}, }, ] diff --git a/tests/lksh218.py b/tests/lksh218.py index 58a13a96..40d86063 100644 --- a/tests/lksh218.py +++ b/tests/lksh218.py @@ -1,6 +1,7 @@ import unittest from utils.channel_access import ChannelAccess +from utils.emulator_launcher import EmulatorLauncher from utils.ioc_launcher import get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc, skip_if_recsim @@ -34,12 +35,14 @@ def tearDown(self): self._lewis.backdoor_set_on_device("connected", True) def _set_temperature(self, number, temperature): - pv = "SIM:TEMP{}".format(number) + pv = f"SIM:TEMP{number}" + assert isinstance(self._lewis, EmulatorLauncher), "_lewis must be an EmulatorLauncher" self._lewis.backdoor_run_function_on_device("set_temp", [number, temperature]) self._ioc.set_simulated_value(pv, temperature) def _set_sensor(self, number, value): - pv = "SIM:SENSOR{}".format(number) + assert isinstance(self._lewis, EmulatorLauncher), "_lewis must be an EmulatorLauncher" + pv = f"SIM:SENSOR{number}" self._lewis.backdoor_run_function_on_device("set_sensor", [number, value]) self._ioc.set_simulated_value(pv, value) @@ -50,7 +53,7 @@ def test_that_GIVEN_temp_float_WHEN_temp_pvs_are_read_THEN_temp_is_as_expected(s expected_value = 10.586 for index in range(1, 9): - pv = "TEMP{}".format(index) + pv = f"TEMP{index}" self._set_temperature(index, expected_value) self.ca.assert_that_pv_is(pv, expected_value) @@ -58,7 +61,7 @@ def test_that_GIVEN_sensor_float_WHEN_sensor_pvs_are_read_THEN_sensor_is_as_expe expected_value = 11.386 for index in range(1, 9): - pv = "SENSOR{}".format(index) + pv = f"SENSOR{index}" self._set_sensor(index, expected_value) self.ca.assert_that_pv_is(pv, expected_value) @@ -84,8 +87,8 @@ def _check_TEMP_and_SENSOR_alarms(self, alarm_mode): correct state """ for i in range(1, 9): - self.ca.assert_that_pv_alarm_is("TEMP{}".format(i), alarm_mode, timeout=30) - self.ca.assert_that_pv_alarm_is("SENSOR{}".format(i), alarm_mode, timeout=30) + self.ca.assert_that_pv_alarm_is(f"TEMP{i}", alarm_mode, timeout=30) + self.ca.assert_that_pv_alarm_is(f"SENSOR{i}", alarm_mode, timeout=30) @skip_if_recsim("Recsim is unable to simulate a disconnected device.") def test_that_WHEN_the_emulator_is_disconnected_THEN_an_alarm_is_raised_on_TEMP_and_SENSOR( diff --git a/tests/lsicorr.py b/tests/lsicorr.py index de8b91aa..a58d332b 100644 --- a/tests/lsicorr.py +++ b/tests/lsicorr.py @@ -11,9 +11,10 @@ dir_path = os.path.dirname(os.path.realpath(__file__)) ioc_number = 1 -DEVICE_PREFIX = "LSICORR_{:02d}".format(ioc_number) +DEVICE_PREFIX = f"LSICORR_{ioc_number:02d}" + +LSICORR_PATH = EPICS_TOP / "support" / "lsicorr" / "master" -LSICORR_PATH = os.path.join(EPICS_TOP, "support", "lsicorr", "master") IOCS = [ { "ioc_launcher_class": ProcServLauncher, @@ -167,7 +168,7 @@ def test_GIVEN_enum_setting_WHEN_setting_pv_written_to_THEN_new_value_read_back( def test_GIVEN_pv_with_unit_WHEN_EGU_field_read_from_THEN_unit_returned( self, pv, expected_unit ): - self.ca.assert_that_pv_is("{pv}.EGU".format(pv=pv), expected_unit) + self.ca.assert_that_pv_is(f"{pv}.EGU", expected_unit) @parameterized.expand( [ @@ -178,7 +179,7 @@ def test_GIVEN_pv_with_unit_WHEN_EGU_field_read_from_THEN_unit_returned( def test_GIVEN_array_pv_WHEN_NELM_field_read_THEN_length_of_array_returned( self, pv, expected_length ): - self.ca.assert_that_pv_is_number("{pv}.NELM".format(pv=pv), expected_length) + self.ca.assert_that_pv_is_number(f"{pv}.NELM", expected_length) @parameterized.expand(parameterized_list(SETTING_PVS)) def test_GIVEN_pv_name_THEN_setpoint_exists_for_that_pv(self, _, pv, value): @@ -186,7 +187,7 @@ def test_GIVEN_pv_name_THEN_setpoint_exists_for_that_pv(self, _, pv, value): @parameterized.expand(parameterized_list(PV_NAMES)) def test_GIVEN_pv_name_THEN_val_field_exists_for_that_pv(self, _, pv): - self.ca.assert_that_pv_is("{pv}.VAL".format(pv=pv), self.ca.get_pv_value(pv)) + self.ca.assert_that_pv_is(f"{pv}.VAL", self.ca.get_pv_value(pv)) @parameterized.expand(parameterized_list(PV_NAMES)) def test_GIVEN_pv_WHEN_pv_read_THEN_pv_has_no_alarms(self, _, pv): @@ -199,7 +200,8 @@ def test_GIVEN_start_pressed_WHEN_measurement_is_possible_THEN_correlation_and_l self.ca.assert_setting_setpoint_sets_readback(0, "MIN_TIME_LAG") self.ca.assert_that_pv_is("TAKING_DATA", "NO", timeout=10) self.ca.set_pv_value("START", 1, sleep_after_set=0.0) - array_size = self.ca.get_pv_value("{pv}.NELM".format(pv=pv)) + array_size = self.ca.get_pv_value(f"{pv}.NELM") + assert isinstance(array_size, int), "array_size must be integer" test_data = np.linspace(0, array_size, array_size) self.ca.assert_that_pv_value_causes_func_to_return_true( pv, lambda pv_value: np.allclose(pv_value, test_data) @@ -217,7 +219,8 @@ def test_GIVEN_start_pressed_WHEN_measurement_is_possible_THEN_lags_data_below_m # Act self.ca.set_pv_value("START", 1, sleep_after_set=0.0) # Assert - array_size = self.ca.get_pv_value("{pv}.NELM".format(pv=pv)) + array_size = self.ca.get_pv_value(f"{pv}.NELM") + assert isinstance(array_size, int), "array_size must be int" test_data = np.linspace(0, array_size, array_size) # Scale minimum time lag from nanoseconds to seconds before comparison with test data min_time_lag_seconds = min_time_lag / 1e9 diff --git a/tests/mecfrf.py b/tests/mecfrf.py index 955c23df..a4343409 100644 --- a/tests/mecfrf.py +++ b/tests/mecfrf.py @@ -49,9 +49,9 @@ def test_WHEN_device_is_started_THEN_it_is_not_disabled(self): @parameterized.expand(parameterized_list(itertools.product(SENSORS, TEST_LENGTHS))) @skip_if_recsim("Uses Lewis backdoor") def test_WHEN_value_is_written_to_emulator_THEN_record_updates(self, _, sensor, length): - self._lewis.backdoor_set_on_device("sensor{}".format(sensor), length * RAW_READING_SCALING) - self.ca.assert_that_pv_is("SENSOR{}".format(sensor), length) - self.ca.assert_that_pv_alarm_is("SENSOR{}".format(sensor), self.ca.Alarms.NONE) + self._lewis.backdoor_set_on_device(f"sensor{sensor}", length * RAW_READING_SCALING) + self.ca.assert_that_pv_is(f"SENSOR{sensor}", length) + self.ca.assert_that_pv_alarm_is(f"SENSOR{sensor}", self.ca.Alarms.NONE) @skip_if_recsim("Uses Lewis backdoor") def test_WHEN_emulator_sends_corrupt_packets_THEN_records_go_into_alarm(self): @@ -69,12 +69,12 @@ def test_WHEN_emulator_sends_corrupt_packets_THEN_records_go_into_alarm(self): @skip_if_recsim("Uses Lewis backdoor") def test_WHEN_emulator_disconnected_THEN_records_go_into_alarm(self, _, sensor): self.ca.assert_that_pv_is("_READINGS_OUTDATED", "No") - self.ca.assert_that_pv_alarm_is("SENSOR{}".format(sensor), self.ca.Alarms.NONE) + self.ca.assert_that_pv_alarm_is(f"SENSOR{sensor}", self.ca.Alarms.NONE) with self._lewis.backdoor_simulate_disconnected_device(): self.ca.assert_that_pv_is("_READINGS_OUTDATED", "Yes") - self.ca.assert_that_pv_alarm_is("SENSOR{}".format(sensor), self.ca.Alarms.INVALID) + self.ca.assert_that_pv_alarm_is(f"SENSOR{sensor}", self.ca.Alarms.INVALID) # Assert alarms clear on reconnection self.ca.assert_that_pv_is("_READINGS_OUTDATED", "No") - self.ca.assert_that_pv_alarm_is("SENSOR{}".format(sensor), self.ca.Alarms.NONE) + self.ca.assert_that_pv_alarm_is(f"SENSOR{sensor}", self.ca.Alarms.NONE) diff --git a/tests/mercuryitc.py b/tests/mercuryitc.py index 42f80c6d..e9a90537 100644 --- a/tests/mercuryitc.py +++ b/tests/mercuryitc.py @@ -1,5 +1,5 @@ import itertools -import os +import pathlib import unittest from parameterized import parameterized @@ -37,25 +37,23 @@ def get_card_pv_prefix(card): """ if card in TEMP_CARDS: assert card not in PRESSURE_CARDS and card not in LEVEL_CARDS - return "{}".format( - TEMP_CARDS.index(card) + 1 - ) # Only a numeric prefix for temperature cards + return f"{TEMP_CARDS.index(card) + 1}" # Only a numeric prefix for temperature cards elif card in PRESSURE_CARDS: assert card not in LEVEL_CARDS - return "PRESSURE:{}".format(PRESSURE_CARDS.index(card) + 1) + return f"PRESSURE:{PRESSURE_CARDS.index(card) + 1}" elif card in LEVEL_CARDS: - return "LEVEL:{}".format(LEVEL_CARDS.index(card) + 1) + return f"LEVEL:{LEVEL_CARDS.index(card) + 1}" else: raise ValueError("Unknown card") macros = {} -macros.update({"TEMP_{}".format(key): val for key, val in enumerate(TEMP_CARDS, start=1)}) -macros.update({"PRESSURE_{}".format(key): val for key, val in enumerate(PRESSURE_CARDS, start=1)}) -macros.update({"LEVEL_{}".format(key): val for key, val in enumerate(LEVEL_CARDS, start=1)}) +macros.update({f"TEMP_{key}": val for key, val in enumerate(TEMP_CARDS, start=1)}) +macros.update({f"PRESSURE_{key}": val for key, val in enumerate(PRESSURE_CARDS, start=1)}) +macros.update({f"LEVEL_{key}": val for key, val in enumerate(LEVEL_CARDS, start=1)}) -macros["CALIB_BASE_DIR"] = EPICS_TOP.replace("\\", "/") -macros["CALIB_DIR"] = os.path.join("support", "mercuryitc", "master", "settings").replace("\\", "/") +macros["CALIB_BASE_DIR"] = EPICS_TOP.as_posix() +macros["CALIB_DIR"] = pathlib.PurePath("support", "mercuryitc", "master", "settings").as_posix() DEVICE_PREFIX = "MERCURY_01" @@ -63,9 +61,9 @@ def get_card_pv_prefix(card): IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join( - EPICS_TOP, "ioc", "master", "MERCURY_ITC", "iocBoot", "iocMERCURY-IOC-01" - ), + "directory": ( + EPICS_TOP / "ioc" / "master" / "MERCURY_ITC" / "iocBoot" / "iocMERCURY-IOC-01" + ).as_posix(), "emulator": "mercuryitc", "macros": macros, }, @@ -137,7 +135,7 @@ def setUp(self): self._lewis, self._ioc = get_running_lewis_and_ioc("mercuryitc", DEVICE_PREFIX) self._lewis.backdoor_set_on_device("connected", True) self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX, default_timeout=20) - card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) + get_card_pv_prefix(TEMP_CARDS[0]) @parameterized.expand( parameterized_list( @@ -153,7 +151,7 @@ def test_WHEN_pid_params_set_via_backdoor_THEN_readback_updates( self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, param.lower(), test_value] ) - self.ca.assert_that_pv_is("{}:{}".format(card_pv_prefix, param), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:{param}", test_value) @parameterized.expand( parameterized_list( @@ -165,8 +163,8 @@ def test_WHEN_pid_params_set_THEN_readback_updates(self, _, param, test_value, c self.ca.assert_setting_setpoint_sets_readback( test_value, - readback_pv="{}:{}".format(card_pv_prefix, param), - set_point_pv="{}:{}:SP".format(card_pv_prefix, param), + readback_pv=f"{card_pv_prefix}:{param}", + set_point_pv=f"{card_pv_prefix}:{param}:SP", ) @parameterized.expand( @@ -177,8 +175,8 @@ def test_WHEN_autopid_set_THEN_readback_updates(self, _, test_value, card): self.ca.assert_setting_setpoint_sets_readback( test_value, - readback_pv="{}:PID:AUTO".format(card_pv_prefix), - set_point_pv="{}:PID:AUTO:SP".format(card_pv_prefix), + readback_pv=f"{card_pv_prefix}:PID:AUTO", + set_point_pv=f"{card_pv_prefix}:PID:AUTO:SP", ) @parameterized.expand( @@ -191,7 +189,7 @@ def test_WHEN_actual_temp_is_set_via_backdoor_THEN_pv_updates(self, _, test_valu self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "temperature", test_value] ) - self.ca.assert_that_pv_is("{}:TEMP".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:TEMP", test_value) @parameterized.expand( parameterized_list(itertools.product(TEMPERATURE_TEST_VALUES, PRESSURE_CARDS)) @@ -203,7 +201,7 @@ def test_WHEN_actual_pressure_is_set_via_backdoor_THEN_pv_updates(self, _, test_ self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "pressure", test_value] ) - self.ca.assert_that_pv_is("{}:PRESSURE".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:PRESSURE", test_value) @parameterized.expand(parameterized_list(itertools.product(RESISTANCE_TEST_VALUES, TEMP_CARDS))) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -213,7 +211,7 @@ def test_WHEN_resistance_is_set_via_backdoor_THEN_pv_updates(self, _, test_value self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "resistance", test_value] ) - self.ca.assert_that_pv_is("{}:RESISTANCE".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:RESISTANCE", test_value) @parameterized.expand( parameterized_list(itertools.product(RESISTANCE_TEST_VALUES, PRESSURE_CARDS)) @@ -225,7 +223,7 @@ def test_WHEN_voltage_is_set_via_backdoor_THEN_pv_updates(self, _, test_value, c self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "voltage", test_value] ) - self.ca.assert_that_pv_is("{}:VOLT".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:VOLT", test_value) @parameterized.expand( parameterized_list(itertools.product(TEMPERATURE_TEST_VALUES, TEMP_CARDS)) @@ -235,8 +233,8 @@ def test_WHEN_sp_temp_is_set_THEN_pv_updates(self, _, test_value, card): self.ca.assert_setting_setpoint_sets_readback( test_value, - set_point_pv="{}:TEMP:SP".format(card_pv_prefix), - readback_pv="{}:TEMP:SP:RBV".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:TEMP:SP", + readback_pv=f"{card_pv_prefix}:TEMP:SP:RBV", ) @parameterized.expand( @@ -247,8 +245,8 @@ def test_WHEN_sp_pressure_is_set_THEN_pv_updates(self, _, test_value, card): self.ca.assert_setting_setpoint_sets_readback( test_value, - set_point_pv="{}:PRESSURE:SP".format(card_pv_prefix), - readback_pv="{}:PRESSURE:SP:RBV".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:PRESSURE:SP", + readback_pv=f"{card_pv_prefix}:PRESSURE:SP:RBV", ) @parameterized.expand( @@ -259,8 +257,8 @@ def test_WHEN_heater_mode_is_set_THEN_pv_updates(self, _, mode, card): self.ca.assert_setting_setpoint_sets_readback( mode, - set_point_pv="{}:HEATER:MODE:SP".format(card_pv_prefix), - readback_pv="{}:HEATER:MODE".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:HEATER:MODE:SP", + readback_pv=f"{card_pv_prefix}:HEATER:MODE", ) @parameterized.expand( @@ -271,8 +269,8 @@ def test_WHEN_gas_flow_mode_is_set_THEN_pv_updates(self, _, mode, card): self.ca.assert_setting_setpoint_sets_readback( mode, - set_point_pv="{}:FLOW:STAT:SP".format(card_pv_prefix), - readback_pv="{}:FLOW:STAT".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:FLOW:STAT:SP", + readback_pv=f"{card_pv_prefix}:FLOW:STAT", ) @parameterized.expand( @@ -283,8 +281,8 @@ def test_WHEN_gas_flow_is_set_THEN_pv_updates(self, _, mode, card): self.ca.assert_setting_setpoint_sets_readback( mode, - set_point_pv="{}:FLOW:SP".format(card_pv_prefix), - readback_pv="{}:FLOW".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:FLOW:SP", + readback_pv=f"{card_pv_prefix}:FLOW", ) @parameterized.expand( @@ -297,8 +295,8 @@ def test_WHEN_heater_percent_is_set_THEN_pv_updates(self, _, mode, card): self.ca.assert_setting_setpoint_sets_readback( mode, - set_point_pv="{}:HEATER:SP".format(card_pv_prefix), - readback_pv="{}:HEATER".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:HEATER:SP", + readback_pv=f"{card_pv_prefix}:HEATER", ) @parameterized.expand( @@ -311,8 +309,8 @@ def test_WHEN_heater_voltage_limit_is_set_THEN_pv_updates(self, _, mode, card): self.ca.assert_setting_setpoint_sets_readback( mode, - set_point_pv="{}:HEATER:VOLT_LIMIT:SP".format(card_pv_prefix), - readback_pv="{}:HEATER:VOLT_LIMIT".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:HEATER:VOLT_LIMIT:SP", + readback_pv=f"{card_pv_prefix}:HEATER:VOLT_LIMIT", ) @parameterized.expand( @@ -324,12 +322,12 @@ def test_WHEN_heater_voltage_limit_is_set_THEN_pv_updates(self, _, mode, card): def test_WHEN_heater_power_is_set_via_backdoor_THEN_pv_updates(self, _, test_value, card): card_pv_prefix = get_card_pv_prefix(card) - heater_chan_name = self.ca.get_pv_value("{}:HTRCHAN".format(card_pv_prefix)) + heater_chan_name = self.ca.get_pv_value(f"{card_pv_prefix}:HTRCHAN") self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "power", test_value] ) - self.ca.assert_that_pv_is("{}:HEATER:POWER".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:POWER", test_value) @parameterized.expand( parameterized_list( @@ -340,12 +338,12 @@ def test_WHEN_heater_power_is_set_via_backdoor_THEN_pv_updates(self, _, test_val def test_WHEN_heater_curr_is_set_via_backdoor_THEN_pv_updates(self, _, test_value, card): card_pv_prefix = get_card_pv_prefix(card) - heater_chan_name = self.ca.get_pv_value("{}:HTRCHAN".format(card_pv_prefix)) + heater_chan_name = self.ca.get_pv_value(f"{card_pv_prefix}:HTRCHAN") self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "current", test_value] ) - self.ca.assert_that_pv_is("{}:HEATER:CURR".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:CURR", test_value) @parameterized.expand( parameterized_list( @@ -356,12 +354,12 @@ def test_WHEN_heater_curr_is_set_via_backdoor_THEN_pv_updates(self, _, test_valu def test_WHEN_heater_voltage_is_set_via_backdoor_THEN_pv_updates(self, _, test_value, card): card_pv_prefix = get_card_pv_prefix(card) - heater_chan_name = self.ca.get_pv_value("{}:HTRCHAN".format(card_pv_prefix)) + heater_chan_name = self.ca.get_pv_value(f"{card_pv_prefix}:HTRCHAN") self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "voltage", test_value] ) - self.ca.assert_that_pv_is("{}:HEATER:VOLT".format(card_pv_prefix), test_value) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:VOLT", test_value) @parameterized.expand( parameterized_list( @@ -373,8 +371,8 @@ def test_WHEN_name_is_set_THEN_pv_updates(self, _, test_value, card): self.ca.assert_setting_setpoint_sets_readback( test_value, - readback_pv="{}:NAME".format(card_pv_prefix), - set_point_pv="{}:NAME:SP".format(card_pv_prefix), + readback_pv=f"{card_pv_prefix}:NAME", + set_point_pv=f"{card_pv_prefix}:NAME:SP", ) @parameterized.expand(parameterized_list(itertools.product(GAS_LEVEL_TEST_VALUES, LEVEL_CARDS))) @@ -385,9 +383,7 @@ def test_WHEN_helium_level_is_set_via_backdoor_THEN_pv_updates(self, _, test_val self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "helium_level", test_value] ) - self.ca.assert_that_pv_is_number( - "{}:HELIUM".format(card_pv_prefix), test_value, tolerance=0.01 - ) + self.ca.assert_that_pv_is_number(f"{card_pv_prefix}:HELIUM", test_value, tolerance=0.01) @parameterized.expand(parameterized_list(itertools.product(GAS_LEVEL_TEST_VALUES, LEVEL_CARDS))) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -397,9 +393,7 @@ def test_WHEN_nitrogen_level_is_set_via_backdoor_THEN_pv_updates(self, _, test_v self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [card, "nitrogen_level", test_value] ) - self.ca.assert_that_pv_is_number( - "{}:NITROGEN".format(card_pv_prefix), test_value, tolerance=0.01 - ) + self.ca.assert_that_pv_is_number(f"{card_pv_prefix}:NITROGEN", test_value, tolerance=0.01) @parameterized.expand( parameterized_list(itertools.product(TEMP_CARDS + PRESSURE_CARDS, HEATER_CARDS)) @@ -409,7 +403,7 @@ def test_WHEN_heater_association_is_set_THEN_pv_updates(self, _, parent_card, as with ManagerMode(ChannelAccess()): self.ca.assert_setting_setpoint_sets_readback( - associated_card, "{}:HTRCHAN".format(card_pv_prefix) + associated_card, f"{card_pv_prefix}:HTRCHAN" ) @parameterized.expand( @@ -419,14 +413,14 @@ def test_WHEN_aux_association_is_set_THEN_pv_updates(self, _, parent_card, assoc card_pv_prefix = get_card_pv_prefix(parent_card) with ManagerMode(ChannelAccess()): self.ca.assert_setting_setpoint_sets_readback( - associated_card, "{}:AUXCHAN".format(card_pv_prefix) + associated_card, f"{card_pv_prefix}:AUXCHAN" ) @parameterized.expand(parameterized_list(itertools.product(HELIUM_READ_RATES, LEVEL_CARDS))) def test_WHEN_he_read_rate_is_set_THEN_pv_updates(self, _, test_value, card): card_pv_prefix = get_card_pv_prefix(card) self.ca.assert_setting_setpoint_sets_readback( - test_value, "{}:HELIUM:READ_RATE".format(card_pv_prefix) + test_value, f"{card_pv_prefix}:HELIUM:READ_RATE" ) @parameterized.expand( @@ -443,7 +437,9 @@ def test_WHEN_he_read_rate_is_set_THEN_pv_updates(self, _, test_value, card): @skip_if_recsim("Complex logic not tested in recsim") def test_WHEN_getting_catalog_it_contains_all_cards(self, _, pv, cards): for card in cards: - self.ca.assert_that_pv_value_causes_func_to_return_true(pv, lambda val: card in val) + self.ca.assert_that_pv_value_causes_func_to_return_true( + pv, lambda val, card=card: card in val + ) @parameterized.expand( parameterized_list(itertools.product(MOCK_CALIB_FILES, TEMP_CARDS + PRESSURE_CARDS)) @@ -451,9 +447,7 @@ def test_WHEN_getting_catalog_it_contains_all_cards(self, _, pv, cards): def test_WHEN_setting_calibration_file_THEN_pv_updates(self, _, test_value, card): card_pv_prefix = get_card_pv_prefix(card) with ManagerMode(ChannelAccess()): - self.ca.assert_setting_setpoint_sets_readback( - test_value, "{}:CALFILE".format(card_pv_prefix) - ) + self.ca.assert_setting_setpoint_sets_readback(test_value, f"{card_pv_prefix}:CALFILE") @parameterized.expand(parameterized_list(["O", "R"])) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -467,11 +461,11 @@ def test_WHEN_resistance_suffix_is_changed_THEN_resistance_reads_correctly( [PRIMARY_TEMPERATURE_CHANNEL, "resistance", resistance_value], ) self.ca.assert_that_pv_is( - "{}:RESISTANCE".format(get_card_pv_prefix(PRIMARY_TEMPERATURE_CHANNEL)), + f"{get_card_pv_prefix(PRIMARY_TEMPERATURE_CHANNEL)}:RESISTANCE", resistance_value, ) self.ca.assert_that_pv_alarm_is( - "{}:RESISTANCE".format(get_card_pv_prefix(PRIMARY_TEMPERATURE_CHANNEL)), + f"{get_card_pv_prefix(PRIMARY_TEMPERATURE_CHANNEL)}:RESISTANCE", self.ca.Alarms.NONE, ) @@ -485,7 +479,7 @@ def test_WHEN_heater_voltage_updated_THEN_heater_voltage_percent_updated(self, _ new_percent = 40 card_pv_prefix = get_card_pv_prefix(card) - heater_chan_name = self.ca.get_pv_value("{}:HTRCHAN".format(card_pv_prefix)) + heater_chan_name = self.ca.get_pv_value(f"{card_pv_prefix}:HTRCHAN") self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "voltage", original_voltage] @@ -494,13 +488,13 @@ def test_WHEN_heater_voltage_updated_THEN_heater_voltage_percent_updated(self, _ "backdoor_set_channel_property", [heater_chan_name, "voltage_limit", voltage_limit] ) - self.ca.assert_that_pv_is("{}:HEATER:VOLT_PRCNT".format(card_pv_prefix), original_percent) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:VOLT_PRCNT", original_percent) self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "voltage", new_voltage] ) - self.ca.assert_that_pv_is("{}:HEATER:VOLT_PRCNT".format(card_pv_prefix), new_percent) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:VOLT_PRCNT", new_percent) @parameterized.expand(parameterized_list(itertools.product(TEMP_CARDS + PRESSURE_CARDS))) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -512,7 +506,7 @@ def test_WHEN_voltage_limit_updated_then_voltage_percent_updated(self, _, card): new_percent = 50 card_pv_prefix = get_card_pv_prefix(card) - heater_chan_name = self.ca.get_pv_value("{}:HTRCHAN".format(card_pv_prefix)) + heater_chan_name = self.ca.get_pv_value(f"{card_pv_prefix}:HTRCHAN") self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [heater_chan_name, "voltage", voltage] @@ -521,8 +515,8 @@ def test_WHEN_voltage_limit_updated_then_voltage_percent_updated(self, _, card): "backdoor_set_channel_property", [heater_chan_name, "voltage_limit", original_limit] ) - self.ca.assert_that_pv_is("{}:HEATER:VOLT_PRCNT".format(card_pv_prefix), original_percent) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:VOLT_PRCNT", original_percent) - self.ca.set_pv_value("{}:HEATER:VOLT_LIMIT:SP".format(card_pv_prefix), new_limit) + self.ca.set_pv_value(f"{card_pv_prefix}:HEATER:VOLT_LIMIT:SP", new_limit) - self.ca.assert_that_pv_is("{}:HEATER:VOLT_PRCNT".format(card_pv_prefix), new_percent) + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:VOLT_PRCNT", new_percent) diff --git a/tests/mercuryitc_FLOW_SPC.py b/tests/mercuryitc_FLOW_SPC.py index a7c010af..84f8e8dc 100644 --- a/tests/mercuryitc_FLOW_SPC.py +++ b/tests/mercuryitc_FLOW_SPC.py @@ -1,4 +1,4 @@ -import os +import pathlib import unittest from time import sleep @@ -37,22 +37,20 @@ def get_card_pv_prefix(card): """ if card in TEMP_CARDS: assert card not in PRESSURE_CARDS and card not in LEVEL_CARDS - return "{}".format( - TEMP_CARDS.index(card) + 1 - ) # Only a numeric prefix for temperature cards + return f"{TEMP_CARDS.index(card) + 1}" # Only a numeric prefix for temperature cards elif card in PRESSURE_CARDS: assert card not in LEVEL_CARDS - return "PRESSURE:{}".format(PRESSURE_CARDS.index(card) + 1) + return f"PRESSURE:{PRESSURE_CARDS.index(card) + 1}" elif card in LEVEL_CARDS: - return "LEVEL:{}".format(LEVEL_CARDS.index(card) + 1) + return f"LEVEL:{LEVEL_CARDS.index(card) + 1}" else: raise ValueError("Unknown card") macros = {} -macros.update({"TEMP_{}".format(key): val for key, val in enumerate(TEMP_CARDS, start=1)}) -macros.update({"PRESSURE_{}".format(key): val for key, val in enumerate(PRESSURE_CARDS, start=1)}) -macros.update({"LEVEL_{}".format(key): val for key, val in enumerate(LEVEL_CARDS, start=1)}) +macros.update({f"TEMP_{key}": val for key, val in enumerate(TEMP_CARDS, start=1)}) +macros.update({f"PRESSURE_{key}": val for key, val in enumerate(PRESSURE_CARDS, start=1)}) +macros.update({f"LEVEL_{key}": val for key, val in enumerate(LEVEL_CARDS, start=1)}) macros["SPC_TYPE_1"] = "FLOW" macros["SPC_TYPE_2"] = "FLOW" macros["FLOW_SPC_PRESSURE_1"] = 1 @@ -64,8 +62,8 @@ def get_card_pv_prefix(card): macros["FLOW_SPC_OFFSET_DURATION"] = SPC_OFFSET_DURATION macros["FLOW_SPC_GAIN"] = SPC_GAIN -macros["CALIB_BASE_DIR"] = EPICS_TOP.replace("\\", "/") -macros["CALIB_DIR"] = os.path.join("support", "mercuryitc", "master", "settings").replace("\\", "/") +macros["CALIB_BASE_DIR"] = EPICS_TOP.as_posix() +macros["CALIB_DIR"] = pathlib.PurePath("support", "mercuryitc", "master", "settings").as_posix() macros["FLOW_SPC_TABLE_FILE"] = "little_blue_cryostat.txt" DEVICE_PREFIX = "MERCURY_01" @@ -73,9 +71,9 @@ def get_card_pv_prefix(card): IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join( - EPICS_TOP, "ioc", "master", "MERCURY_ITC", "iocBoot", "iocMERCURY-IOC-01" - ), + "directory": ( + EPICS_TOP / "ioc" / "master" / "MERCURY_ITC" / "iocBoot" / "iocMERCURY-IOC-01" + ).as_posix(), "emulator": "mercuryitc", "macros": macros, }, @@ -149,49 +147,49 @@ def setUp(self): self.ca = ChannelAccess(device_prefix=DEVICE_PREFIX, default_timeout=20) card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) self.ca.assert_setting_setpoint_sets_readback( - "OFF", readback_pv="{}:SPC".format(card_pv_prefix), expected_alarm=self.ca.Alarms.MAJOR + "OFF", readback_pv=f"{card_pv_prefix}:SPC", expected_alarm=self.ca.Alarms.MAJOR ) def test_WHEN_auto_flow_set_THEN_pv_updates_and_states_are_set(self): card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) pressure_card_pv_prefix = get_card_pv_prefix(PRESSURE_CARDS[0]) - self.ca.set_pv_value("{}:PID:AUTO:SP".format(card_pv_prefix), "OFF") - self.ca.set_pv_value("{}:FLOW:STAT:SP".format(card_pv_prefix), "Auto") - self.ca.set_pv_value("{}:HEATER:MODE:SP".format(card_pv_prefix), "Manual") - self.ca.set_pv_value("{}:FLOW:STAT:SP".format(pressure_card_pv_prefix), "Manual") + self.ca.set_pv_value(f"{card_pv_prefix}:PID:AUTO:SP", "OFF") + self.ca.set_pv_value(f"{card_pv_prefix}:FLOW:STAT:SP", "Auto") + self.ca.set_pv_value(f"{card_pv_prefix}:HEATER:MODE:SP", "Manual") + self.ca.set_pv_value(f"{pressure_card_pv_prefix}:FLOW:STAT:SP", "Manual") self.ca.assert_setting_setpoint_sets_readback( "ON", - set_point_pv="{}:SPC:SP".format(card_pv_prefix), - readback_pv="{}:SPC".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:SPC:SP", + readback_pv=f"{card_pv_prefix}:SPC", ) - self.ca.assert_that_pv_is("{}:PID:AUTO".format(card_pv_prefix), "ON") - self.ca.assert_that_pv_is("{}:FLOW:STAT".format(card_pv_prefix), "Manual") - self.ca.assert_that_pv_is("{}:HEATER:MODE".format(card_pv_prefix), "Auto") - self.ca.assert_that_pv_is("{}:FLOW:STAT".format(pressure_card_pv_prefix), "Auto") - self.ca.assert_that_pv_is("{}:SPC:SP".format(pressure_card_pv_prefix), "ON") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:PID:AUTO", "ON") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:FLOW:STAT", "Manual") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:MODE", "Auto") + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:FLOW:STAT", "Auto") + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:SPC:SP", "ON") def test_WHEN_auto_flow_set_off_THEN_pv_updates_and_states_are_not_set(self): card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) pressure_card_pv_prefix = get_card_pv_prefix(PRESSURE_CARDS[0]) - self.ca.set_pv_value("{}:PID:AUTO:SP".format(card_pv_prefix), "OFF") - self.ca.set_pv_value("{}:FLOW:STAT:SP".format(card_pv_prefix), "Auto") - self.ca.set_pv_value("{}:HEATER:MODE:SP".format(card_pv_prefix), "Manual") - self.ca.set_pv_value("{}:FLOW:STAT:SP".format(pressure_card_pv_prefix), "Manual") + self.ca.set_pv_value(f"{card_pv_prefix}:PID:AUTO:SP", "OFF") + self.ca.set_pv_value(f"{card_pv_prefix}:FLOW:STAT:SP", "Auto") + self.ca.set_pv_value(f"{card_pv_prefix}:HEATER:MODE:SP", "Manual") + self.ca.set_pv_value(f"{pressure_card_pv_prefix}:FLOW:STAT:SP", "Manual") self.ca.assert_setting_setpoint_sets_readback( "OFF", - set_point_pv="{}:SPC:SP".format(card_pv_prefix), - readback_pv="{}:SPC".format(card_pv_prefix), + set_point_pv=f"{card_pv_prefix}:SPC:SP", + readback_pv=f"{card_pv_prefix}:SPC", expected_alarm=self.ca.Alarms.MAJOR, ) - self.ca.assert_that_pv_is("{}:PID:AUTO".format(card_pv_prefix), "OFF") - self.ca.assert_that_pv_is("{}:FLOW:STAT".format(card_pv_prefix), "Auto") - self.ca.assert_that_pv_is("{}:HEATER:MODE".format(card_pv_prefix), "Manual") - self.ca.assert_that_pv_is("{}:FLOW:STAT".format(pressure_card_pv_prefix), "Manual") - self.ca.assert_that_pv_is("{}:SPC:SP".format(pressure_card_pv_prefix), "OFF") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:PID:AUTO", "OFF") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:FLOW:STAT", "Auto") + self.ca.assert_that_pv_is(f"{card_pv_prefix}:HEATER:MODE", "Manual") + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:FLOW:STAT", "Manual") + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:SPC:SP", "OFF") def set_temp_reading_and_sp(self, reading, set_point, spc_state="On"): """ @@ -201,8 +199,8 @@ def set_temp_reading_and_sp(self, reading, set_point, spc_state="On"): :param spc_state: State to set SPC to (defaults to On) """ card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) - self.ca.set_pv_value("{}:SPC:SP".format(card_pv_prefix), spc_state) - self.ca.set_pv_value("{}:TEMP:SP".format(card_pv_prefix), set_point) + self.ca.set_pv_value(f"{card_pv_prefix}:SPC:SP", spc_state) + self.ca.set_pv_value(f"{card_pv_prefix}:TEMP:SP", set_point) self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [TEMP_CARDS[0], "temperature", reading] ) @@ -216,9 +214,7 @@ def test_WHEN_auto_flow_set_on_and_temp_lower_than_2_deadbands_THEN_pressure_set pressure_card_pv_prefix = get_card_pv_prefix(PRESSURE_CARDS[0]) self.set_temp_reading_and_sp(reading, set_point) - self.ca.assert_that_pv_is( - "{}:PRESSURE:SP:RBV".format(pressure_card_pv_prefix), SPC_MIN_PRESSURE - ) + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:PRESSURE:SP:RBV", SPC_MIN_PRESSURE) @parameterized.expand([(10,), (1,), (300,), (12,), (20,)]) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -230,11 +226,11 @@ def test_WHEN_auto_flow_set_on_and_temp_low_but_within_1_to_2_deadbands_THEN_pre self.set_temp_reading_and_sp(reading, set_point) self.ca.assert_that_pv_is( - "{}:PRESSURE:SP:RBV".format(pressure_card_pv_prefix), pressure_for(set_point) + f"{pressure_card_pv_prefix}:PRESSURE:SP:RBV", pressure_for(set_point) ) sleep(1.5) self.ca.assert_that_pv_is( - "{}:PRESSURE:SP:RBV".format(pressure_card_pv_prefix), pressure_for(set_point) + f"{pressure_card_pv_prefix}:PRESSURE:SP:RBV", pressure_for(set_point) ) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -247,12 +243,12 @@ def test_WHEN_auto_flow_set_on_and_temp_at_setpoint_THEN_pressure_set_to_pressur self.set_temp_reading_and_sp(reading, set_point) self.ca.assert_that_pv_is_number( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), + f"{pressure_card_pv_prefix}:PRESSURE:SP", pressure_for(set_point) + SPC_OFFSET, tolerance=SPC_OFFSET / 4, ) # should see number in ramp self.ca.assert_that_pv_is( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), pressure_for(set_point) + f"{pressure_card_pv_prefix}:PRESSURE:SP", pressure_for(set_point) ) # final value @skip_if_recsim("Lewis backdoor not available in recsim") @@ -274,11 +270,11 @@ def test_WHEN_auto_flow_set_on_and_temp_above_setpoint_by_more_than_deadband_THE self.set_temp_reading_and_sp(reading, set_point) self.ca.assert_that_pv_is_number( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_pressure, tolerance=0.01 + f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_pressure, tolerance=0.01 ) # final value sleep(1.5) # wait for possible ramp self.ca.assert_that_pv_is_number( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_pressure, tolerance=0.01 + f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_pressure, tolerance=0.01 ) # final value @skip_if_recsim("Lewis backdoor not available in recsim") @@ -293,7 +289,7 @@ def test_WHEN_auto_flow_set_on_and_pressure_would_be_high_THEN_pressure_set_to_m self.set_temp_reading_and_sp(reading, set_point) self.ca.assert_that_pv_is( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), SPC_MAX_PRESSURE + f"{pressure_card_pv_prefix}:PRESSURE:SP", SPC_MAX_PRESSURE ) # final value @skip_if_recsim("Lewis backdoor not available in recsim") @@ -304,11 +300,11 @@ def test_WHEN_auto_flow_set_off_THEN_pressure_is_not_updated(self): pressure_card_pv_prefix = get_card_pv_prefix(PRESSURE_CARDS[0]) expected_value = -10 - self.ca.set_pv_value("{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_value) + self.ca.set_pv_value(f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_value) self.set_temp_reading_and_sp(reading, set_point, "OFF") - self.ca.assert_that_pv_is("{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_value) + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_auto_flow_on_but_error_in_temp_readback_THEN_pressure_is_not_updated(self): @@ -317,7 +313,7 @@ def test_WHEN_auto_flow_on_but_error_in_temp_readback_THEN_pressure_is_not_updat card_pv_prefix = get_card_pv_prefix(TEMP_CARDS[0]) pressure_card_pv_prefix = get_card_pv_prefix(PRESSURE_CARDS[0]) expected_value = -10 - self.ca.set_pv_value("{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_value) + self.ca.set_pv_value(f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_value) with self._lewis.backdoor_simulate_disconnected_device(): # we have a lot of db records scanning in the ioc, they will start to fail but it may take a while @@ -325,16 +321,14 @@ def test_WHEN_auto_flow_on_but_error_in_temp_readback_THEN_pressure_is_not_updat # the stream device lock timeout instead. # So we need to wait for at least as long as stream device lock timeout to see an alarm raised` self.ca.assert_that_pv_alarm_is( - "{}:TEMP:SP:RBV".format(card_pv_prefix), self.ca.Alarms.INVALID, timeout=60 + f"{card_pv_prefix}:TEMP:SP:RBV", self.ca.Alarms.INVALID, timeout=60 ) - self.ca.set_pv_value("{}:SPC:SP".format(card_pv_prefix), "ON") - self.ca.set_pv_value("{}:TEMP:SP".format(card_pv_prefix), set_point) + self.ca.set_pv_value(f"{card_pv_prefix}:SPC:SP", "ON") + self.ca.set_pv_value(f"{card_pv_prefix}:TEMP:SP", set_point) - self.ca.assert_that_pv_is( - "{}:PRESSURE:SP".format(pressure_card_pv_prefix), expected_value - ) + self.ca.assert_that_pv_is(f"{pressure_card_pv_prefix}:PRESSURE:SP", expected_value) self.ca.assert_that_pv_alarm_is( - "{}:TEMP:SP:RBV".format(card_pv_prefix), self.ca.Alarms.NONE, timeout=60 + f"{card_pv_prefix}:TEMP:SP:RBV", self.ca.Alarms.NONE, timeout=60 ) diff --git a/tests/mercuryitc_VTI_SPC.py b/tests/mercuryitc_VTI_SPC.py index 6b50f8e6..a8eb1f76 100644 --- a/tests/mercuryitc_VTI_SPC.py +++ b/tests/mercuryitc_VTI_SPC.py @@ -1,4 +1,4 @@ -import os +import pathlib import unittest from utils.channel_access import ChannelAccess @@ -34,27 +34,25 @@ def get_card_pv_prefix(card): """ if card in TEMP_CARDS: assert card not in PRESSURE_CARDS and card not in LEVEL_CARDS - return "{}".format( - TEMP_CARDS.index(card) + 1 - ) # Only a numeric prefix for temperature cards + return f"{TEMP_CARDS.index(card) + 1}" # Only a numeric prefix for temperature cards elif card in PRESSURE_CARDS: assert card not in LEVEL_CARDS - return "PRESSURE:{}".format(PRESSURE_CARDS.index(card) + 1) + return f"PRESSURE:{PRESSURE_CARDS.index(card) + 1}" elif card in LEVEL_CARDS: - return "LEVEL:{}".format(LEVEL_CARDS.index(card) + 1) + return f"LEVEL:{LEVEL_CARDS.index(card) + 1}" else: raise ValueError("Unknown card") macros = {} -macros.update({"TEMP_{}".format(key): val for key, val in enumerate(TEMP_CARDS, start=1)}) -macros.update({"PRESSURE_{}".format(key): val for key, val in enumerate(PRESSURE_CARDS, start=1)}) -macros.update({"LEVEL_{}".format(key): val for key, val in enumerate(LEVEL_CARDS, start=1)}) +macros.update({f"TEMP_{key}": val for key, val in enumerate(TEMP_CARDS, start=1)}) +macros.update({f"PRESSURE_{key}": val for key, val in enumerate(PRESSURE_CARDS, start=1)}) +macros.update({f"LEVEL_{key}": val for key, val in enumerate(LEVEL_CARDS, start=1)}) macros["SPC_TYPE_1"] = "VTI" macros["SPC_TYPE_2"] = "VTI" -macros["CALIB_BASE_DIR"] = EPICS_TOP.replace("\\", "/") -macros["CALIB_DIR"] = os.path.join("support", "mercuryitc", "master", "settings").replace("\\", "/") +macros["CALIB_BASE_DIR"] = pathlib.PurePath(EPICS_TOP).as_posix() +macros["CALIB_DIR"] = pathlib.PurePath("support", "mercuryitc", "master", "settings").as_posix() macros["VTI_SPC_PRESSURE_1"] = 1 macros["VTI_SPC_PRESSURE_2"] = 2 @@ -64,8 +62,10 @@ def get_card_pv_prefix(card): macros["VTI_SPC_TEMP_CUTOFF_POINT"] = 5 macros["VTI_SPC_TEMP_SCALE"] = 5 -macros["VTI_CALIB_BASE_DIR"] = "C:/Instrument/Apps/EPICS/support" -macros["VTI_SENS_DIR"] = "mercuryitc/master/test_calib/vti_spc" +macros["VTI_CALIB_BASE_DIR"] = (EPICS_TOP / "support").as_posix() +macros["VTI_SENS_DIR"] = pathlib.PurePath( + "mercuryitc", "master", "test_calib", "vti_spc" +).as_posix() DEVICE_PREFIX = "MERCURY_01" @@ -73,9 +73,9 @@ def get_card_pv_prefix(card): IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join( - EPICS_TOP, "ioc", "master", "MERCURY_ITC", "iocBoot", "iocMERCURY-IOC-01" - ), + "directory": ( + EPICS_TOP / "ioc" / "master" / "MERCURY_ITC" / "iocBoot" / "iocMERCURY-IOC-01" + ).as_posix(), "emulator": "mercuryitc", "macros": macros, }, diff --git a/tests/mezflipr_v1.py b/tests/mezflipr_v1.py index 74b5c6dd..1e747300 100644 --- a/tests/mezflipr_v1.py +++ b/tests/mezflipr_v1.py @@ -21,15 +21,15 @@ "emulator_launcher_class": CommandLineEmulatorLauncher, "emulator_command_line": "{} {} --port {{port}}".format( os.path.join(DEFAULT_PY_PATH, "python.exe"), - os.path.join( - EPICS_TOP, - "support", - "deviceemulator", - "master", - "other_emulators", - "mezei_flipper", - "flipper_emulator.py", - ), + ( + EPICS_TOP + / "support" + / "deviceemulator" + / "master" + / "other_emulators" + / "mezei_flipper" + / "flipper_emulator.py" + ).as_posix(), ), "macros": { "POLARISERPRESENT": "yes", @@ -60,34 +60,30 @@ def test_GIVEN_device_is_connected_THEN_can_read_id(self): @parameterized.expand(["ANALYSER", "POLARISER"]) def test_GIVEN_amplitude_is_set_THEN_amplitude_can_be_read_back(self, flipper): for val in [0.0, 0.12, 2.99]: # Amplitude should be limited to 3A - self.ca.assert_setting_setpoint_sets_readback( - val, readback_pv="{}:AMPLITUDE".format(flipper) - ) + self.ca.assert_setting_setpoint_sets_readback(val, readback_pv=f"{flipper}:AMPLITUDE") @parameterized.expand(["ANALYSER", "POLARISER"]) def test_GIVEN_compensation_is_set_THEN_compensation_can_be_read_back(self, flipper): for val in [0.0, 0.12, 5000.5]: self.ca.assert_setting_setpoint_sets_readback( - val, readback_pv="{}:COMPENSATION".format(flipper) + val, readback_pv=f"{flipper}:COMPENSATION" ) @parameterized.expand(["ANALYSER", "POLARISER"]) def test_GIVEN_dt_is_set_THEN_dt_can_be_read_back(self, flipper): for val in [0.0, -0.12, -5000.5]: # DT only accepts negative values. - self.ca.assert_setting_setpoint_sets_readback(val, readback_pv="{}:DT".format(flipper)) + self.ca.assert_setting_setpoint_sets_readback(val, readback_pv=f"{flipper}:DT") @parameterized.expand(["ANALYSER", "POLARISER"]) def test_GIVEN_constant_is_set_THEN_constant_can_be_read_back(self, flipper): for val in [0.0, 0.12, 5000.5]: - self.ca.assert_setting_setpoint_sets_readback( - val, readback_pv="{}:CONSTANT".format(flipper) - ) + self.ca.assert_setting_setpoint_sets_readback(val, readback_pv=f"{flipper}:CONSTANT") @parameterized.expand(["ANALYSER", "POLARISER"]) - def test_GIVEN_constant_is_set_THEN_constant_can_be_read_back(self, flipper): + def test_GIVEN_filename_is_set_THEN_filename_can_be_read_back(self, flipper): for filename in [r"C:\a.txt", r"C:\b.txt"]: self.ca.assert_setting_setpoint_sets_readback( - filename, readback_pv="{}:FILENAME".format(flipper) + filename, readback_pv=f"{flipper}:FILENAME" ) @parameterized.expand( diff --git a/tests/mezflipr_v2.py b/tests/mezflipr_v2.py index 77dee06d..cb44a3af 100644 --- a/tests/mezflipr_v2.py +++ b/tests/mezflipr_v2.py @@ -3,6 +3,7 @@ from parameterized import parameterized from utils.channel_access import ChannelAccess +from utils.emulator_launcher import EmulatorLauncher from utils.ioc_launcher import get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc, parameterized_list, skip_if_recsim @@ -38,38 +39,38 @@ def test_WHEN_ioc_is_started_THEN_ioc_is_not_disabled(self): @parameterized.expand(parameterized_list(["On", "Off"])) def test_GIVEN_power_is_set_THEN_can_be_read_back(self, _, state): - self.ca.assert_setting_setpoint_sets_readback(state, readback_pv="{}:POWER".format(flipper)) + self.ca.assert_setting_setpoint_sets_readback(state, readback_pv=f"{flipper}:POWER") @parameterized.expand(parameterized_list([0.0, 0.12, 5000.5])) def test_GIVEN_compensation_is_set_THEN_compensation_can_be_read_back(self, _, compensation): self.ca.assert_setting_setpoint_sets_readback( - compensation, readback_pv="{}:COMPENSATION".format(flipper) + compensation, readback_pv=f"{flipper}:COMPENSATION" ) def _assert_mode(self, mode): - self.ca.assert_that_pv_is("{}:MODE".format(flipper), mode) - self.ca.assert_that_pv_alarm_is("{}:MODE".format(flipper), self.ca.Alarms.NONE) + self.ca.assert_that_pv_is(f"{flipper}:MODE", mode) + self.ca.assert_that_pv_alarm_is(f"{flipper}:MODE", self.ca.Alarms.NONE) def _assert_params(self, param): self.ca.assert_that_pv_value_causes_func_to_return_true( - "{}:PARAMS".format(flipper), lambda val: val is not None and val.rstrip() == param + f"{flipper}:PARAMS", lambda val: val is not None and val.rstrip() == param ) - self.ca.assert_that_pv_alarm_is("{}:PARAMS".format(flipper), self.ca.Alarms.NONE) + self.ca.assert_that_pv_alarm_is(f"{flipper}:PARAMS", self.ca.Alarms.NONE) @skip_if_recsim("State of device not simulated in recsim") def test_WHEN_constant_current_mode_set_THEN_parameters_reflected_and_mode_is_constant_current( self, ): param = 25 - self.ca.set_pv_value("{}:CURRENT:SP".format(flipper), param) + self.ca.set_pv_value(f"{flipper}:CURRENT:SP", param) - self._assert_params("{:.1f}".format(param)) + self._assert_params(f"{param:.1f}") self._assert_mode("static") @skip_if_recsim("State of device not simulated in recsim") def test_WHEN_steps_mode_set_THEN_parameters_reflected_and_mode_is_steps(self): param = "[some, random, list, of, data]" - self.ca.set_pv_value("{}:CURRENT_STEPS:SP".format(flipper), param) + self.ca.set_pv_value(f"{flipper}:CURRENT_STEPS:SP", param) self._assert_params(param) self._assert_mode("steps") @@ -77,7 +78,7 @@ def test_WHEN_steps_mode_set_THEN_parameters_reflected_and_mode_is_steps(self): @skip_if_recsim("State of device not simulated in recsim") def test_WHEN_analytical_mode_set_THEN_parameters_reflected_and_mode_is_analytical(self): param = "a long string of parameters which is longer than 40 characters" - self.ca.set_pv_value("{}:CURRENT_ANALYTICAL:SP".format(flipper), param) + self.ca.set_pv_value(f"{flipper}:CURRENT_ANALYTICAL:SP", param) self._assert_params(param) self._assert_mode("analytical") @@ -85,7 +86,7 @@ def test_WHEN_analytical_mode_set_THEN_parameters_reflected_and_mode_is_analytic @skip_if_recsim("State of device not simulated in recsim") def test_WHEN_file_mode_set_THEN_parameters_reflected_and_mode_is_file(self): param = r"C:\some\file\path\to\a\file\in\a\really\deep\directory\structure\with\path\longer\than\40\characters" - self.ca.set_pv_value("{}:FILENAME:SP".format(flipper), param) + self.ca.set_pv_value(f"{flipper}:FILENAME:SP", param) self._assert_params(param) self._assert_mode("file") @@ -93,8 +94,9 @@ def test_WHEN_file_mode_set_THEN_parameters_reflected_and_mode_is_file(self): @parameterized.expand(parameterized_list(["MODE", "COMPENSATION", "PARAMS"])) @skip_if_recsim("Recsim cannot test disconnected device") def test_WHEN_device_is_disconnected_THEN_pvs_are_in_invalid_alarm(self, _, pv): - self.ca.assert_that_pv_alarm_is("{}:{}".format(flipper, pv), self.ca.Alarms.NONE) + assert isinstance(self._lewis, EmulatorLauncher), "_lewis must be an EmulatorLauncher" + self.ca.assert_that_pv_alarm_is(f"{flipper}:{pv}", self.ca.Alarms.NONE) with self._lewis.backdoor_simulate_disconnected_device(): - self.ca.assert_that_pv_alarm_is("{}:{}".format(flipper, pv), self.ca.Alarms.INVALID) + self.ca.assert_that_pv_alarm_is(f"{flipper}:{pv}", self.ca.Alarms.INVALID) # Assert alarms clear on reconnection - self.ca.assert_that_pv_alarm_is("{}:{}".format(flipper, pv), self.ca.Alarms.NONE) + self.ca.assert_that_pv_alarm_is(f"{flipper}:{pv}", self.ca.Alarms.NONE) diff --git a/tests/mk3chopper.py b/tests/mk3chopper.py index aa35a9f7..6d2744d4 100644 --- a/tests/mk3chopper.py +++ b/tests/mk3chopper.py @@ -38,13 +38,13 @@ def test_WHEN_ioc_is_in_remote_mode_THEN_it_has_no_alarm(self): # In RECSIM, switch to remote explicitly. DEVSIM can only have remote mode so no switch needed if IOCRegister.uses_rec_sim: # Bug in CA channel. Reports invalid alarm severity if you set enum directly - self.ca.set_pv_value("SIM:{}.VAL".format(self.COMP_MODE_PV), 1) + self.ca.set_pv_value(f"SIM:{self.COMP_MODE_PV}.VAL", 1) self.ca.assert_that_pv_is(self.COMP_MODE_PV, self.REMOTE) self.ca.assert_that_pv_alarm_is(self.COMP_MODE_PV, ChannelAccess.Alarms.NONE) @skip_if_devsim("Can't switch to local mode in DEVSIM") def test_WHEN_ioc_is_in_local_mode_THEN_it_has_a_major_alarm(self): # Bug in CA channel. Reports invalid alarm severity if you set enum directly - self.ca.set_pv_value("SIM:{}.VAL".format(self.COMP_MODE_PV), 0) + self.ca.set_pv_value(f"SIM:{self.COMP_MODE_PV}.VAL", 0) self.ca.assert_that_pv_is(self.COMP_MODE_PV, self.LOCAL) self.ca.assert_that_pv_alarm_is(self.COMP_MODE_PV, ChannelAccess.Alarms.MAJOR) diff --git a/tests/mkspr4kb.py b/tests/mkspr4kb.py index 983666ca..ce1d50d1 100644 --- a/tests/mkspr4kb.py +++ b/tests/mkspr4kb.py @@ -60,7 +60,7 @@ CHANNELS = ["CH1", "CH2"] -class MKS_PR4000B_Tests(unittest.TestCase): +class MKSPR4000BTests(unittest.TestCase): """ Tests for the MKSPR4K IOC. """ @@ -74,7 +74,7 @@ def test_WHEN_ioc_is_started_THEN_it_is_not_disabled(self): @parameterized.expand(parameterized_list(CHANNELS)) def test_WHEN_ioc_is_started_THEN_channels_are_not_disabled(self, _, chan): - self.ca.assert_that_pv_is("{}:DISABLE".format(chan), "COMMS ENABLED") + self.ca.assert_that_pv_is(f"{chan}:DISABLE", "COMMS ENABLED") @parameterized.expand(parameterized_list(CONTROL_MODES)) def test_WHEN_set_control_mode_THEN_readback_updates(self, _, mode): @@ -87,109 +87,109 @@ def test_WHEN_set_control_mode_THEN_readback_updates(self, _, mode): @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) def test_WHEN_channel_setpoint_is_set_THEN_setpoint_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:VAL:SP".format(chan), readback_pv="{}:VAL:SP:RBV".format(chan) + val, set_point_pv=f"{chan}:VAL:SP", readback_pv=f"{chan}:VAL:SP:RBV" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) def test_WHEN_channel_setpoint_is_set_THEN_value_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:VAL:SP".format(chan), readback_pv="{}:VAL".format(chan) + val, set_point_pv=f"{chan}:VAL:SP", readback_pv=f"{chan}:VAL" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, VALVE_STATES))) def test_WHEN_valve_state_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:VALVE:SP".format(chan), readback_pv="{}:VALVE".format(chan) + val, set_point_pv=f"{chan}:VALVE:SP", readback_pv=f"{chan}:VALVE" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, VALVE_STATES))) def test_WHEN_relay_state_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:RELAY:SP".format(chan), readback_pv="{}:RELAY".format(chan) + val, set_point_pv=f"{chan}:RELAY:SP", readback_pv=f"{chan}:RELAY" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) def test_WHEN_gain_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:GAIN:SP".format(chan), readback_pv="{}:GAIN".format(chan) + val, set_point_pv=f"{chan}:GAIN:SP", readback_pv=f"{chan}:GAIN" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_offset_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, set_point_pv="{}:OFFSET:SP".format(chan), readback_pv="{}:OFFSET".format(chan) + val, set_point_pv=f"{chan}:OFFSET:SP", readback_pv=f"{chan}:OFFSET" ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_rtd_offset_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:RTDOFFSET:SP".format(chan), - readback_pv="{}:RTDOFFSET".format(chan), + set_point_pv=f"{chan}:RTDOFFSET:SP", + readback_pv=f"{chan}:RTDOFFSET", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_input_range_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:INP:RANGE:SP".format(chan), - readback_pv="{}:INP:RANGE".format(chan), + set_point_pv=f"{chan}:INP:RANGE:SP", + readback_pv=f"{chan}:INP:RANGE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_output_range_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:OUTP:RANGE:SP".format(chan), - readback_pv="{}:OUTP:RANGE".format(chan), + set_point_pv=f"{chan}:OUTP:RANGE:SP", + readback_pv=f"{chan}:OUTP:RANGE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_external_input_range_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:EXTINP:RANGE:SP".format(chan), - readback_pv="{}:EXTINP:RANGE".format(chan), + set_point_pv=f"{chan}:EXTINP:RANGE:SP", + readback_pv=f"{chan}:EXTINP:RANGE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_INTEGER_VALUES))) def test_WHEN_external_output_range_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:EXTOUTP:RANGE:SP".format(chan), - readback_pv="{}:EXTOUTP:RANGE".format(chan), + set_point_pv=f"{chan}:EXTOUTP:RANGE:SP", + readback_pv=f"{chan}:EXTOUTP:RANGE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, SIGNAL_MODES))) def test_WHEN_signal_mode_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:SIGNALMODE:SP".format(chan), - readback_pv="{}:SIGNALMODE".format(chan), + set_point_pv=f"{chan}:SIGNALMODE:SP", + readback_pv=f"{chan}:SIGNALMODE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, LIMIT_MODES))) def test_WHEN_limit_mode_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:LIMITMODE:SP".format(chan), - readback_pv="{}:LIMITMODE".format(chan), + set_point_pv=f"{chan}:LIMITMODE:SP", + readback_pv=f"{chan}:LIMITMODE", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) def test_WHEN_upper_limit_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:UPPERLIMIT:SP".format(chan), - readback_pv="{}:UPPERLIMIT".format(chan), + set_point_pv=f"{chan}:UPPERLIMIT:SP", + readback_pv=f"{chan}:UPPERLIMIT", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) def test_WHEN_lower_limit_setpoint_is_set_THEN_readback_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( val, - set_point_pv="{}:LOWERLIMIT:SP".format(chan), - readback_pv="{}:LOWERLIMIT".format(chan), + set_point_pv=f"{chan}:LOWERLIMIT:SP", + readback_pv=f"{chan}:LOWERLIMIT", ) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) @@ -200,25 +200,25 @@ def test_WHEN_external_input_is_set_via_backdoor_THEN_readback_updates(self, _, self._lewis.backdoor_run_function_on_device( "backdoor_set_channel_property", [chan_number, "external_input", val] ) - self.ca.assert_that_pv_is_number("{}:EXTIN".format(chan), val, tolerance=0.001) + self.ca.assert_that_pv_is_number(f"{chan}:EXTIN", val, tolerance=0.001) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, UNITS))) @skip_if_recsim("Complex behaviour not properly emulated (values push from protocol).") def test_WHEN_range_units_are_set_THEN_readbacks_updates(self, _, chan, units): self.ca.assert_setting_setpoint_sets_readback( units, - readback_pv="{}:RANGE:UNITS".format(chan), - set_point_pv="{}:RANGE:UNITS:SP".format(chan), + readback_pv=f"{chan}:RANGE:UNITS", + set_point_pv=f"{chan}:RANGE:UNITS:SP", ) # Units should also be copied to value's EGU field - self.ca.assert_that_pv_is("{}:VAL.EGU".format(chan), units) - self.ca.assert_that_pv_is("{}:VAL:SP.EGU".format(chan), units) - self.ca.assert_that_pv_is("{}:VAL:SP:RBV.EGU".format(chan), units) + self.ca.assert_that_pv_is(f"{chan}:VAL.EGU", units) + self.ca.assert_that_pv_is(f"{chan}:VAL:SP.EGU", units) + self.ca.assert_that_pv_is(f"{chan}:VAL:SP:RBV.EGU", units) @parameterized.expand(parameterized_list(itertools.product(CHANNELS, TEST_FLOAT_VALUES))) @skip_if_recsim("Complex behaviour not properly emulated (values push from protocol).") def test_WHEN_range_is_set_THEN_readbacks_updates(self, _, chan, val): self.ca.assert_setting_setpoint_sets_readback( - val, readback_pv="{}:RANGE".format(chan), set_point_pv="{}:RANGE:SP".format(chan) + val, readback_pv=f"{chan}:RANGE", set_point_pv=f"{chan}:RANGE:SP" ) diff --git a/tests/motion_setpoints.py b/tests/motion_setpoints.py index 50b3024e..14a6e722 100644 --- a/tests/motion_setpoints.py +++ b/tests/motion_setpoints.py @@ -21,13 +21,13 @@ # Create 2 Galils IOCS = [ { - "name": "GALIL_0{}".format(i), + "name": f"GALIL_0{i}", "directory": get_default_ioc_dir("GALIL", i), "custom_prefix": "MOT", - "pv_for_existence": "MTR0{}01".format(i), + "pv_for_existence": f"MTR0{i}01", "macros": { "GALILADDR": GALIL_ADDR, - "MTRCTRL": "0{}".format(i), + "MTRCTRL": f"0{i}", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, } @@ -96,7 +96,7 @@ def assert_alarm_state_of_posn(channel_access, expected_state): def get_motor_pv_from_axis_num(axis_num): controller = 1 if axis_num < GALIL_AXES_PER_CONTROLLER else 2 axis_num = (axis_num % GALIL_AXES_PER_CONTROLLER) + 1 - return "MTR0{}0{}".format(controller, axis_num) + return f"MTR0{controller}0{axis_num}" def modify_file_and_assert_test(channel_access, lookup_file, old_text, new_text, test): @@ -133,30 +133,30 @@ def setUpClass(cls): cls.channel_access_instances = {1: cls.ca1D, 2: cls.ca2D, 10: cls.ca10D} for axis in range(1, 9): - cls.motor_ca.set_pv_value("MTR010{}.VMAX".format(axis), 5, sleep_after_set=0) - cls.motor_ca.set_pv_value("MTR010{}.VELO".format(axis), 5, sleep_after_set=0) + cls.motor_ca.set_pv_value(f"MTR010{axis}.VMAX", 5, sleep_after_set=0) + cls.motor_ca.set_pv_value(f"MTR010{axis}.VELO", 5, sleep_after_set=0) for axis in range(1, 3): - cls.motor_ca.set_pv_value("MTR020{}.VMAX".format(axis), 5, sleep_after_set=0) - cls.motor_ca.set_pv_value("MTR020{}.VELO".format(axis), 5, sleep_after_set=0) + cls.motor_ca.set_pv_value(f"MTR020{axis}.VMAX", 5, sleep_after_set=0) + cls.motor_ca.set_pv_value(f"MTR020{axis}.VELO", 5, sleep_after_set=0) def setUp(self): self.ca1D.set_pv_value("COORD0:OFFSET:SP", 0, sleep_after_set=0) self.ca1D.assert_that_pv_is("STATIONARY0", 1, timeout=10) for axis in range(2): - self.ca2D.set_pv_value("COORD{}:OFFSET:SP".format(axis), 0, sleep_after_set=0) - self.ca2D.assert_that_pv_is("STATIONARY{}".format(axis), 1, timeout=10) + self.ca2D.set_pv_value(f"COORD{axis}:OFFSET:SP", 0, sleep_after_set=0) + self.ca2D.assert_that_pv_is(f"STATIONARY{axis}", 1, timeout=10) for axis in range(10): - self.ca10D.set_pv_value("COORD{}:OFFSET:SP".format(axis), 0, sleep_after_set=0) - self.ca10D.assert_that_pv_is("STATIONARY{}".format(axis), 1, timeout=10) + self.ca10D.set_pv_value(f"COORD{axis}:OFFSET:SP", 0, sleep_after_set=0) + self.ca10D.assert_that_pv_is(f"STATIONARY{axis}", 1, timeout=10) for axis in range(1, 9): - self.motor_ca.set_pv_value("MTR010{}.HLM".format(axis), 100000, sleep_after_set=0) + self.motor_ca.set_pv_value(f"MTR010{axis}.HLM", 100000, sleep_after_set=0) for axis in range(1, 3): - self.motor_ca.set_pv_value("MTR020{}.HLM".format(axis), 100000, sleep_after_set=0) + self.motor_ca.set_pv_value(f"MTR020{axis}.HLM", 100000, sleep_after_set=0) def test_GIVEN_1D_WHEN_set_position_THEN_position_is_set_and_motor_moves_to_position(self): for index, (expected_position, expected_motor_position) in enumerate(POSITIONS_1D): @@ -168,8 +168,8 @@ def test_GIVEN_1D_WHEN_set_position_THEN_position_is_set_and_motor_moves_to_posi self.ca1D.assert_that_pv_is("POSN", expected_position) self.ca1D.assert_that_pv_alarm_is("POSN", ChannelAccess.Alarms.NONE) self.ca1D.assert_that_pv_is("IPOSN", index) - self.ca1D.assert_that_pv_is("INPOS{index}".format(index=index), 1) - self.ca1D.assert_that_pv_is("INPOS{index}".format(index=index + 1), 0) + self.ca1D.assert_that_pv_is(f"INPOS{index}", 1) + self.ca1D.assert_that_pv_is(f"INPOS{index + 1}", 0) self.ca1D.assert_that_pv_is("COORD0:IN_POSITION", 1) def test_GIVEN_1D_WHEN_set_position_by_index_THEN_position_is_set_and_motor_moves_to_position( @@ -181,8 +181,8 @@ def test_GIVEN_1D_WHEN_set_position_by_index_THEN_position_is_set_and_motor_move self.ca1D.assert_that_pv_is("IPOSN", index) self.ca1D.assert_that_pv_is("POSN", expected_position) self.motor_ca.assert_that_pv_is("MTR0101.RBV", expected_motor_position) - self.ca1D.assert_that_pv_is("INPOS{index}".format(index=index), 1) - self.ca1D.assert_that_pv_is("INPOS{index}".format(index=index + 1), 0) + self.ca1D.assert_that_pv_is(f"INPOS{index}", 1) + self.ca1D.assert_that_pv_is(f"INPOS{index + 1}", 0) self.ca1D.assert_that_pv_is("COORD0:IN_POSITION", 1) @parameterized.expand(parameterized_list([1, 2, 10])) @@ -204,8 +204,8 @@ def test_GIVEN_2D_WHEN_set_position_THEN_position_is_set_and_motor_moves_to_posi self.ca2D.assert_that_pv_is("IPOSN", index) self.motor_ca.assert_that_pv_is("MTR0101.RBV", expected_motor_position_cord1) self.motor_ca.assert_that_pv_is("MTR0102.RBV", expected_motor_position_cord2) - self.ca2D.assert_that_pv_is("INPOS{index}".format(index=index), 1) - self.ca2D.assert_that_pv_is("INPOS{index}".format(index=index + 1), 0) + self.ca2D.assert_that_pv_is(f"INPOS{index}", 1) + self.ca2D.assert_that_pv_is(f"INPOS{index + 1}", 0) self.ca2D.assert_that_pv_is("COORD0:IN_POSITION", 1) self.ca2D.assert_that_pv_is("COORD1:IN_POSITION", 1) @@ -227,7 +227,7 @@ def test_GIVEN_XD_WHEN_move_to_out_position_THEN_in_position_light_goes_off_then channel_access.set_pv_value("POSN:SP", second_position, sleep_after_set=0) for axis in range(axis_num): - channel_access.assert_that_pv_is("STATIONARY{}".format(axis), 0) + channel_access.assert_that_pv_is(f"STATIONARY{axis}", 0) channel_access.assert_that_pv_is("STATIONARY".format(), 0) channel_access.assert_that_pv_is("POSITIONED", 0) channel_access.assert_that_pv_is("INPOS0", 0) @@ -235,7 +235,7 @@ def test_GIVEN_XD_WHEN_move_to_out_position_THEN_in_position_light_goes_off_then channel_access.assert_that_pv_is("POSITIONED", 1, timeout=10) for axis in range(axis_num): - channel_access.assert_that_pv_is("STATIONARY{}".format(axis), 1) + channel_access.assert_that_pv_is(f"STATIONARY{axis}", 1) channel_access.assert_that_pv_is("STATIONARY".format(), 1) channel_access.assert_that_pv_is("INPOS0", 0) channel_access.assert_that_pv_is(f"INPOS{second_index}", 1) @@ -257,18 +257,16 @@ def test_GIVEN_XD_WHEN_set_offset_THEN_in_position_light_goes_off_then_on_and_mo channel_access.assert_that_pv_is("INPOS1", 0) for axis in range(axis_num): - channel_access.set_pv_value("COORD{}:OFFSET:SP".format(axis), expected_offsets[axis]) + channel_access.set_pv_value(f"COORD{axis}:OFFSET:SP", expected_offsets[axis]) channel_access.assert_that_pv_is("POSITIONED", 0) channel_access.assert_that_pv_is("INPOS0", 0) channel_access.assert_that_pv_is("INPOS1", 0) channel_access.assert_that_pv_is("POSITIONED", 1) for axis in range(axis_num): - channel_access.assert_that_pv_is("COORD{}:OFFSET".format(axis), expected_offsets[axis]) + channel_access.assert_that_pv_is(f"COORD{axis}:OFFSET", expected_offsets[axis]) motor_pv = get_motor_pv_from_axis_num(axis) - self.motor_ca.assert_that_pv_is( - "{}.RBV".format(motor_pv), expected_motor_positions[axis] - ) + self.motor_ca.assert_that_pv_is(f"{motor_pv}.RBV", expected_motor_positions[axis]) channel_access.assert_that_pv_is("INPOS0", 1) channel_access.assert_that_pv_is("INPOS1", 0) @@ -292,7 +290,7 @@ def test_GIVEN_XD_WHEN_set_large_offset_THEN_current_position_is_correct(self, _ ] for axis in range(axis_num): - channel_access.set_pv_value("COORD{}:OFFSET:SP".format(axis), -offset_coords[axis]) + channel_access.set_pv_value(f"COORD{axis}:OFFSET:SP", -offset_coords[axis]) channel_access.set_pv_value("POSN:SP", position_table[0][0]) channel_access.assert_that_pv_is("POSITIONED", 0) @@ -351,9 +349,9 @@ def _test_alarm_propogates(self, channel_access, motor_num): # Sets the high limit severity to be MAJOR and sets the high limit to be slightly lower than the current # position. This will force the underlying motor into alarm. motor_pv = get_motor_pv_from_axis_num(motor_num) - self.motor_ca.set_pv_value("{}.HLSV".format(motor_pv), ChannelAccess.Alarms.MAJOR) + self.motor_ca.set_pv_value(f"{motor_pv}.HLSV", ChannelAccess.Alarms.MAJOR) current_posn = self.motor_ca.get_pv_value(motor_pv) - self.motor_ca.set_pv_value("{}.HLM".format(motor_pv), current_posn - 1) + self.motor_ca.set_pv_value(f"{motor_pv}.HLM", current_posn - 1) self.motor_ca.assert_that_pv_alarm_is(motor_pv, ChannelAccess.Alarms.MAJOR) assert_alarm_state_of_posn(channel_access, ChannelAccess.Alarms.MAJOR) @@ -377,7 +375,7 @@ def check_motor_positions(expected_coords, readback): self.motor_ca.assert_that_pv_is_number(motor_pv, coord, timeout=timeout) for sample_num in range(2): - sample_name = "Sample{}".format(sample_num + 1) + sample_name = f"Sample{sample_num + 1}" self.ca10D.set_pv_value("POSN:SP", sample_name) expected_coords = [i + sample_num * 5 for i in range(1, 11)] @@ -388,24 +386,24 @@ def check_motor_positions(expected_coords, readback): self.ca10D.assert_that_pv_alarm_is("POSN", ChannelAccess.Alarms.NONE) self.ca10D.assert_that_pv_is("POSN:SP:RBV", sample_name) self.ca10D.assert_that_pv_is("IPOSN", sample_num) - self.ca10D.assert_that_pv_is("INPOS{index}".format(index=sample_num), 1) - self.ca10D.assert_that_pv_is("INPOS{index}".format(index=sample_num + 1), 0) + self.ca10D.assert_that_pv_is(f"INPOS{sample_num}", 1) + self.ca10D.assert_that_pv_is(f"INPOS{sample_num + 1}", 0) def test_GIVEN_10D_WHEN_units_of_motor_set_THEN_units_of_coordinates_also_set(self): - motor_pvs = ["MTR010{}".format(i) for i in range(1, 9)] + motor_pvs = [f"MTR010{i}" for i in range(1, 9)] motor_pvs.extend(["MTR0201", "MTR0202"]) for motor_num, motor_pv in enumerate(motor_pvs): # Set motor unit to PV name - self.motor_ca.set_pv_value("{}.EGU".format(motor_pv), motor_pv) + self.motor_ca.set_pv_value(f"{motor_pv}.EGU", motor_pv) - self.ca10D.assert_that_pv_is("COORD{}.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:RBV.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:NO_OFF.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:OFFSET.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:OFFSET:SP.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:RBV:OFF.EGU".format(motor_num), motor_pv) - self.ca10D.assert_that_pv_is("COORD{}:SET:RBV.EGU".format(motor_num), motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:RBV.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:NO_OFF.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:OFFSET.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:OFFSET:SP.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:RBV:OFF.EGU", motor_pv) + self.ca10D.assert_that_pv_is(f"COORD{motor_num}:SET:RBV.EGU", motor_pv) def test_WHEN_lookup_modified_and_reset_called_THEN_new_position_names_picked_up(self): lookup_file = os.path.join(test_path, "lookup10D.txt") @@ -488,7 +486,7 @@ def test_GIVEN_2D_WHEN_coords_set_through_motion_set_points_THEN_underlying_axis self.ca2D.assert_setting_setpoint_sets_readback( new_position, f"COORD{coord}:RBV", f"COORD{coord}:SP" ) - self.motor_ca.assert_that_pv_is(f"MTR010{coord+1}.RBV", new_position) + self.motor_ca.assert_that_pv_is(f"MTR010{coord + 1}.RBV", new_position) def test_GIVEN_files_WHEN_file_names_checked_THEN_current_names_correct(self): # Motion setpoints changes path separators to / so use posixpath for asserting diff --git a/tests/moxa1210.py b/tests/moxa1210.py index 638d504e..d5139348 100644 --- a/tests/moxa1210.py +++ b/tests/moxa1210.py @@ -3,6 +3,7 @@ from parameterized import parameterized from utils.channel_access import ChannelAccess +from utils.emulator_launcher import EmulatorLauncher from utils.ioc_launcher import get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc @@ -54,36 +55,37 @@ def resetDICounter(self, channel): We typically want to preserve our counter values for each channel even upon restart. For testing purposes this function will reset the counter values to 0. """ - self.ca.set_pv_value("CH{:01d}:DI:CNT".format(channel), 0) + self.ca.set_pv_value(f"CH{channel:01d}:DI:CNT", 0) - @parameterized.expand([("CH{:01d}".format(channel), channel) for channel in CHANNELS]) + @parameterized.expand([(f"CH{channel:01d}", channel) for channel in CHANNELS]) def test_WHEN_DI_input_is_switched_on_THEN_only_that_channel_readback_changes_to_state_just_set( self, _, channel ): self._lewis.backdoor_run_function_on_device("set_di", (channel, (True,))) - self.ca.assert_that_pv_is("CH{:d}:DI".format(channel), "High") + self.ca.assert_that_pv_is(f"CH{channel:d}:DI", "High") # Test that all other channels are still off for test_channel in CHANNELS: if test_channel == channel: continue - self.ca.assert_that_pv_is("CH{:1d}:DI".format(test_channel), "Low") + self.ca.assert_that_pv_is(f"CH{test_channel:1d}:DI", "Low") - @parameterized.expand([("CH{:01d}:DI:CNT".format(channel), channel) for channel in CHANNELS]) + @parameterized.expand([(f"CH{channel:01d}:DI:CNT", channel) for channel in CHANNELS]) def test_WHEN_di_input_is_triggered_a_number_of_times_THEN_di_counter_matches( self, channel_pv, channel ): self.resetDICounter(channel) expected_count = 5 + assert isinstance(self._lewis, EmulatorLauncher), "_lewis must be an EmulatorLauncher" for i in range(expected_count): # Toggle channel and ensure it's registered the trigger - self._lewis.backdoor_run_function_on_device("set_di", (channel, (True,))) - self.ca.assert_that_pv_is("CH{:d}:DI".format(channel), "High") - self._lewis.backdoor_run_function_on_device("set_di", (channel, (False,))) - self.ca.assert_that_pv_is("CH{:d}:DI".format(channel), "Low") + self._lewis.backdoor_run_function_on_device("set_di", [channel, (True,)]) + self.ca.assert_that_pv_is(f"CH{channel:d}:DI", "High") + self._lewis.backdoor_run_function_on_device("set_di", [channel, (False,)]) + self.ca.assert_that_pv_is(f"CH{channel:d}:DI", "Low") self.ca.assert_that_pv_is(channel_pv, i + 1, timeout=5) self.ca.assert_that_pv_is(channel_pv, expected_count) diff --git a/tests/moxa1240.py b/tests/moxa1240.py index 58a0afc0..b32b7bff 100644 --- a/tests/moxa1240.py +++ b/tests/moxa1240.py @@ -22,10 +22,10 @@ "MODELNO": "1240", } for channel in range(NUMBER_OF_CHANNELS): - macros["CHAN{:1d}NAME".format(channel)] = CHANNEL_FORMAT.format(channel) - macros["CHAN{:1d}LOWLIMIT".format(channel)] = LOW_ALARM_LIMIT - macros["CHAN{:1d}HILIMIT".format(channel)] = HIGH_ALARM_LIMIT - macros["CHAN{:1d}SCLEFACTR".format(channel)] = SCALING_FACTOR + macros[f"CHAN{channel:1d}NAME"] = str(CHANNEL_FORMAT.format(channel)) + macros[f"CHAN{channel:1d}LOWLIMIT"] = str(LOW_ALARM_LIMIT) + macros[f"CHAN{channel:1d}HILIMIT"] = str(HIGH_ALARM_LIMIT) + macros[f"CHAN{channel:1d}SCLEFACTR"] = str(SCALING_FACTOR) IOCS = [ { @@ -105,9 +105,7 @@ def test_WHEN_an_AI_input_is_changed_THEN_that_unscaled_channel_readback_updates ) self.ca.assert_that_pv_is_number( - "CH{:01d}:AI:RBV".format( - channel, - ), + f"CH{channel:01d}:AI:RBV", test_value, tolerance=0.1 * abs(test_value), ) diff --git a/tests/moxa1242.py b/tests/moxa1242.py index 2910dece..c0bb79ed 100644 --- a/tests/moxa1242.py +++ b/tests/moxa1242.py @@ -27,13 +27,13 @@ } for channel in range(NUMBER_OF_AI_CHANNELS): - macros["AICHAN{:1d}NAME".format(channel)] = CHANNEL_FORMAT.format(channel) - macros["CHAN{:1d}LOWLIMIT".format(channel)] = LOW_ALARM_LIMIT - macros["CHAN{:1d}HILIMIT".format(channel)] = HIGH_ALARM_LIMIT - macros["CHAN{:1d}SCLEFACTR".format(channel)] = SCALING_FACTOR + macros[f"AICHAN{channel:1d}NAME"] = str(CHANNEL_FORMAT.format(channel)) + macros[f"CHAN{channel:1d}LOWLIMIT"] = str(LOW_ALARM_LIMIT) + macros[f"CHAN{channel:1d}HILIMIT"] = str(HIGH_ALARM_LIMIT) + macros[f"CHAN{channel:1d}SCLEFACTR"] = str(SCALING_FACTOR) for channel in range(NUMBER_OF_DI_CHANNELS): - macros["DICHAN{:1d}NAME".format(channel)] = CHANNEL_FORMAT.format(channel) + macros[f"DICHAN{channel:1d}NAME"] = CHANNEL_FORMAT.format(channel) IOCS = [ @@ -115,9 +115,7 @@ def test_WHEN_an_AI_input_is_changed_THEN_that_unscaled_channel_readback_updates ) self.ca.assert_that_pv_is_number( - "CH{:01d}:AI:RBV".format( - channel, - ), + f"CH{channel:01d}:AI:RBV", test_value, tolerance=0.1 * abs(test_value), ) @@ -147,22 +145,22 @@ def resetDICounter(self, channel): We typically want to preserve our counter values for each channel even upon restart. For testing purposes this function will reset the counter values to 0. """ - self.ca.set_pv_value("CH{:01d}:DI:CNT".format(channel), 0) + self.ca.set_pv_value(f"CH{channel:01d}:DI:CNT", 0) - @parameterized.expand([("CH{:01d}".format(channel), channel) for channel in DICHANNELS]) + @parameterized.expand([(f"CH{channel:01d}", channel) for channel in DICHANNELS]) def test_WHEN_DI_input_is_switched_on_THEN_only_that_channel_readback_changes_to_state_just_set( self, _, channel ): self._lewis.backdoor_run_function_on_device("set_di", (channel, (True,))) - self.ca.assert_that_pv_is("CH{:d}:DI".format(channel), "High") + self.ca.assert_that_pv_is(f"CH{channel:d}:DI", "High") # Test that all other channels are still off for test_channel in DICHANNELS: if test_channel == channel: continue - self.ca.assert_that_pv_is("CH{:1d}:DI".format(test_channel), "Low") + self.ca.assert_that_pv_is(f"CH{test_channel:1d}:DI", "Low") # @parameterized.expand([ This needs to be fixed in #7963 # ("CH{:01d}:DI:CNT".format(channel), channel) for channel in DICHANNELS diff --git a/tests/moxa1262.py b/tests/moxa1262.py index 7ea7d7a5..8e72c79c 100644 --- a/tests/moxa1262.py +++ b/tests/moxa1262.py @@ -21,9 +21,9 @@ "MODELNO": "1262", } for channel in range(NUMBER_OF_CHANNELS): - macros["CHAN{:1d}NAME".format(channel)] = CHANNEL_FORMAT.format(channel) - macros["CHAN{:1d}LOWLIMIT".format(channel)] = LOW_ALARM_LIMIT - macros["CHAN{:1d}HILIMIT".format(channel)] = HIGH_ALARM_LIMIT + macros[f"CHAN{channel:1d}NAME"] = str(CHANNEL_FORMAT.format(channel)) + macros[f"CHAN{channel:1d}LOWLIMIT"] = str(LOW_ALARM_LIMIT) + macros[f"CHAN{channel:1d}HILIMIT"] = str(HIGH_ALARM_LIMIT) IOCS = [ { diff --git a/tests/neocera.py b/tests/neocera.py index 51df8113..a837353e 100644 --- a/tests/neocera.py +++ b/tests/neocera.py @@ -42,10 +42,10 @@ def test_WHEN_temperatue_setpoint_is_set_THEN_readback_updates_to_the_value_just for sensor, value in itertools.product(SENSORS, TEST_VALUES): self.ca.assert_setting_setpoint_sets_readback( value, - set_point_pv="{}:TEMP:SP".format(sensor), - readback_pv="{}:TEMP:SP:RBV".format(sensor), + set_point_pv=f"{sensor}:TEMP:SP", + readback_pv=f"{sensor}:TEMP:SP:RBV", ) def test_WHEN_pid_settings_are_set_THEN_readbacks_update_to_the_values_just_set(self): for sensor, value, control in itertools.product(SENSORS, TEST_VALUES, ["P", "I", "D"]): - self.ca.assert_setting_setpoint_sets_readback(value, "{}:{}".format(sensor, control)) + self.ca.assert_setting_setpoint_sets_readback(value, f"{sensor}:{control}") diff --git a/tests/ngpspsu.py b/tests/ngpspsu.py index 5a920e56..23bce56e 100644 --- a/tests/ngpspsu.py +++ b/tests/ngpspsu.py @@ -142,7 +142,7 @@ class NgpspsuStatusTests(unittest.TestCase): def test_that_GIVEN_a_setup_device_THEN_the_status_is_zero(self): # When/Then: for digit in range(1, 9): - self.ca.assert_that_pv_is("STAT:HEX:{}".format(digit), 0) + self.ca.assert_that_pv_is(f"STAT:HEX:{digit}", 0) @add_method(setUp) diff --git a/tests/nimrod_jaws_manager.py b/tests/nimrod_jaws_manager.py index b677afa7..45fd2d2f 100644 --- a/tests/nimrod_jaws_manager.py +++ b/tests/nimrod_jaws_manager.py @@ -19,20 +19,21 @@ "motorExtensions", "master", "settings", - "nimrod_jaws", + "NIMROD", + "galil", ) ) # Create 3 Galils IOCS = [ { - "name": "GALIL_0{}".format(i), + "name": f"GALIL_0{i}", "directory": get_default_ioc_dir("GALIL", i), "custom_prefix": "MOT", - "pv_for_existence": "MTR0{}01".format(i), + "pv_for_existence": f"MTR0{i}01", "macros": { "GALILADDR": GALIL_ADDR, - "MTRCTRL": "0{}".format(i), + "MTRCTRL": f"0{i}", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, } diff --git a/tests/oscillating_collimator_let.py b/tests/oscillating_collimator_let.py index be39d0b8..077845b9 100644 --- a/tests/oscillating_collimator_let.py +++ b/tests/oscillating_collimator_let.py @@ -66,7 +66,8 @@ def setUp(self): # Set to 0 so stability buffer contents are consistent & known for each test # Takes 10 seconds for buffer to have consistent contents, so to be certain sleep for 11 - self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS", 0, sleep_after_set=11) + self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS:SIM", 1) + self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS:SIM:VAL", 0, sleep_after_set=11) @parameterized.expand( # [(angle, frequency, radius), (expected distance, expected velocity) @@ -119,7 +120,7 @@ def test_WHEN_laser_unstable_THEN_collimator_is_reported_moving(self): self.ca.assert_that_pv_is("MOVING", "Not Moving", timeout=30) self.ca.assert_that_pv_value_is_unchanged("MOVING", 5) # Give laser new value - self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS", 1) + self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS:SIM:VAL", 1) # Assert # Check PV is now moving @@ -129,7 +130,7 @@ def test_WHEN_laser_unstable_THEN_collimator_is_reported_moving(self): def test_WHEN_laser_stable_THEN_collimator_is_reported_not_moving(self): # Act - self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS", 1) + self.ca_mot.set_pv_value("DMC01:Galil0Bi5_STATUS:SIM:VAL", 1) # Assert # Check that PV was moving after laser change, then stops moving after buffer clears diff --git a/tests/polaris_jaws_manager.py b/tests/polaris_jaws_manager.py index 53672049..242d5432 100644 --- a/tests/polaris_jaws_manager.py +++ b/tests/polaris_jaws_manager.py @@ -21,20 +21,21 @@ "motorExtensions", "master", "settings", - "polaris_jaws", + "POLARIS", + "galil", ) ) # Create 3 Galils IOCS = [ { - "name": "GALIL_0{}".format(i), + "name": f"GALIL_0{i}", "directory": get_default_ioc_dir("GALIL", i), "custom_prefix": "MOT", - "pv_for_existence": "MTR0{}01".format(i), + "pv_for_existence": f"MTR0{i}01", "macros": { "GALILADDR": GALIL_ADDR, - "MTRCTRL": "0{}".format(i), + "MTRCTRL": f"0{i}", "GALILCONFIGDIR": test_path.replace("\\", "/"), }, } @@ -65,7 +66,7 @@ class PolarisJawsManagerTests(JawsManagerBase, unittest.TestCase): """ def setUp(self): - super(PolarisJawsManagerTests, self).setUp() + super().setUp() with ManagerMode(self.ca): # Use a retry loop here in case the IOC has not connected to the manager mode PV yet for _ in range(10): diff --git a/tests/readascii.py b/tests/readascii.py index c9d3e01c..59a84d74 100644 --- a/tests/readascii.py +++ b/tests/readascii.py @@ -10,9 +10,9 @@ from utils.ioc_launcher import EPICS_TOP, IOCRegister from utils.test_modes import TestModes -DEFAULT_SETTINGS_DIR = os.path.join( - "C:/", "Instrument", "Apps", "EPICS", "support", "ReadASCII", "master", "example_settings" -) +DEFAULT_SETTINGS_DIR = ( + EPICS_TOP / "support" / "ReadASCII" / "master" / "example_settings" +).as_posix() DEFAULT_SETTINGS_FILE = "Default.txt" TEMP_TEST_SETTINGS_DIR = os.path.join("C:/", "Instrument", "var", "tmp", "readascii_test") @@ -26,9 +26,9 @@ IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join( - EPICS_TOP, "support", "ReadASCII", "master", "iocBoot", "iocReadASCIITest" - ), + "directory": ( + EPICS_TOP / "support" / "ReadASCII" / "master" / "iocBoot" / "iocReadASCIITest" + ).as_posix(), "pv_for_existence": "DIRBASE", }, ] @@ -58,8 +58,7 @@ def _write_contents_of_temporary_test_file(self, headers, data, name=TEMP_SETTIN """ with open(os.path.join(TEMP_TEST_SETTINGS_DIR, name), "w") as f: f.write("{}\n".format(" ".join(str(d) for d in headers))) - for row in data: - f.write("{}\n".format(" ".join(str(d) for d in row))) + f.writelines("{}\n".format(" ".join(str(d) for d in row)) for row in data) time.sleep(5) # allow new file on disk to be noticed @contextmanager @@ -141,9 +140,9 @@ def _set_ramp_status(self, status): ] ) def test_GIVEN_the_test_file_has_entries_for_a_setpoint_WHEN_that_exact_setpoint_is_set_THEN_it_updates_the_pid_pvs_with_the_values_from_the_file( - self, _, MH_name + self, _, mh_name ): - headers = ["SP", "P", "I", "D", MH_name] + headers = ["SP", "P", "I", "D", mh_name] rows = [ (50, 1, 2, 3, 4), (100, 5, 6, 7, 8), @@ -368,8 +367,9 @@ def test_GIVEN_data_file_name_changed_THEN_new_file_used(self): check_pvs = ["OUT_P", "OUT_I", "OUT_D", "OUT_MAX"] # we use file2 this time and expect new values - with self._generate_temporary_test_file(headers, rows, "file2"), self._use_test_file( - "file2" + with ( + self._generate_temporary_test_file(headers, rows, "file2"), + self._use_test_file("file2"), ): for row in rows: self._set_and_check_flexible(row[0], check_pvs, row[1:]) @@ -391,8 +391,9 @@ def test_GIVEN_invalid_filename_then_fixing_it_THEN_first_alarm_then_correct(sel ] check_pvs = ["OUT_P", "OUT_I", "OUT_D", "OUT_MAX"] - with self._generate_temporary_test_file(headers, rows, "RealFile"), self._use_test_file( - "RealFile" + with ( + self._generate_temporary_test_file(headers, rows, "RealFile"), + self._use_test_file("RealFile"), ): for row in rows: self._set_and_check_flexible(row[0], check_pvs, row[1:]) @@ -407,7 +408,8 @@ def test_GIVEN_file_is_set_THEN__file_not_default_PV_is_true(self): (0, 0, 0, 0, 0), ] - with self._generate_temporary_test_file(headers, rows, "RealFile"), self._use_test_file( - "RealFile" + with ( + self._generate_temporary_test_file(headers, rows, "RealFile"), + self._use_test_file("RealFile"), ): self.ca.assert_that_pv_is("RAMP_FILE_NOT_DEFAULT", 1) diff --git a/tests/refl.py b/tests/refl.py index f94f0731..9774ef5e 100644 --- a/tests/refl.py +++ b/tests/refl.py @@ -26,7 +26,7 @@ SOFT_LIMIT_LO = -10000 ioc_number = 1 -DEVICE_PREFIX = "REFL_{:02d}".format(ioc_number) +DEVICE_PREFIX = f"REFL_{ioc_number:02d}" GALIL1_PREFIX = "GALIL_01" GALIL2_PREFIX_JAWS = "GALIL_02" GALIL3_PREFIX = "GALIL_03" @@ -464,12 +464,12 @@ def test_GIVEN_mode_is_NR_WHEN_change_mode_THEN_monitor_updates_to_new_mode_and_ for param in test_in_mode_param_names: self.ca.assert_that_pv_monitor_is( - "{}{}{}".format(param_prefix, param, in_mode_suffix), expected_in_mode_value + f"{param_prefix}{param}{in_mode_suffix}", expected_in_mode_value ) for param in test_out_of_mode_params: self.ca.assert_that_pv_monitor_is( - "{}{}{}".format(param_prefix, param, in_mode_suffix), expected_out_of_mode_value + f"{param_prefix}{param}{in_mode_suffix}", expected_out_of_mode_value ) def test_GIVEN_jaws_set_to_value_WHEN_change_sp_at_low_level_THEN_jaws_sp_rbv_does_not_change( @@ -504,10 +504,9 @@ def test_GIVEN_new_parameter_sp_WHEN_parameter_rbv_changing_THEN_parameter_chang self, _, param, value ): expected_value = "YES" - value = value - self.ca.set_pv_value("PARAM:{}:SP".format(param), value) - self.ca.assert_that_pv_is("PARAM:{}:CHANGING".format(param), expected_value) + self.ca.set_pv_value(f"PARAM:{param}:SP", value) + self.ca.assert_that_pv_is(f"PARAM:{param}:CHANGING", expected_value) @parameterized.expand( [ @@ -523,12 +522,11 @@ def test_GIVEN_new_parameter_sp_WHEN_parameter_rbv_not_changing_THEN_parameter_c self, _, param, value ): expected_value = "NO" - value = value - self.ca.set_pv_value("PARAM:{}:SP".format(param), value) + self.ca.set_pv_value(f"PARAM:{param}:SP", value) stop_motors_with_retry(self.ca_cs, 5) - self.ca.assert_that_pv_is("PARAM:{}:CHANGING".format(param), expected_value) + self.ca.assert_that_pv_is(f"PARAM:{param}:CHANGING", expected_value) @parameterized.expand( [ @@ -543,12 +541,11 @@ def test_GIVEN_new_parameter_sp_WHEN_parameter_rbv_outside_of_sp_target_toleranc self, _, param, value ): expected_value = "NO" - value = value - self.ca.set_pv_value("PARAM:{}:SP".format(param), value) + self.ca.set_pv_value(f"PARAM:{param}:SP", value) stop_motors_with_retry(self.ca_cs, 5) - self.ca.assert_that_pv_is("PARAM:{}:RBV:AT_SP".format(param), expected_value) + self.ca.assert_that_pv_is(f"PARAM:{param}:RBV:AT_SP", expected_value) @parameterized.expand( [ @@ -563,12 +560,11 @@ def test_GIVEN_new_parameter_sp_WHEN_parameter_rbv_within_sp_target_tolerance_TH self, _, param, value ): expected_value = "YES" - value = value - self.ca.set_pv_value("PARAM:{}:SP".format(param), value) + self.ca.set_pv_value(f"PARAM:{param}:SP", value) stop_motors_with_retry(self.ca_cs, 5) - self.ca.assert_that_pv_is("PARAM:{}:RBV:AT_SP".format(param), expected_value) + self.ca.assert_that_pv_is(f"PARAM:{param}:RBV:AT_SP", expected_value) def test_GIVEN_a_low_level_beamline_change_WHEN_values_changed_THEN_high_level_parameters_updated( self, @@ -765,32 +761,30 @@ def test_GIVEN_motors_not_at_zero_WHEN_define_motor_position_to_THEN_motor_posit ): offset = 10 new_position = 2 - self.ca.set_pv_value("PARAM:{}:SP".format(param_name), offset) + self.ca.set_pv_value(f"PARAM:{param_name}:SP", offset) self.ca_galil.set_pv_value("MTR0104.FOFF", initial_foff) self.ca_galil.set_pv_value("MTR0104.OFF", 0) self.ca.assert_that_pv_is_number( - "PARAM:{}".format(param_name), offset, tolerance=MOTOR_TOLERANCE, timeout=30 + f"PARAM:{param_name}", offset, tolerance=MOTOR_TOLERANCE, timeout=30 ) self.ca_galil.assert_that_pv_is("MTR0104.DMOV", 1, timeout=30) with ManagerMode(self.ca_no_prefix): - self.ca.set_pv_value("PARAM:{}:DEFINE_POS_SP".format(param_name), new_position) + self.ca.set_pv_value(f"PARAM:{param_name}:DEFINE_POS_SP", new_position) # soon after change there should be no movement, ie a move is triggered but the motor itself does not move so it # is very quick - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=1) - self.ca_galil.assert_that_pv_is("{}.RBV".format(motor_name), new_position) - self.ca_galil.assert_that_pv_is("{}.VAL".format(motor_name), new_position) - self.ca_galil.assert_that_pv_is("{}.SET".format(motor_name), "Use") - self.ca_galil.assert_that_pv_is("{}.FOFF".format(motor_name), initial_foff) - self.ca_galil.assert_that_pv_is_number( - "{}.OFF".format(motor_name), 0.0, tolerance=MOTOR_TOLERANCE - ) - - self.ca.assert_that_pv_is("PARAM:{}".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:SP".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:SP_NO_ACTION".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:CHANGED".format(param_name), "NO") + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=1) + self.ca_galil.assert_that_pv_is(f"{motor_name}.RBV", new_position) + self.ca_galil.assert_that_pv_is(f"{motor_name}.VAL", new_position) + self.ca_galil.assert_that_pv_is(f"{motor_name}.SET", "Use") + self.ca_galil.assert_that_pv_is(f"{motor_name}.FOFF", initial_foff) + self.ca_galil.assert_that_pv_is_number(f"{motor_name}.OFF", 0.0, tolerance=MOTOR_TOLERANCE) + + self.ca.assert_that_pv_is(f"PARAM:{param_name}", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP_NO_ACTION", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:CHANGED", "NO") self.ca.assert_that_pv_is("PARAM:THETA", 0) self.ca.assert_that_pv_is("PARAM:THETA:SP", 0) self.ca.assert_that_pv_is("PARAM:THETA:SP:RBV", 0) @@ -814,33 +808,33 @@ def test_GIVEN_jaws_not_at_zero_WHEN_define_motor_position_for_jaw_gaps_THEN_jaw initial_centre, "PARAM:S1VC", expected_alarm=None, timeout=30 ) for motor_name in jaw_motors: - self.ca_galil.set_pv_value("{}.FOFF".format(motor_name), "Frozen") - self.ca_galil.set_pv_value("{}.OFF".format(motor_name), 0) + self.ca_galil.set_pv_value(f"{motor_name}.FOFF", "Frozen") + self.ca_galil.set_pv_value(f"{motor_name}.OFF", 0) for motor_name in jaw_motors: - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=30) + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=30) with ManagerMode(self.ca_no_prefix): - self.ca.set_pv_value("PARAM:{}:DEFINE_POS_SP".format(param_name), new_gap) + self.ca.set_pv_value(f"PARAM:{param_name}:DEFINE_POS_SP", new_gap) # soon after change there should be no movement, ie a move is triggered but the motor itself does not move so it # is very quick for motor_name in jaw_motors: - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=1) + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=1) for motor_name in jaw_motors: # jaws are open to half the gap - self.ca_galil.assert_that_pv_is("{}.RBV".format(motor_name), expected_pos[motor_name]) - self.ca_galil.assert_that_pv_is("{}.VAL".format(motor_name), expected_pos[motor_name]) - self.ca_galil.assert_that_pv_is("{}.SET".format(motor_name), "Use") - self.ca_galil.assert_that_pv_is("{}.FOFF".format(motor_name), "Frozen") + self.ca_galil.assert_that_pv_is(f"{motor_name}.RBV", expected_pos[motor_name]) + self.ca_galil.assert_that_pv_is(f"{motor_name}.VAL", expected_pos[motor_name]) + self.ca_galil.assert_that_pv_is(f"{motor_name}.SET", "Use") + self.ca_galil.assert_that_pv_is(f"{motor_name}.FOFF", "Frozen") self.ca_galil.assert_that_pv_is_number( - "{}.OFF".format(motor_name), 0.0, tolerance=MOTOR_TOLERANCE + f"{motor_name}.OFF", 0.0, tolerance=MOTOR_TOLERANCE ) - self.ca.assert_that_pv_is("PARAM:{}".format(param_name), new_gap) - self.ca.assert_that_pv_is("PARAM:{}:SP".format(param_name), new_gap) - self.ca.assert_that_pv_is("PARAM:{}:SP_NO_ACTION".format(param_name), new_gap) - self.ca.assert_that_pv_is("PARAM:{}:CHANGED".format(param_name), "NO") + self.ca.assert_that_pv_is(f"PARAM:{param_name}", new_gap) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP", new_gap) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP_NO_ACTION", new_gap) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:CHANGED", "NO") def test_GIVEN_jaws_not_at_zero_WHEN_define_motor_position_for_jaw_centres_THEN_jaws_position_are_changed_without_move( self, @@ -861,33 +855,33 @@ def test_GIVEN_jaws_not_at_zero_WHEN_define_motor_position_for_jaw_centres_THEN_ initial_centre, "PARAM:S1HC", expected_alarm=None, timeout=30 ) for motor_name in jaw_motors: - self.ca_galil.set_pv_value("{}.FOFF".format(motor_name), "Frozen") - self.ca_galil.set_pv_value("{}.OFF".format(motor_name), 0) + self.ca_galil.set_pv_value(f"{motor_name}.FOFF", "Frozen") + self.ca_galil.set_pv_value(f"{motor_name}.OFF", 0) for motor_name in jaw_motors: - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=30) + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=30) with ManagerMode(self.ca_no_prefix): - self.ca.set_pv_value("PARAM:{}:DEFINE_POS_SP".format(param_name), new_centre) + self.ca.set_pv_value(f"PARAM:{param_name}:DEFINE_POS_SP", new_centre) # soon after change there should be no movement, ie a move is triggered but the motor itself does not move so it # is very quick for motor_name in jaw_motors: - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=1) + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=1) for motor_name in jaw_motors: # jaws are open to half the gap - self.ca_galil.assert_that_pv_is("{}.RBV".format(motor_name), expected_pos[motor_name]) - self.ca_galil.assert_that_pv_is("{}.VAL".format(motor_name), expected_pos[motor_name]) - self.ca_galil.assert_that_pv_is("{}.SET".format(motor_name), "Use") - self.ca_galil.assert_that_pv_is("{}.FOFF".format(motor_name), "Frozen") + self.ca_galil.assert_that_pv_is(f"{motor_name}.RBV", expected_pos[motor_name]) + self.ca_galil.assert_that_pv_is(f"{motor_name}.VAL", expected_pos[motor_name]) + self.ca_galil.assert_that_pv_is(f"{motor_name}.SET", "Use") + self.ca_galil.assert_that_pv_is(f"{motor_name}.FOFF", "Frozen") self.ca_galil.assert_that_pv_is_number( - "{}.OFF".format(motor_name), 0.0, tolerance=MOTOR_TOLERANCE + f"{motor_name}.OFF", 0.0, tolerance=MOTOR_TOLERANCE ) - self.ca.assert_that_pv_is("PARAM:{}".format(param_name), new_centre) - self.ca.assert_that_pv_is("PARAM:{}:SP".format(param_name), new_centre) - self.ca.assert_that_pv_is("PARAM:{}:SP_NO_ACTION".format(param_name), new_centre) - self.ca.assert_that_pv_is("PARAM:{}:CHANGED".format(param_name), "NO") + self.ca.assert_that_pv_is(f"PARAM:{param_name}", new_centre) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP", new_centre) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP_NO_ACTION", new_centre) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:CHANGED", "NO") @parameterized.expand( parameterized_list( @@ -910,34 +904,34 @@ def test_GIVEN_motors_at_zero_WHEN_define_motor_position_to_and_back_multiple_ti param_name = "DET_POS" motor_name = "MTR0104" initial_foff = "Frozen" - self.ca.set_pv_value("PARAM:{}:SP".format(param_name), 0) + self.ca.set_pv_value(f"PARAM:{param_name}:SP", 0) self.ca_galil.set_pv_value("MTR0104.FOFF", initial_foff) self.ca_galil.set_pv_value("MTR0104.OFF", 0) self.ca.assert_that_pv_is_number( - "PARAM:{}".format(param_name), 0, tolerance=MOTOR_TOLERANCE, timeout=30 + f"PARAM:{param_name}", 0, tolerance=MOTOR_TOLERANCE, timeout=30 ) self.ca_galil.assert_that_pv_is("MTR0104.DMOV", 1, timeout=30) for i in range(20): new_position = i - 5 with ManagerMode(self.ca_no_prefix): - self.ca.set_pv_value("PARAM:{}:DEFINE_POS_SP".format(param_name), new_position) + self.ca.set_pv_value(f"PARAM:{param_name}:DEFINE_POS_SP", new_position) # soon after change there should be no movement, ie a move is triggered but the motor itself does not move so it # is very quick - self.ca_galil.assert_that_pv_is("{}.DMOV".format(motor_name), 1, timeout=1) - self.ca_galil.assert_that_pv_is("{}.RBV".format(motor_name), new_position) - self.ca_galil.assert_that_pv_is("{}.VAL".format(motor_name), new_position) - self.ca_galil.assert_that_pv_is("{}.SET".format(motor_name), "Use") - self.ca_galil.assert_that_pv_is("{}.FOFF".format(motor_name), initial_foff) + self.ca_galil.assert_that_pv_is(f"{motor_name}.DMOV", 1, timeout=1) + self.ca_galil.assert_that_pv_is(f"{motor_name}.RBV", new_position) + self.ca_galil.assert_that_pv_is(f"{motor_name}.VAL", new_position) + self.ca_galil.assert_that_pv_is(f"{motor_name}.SET", "Use") + self.ca_galil.assert_that_pv_is(f"{motor_name}.FOFF", initial_foff) self.ca_galil.assert_that_pv_is_number( - "{}.OFF".format(motor_name), 0.0, tolerance=MOTOR_TOLERANCE + f"{motor_name}.OFF", 0.0, tolerance=MOTOR_TOLERANCE ) - self.ca.assert_that_pv_is("PARAM:{}".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:SP".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:SP_NO_ACTION".format(param_name), new_position) - self.ca.assert_that_pv_is("PARAM:{}:CHANGED".format(param_name), "NO") + self.ca.assert_that_pv_is(f"PARAM:{param_name}", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:SP_NO_ACTION", new_position) + self.ca.assert_that_pv_is(f"PARAM:{param_name}:CHANGED", "NO") def test_GIVEN_parameter_not_in_manager_mode_WHEN_define_position_THEN_position_is_not_defined( self, @@ -967,7 +961,7 @@ def test_GIVEN_value_parameter_WHEN_read_THEN_value_returned(self): param_pv = "CONST:TEN" self.ca.assert_that_pv_is(param_pv, 10) - self.ca.assert_that_pv_is("{}.DESC".format(param_pv), "The value 10") + self.ca.assert_that_pv_is(f"{param_pv}.DESC", "The value 10") def test_GIVEN_bool_parameter_WHEN_read_THEN_value_returned(self): param_pv = "CONST:YES" diff --git a/tests/refl_init.py b/tests/refl_init.py index 874867e6..cd6e6bcf 100644 --- a/tests/refl_init.py +++ b/tests/refl_init.py @@ -15,7 +15,7 @@ FAST_VELOCITY = 10 ioc_number = 1 -DEVICE_PREFIX = "REFL_{:02d}".format(ioc_number) +DEVICE_PREFIX = f"REFL_{ioc_number:02d}" GALIL_PREFIX = "GALIL_01" test_config_path = os.path.abspath( os.path.join(os.path.dirname(os.path.dirname(__file__)), "test_config", "good_for_refl") @@ -87,18 +87,20 @@ def setUp(self): self.ca_galil.assert_that_pv_is("MTR0104", 0.0) def _check_param_pvs(self, param_name, expected_value): - self.ca.assert_that_pv_is_number("PARAM:%s" % param_name, expected_value, 0.01) - self.ca.assert_that_pv_is_number("PARAM:%s:SP" % param_name, expected_value, 0.01) - self.ca.assert_that_pv_is_number("PARAM:%s:SP:RBV" % param_name, expected_value, 0.01) + self.ca.assert_that_pv_is_number(f"PARAM:{param_name}", expected_value, 0.01) + self.ca.assert_that_pv_is_number(f"PARAM:{param_name}:SP", expected_value, 0.01) + self.ca.assert_that_pv_is_number(f"PARAM:{param_name}:SP:RBV", expected_value, 0.01) @contextmanager def _assert_pv_monitors(self, param_name, expected_value): - with self.ca.assert_that_pv_monitor_is_number( - "PARAM:%s" % param_name, expected_value, 0.01 - ), self.ca.assert_that_pv_monitor_is_number( - "PARAM:%s:SP" % param_name, expected_value, 0.01 - ), self.ca.assert_that_pv_monitor_is_number( - "PARAM:%s:SP:RBV" % param_name, expected_value, 0.01 + with ( + self.ca.assert_that_pv_monitor_is_number(f"PARAM:{param_name}", expected_value, 0.01), + self.ca.assert_that_pv_monitor_is_number( + f"PARAM:{param_name}:SP", expected_value, 0.01 + ), + self.ca.assert_that_pv_monitor_is_number( + f"PARAM:{param_name}:SP:RBV", expected_value, 0.01 + ), ): yield diff --git a/tests/refl_trunc.py b/tests/refl_trunc.py index d430c8ce..f434534c 100644 --- a/tests/refl_trunc.py +++ b/tests/refl_trunc.py @@ -15,7 +15,7 @@ ioc_number = 1 -DEVICE_PREFIX = "REFL_{:02d}".format(ioc_number) +DEVICE_PREFIX = f"REFL_{ioc_number:02d}" test_config_path = os.path.abspath( os.path.join(os.path.dirname(os.path.dirname(__file__)), "test_config", "good_for_refl") ) @@ -95,34 +95,34 @@ def test_GIVEN_saturated_configuration_WHEN_waveform_pv_read_THEN_value_truncate ) def test_WHEN_server_message_exceeds_character_limit_THEN_message_truncated_correctly(self): - SERVER_MESSAGE_MAX_SIZE = 400 + server_message_max_size = 400 self.ca.set_pv_value("PARAM:INBEAM:SP", 0, wait=True) self.ca.assert_that_pv_value_causes_func_to_return_true( "MSG", lambda val: val.endswith("") ) self.ca.assert_that_pv_value_causes_func_to_return_true( - "MSG", lambda val: len(val) == SERVER_MESSAGE_MAX_SIZE + "MSG", lambda val: len(val) == server_message_max_size ) def test_WHEN_log_error_messages_exceed_character_limit_THEN_log_truncated_correctly(self): - ERROR_LOG_MAX_SIZE = 10_000 - ERROR_MESSAGE = "Error: PV FOOTPRINT_INFO is read only" - NUM_ERROR_MESSAGES = int((ERROR_LOG_MAX_SIZE / len(ERROR_MESSAGE)) * 1.2) + error_log_max_size = 10_000 + error_message = "Error: PV FOOTPRINT_INFO is read only" + num_error_messages = int((error_log_max_size / len(error_message)) * 1.2) with assert_log_messages(self._ioc, in_time=20) as cm: - for _ in range(NUM_ERROR_MESSAGES): + for _ in range(num_error_messages): self.ca.set_pv_value("FOOTPRINT_INFO", "") count = 0 for message in cm.messages: - if ERROR_MESSAGE in message: + if error_message in message: count += 1 self.assertEqual( count, - NUM_ERROR_MESSAGES, - f"Expected {NUM_ERROR_MESSAGES} got {count} number of error messages.", + num_error_messages, + f"Expected {num_error_messages} got {count} number of error messages.", ) self.ca.assert_that_pv_value_causes_func_to_return_true( - "LOG", lambda val: len(val) == ERROR_LOG_MAX_SIZE + "LOG", lambda val: len(val) == error_log_max_size ) diff --git a/tests/rikenfe_plc.py b/tests/rikenfe_plc.py index 3a95b9df..c702a74b 100644 --- a/tests/rikenfe_plc.py +++ b/tests/rikenfe_plc.py @@ -159,10 +159,10 @@ def test_GIVEN_temperature_monitoring_db_loaded_THEN_pvs_can_be_read( def test_GIVEN_pumpsets_state_THEN_pumpset_summary_has_correct_state( self, _, gh1, gh2, gh3, gh4, tp, bp, piv, pumpset, gh_state, other_state, expected_state ): - self.ca.set_pv_value(f"SIM:GH{(pumpset*4)-3}:STAT", gh1) - self.ca.set_pv_value(f"SIM:GH{(pumpset*4)-2}:STAT", gh2) - self.ca.set_pv_value(f"SIM:GH{(pumpset*4)-1}:STAT", gh3) - self.ca.set_pv_value(f"SIM:GH{pumpset*4}:STAT", gh4) + self.ca.set_pv_value(f"SIM:GH{(pumpset * 4) - 3}:STAT", gh1) + self.ca.set_pv_value(f"SIM:GH{(pumpset * 4) - 2}:STAT", gh2) + self.ca.set_pv_value(f"SIM:GH{(pumpset * 4) - 1}:STAT", gh3) + self.ca.set_pv_value(f"SIM:GH{pumpset * 4}:STAT", gh4) self.ca.assert_that_pv_is(f"PUMPSET:{pumpset}:GH", gh_state) diff --git a/tests/rkndio.py b/tests/rkndio.py index 4b5b5465..b9fe63da 100644 --- a/tests/rkndio.py +++ b/tests/rkndio.py @@ -84,10 +84,10 @@ def test_that_we_can_get_the_error_status_of_the_device(self): # When/Then: self.ca.assert_that_pv_is("ERROR", error_message) - @parameterized.expand([("Pin_{}".format(i), i) for i in range(2, 8)]) + @parameterized.expand([(f"Pin_{i}", i) for i in range(2, 8)]) def test_that_we_can_read_a_digital_input(self, _, pin): # Given - pv = "PIN:{}".format(pin) + pv = f"PIN:{pin}" self._lewis.backdoor_run_function_on_device( "set_input_state_via_the_backdoor", [pin, "FALSE"] ) @@ -103,10 +103,10 @@ def test_that_we_can_read_a_digital_input(self, _, pin): # Then: self.ca.assert_that_pv_is(pv, "TRUE") - @parameterized.expand([("Pin_{}".format(i), i) for i in range(8, 14)]) + @parameterized.expand([(f"Pin_{i}", i) for i in range(8, 14)]) def test_that_we_can_write_to_a_digital_output(self, _, pin): # Given - pv = "PIN:{}".format(pin) + pv = f"PIN:{pin}" self.ca.set_pv_value(pv, "FALSE") reset_check = self._lewis.backdoor_run_function_on_device( "get_output_state_via_the_backdoor", [pin] diff --git a/tests/samplechanger.py b/tests/samplechanger.py index 0257b2ce..45a747d0 100644 --- a/tests/samplechanger.py +++ b/tests/samplechanger.py @@ -54,7 +54,7 @@ def setUp(self): self.ca.assert_that_pv_exists("SAMPCHNG:SLOT") for axis in AXES: - self.ca.assert_that_pv_exists("MOT:{}".format(axis)) + self.ca.assert_that_pv_exists(f"MOT:{axis}") # Select one of the standard slots. self.ca.assert_setting_setpoint_sets_readback(readback_pv="SAMPCHNG:SLOT", value=SLOTS[0]) @@ -64,19 +64,19 @@ def setUp(self): [ { "slot_name": "_ALL", - "positions_exist": ["{}CB".format(n) for n in range(1, 14 + 1)] - + ["{}CT".format(n) for n in range(1, 14 + 1)], + "positions_exist": [f"{n}CB" for n in range(1, 14 + 1)] + + [f"{n}CT" for n in range(1, 14 + 1)], "positions_not_exist": [], }, { "slot_name": "CT", - "positions_exist": ["{}CT".format(n) for n in range(1, 14 + 1)], - "positions_not_exist": ["{}CB".format(n) for n in range(1, 14 + 1)], + "positions_exist": [f"{n}CT" for n in range(1, 14 + 1)], + "positions_not_exist": [f"{n}CB" for n in range(1, 14 + 1)], }, { "slot_name": "CB", - "positions_exist": ["{}CB".format(n) for n in range(1, 14 + 1)], - "positions_not_exist": ["{}CT".format(n) for n in range(1, 14 + 1)], + "positions_exist": [f"{n}CB" for n in range(1, 14 + 1)], + "positions_not_exist": [f"{n}CT" for n in range(1, 14 + 1)], }, ] ) @@ -90,19 +90,19 @@ def test_WHEN_slot_set_THEN_only_slot_positions_listed_in_sample_changer_but_all def pos_in_motion_set_point(position): self.ca.assert_that_pv_value_causes_func_to_return_true( - "LKUP:SAMPLE:POSITIONS", func=lambda val: pos in val + "LKUP:SAMPLE:POSITIONS", func=lambda val, position=position: position in val ) for pos in settings["positions_exist"]: pos_in_motion_set_point(pos) self.ca.assert_that_pv_value_causes_func_to_return_true( - "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val: pos in val + "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val, pos=pos: pos in val ) for pos in settings["positions_not_exist"]: pos_in_motion_set_point(pos) self.ca.assert_that_pv_value_causes_func_to_return_true( - "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val: pos not in val + "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val, pos=pos: pos not in val ) def test_WHEN_invalid_slot_is_entered_THEN_old_slot_kept(self): @@ -114,9 +114,9 @@ def test_WHEN_invalid_slot_is_entered_THEN_old_slot_kept(self): self.ca.assert_that_pv_is("SAMPCHNG:SLOT", "CT") self.ca.assert_that_pv_value_is_unchanged("SAMPCHNG:SLOT", wait=3) - for pos in ["{}CT".format(n) for n in range(1, 14 + 1)]: + for pos in [f"{n}CT" for n in range(1, 14 + 1)]: self.ca.assert_that_pv_value_causes_func_to_return_true( - "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val: pos in val + "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val, pos=pos: pos in val ) def test_available_slots_can_be_loaded(self): @@ -221,9 +221,9 @@ def test_WHEN_slot_with_different_suffix_selected_THEN_samples_have_new_suffix(s readback_pv="SAMPCHNG:SLOT", value="DURHAM_TOP" ) - for pos in ["{}GT".format(n) for n in range(1, 12 + 1)]: + for pos in [f"{n}GT" for n in range(1, 12 + 1)]: self.ca.assert_that_pv_value_causes_func_to_return_true( - "LKUP:SAMPLE:POSITIONS", func=lambda val: pos in val + "LKUP:SAMPLE:POSITIONS", func=lambda val, pos=pos: pos in val ) def test_GIVEN_a_different_slot_WHEN_a_position_is_selected_THEN_the_associated_slot_is_selected( @@ -235,7 +235,7 @@ def test_GIVEN_a_different_slot_WHEN_a_position_is_selected_THEN_the_associated_ self.ca.assert_that_pv_is("SAMPCHNG:SLOT:SP", "CT") self.ca.assert_that_pv_is("SAMPCHNG:SLOT", "CT") - for pos in ["{}CT".format(n) for n in range(1, 14 + 1)]: + for pos in [f"{n}CT" for n in range(1, 14 + 1)]: self.ca.assert_that_pv_value_causes_func_to_return_true( - "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val: pos in val + "SAMPCHNG:AVAILABLE_IN_SLOT", func=lambda val, pos=pos: pos in val ) diff --git a/tests/sampos.py b/tests/sampos.py index d2a36b4f..4bd1c2b0 100644 --- a/tests/sampos.py +++ b/tests/sampos.py @@ -1,4 +1,3 @@ -import os import unittest from utils.channel_access import ChannelAccess @@ -11,7 +10,7 @@ IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join(EPICS_TOP, "ioc", "master", "SAMPOS", "iocBoot", "iocSAMPOS"), + "directory": (EPICS_TOP / "ioc" / "master" / "SAMPOS" / "iocBoot" / "iocSAMPOS").as_posix(), "macros": {}, }, ] @@ -25,10 +24,9 @@ class SamposTests(unittest.TestCase): Tests for the sampos IOC. """ - test_values = [0, 10] - axes = ["X", "Y", "Z", "W", "S"] - def setUp(self): + self.test_values = [0, 10] + self.axes = ["X", "Y", "Z", "W", "S"] self._ioc = IOCRegister.get_running("SAMPOS") self.ca = ChannelAccess(20, device_prefix=DEVICE_PREFIX) @@ -41,12 +39,12 @@ def test_WHEN_values_are_set_THEN_readbacks_update(self): for axis in self.axes: for value in self.test_values: self.ca.assert_setting_setpoint_sets_readback( - value, readback_pv="{}".format(axis), set_point_pv="{}:SP".format(axis) + value, readback_pv=f"{axis}", set_point_pv=f"{axis}:SP" ) def test_WHEN_values_are_set_THEN_setpoint_readbacks_update(self): for axis in self.axes: for value in self.test_values: self.ca.assert_setting_setpoint_sets_readback( - value, readback_pv="{}:SP:RBV".format(axis), set_point_pv="{}:SP".format(axis) + value, readback_pv=f"{axis}:SP:RBV", set_point_pv=f"{axis}:SP" ) diff --git a/tests/sans2d_apertures_guides.py b/tests/sans2d_apertures_guides.py index 69c67f81..e57ca3ee 100644 --- a/tests/sans2d_apertures_guides.py +++ b/tests/sans2d_apertures_guides.py @@ -1,4 +1,3 @@ -import os import unittest from parameterized import parameterized @@ -8,24 +7,16 @@ from utils.ioc_launcher import EPICS_TOP, get_default_ioc_dir from utils.test_modes import TestModes -galil_settings_path = os.path.realpath( - os.path.join( - os.getenv("EPICS_KIT_ROOT"), - "support", - "motorExtensions", - "master", - "settings", - "sans2d_apertures_guides", - ) +galil_settings_path = ( + EPICS_TOP / "support" / "motorExtensions" / "master" / "settings" / "sans2d_apertures_guides" ) GALIL_ADDR1 = "127.0.0.11" GALIL_ADDR2 = "127.0.0.12" ioc_name = "FINS" -fins_settings_path = os.path.join( - EPICS_TOP, "ioc", "master", ioc_name, "exampleSettings", "SANS2D_vacuum" -) +fins_settings_path = EPICS_TOP / "ioc" / "master" / ioc_name / "exampleSettings" / "SANS2D_vacuum" + ioc_prefix = "FINS_VAC" IOCS = [ @@ -39,7 +30,7 @@ "GALILADDR1": GALIL_ADDR1, "MTRCTRL2": "02", "GALILADDR2": GALIL_ADDR2, - "GALILCONFIGDIR": galil_settings_path.replace("\\", "/"), + "GALILCONFIGDIR": galil_settings_path.as_posix(), }, }, { @@ -47,15 +38,13 @@ "directory": get_default_ioc_dir(ioc_name), "custom_prefix": ioc_prefix, "pv_for_existence": "HEARTBEAT", - "macros": {"FINSCONFIGDIR": fins_settings_path.replace("\\", "/"), "PLCIP": "127.0.0.3"}, + "macros": {"FINSCONFIGDIR": fins_settings_path.as_posix(), "PLCIP": "127.0.0.3"}, }, ] TEST_MODES = [TestModes.RECSIM] -AXES_TO_STOP = ["APERTURE_{}".format(i) for i in range(1, 6)] + [ - "GUIDE_{}".format(j) for j in range(1, 6) -] +AXES_TO_STOP = [f"APERTURE_{i}" for i in range(1, 6)] + [f"GUIDE_{j}" for j in range(1, 6)] class Sans2dAperturesGuidesTests(unittest.TestCase): diff --git a/tests/sans2d_vacuum.py b/tests/sans2d_vacuum.py index ce0762a4..43d8cde3 100644 --- a/tests/sans2d_vacuum.py +++ b/tests/sans2d_vacuum.py @@ -1,4 +1,3 @@ -import os import unittest from parameterized import parameterized @@ -16,16 +15,16 @@ "pv_for_existence": "HEARTBEAT", "macros": { "FINSCONFIGDIR": ( - os.path.join(EPICS_TOP, "ioc", "master", "FINS", "exampleSettings", "SANS2D_vacuum") - ).replace("\\", "/"), + EPICS_TOP / "ioc" / "master" / "FINS" / "exampleSettings" / "SANS2D_vacuum" + ).as_posix(), "PLCIP": "127.0.0.1", }, }, { "name": "RUNCTRL_01", "directory": ( - os.path.join(EPICS_TOP, "ioc", "master", "RUNCTRL", "iocBoot", "iocRUNCTRL_01") - ).replace("\\", "/"), + EPICS_TOP / "ioc" / "master" / "RUNCTRL" / "iocBoot" / "iocRUNCTRL_01" + ).as_posix(), "custom_prefix": "CS:IOC:RUNCTRL_01", "pv_for_existence": "DEVIOS:HEARTBEAT", }, @@ -130,9 +129,9 @@ def _set_sp_and_assert(self, set_pv, state, expected_state=None, int_state=None) int_state = state if expected_state is None: expected_state = state - self.ca.set_pv_value("{}:STATUS:SP".format(set_pv), int_state) + self.ca.set_pv_value(f"{set_pv}:STATUS:SP", int_state) self.ca.assert_that_pv_monitor_gets_values( - "{}:{}:SP".format(set_pv, expected_state), [expected_state, "..."] + f"{set_pv}:{expected_state}:SP", [expected_state, "..."] ) def test_WHEN_opening_and_closing_shutter_THEN_propogates(self): diff --git a/tests/sans2d_vacuum_collision_avoidance.py b/tests/sans2d_vacuum_collision_avoidance.py index 050b9023..c510cc1b 100644 --- a/tests/sans2d_vacuum_collision_avoidance.py +++ b/tests/sans2d_vacuum_collision_avoidance.py @@ -10,11 +10,6 @@ from utils.test_modes import TestModes from utils.testing import ManagerMode, parameterized_list -try: - from contextlib import nullcontext -except ImportError: - pass - test_path = os.path.realpath( os.path.join( os.getenv("EPICS_KIT_ROOT"), @@ -70,7 +65,7 @@ ERRORS = {"FDFB": "FDFB Collision", "FBRB": "FBRB Collision", "RBRD": "RBRD Collision"} -class AxisPair(object): +class AxisPair: def __init__(self, front_axis, rear_axis, name, interval_setpoint_name, minimum_interval): self.front_axis = front_axis self.front_axis_sp = front_axis + ":SP" @@ -81,7 +76,7 @@ def __init__(self, front_axis, rear_axis, name, interval_setpoint_name, minimum_ self.minimum_interval = minimum_interval def __repr__(self): - return "Interval between {} and {}".format(self.front_axis, self.rear_axis) + return f"Interval between {self.front_axis} and {self.rear_axis}" AXIS_PAIRS = [ @@ -136,9 +131,9 @@ def setUp(self): self.set_motor_speed_settings(axis, TEST_SPEED, TEST_SPEED, TEST_ACCELERATION) def set_motor_speed_settings(self, axis, velocity, max_velocity, acceleration): - self.ca.set_pv_value("{}:MTR.VMAX".format(axis), max_velocity) - self.ca.set_pv_value("{}:MTR.VELO".format(axis), velocity) - self.ca.set_pv_value("{}:MTR.ACCL".format(axis), acceleration) + self.ca.set_pv_value(f"{axis}:MTR.VMAX", max_velocity) + self.ca.set_pv_value(f"{axis}:MTR.VELO", velocity) + self.ca.set_pv_value(f"{axis}:MTR.ACCL", acceleration) @parameterized.expand(parameterized_list(AXIS_PAIRS)) def test_GIVEN_setpoint_for_each_axis_THEN_axis_not_moved(self, _, axis_pair): @@ -163,7 +158,7 @@ def test_GIVEN_front_axis_moves_towards_rear_axis_WHEN_setpoint_interval_smaller ) + 50 self.ca.set_pv_value(axis_pair.front_axis_sp, front_axis_new_position) - error_message = self.ca.get_pv_value("SANS2DVAC:{}_COLLISION".format(axis_pair.name)) + error_message = self.ca.get_pv_value(f"SANS2DVAC:{axis_pair.name}_COLLISION") self.assertEqual(error_message, ERRORS[axis_pair.name]) @parameterized.expand(parameterized_list(AXIS_PAIRS)) @@ -175,7 +170,7 @@ def test_GIVEN_front_axis_moves_towards_rear_axis_WHEN_setpoint_interval_smaller ) - 51 self.ca.set_pv_value(axis_pair.front_axis_sp, front_axis_new_position, sleep_after_set=1) - error_message = self.ca.get_pv_value("SANS2DVAC:{}_COLLISION".format(axis_pair.name)) + error_message = self.ca.get_pv_value(f"SANS2DVAC:{axis_pair.name}_COLLISION") self.assertEqual(error_message, "") def test_GIVEN_all_positions_valid_WHEN_move_all_THEN_all_axes_moved(self): @@ -190,8 +185,8 @@ def test_GIVEN_all_positions_valid_WHEN_move_all_THEN_all_axes_moved(self): self.ca.set_pv_value(axis_pair.rear_axis_sp, rear_axis_pos) self.ca.set_pv_value("SANS2DVAC:MOVE_ALL.PROC", 1, sleep_after_set=10) - for key in end_values.keys(): - self.assertEqual(end_values[key], self.ca.get_pv_value(key)) + for key, value in end_values.items(): + self.assertEqual(value, self.ca.get_pv_value(key)) def test_GIVEN_positions_invalid_WHEN_move_all_THEN_axes_movement_is_inhibited(self): for axis_pair in AXIS_PAIRS: @@ -214,16 +209,16 @@ def test_GIVEN_some_positions_invalid_WHEN_move_all_THEN_axes_movement_is_inhibi def test_GIVEN_some_axis_are_moving_THEN_not_possible_to_change_SP(self): positions = {"FRONTDETZ": 5000, "FRONTBAFFLEZ": 6100, "REARBAFFLEZ": 7500, "REARDETZ": 8000} - for axis_position in positions: - self.ca.set_pv_value(axis_position + ":SP", positions[axis_position]) + for axis_pv, axis_position in positions.items(): + self.ca.set_pv_value(axis_pv + ":SP", axis_position) self.ca.set_pv_value("SANS2DVAC:MOVE_ALL.PROC", 1) - for axis_position in positions: + for axis_pv, axis_position in positions.items(): with self.assertRaises( WriteAccessException, msg="DISP should be set on inhibited axis" ): - self.ca.set_pv_value(axis_position + ":SP", positions[axis_position]) + self.ca.set_pv_value(axis_pv + ":SP", axis_position) @parameterized.expand(parameterized_list(BAFFLES_AND_DETECTORS_Z_AXES)) def test_GIVEN_some_axes_have_stopped_moving_THEN_stopped_axes_are_set_to_PAUSE(self, _, axis): @@ -241,14 +236,14 @@ def test_GIVEN_some_axes_have_stopped_moving_THEN_stopped_axes_are_set_to_PAUSE( self.ca.set_pv_value("SANS2DVAC:MOVE_ALL.PROC", 1, sleep_after_set=5) for tank_axis in BAFFLES_AND_DETECTORS_Z_AXES: - movn = self.ca.get_pv_value("{}:MTR.MOVN".format(tank_axis)) - spmg = self.ca.get_pv_value("{}:MTR.SPMG".format(tank_axis)) + movn = self.ca.get_pv_value(f"{tank_axis}:MTR.MOVN") + spmg = self.ca.get_pv_value(f"{tank_axis}:MTR.SPMG") # we have a potential race condition in that motor may stop after we have read movn # but before we read spmg. So re-read movn if mismatch. Because of sleep_after_set # we should only need to worry about a motor stopping and not one starting if movn and spmg == "Pause": print("Re-reading MOVN to workaround race condition") - movn = self.ca.get_pv_value("{}:MTR.MOVN".format(tank_axis)) + movn = self.ca.get_pv_value(f"{tank_axis}:MTR.MOVN") if movn: self.assertEqual(spmg, "Move") else: diff --git a/tests/sans2d_vacuum_tank.py b/tests/sans2d_vacuum_tank.py index c18065a8..655f8860 100644 --- a/tests/sans2d_vacuum_tank.py +++ b/tests/sans2d_vacuum_tank.py @@ -1,4 +1,3 @@ -import os import unittest from genie_python.channel_access_exceptions import WriteAccessException @@ -10,16 +9,7 @@ from utils.test_modes import TestModes from utils.testing import parameterized_list -test_path = os.path.realpath( - os.path.join( - os.getenv("EPICS_KIT_ROOT"), - "support", - "motorExtensions", - "master", - "settings", - "sans2d_vacuum_tank", - ) -) +test_path = EPICS_TOP / "support" / "motorExtensions" / "master" / "settings" / "sans2d_vacuum_tank" GALIL_ADDR1 = "127.0.0.11" GALIL_ADDR2 = "127.0.0.12" @@ -34,8 +24,8 @@ "pv_for_existence": "HEARTBEAT", "macros": { "FINSCONFIGDIR": ( - os.path.join(EPICS_TOP, "ioc", "master", "FINS", "exampleSettings", "SANS2D_vacuum") - ).replace("\\", "/"), + EPICS_TOP / "ioc" / "master" / "FINS" / "exampleSettings" / "SANS2D_vacuum" + ).as_posix(), "PLCIP": "127.0.0.1", }, }, @@ -47,7 +37,7 @@ "macros": { "GALILADDR": GALIL_ADDR1, "MTRCTRL": "03", - "GALILCONFIGDIR": test_path.replace("\\", "/"), + "GALILCONFIGDIR": test_path.as_posix(), }, }, { @@ -60,7 +50,7 @@ "GALILADDR1": GALIL_ADDR2, "MTRCTRL2": "05", "GALILADDR2": GALIL_ADDR3, - "GALILCONFIGDIR": test_path.replace("\\", "/"), + "GALILCONFIGDIR": test_path.as_posix(), }, }, ] @@ -114,12 +104,12 @@ def setUp(self): self.upper_inhibit_bound = 2 def reset_axis_to_non_inhibit(self, axis): - self.ca.set_pv_value("{}:SP".format(axis), 0) + self.ca.set_pv_value(f"{axis}:SP", 0) self.ca.assert_that_pv_is_number(axis, 0, timeout=10) def reset_axes_to_non_inhibit(self, axis_one, axis_two): - axis_one_val = self.ca.get_pv_value("{}:SP".format(axis_one)) - axis_two_val = self.ca.get_pv_value("{}:SP".format(axis_two)) + axis_one_val = self.ca.get_pv_value(f"{axis_one}:SP") + axis_two_val = self.ca.get_pv_value(f"{axis_two}:SP") axis_one_inhibiting = ( axis_one_val < self.lower_inhibit_bound or axis_one_val > self.upper_inhibit_bound ) @@ -128,9 +118,7 @@ def reset_axes_to_non_inhibit(self, axis_one, axis_two): ) if axis_one_inhibiting and axis_two_inhibiting: self.fail( - "Both {} and {} are inhibiting each other, cannot reliably run test".format( - axis_one, axis_two - ) + f"Both {axis_one} and {axis_two} are inhibiting each other, cannot reliably run test" ) elif axis_one_inhibiting: self.reset_axis_to_non_inhibit(axis_one) @@ -145,15 +133,15 @@ def test_GIVEN_axes_in_range_WHEN_axis_goes_out_of_range_THEN_other_axis_inhibit self.reset_axes_to_non_inhibit(inhibited_axis, inhibiting_axis) try: # Act - self.ca.set_pv_value("{}:SP".format(inhibiting_axis), -3) - self.ca.assert_that_pv_is_number("{}:SP".format(inhibiting_axis), -3) + self.ca.set_pv_value(f"{inhibiting_axis}:SP", -3) + self.ca.assert_that_pv_is_number(f"{inhibiting_axis}:SP", -3) start_position = self.ca.get_pv_value(inhibited_axis) with self.assertRaises( WriteAccessException, msg="DISP should be set on inhibited axis" ): set_axis_moving(inhibited_axis) # Assert - self.ca.assert_that_pv_is("SANS2DVAC:INHIBIT_{}".format(inhibited_axis), 1) + self.ca.assert_that_pv_is(f"SANS2DVAC:INHIBIT_{inhibited_axis}", 1) end_position = self.ca.get_pv_value(inhibited_axis) self.assertEqual(start_position, end_position) finally: diff --git a/tests/separator.py b/tests/separator.py index 88b73f9e..5c3ce4b0 100644 --- a/tests/separator.py +++ b/tests/separator.py @@ -1,6 +1,7 @@ import threading import unittest from time import perf_counter, sleep +from typing import ClassVar from numpy import dot from parameterized import parameterized @@ -240,8 +241,6 @@ def shared_setup(ca): current_set_up(ca) stability_set_up(ca) - return None - def apply_average_filter(unfiltered_data, stride=1): """ @@ -255,7 +254,7 @@ def apply_average_filter(unfiltered_data, stride=1): """ data = [ 0.5 * (unfiltered_data[i] + unfiltered_data[i + stride]) - for i in range(0, len(unfiltered_data) - stride) + for i in range(len(unfiltered_data) - stride) ] return data @@ -354,8 +353,13 @@ def test_that_GIVEN_psu_on_WHEN_voltage_setpoint_changed_lower_than_threshold_TH class VoltageTests(unittest.TestCase): - voltage_values = [0, 10.1111111, 10e1, 20e-2, 200] - voltage_values_which_give_alarms = [-50, MIN_SEPARATOR_VOLT, MAX_SEPARATOR_VOLT, 250] + voltage_values: ClassVar[list[float]] = [0, 10.1111111, 10e1, 20e-2, 200] + voltage_values_which_give_alarms: ClassVar[list[float]] = [ + -50, + MIN_SEPARATOR_VOLT, + MAX_SEPARATOR_VOLT, + 250, + ] def setUp(self): self.ca = ChannelAccess(20, device_prefix=DEVICE_PREFIX) @@ -449,8 +453,8 @@ def test_GIVEN_unfiltered_data_WHEN_filtering_applied_THEN_corrected_data_is_ret class CurrentTests(unittest.TestCase): # These current testing values are uncalibrated values from the DAQ lying between 0 and 10. - current_values = [0, 1.33333, 5e1, 10e-3, 10] - current_values_which_give_alarms = [10, 11] + current_values: ClassVar[list[float]] = [0, 1.33333, 5e1, 10e-3, 10] + current_values_which_give_alarms: ClassVar[list[float]] = [10, 11] def setUp(self): self.ca = ChannelAccess(20, device_prefix=DEVICE_PREFIX) diff --git a/tests/simple.py b/tests/simple.py index 103aeaa4..2ce9a7fa 100644 --- a/tests/simple.py +++ b/tests/simple.py @@ -58,12 +58,16 @@ def write_through_cmd(address, new_val): - null_file = open(os.devnull, "w") - subprocess.call( - ["caput", "{}{}:{}".format(os.environ["MYPVPREFIX"], DEVICE_PREFIX, address), str(new_val)], - stdout=null_file, - stderr=subprocess.STDOUT, - ) + with open(os.devnull, "w") as null_file: + subprocess.call( + [ + "caput", + "{}{}:{}".format(os.environ["MYPVPREFIX"], DEVICE_PREFIX, address), + str(new_val), + ], + stdout=null_file, + stderr=subprocess.STDOUT, + ) class SimpleTests(unittest.TestCase): @@ -79,7 +83,7 @@ def setUp(self): # Some of the ca test PVs seem to take a while to appear on build server. for protection, record in itertools.product(PROTECTION_TYPES, RECORD_TYPES): - self.ca.assert_that_pv_exists("CATEST:{}:{}".format(record, protection), timeout=120) + self.ca.assert_that_pv_exists(f"CATEST:{record}:{protection}", timeout=120) self.set_auto_restart_to_true() @@ -129,13 +133,11 @@ def check_write_through_python(addr, record_type): pass return val_before != self.ca.get_pv_value(addr) - address = "CATEST:{}:{}".format(record, protection) + address = f"CATEST:{record}:{protection}" self.ca.assert_that_pv_exists(address) if check_write_through_python(address, record): self.fail( - "Could (wrongly) use python to write to {} pvs {}".format( - record, protection_dict[protection] - ) + f"Could (wrongly) use python to write to {record} pvs {protection_dict[protection]}" ) @parameterized.expand(parameterized_list(itertools.product(PROTECTION_TYPES, RECORD_TYPES))) @@ -148,23 +150,21 @@ def check_write_through_cmd(addr): write_through_cmd(addr, new_val) return val_before != self.ca.get_pv_value(addr) - address = "CATEST:{}:{}".format(record, protection) + address = f"CATEST:{record}:{protection}" self.ca.assert_that_pv_exists(address) if check_write_through_cmd(address): self.fail( - "Could (wrongly) use cmd to write to {} pvs {}".format( - record, protection_dict[protection] - ) + f"Could (wrongly) use cmd to write to {record} pvs {protection_dict[protection]}" ) @parameterized.expand(parameterized_list(RECORD_TYPES)) @unstable_test(max_retries=5, wait_between_runs=10) def test_GIVEN_PV_in_hidden_mode_WHEN_read_attempted_THEN_get_error(self, _, record): - address = "CATEST:{}:HIDDEN".format(record) + address = f"CATEST:{record}:HIDDEN" self.ca.assert_that_pv_exists(address) try: self.ca.get_pv_value(address) - self.fail("{} pv could be read in hidden mode".format(record)) + self.fail(f"{record} pv could be read in hidden mode") except ReadAccessException: pass @@ -173,16 +173,14 @@ def test_GIVEN_PV_in_hidden_mode_WHEN_read_attempted_THEN_get_error(self, _, rec def test_GIVEN_PV_in_READONLY_mode_or_with_disp_true_WHEN_linked_to_THEN_link_successful( self, _, protection, record ): - address = "CATEST:{}:{}".format(record, protection) - address_out = "{}:OUT".format(address) + address = f"CATEST:{record}:{protection}" + address_out = f"{address}:OUT" self.ca.assert_that_pv_exists(address) val_before, new_val = self.get_toggle_value(address) write_through_cmd(address_out, new_val) if val_before == self.ca.get_pv_value(address): self.fail( - "OUT field failed to forward value to {} pvs {}".format( - record, protection_dict[protection] - ) + f"OUT field failed to forward value to {record} pvs {protection_dict[protection]}" ) @parameterized.expand(parameterized_list(itertools.product(PROTECTION_TYPES, RECORD_TYPES))) @@ -202,13 +200,11 @@ def check_write_through_python(addr): self.ca.get_pv_value(addr + ":PROC") == "1" ) # starts off as 0, goes to 1 when processed (fail) - address = "CATEST:{}:{}".format(record, protection) + address = f"CATEST:{record}:{protection}" self.ca.assert_that_pv_exists(address) if check_write_through_python(address): self.fail( - "Could (wrongly) use python to process protected pvs using {} pvs {}".format( - record, protection_dict[protection] - ) + f"Could (wrongly) use python to process protected pvs using {record} pvs {protection_dict[protection]}" ) @parameterized.expand(parameterized_list(itertools.product(PROTECTION_TYPES, RECORD_TYPES))) @@ -222,13 +218,11 @@ def check_write_through_cmd(addr): self.ca.get_pv_value(addr + ":PROC") == "1" ) # starts off as 0, goes to 1 when processed (fail) - address = "CATEST:{}:{}".format(record, protection) + address = f"CATEST:{record}:{protection}" self.ca.assert_that_pv_exists(address) if check_write_through_cmd(address): self.fail( - "Could (wrongly) use cmd to process protected pvs using {} pvs {}".format( - record, protection_dict[protection] - ) + f"Could (wrongly) use cmd to process protected pvs using {record} pvs {protection_dict[protection]}" ) def test_GIVEN_PV_WHEN_written_and_read_million_times_THEN_value_read_correctly(self): diff --git a/tests/skf_mb350_chopper.py b/tests/skf_mb350_chopper.py index b57ec609..d173787b 100644 --- a/tests/skf_mb350_chopper.py +++ b/tests/skf_mb350_chopper.py @@ -114,7 +114,7 @@ def _set_and_assert_interlock_state(interlock, on): self._lewis.backdoor_command( ["device", "set_interlock_state", interlock, "True" if on else "False"] ) - self.ca.assert_that_pv_is("ILK:{}".format(interlock), "Active" if on else "Inactive") + self.ca.assert_that_pv_is(f"ILK:{interlock}", "Active" if on else "Inactive") for interlock in INTERLOCKS: _set_and_assert_interlock_state(interlock, True) diff --git a/tests/sp2xx.py b/tests/sp2xx.py index d9cf72bf..9e6566ad 100644 --- a/tests/sp2xx.py +++ b/tests/sp2xx.py @@ -128,7 +128,7 @@ def test_that_GIVEN_a_stopped_pump_THEN_the_pump_remains_stopped(self): self.ca.assert_that_pv_is("STATUS", "Stopped") -class ErrorType(object): +class ErrorType: """ Error Type. @@ -197,13 +197,14 @@ def test_that_GIVEN_a_device_with_an_error_WHEN_trying_to_start_the_device_THEN_ self.ca.assert_that_pv_is("STATUS", "Stopped") +MODES = ["Infusion/Withdrawal", "Withdrawal/Infusion", "Infusion", "Withdrawal", "Continuous"] + + class ModeSwitchingTests(unittest.TestCase): def setUp(self): # Given self._lewis, self._ioc, self.ca = _reset_device() - MODES = ["Infusion/Withdrawal", "Withdrawal/Infusion", "Infusion", "Withdrawal", "Continuous"] - def test_that_GIVEN_an_initialized_pump_THEN_the_mode_is_set_to_infusing(self): # Then: self.ca.assert_that_pv_is("MODE", "Infusion") diff --git a/tests/spinflipper.py b/tests/spinflipper.py index 63130251..d514f778 100644 --- a/tests/spinflipper.py +++ b/tests/spinflipper.py @@ -1,19 +1,18 @@ -import os import unittest from utils.channel_access import ChannelAccess +from utils.ioc_launcher import EPICS_TOP from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc DEVICE_PREFIX = "SPINFLIPPER_01" -EPICS_TOP = os.environ.get("KIT_ROOT", os.path.join("C:\\", "Instrument", "Apps", "EPICS")) IOCS = [ { "name": DEVICE_PREFIX, - "directory": os.path.join( - EPICS_TOP, "ioc", "master", "SPINFLIPPER306015", "iocBoot", "iocSPINFLIPPER-IOC-01" - ), + "directory": ( + EPICS_TOP / "ioc" / "master" / "SPINFLIPPER306015" / "iocBoot" / "iocSPINFLIPPER-IOC-01" + ).as_posix(), "macros": {}, "emulator": "Spinflipper", }, diff --git a/tests/tdk_lambda_genesys.py b/tests/tdk_lambda_genesys.py index fc3156d8..7bf58931 100644 --- a/tests/tdk_lambda_genesys.py +++ b/tests/tdk_lambda_genesys.py @@ -1,5 +1,4 @@ import contextlib -import os import unittest from utils.channel_access import ChannelAccess @@ -19,13 +18,13 @@ IOCS = [ { "name": "GENESYS_01", - "directory": os.path.join( - EPICS_TOP, "ioc", "master", "TDK_LAMBDA_GENESYS", "iocBoot", "iocGENESYS-IOC-01" - ), + "directory": ( + EPICS_TOP / "ioc" / "master" / "TDK_LAMBDA_GENESYS" / "iocBoot" / "iocGENESYS-IOC-01" + ).as_posix(), "macros": { "ADDR1": "1", "PORT1": "1", - "AMPSTOGAUSS1": "{}".format(AMPS_TO_GAUSS), + "AMPSTOGAUSS1": f"{AMPS_TO_GAUSS}", "TOLERANCE": 0.1, "READ_OFFSET1": DEFAULT_READ_OFFSET, "WRITE_OFFSET1": DEFAULT_WRITE_OFFSET, @@ -41,7 +40,7 @@ TEST_MODES = [TestModes.RECSIM, TestModes.DEVSIM] -class OutputMode(object): +class OutputMode: VOLTAGE = "VOLTAGE" CURRENT = "CURRENT" diff --git a/tests/tekafg3XXX.py b/tests/tekafg3XXX.py index 7f5f5825..f81df34f 100644 --- a/tests/tekafg3XXX.py +++ b/tests/tekafg3XXX.py @@ -76,7 +76,7 @@ def test_GIVEN_scan_macro_set_passive_WHEN_sp_changed_THEN_sp_rbv_changed(self): def test_GIVEN_arbitrary_command_WHEN_sent_THEN_output_received(self): expected_value = 15.0 self.ca.set_pv_value("WRITE:SP", f"SOUR1:VOLT {expected_value}", wait=True) - self.ca.set_pv_value("OUTPUT1:VOLT.PROC", 1) # needed as SCAN macro for tests is "Passive" + self.ca.set_pv_value("OUTPUT1:VOLT.PROC", 1) # needed as SCAN macro for tests is "Passive" self.ca.assert_that_pv_is("OUTPUT1:VOLT", expected_value) self.ca.set_pv_value("READ:SP", "SOUR1:VOLT?") self.ca.assert_that_pv_is("READ", str(expected_value)) diff --git a/tests/tizr.py b/tests/tizr.py index 2e99b147..5bcb5b29 100644 --- a/tests/tizr.py +++ b/tests/tizr.py @@ -1,4 +1,3 @@ -import os import time import unittest from contextlib import contextmanager @@ -26,8 +25,8 @@ SAFE_VALUE = 11 tizr_macros = { - "PVONE": "{prefix}{pv}".format(prefix=DEVICE_PREFIX, pv=SIMPLE_VALUE_ONE), - "PVTWO": "{prefix}{pv}".format(prefix=DEVICE_PREFIX, pv=SIMPLE_VALUE_TWO), + "PVONE": f"{DEVICE_PREFIX}{SIMPLE_VALUE_ONE}", + "PVTWO": f"{DEVICE_PREFIX}{SIMPLE_VALUE_TWO}", "PVONE_MAX": PVONE_MAX, "PVTWO_MAX": PVTWO_MAX, "SAFE_VALUE": SAFE_VALUE, @@ -44,13 +43,15 @@ }, { "name": "SIMPLE", - "directory": os.path.join(EPICS_TOP, "ISIS", "SimpleIoc", "master", "iocBoot", "iocsimple"), + "directory": ( + EPICS_TOP / "ISIS" / "SimpleIoc" / "master" / "iocBoot" / "iocsimple" + ).as_posix(), "macros": {}, }, ] -WARNING_PV = "{}:TIZRWARNING".format(IOC_PREFIX) -MONITORING_ON_PV = "{}:MONITORING_ON".format(IOC_PREFIX) +WARNING_PV = f"{IOC_PREFIX}:TIZRWARNING" +MONITORING_ON_PV = f"{IOC_PREFIX}:MONITORING_ON" TEST_MODES = [TestModes.RECSIM] diff --git a/tests/triton.py b/tests/triton.py index 83da144e..169f0e06 100644 --- a/tests/triton.py +++ b/tests/triton.py @@ -119,7 +119,7 @@ def test_WHEN_channels_are_enabled_and_disabled_via_pv_THEN_the_readback_pv_upda for chan in VALID_TEMPERATURE_SENSORS: for enabled in [False, True, False]: # Need to check both transitions work properly self.ca.assert_setting_setpoint_sets_readback( - "ON" if enabled else "OFF", "CHANNELS:T{}:STATE".format(chan) + "ON" if enabled else "OFF", f"CHANNELS:T{chan}:STATE" ) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -171,7 +171,7 @@ def test_WHEN_automation_is_set_on_device_THEN_displayed_automation_is_identical def _set_temp_via_backdoor(self, channel, temp): self._lewis.backdoor_command( - ["device", "set_temperature_backdoor", "'{}'".format(channel), "{}".format(temp)] + ["device", "set_temperature_backdoor", f"'{channel}'", f"{temp}"] ) @skip_if_recsim("Lewis backdoor not available in recsim") @@ -210,7 +210,7 @@ def test_WHEN_pressure_is_set_via_backdoor_THEN_pressure_pv_updates(self): self._lewis.backdoor_command( ["device", "set_pressure_backdoor", str(sensor), str(pressure)] ) - self.ca.assert_that_pv_is("PRESSURE:P{}".format(sensor), pressure) + self.ca.assert_that_pv_is(f"PRESSURE:P{sensor}", pressure) def test_WHEN_closed_loop_is_set_via_pv_THEN_readback_updates(self): for state in [False, True, False]: @@ -233,7 +233,7 @@ def test_WHEN_channel_temperature_is_set_via_backdoor_THEN_the_pvs_update_with_v self._lewis.backdoor_command( ["device", "set_sensor_property_backdoor", str(chan), "temperature", str(value)] ) - self.ca.assert_that_pv_is("CHANNELS:T{}:TEMP".format(chan), value) + self.ca.assert_that_pv_is(f"CHANNELS:T{chan}:TEMP", value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_channel_resistance_is_set_via_backdoor_THEN_the_pvs_update_with_values_just_written( @@ -243,7 +243,7 @@ def test_WHEN_channel_resistance_is_set_via_backdoor_THEN_the_pvs_update_with_va self._lewis.backdoor_command( ["device", "set_sensor_property_backdoor", str(chan), "resistance", str(value)] ) - self.ca.assert_that_pv_is("CHANNELS:T{}:RES".format(chan), value) + self.ca.assert_that_pv_is(f"CHANNELS:T{chan}:RES", value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_channel_excitation_is_set_via_backdoor_THEN_the_pvs_update_with_values_just_written( @@ -253,7 +253,7 @@ def test_WHEN_channel_excitation_is_set_via_backdoor_THEN_the_pvs_update_with_va self._lewis.backdoor_command( ["device", "set_sensor_property_backdoor", str(chan), "excitation", str(value)] ) - self.ca.assert_that_pv_is("CHANNELS:T{}:EXCITATION".format(chan), value) + self.ca.assert_that_pv_is(f"CHANNELS:T{chan}:EXCITATION", value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_channel_pause_is_set_via_backdoor_THEN_the_pvs_update_with_values_just_written( @@ -263,7 +263,7 @@ def test_WHEN_channel_pause_is_set_via_backdoor_THEN_the_pvs_update_with_values_ self._lewis.backdoor_command( ["device", "set_sensor_property_backdoor", str(chan), "pause", str(value)] ) - self.ca.assert_that_pv_is("CHANNELS:T{}:PAUSE".format(chan), value) + self.ca.assert_that_pv_is(f"CHANNELS:T{chan}:PAUSE", value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_channel_dwell_is_set_via_backdoor_THEN_the_pvs_update_with_values_just_written( @@ -273,7 +273,7 @@ def test_WHEN_channel_dwell_is_set_via_backdoor_THEN_the_pvs_update_with_values_ self._lewis.backdoor_command( ["device", "set_sensor_property_backdoor", str(chan), "dwell", str(value)] ) - self.ca.assert_that_pv_is("CHANNELS:T{}:DWELL".format(chan), value) + self.ca.assert_that_pv_is(f"CHANNELS:T{chan}:DWELL", value) @skip_if_recsim("Lewis backdoor not available in recsim") def test_WHEN_heater_resistance_is_changed_THEN_heater_heater_resistance_pv_updates(self): diff --git a/tests/zfcntrl.py b/tests/zfcntrl.py index c64fd77b..a862f0a1 100644 --- a/tests/zfcntrl.py +++ b/tests/zfcntrl.py @@ -40,10 +40,10 @@ "OUTPUT_Y_MAX": DEFAULT_HIGH_OUTPUT_LIMIT, "OUTPUT_Z_MIN": DEFAULT_LOW_OUTPUT_LIMIT, "OUTPUT_Z_MAX": DEFAULT_HIGH_OUTPUT_LIMIT, - "PSU_X": r"$(MYPVPREFIX){}".format(X_KEPCO_DEVICE_PREFIX), - "PSU_Y": r"$(MYPVPREFIX){}".format(Y_KEPCO_DEVICE_PREFIX), - "PSU_Z": r"$(MYPVPREFIX){}".format(Z_KEPCO_DEVICE_PREFIX), - "MAGNETOMETER": r"$(MYPVPREFIX){}".format(MAGNETOMETER_DEVICE_PREFIX), + "PSU_X": rf"$(MYPVPREFIX){X_KEPCO_DEVICE_PREFIX}", + "PSU_Y": rf"$(MYPVPREFIX){Y_KEPCO_DEVICE_PREFIX}", + "PSU_Z": rf"$(MYPVPREFIX){Z_KEPCO_DEVICE_PREFIX}", + "MAGNETOMETER": rf"$(MYPVPREFIX){MAGNETOMETER_DEVICE_PREFIX}", "FEEDBACK": "1", "AMPS_PER_MG_X": "1", "AMPS_PER_MG_Y": "1", @@ -72,7 +72,7 @@ "OFFSET_X": 0, "OFFSET_Y": 0, "OFFSET_Z": 0, - "SQNCR": r"$(MYPVPREFIX){}:INPUTS_UPDATED.PROC CA".format(ZF_DEVICE_PREFIX), + "SQNCR": rf"$(MYPVPREFIX){ZF_DEVICE_PREFIX}:INPUTS_UPDATED.PROC CA", "RANGE": 1, }, }, @@ -124,12 +124,10 @@ def _update_fields_continuously(psu_amps_at_measured_zero): } for axis in FIELD_AXES: - magnetometer_ca.set_pv_value( - "SIM:DAQ:{}".format(axis), measured[axis], sleep_after_set=0 - ) + magnetometer_ca.set_pv_value(f"SIM:DAQ:{axis}", measured[axis], sleep_after_set=0) -class Statuses(object): +class Statuses: NO_ERROR = ("No error", ChannelAccess.Alarms.NONE) MAGNETOMETER_READ_ERROR = ("No new magnetometer data", ChannelAccess.Alarms.INVALID) MAGNETOMETER_OVERLOAD = ("Magnetometer overloaded", ChannelAccess.Alarms.MAJOR) @@ -141,7 +139,7 @@ class Statuses(object): PSU_SP_RBV_OUT_OF_LIMITS = ("PSU sp_rbv out of range", ChannelAccess.Alarms.MAJOR) -class AtSetpointStatuses(object): +class AtSetpointStatuses: TRUE = "Yes" FALSE = "No" NA = "N/A" @@ -161,9 +159,7 @@ def _set_simulated_measured_fields(self, fields, overload=False, wait_for_update wait_for_update (bool): whether to wait for the statemachine to pick up the new readings """ for axis in FIELD_AXES: - self.magnetometer_ca.set_pv_value( - "SIM:DAQ:{}".format(axis), fields[axis], sleep_after_set=0 - ) + self.magnetometer_ca.set_pv_value(f"SIM:DAQ:{axis}", fields[axis], sleep_after_set=0) # Just overwrite the calculation to return a constant as we are not interested in testing the # overload logic in the magnetometer in these tests (that logic is tested separately). @@ -173,8 +169,8 @@ def _set_simulated_measured_fields(self, fields, overload=False, wait_for_update if wait_for_update: for axis in FIELD_AXES: - self.zfcntrl_ca.assert_that_pv_is("FIELD:{}".format(axis), fields[axis]) - self.zfcntrl_ca.assert_that_pv_is("FIELD:{}:MEAS".format(axis), fields[axis]) + self.zfcntrl_ca.assert_that_pv_is(f"FIELD:{axis}", fields[axis]) + self.zfcntrl_ca.assert_that_pv_is(f"FIELD:{axis}:MEAS", fields[axis]) def _set_user_setpoints(self, fields): """ @@ -183,9 +179,7 @@ def _set_user_setpoints(self, fields): required fields """ for axis in FIELD_AXES: - self.zfcntrl_ca.set_pv_value( - "FIELD:{}:SP".format(axis), fields[axis], sleep_after_set=0 - ) + self.zfcntrl_ca.set_pv_value(f"FIELD:{axis}:SP", fields[axis], sleep_after_set=0) def _set_simulated_power_supply_currents(self, currents, wait_for_update=True): """ @@ -200,15 +194,13 @@ def _set_simulated_power_supply_currents(self, currents, wait_for_update=True): for axis in FIELD_AXES: self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP".format(axis), currents[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP", currents[axis], sleep_after_set=0 ) if wait_for_update: for axis in FIELD_AXES: - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:CURR".format(axis), currents[axis]) - self.zfcntrl_ca.assert_that_pv_is( - "OUTPUT:{}:CURR:SP:RBV".format(axis), currents[axis] - ) + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:CURR", currents[axis]) + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:CURR:SP:RBV", currents[axis]) def _set_simulated_power_supply_voltages(self, voltages, wait_for_update=True): """ @@ -219,15 +211,13 @@ def _set_simulated_power_supply_voltages(self, voltages, wait_for_update=True): """ for axis in FIELD_AXES: self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:VOLT:SP".format(axis), voltages[axis], sleep_after_set=0 + f"OUTPUT:{axis}:VOLT:SP", voltages[axis], sleep_after_set=0 ) if wait_for_update: for axis in FIELD_AXES: - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:VOLT".format(axis), voltages[axis]) - self.zfcntrl_ca.assert_that_pv_is( - "OUTPUT:{}:VOLT:SP:RBV".format(axis), voltages[axis] - ) + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:VOLT", voltages[axis]) + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:VOLT:SP:RBV", voltages[axis]) def _assert_at_setpoint(self, status): """ @@ -281,30 +271,30 @@ def _set_output_limits(self, lower_limits, upper_limits): """ for axis in FIELD_AXES: self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP.DRVL".format(axis), lower_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP.DRVL", lower_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP.LOLO".format(axis), lower_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP.LOLO", lower_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP.DRVH".format(axis), upper_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP.DRVH", upper_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP.HIHI".format(axis), upper_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP.HIHI", upper_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR.LOLO".format(axis), lower_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR.LOLO", lower_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR.HIHI".format(axis), upper_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR.HIHI", upper_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP:RBV.LOLO".format(axis), lower_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP:RBV.LOLO", lower_limits[axis], sleep_after_set=0 ) self.zfcntrl_ca.set_pv_value( - "OUTPUT:{}:CURR:SP:RBV.HIHI".format(axis), upper_limits[axis], sleep_after_set=0 + f"OUTPUT:{axis}:CURR:SP:RBV.HIHI", upper_limits[axis], sleep_after_set=0 ) @contextlib.contextmanager @@ -325,7 +315,7 @@ def _simulate_invalid_magnetometer_readings(self): """ for axis in FIELD_AXES: self.magnetometer_ca.set_pv_value( - "DAQ:{}:_RAW.SIMS".format(axis), + f"DAQ:{axis}:_RAW.SIMS", self.magnetometer_ca.Alarms.INVALID, sleep_after_set=0, ) @@ -333,21 +323,21 @@ def _simulate_invalid_magnetometer_readings(self): # Wait for RAW PVs to process for axis in FIELD_AXES: self.magnetometer_ca.assert_that_pv_alarm_is( - "DAQ:{}:_RAW.SEVR".format(axis), self.magnetometer_ca.Alarms.INVALID + f"DAQ:{axis}:_RAW.SEVR", self.magnetometer_ca.Alarms.INVALID ) try: yield finally: for axis in FIELD_AXES: self.magnetometer_ca.set_pv_value( - "DAQ:{}:_RAW.SIMS".format(axis), + f"DAQ:{axis}:_RAW.SIMS", self.magnetometer_ca.Alarms.NONE, sleep_after_set=0, ) # Wait for RAW PVs to process for axis in FIELD_AXES: self.magnetometer_ca.assert_that_pv_alarm_is( - "DAQ:{}:_RAW.SEVR".format(axis), self.magnetometer_ca.Alarms.NONE + f"DAQ:{axis}:_RAW.SEVR", self.magnetometer_ca.Alarms.NONE ) @contextlib.contextmanager @@ -369,7 +359,7 @@ def _simulate_invalid_power_supply(self): (self.x_psu_ca, self.y_psu_ca, self.z_psu_ca), pvs_to_make_invalid ): # 3 is the Enum value for an invalid alarm - ca.set_pv_value("{}.SIMS".format(pv), 3, sleep_after_set=0) + ca.set_pv_value(f"{pv}.SIMS", 3, sleep_after_set=0) # Use a separate loop to avoid needing to wait for a 1-second scan 6 times. for ca, pv in itertools.product( @@ -383,7 +373,7 @@ def _simulate_invalid_power_supply(self): for ca, pv in itertools.product( (self.x_psu_ca, self.y_psu_ca, self.z_psu_ca), pvs_to_make_invalid ): - ca.set_pv_value("{}.SIMS".format(pv), 0, sleep_after_set=0) + ca.set_pv_value(f"{pv}.SIMS", 0, sleep_after_set=0) # Use a separate loop to avoid needing to wait for a 1-second scan 6 times. for ca, pv in itertools.product( @@ -446,8 +436,8 @@ def _wait_for_all_iocs_up(self): ca.assert_that_pv_exists("CURRENT:SP:RBV") for axis in FIELD_AXES: - self.zfcntrl_ca.assert_that_pv_exists("FIELD:{}".format(axis)) - self.magnetometer_ca.assert_that_pv_exists("CORRECTEDFIELD:{}".format(axis)) + self.zfcntrl_ca.assert_that_pv_exists(f"FIELD:{axis}") + self.magnetometer_ca.assert_that_pv_exists(f"CORRECTEDFIELD:{axis}") def setUp(self): _, self._ioc = get_running_lewis_and_ioc(None, ZF_DEVICE_PREFIX) @@ -470,7 +460,7 @@ def setUp(self): # Set the magnetometer calibration to the 3x3 identity matrix for x, y in itertools.product(range(1, 3 + 1), range(1, 3 + 1)): self.magnetometer_ca.set_pv_value( - "SENSORMATRIX:{}{}".format(x, y), 1 if x == y else 0, sleep_after_set=0 + f"SENSORMATRIX:{x}{y}", 1 if x == y else 0, sleep_after_set=0 ) self._set_simulated_measured_fields(ZERO_FIELD, overload=False) @@ -506,7 +496,7 @@ def test_WHEN_manual_mode_and_any_readback_value_is_not_equal_to_setpoint_THEN_a self._set_user_setpoints(fields) # Set one of the parameters to a completely different value - self.zfcntrl_ca.set_pv_value("FIELD:{}:SP".format(axis_to_vary), 100, sleep_after_set=0) + self.zfcntrl_ca.set_pv_value(f"FIELD:{axis_to_vary}:SP", 100, sleep_after_set=0) self._assert_at_setpoint(AtSetpointStatuses.NA) self._assert_status(Statuses.NO_ERROR) @@ -560,20 +550,18 @@ def test_WHEN_magnetometer_ioc_does_not_respond_THEN_status_is_magnetometer_read self._assert_status(Statuses.MAGNETOMETER_READ_ERROR) for axis in FIELD_AXES: self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}".format(axis), self.zfcntrl_ca.Alarms.INVALID + f"FIELD:{axis}", self.zfcntrl_ca.Alarms.INVALID ) self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}:MEAS".format(axis), self.zfcntrl_ca.Alarms.INVALID + f"FIELD:{axis}:MEAS", self.zfcntrl_ca.Alarms.INVALID ) # Now simulate recovery and assert error gets cleared correctly self._assert_status(Statuses.NO_ERROR) for axis in FIELD_AXES: + self.zfcntrl_ca.assert_that_pv_alarm_is(f"FIELD:{axis}", self.zfcntrl_ca.Alarms.NONE) self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}".format(axis), self.zfcntrl_ca.Alarms.NONE - ) - self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}:MEAS".format(axis), self.zfcntrl_ca.Alarms.NONE + f"FIELD:{axis}:MEAS", self.zfcntrl_ca.Alarms.NONE ) def test_WHEN_magnetometer_ioc_readings_are_invalid_THEN_status_is_magnetometer_invalid(self): @@ -585,20 +573,18 @@ def test_WHEN_magnetometer_ioc_readings_are_invalid_THEN_status_is_magnetometer_ self._assert_status(Statuses.MAGNETOMETER_DATA_INVALID) for axis in FIELD_AXES: self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}".format(axis), self.zfcntrl_ca.Alarms.INVALID + f"FIELD:{axis}", self.zfcntrl_ca.Alarms.INVALID ) self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}:MEAS".format(axis), self.zfcntrl_ca.Alarms.INVALID + f"FIELD:{axis}:MEAS", self.zfcntrl_ca.Alarms.INVALID ) # Now simulate recovery and assert error gets cleared correctly self._assert_status(Statuses.NO_ERROR) for axis in FIELD_AXES: + self.zfcntrl_ca.assert_that_pv_alarm_is(f"FIELD:{axis}", self.zfcntrl_ca.Alarms.NONE) self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}".format(axis), self.zfcntrl_ca.Alarms.NONE - ) - self.zfcntrl_ca.assert_that_pv_alarm_is( - "FIELD:{}:MEAS".format(axis), self.zfcntrl_ca.Alarms.NONE + f"FIELD:{axis}:MEAS", self.zfcntrl_ca.Alarms.NONE ) def test_WHEN_power_supplies_are_invalid_THEN_status_is_power_supplies_invalid(self): @@ -686,9 +672,9 @@ def test_GIVEN_measured_field_and_setpoints_are_identical_THEN_setpoints_remain_ for axis in FIELD_AXES: self.zfcntrl_ca.assert_that_pv_is_number( - "OUTPUT:{}:CURR".format(axis), outputs[axis], tolerance=0.0001 + f"OUTPUT:{axis}:CURR", outputs[axis], tolerance=0.0001 ) - self.zfcntrl_ca.assert_that_pv_value_is_unchanged("OUTPUT:{}:CURR".format(axis), wait=5) + self.zfcntrl_ca.assert_that_pv_value_is_unchanged(f"OUTPUT:{axis}:CURR", wait=5) @parameterized.expand( parameterized_list( @@ -740,7 +726,7 @@ def test_GIVEN_autofeedback_WHEN_measured_field_different_from_setpoints_THEN_po for axis in FIELD_AXES: self.zfcntrl_ca.assert_that_pv_value_over_time_satisfies_comparator( - "OUTPUT:{}:CURR".format(axis), wait=5, comparator=output_comparator + f"OUTPUT:{axis}:CURR", wait=5, comparator=output_comparator ) # In this happy-path case, we shouldn't be hitting any long timeouts, so loop times should remain fairly quick @@ -764,10 +750,10 @@ def test_GIVEN_output_limits_too_small_for_required_field_THEN_status_error_and_ self._assert_status(Statuses.PSU_ON_LIMITS) for axis in FIELD_AXES: # Value should be on one of the limits - self.zfcntrl_ca.assert_that_pv_is_one_of("OUTPUT:{}:CURR:SP".format(axis), [-0.1, 0.1]) + self.zfcntrl_ca.assert_that_pv_is_one_of(f"OUTPUT:{axis}:CURR:SP", [-0.1, 0.1]) # ...and in alarm self.zfcntrl_ca.assert_that_pv_alarm_is( - "OUTPUT:{}:CURR:SP".format(axis), self.zfcntrl_ca.Alarms.MAJOR + f"OUTPUT:{axis}:CURR:SP", self.zfcntrl_ca.Alarms.MAJOR ) def test_GIVEN_limits_wrong_way_around_THEN_appropriate_error_raised(self): @@ -806,13 +792,13 @@ def test_GIVEN_measured_values_updating_realistically_WHEN_in_auto_mode_THEN_con self._set_autofeedback(True) for axis in FIELD_AXES: self.zfcntrl_ca.assert_that_pv_is_number( - "OUTPUT:{}:CURR:SP:RBV".format(axis), + f"OUTPUT:{axis}:CURR:SP:RBV", psu_amps_at_zero_field[axis], tolerance=STABILITY_TOLERANCE * 0.001, timeout=60, ) self.zfcntrl_ca.assert_that_pv_is_number( - "FIELD:{}".format(axis), 0.0, tolerance=STABILITY_TOLERANCE + f"FIELD:{axis}", 0.0, tolerance=STABILITY_TOLERANCE ) self._assert_at_setpoint(AtSetpointStatuses.TRUE) @@ -823,43 +809,39 @@ def test_GIVEN_measured_values_updating_realistically_WHEN_in_auto_mode_THEN_con def test_GIVEN_output_is_off_WHEN_autofeedback_switched_on_THEN_psu_is_switched_back_on( self, _, axis ): - self.zfcntrl_ca.assert_setting_setpoint_sets_readback( - "Off", "OUTPUT:{}:STATUS".format(axis) - ) + self.zfcntrl_ca.assert_setting_setpoint_sets_readback("Off", f"OUTPUT:{axis}:STATUS") self._set_autofeedback(True) - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:STATUS".format(axis), "On") + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:STATUS", "On") @parameterized.expand(parameterized_list(FIELD_AXES)) def test_GIVEN_output_mode_is_voltage_WHEN_autofeedback_switched_on_THEN_psu_is_switched_to_current_mode( self, _, axis ): self.zfcntrl_ca.assert_setting_setpoint_sets_readback( - "Voltage", "OUTPUT:{}:MODE".format(axis), expected_alarm=self.zfcntrl_ca.Alarms.MAJOR + "Voltage", f"OUTPUT:{axis}:MODE", expected_alarm=self.zfcntrl_ca.Alarms.MAJOR ) self._set_autofeedback(True) - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:MODE".format(axis), "Current") + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:MODE", "Current") @parameterized.expand(parameterized_list(FIELD_AXES)) def test_GIVEN_output_is_off_and_cannot_write_to_psu_WHEN_autofeedback_switched_on_THEN_get_psu_write_error( self, _, axis ): - self.zfcntrl_ca.assert_setting_setpoint_sets_readback( - "Off", "OUTPUT:{}:STATUS".format(axis) - ) + self.zfcntrl_ca.assert_setting_setpoint_sets_readback("Off", f"OUTPUT:{axis}:STATUS") with self._simulate_failing_power_supply_writes(): self._set_autofeedback(True) self._assert_status(Statuses.PSU_WRITE_FAILED) # Check it can recover when writes work again self._assert_status(Statuses.NO_ERROR) - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:STATUS".format(axis), "On") + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:STATUS", "On") @parameterized.expand(parameterized_list(FIELD_AXES)) def test_GIVEN_output_mode_is_voltage_and_cannot_write_to_psu_WHEN_autofeedback_switched_on_THEN_get_psu_write_error( self, _, axis ): self.zfcntrl_ca.assert_setting_setpoint_sets_readback( - "Voltage", "OUTPUT:{}:MODE".format(axis), expected_alarm=self.zfcntrl_ca.Alarms.MAJOR + "Voltage", f"OUTPUT:{axis}:MODE", expected_alarm=self.zfcntrl_ca.Alarms.MAJOR ) with self._simulate_failing_power_supply_writes(): @@ -868,7 +850,7 @@ def test_GIVEN_output_mode_is_voltage_and_cannot_write_to_psu_WHEN_autofeedback_ # Check it can recover when writes work again self._assert_status(Statuses.NO_ERROR) - self.zfcntrl_ca.assert_that_pv_is("OUTPUT:{}:MODE".format(axis), "Current") + self.zfcntrl_ca.assert_that_pv_is(f"OUTPUT:{axis}:MODE", "Current") @parameterized.expand( parameterized_list( diff --git a/tests/zfhifi.py b/tests/zfhifi.py index 36393c71..7c7583db 100644 --- a/tests/zfhifi.py +++ b/tests/zfhifi.py @@ -7,7 +7,7 @@ from utils.channel_access import ChannelAccess from utils.emulator_launcher import EmulatorLauncher -from utils.ioc_launcher import BaseLauncher, get_default_ioc_dir +from utils.ioc_launcher import EPICS_TOP, BaseLauncher, get_default_ioc_dir from utils.test_modes import TestModes from utils.testing import get_running_lewis_and_ioc @@ -30,7 +30,9 @@ def cryosms_macros(iocnum: int) -> dict[str, Any]: "MAX_VOLT": 5, "WRITE_UNIT": "AMPS", "DISPLAY_UNIT": "GAUSS", - "RAMP_FILE": r"C:\\Instrument\\Apps\\EPICS\\support\\cryosms\\master\\ramps\\default.txt", + "RAMP_FILE": ( + EPICS_TOP / "support" / "cryosms" / "master" / "ramps" / "default.txt" + ).as_posix(), "MID_TOLERANCE": 999999999, # 0.1 "TARGET_TOLERANCE": 999999999, # 0.1 "ALLOW_PERSIST": "No", @@ -86,16 +88,9 @@ def group3_hall_probe_ioc(iocnum: int) -> dict[str, Any]: "directory": get_default_ioc_dir("G3HALLPR", iocnum=iocnum), "emulator": "group3hallprobe", "emulator_id": f"group3hallprobe_{iocnum}", - "lewis_additional_path": os.path.join( - "c:\\", - "Instrument", - "Apps", - "EPICS", - "support", - "group3hallprobe", - "master", - "system_tests", - ), + "lewis_additional_path": ( + EPICS_TOP / "support" / "group3hallprobe" / "master" / "system_tests" + ).as_posix(), "macros": { "FIELD_SCAN_RATE": ".1 second", "TEMP_SCAN_RATE": ".1 second", diff --git a/tests/zfmagfld.py b/tests/zfmagfld.py index f3a6bd38..973c75a3 100644 --- a/tests/zfmagfld.py +++ b/tests/zfmagfld.py @@ -67,8 +67,8 @@ def write_offset(self, offset): None """ - for axis in AXES.keys(): - self.ca.set_pv_value("OFFSET:{}".format(axis), offset, sleep_after_set=0.0) + for axis in AXES: + self.ca.set_pv_value(f"OFFSET:{axis}", offset, sleep_after_set=0.0) def write_sensor_matrix(self, sensor_matrix): """ @@ -104,7 +104,7 @@ def apply_offset_to_field(self, simulated_field, offset): """ offset_applied_field = {} - for axis in AXES.keys(): + for axis in AXES: offset_applied_field[axis] = simulated_field[axis] - offset return offset_applied_field @@ -125,13 +125,11 @@ def write_simulated_field_values(self, simulated_field): """ - for component in AXES.keys(): + for component in AXES: self.ca.set_pv_value( - "SIM:DAQ:{}".format(component), simulated_field[component], sleep_after_set=0.0 - ) - self.ca.assert_that_pv_is_number( - "DAQ:{}:_RAW".format(component), simulated_field[component] + f"SIM:DAQ:{component}", simulated_field[component], sleep_after_set=0.0 ) + self.ca.assert_that_pv_is_number(f"DAQ:{component}:_RAW", simulated_field[component]) def apply_offset_and_matrix_multiplication(self, simulated_field, offset, sensor_matrix): """ @@ -174,12 +172,12 @@ def write_simulated_alarm_level(self, level): level: Class attribute of ChannelAccess.Alarms (e.g. ca.Alarms.NONE). The severity level to set to the PV """ - for axis in AXES.keys(): - self.ca.set_pv_value("DAQ:{}:_RAW.SIMS".format(axis), level, sleep_after_set=0.0) + for axis in AXES: + self.ca.set_pv_value(f"DAQ:{axis}:_RAW.SIMS", level, sleep_after_set=0.0) # Wait for the raw PVs to process - for axis in AXES.keys(): - self.ca.assert_that_pv_alarm_is("DAQ:{}:_RAW".format(axis), level) + for axis in AXES: + self.ca.assert_that_pv_alarm_is(f"DAQ:{axis}:_RAW", level) @parameterized.expand(parameterized_list(itertools.product(AXES.keys(), FIELD_STRENGTHS))) def test_GIVEN_field_offset_THEN_field_strength_read_back_with_offset_applied( @@ -193,13 +191,13 @@ def test_GIVEN_field_offset_THEN_field_strength_read_back_with_offset_applied( field[hw_axis] = field_strength self.write_simulated_field_values(field) - self.ca.set_pv_value("SIM:DAQ:{}".format(hw_axis), field_strength, sleep_after_set=0.0) + self.ca.set_pv_value(f"SIM:DAQ:{hw_axis}", field_strength, sleep_after_set=0.0) # WHEN self.ca.process_pv("TAKEDATA") # THEN - self.ca.assert_that_pv_is_number("APPLYOFFSET:{}".format(hw_axis), field_strength - OFFSET) + self.ca.assert_that_pv_is_number(f"APPLYOFFSET:{hw_axis}", field_strength - OFFSET) def test_GIVEN_offset_corrected_field_WHEN_sensor_matrix_is_identity_THEN_input_field_returned_by_matrix_multiplier( self, @@ -214,17 +212,15 @@ def test_GIVEN_offset_corrected_field_WHEN_sensor_matrix_is_identity_THEN_input_ self.ca.process_pv("TAKEDATA") # THEN - for hw_axis in AXES.keys(): + for hw_axis in AXES: expected_value = offset_corrected_field[hw_axis] self.ca.assert_that_pv_is_number( - "CORRECTEDFIELD:{}".format(hw_axis), + f"CORRECTEDFIELD:{hw_axis}", expected_value, tolerance=0.1 * abs(expected_value), ) - self.ca.assert_that_pv_alarm_is( - "CORRECTEDFIELD:{}".format(hw_axis), self.ca.Alarms.NONE - ) + self.ca.assert_that_pv_alarm_is(f"CORRECTEDFIELD:{hw_axis}", self.ca.Alarms.NONE) @parameterized.expand(parameterized_list(["X", "Y", "Z"])) def test_GIVEN_sensor_matrix_with_only_one_nonzero_row_THEN_corrected_field_has_component_in_correct_dimension( @@ -250,13 +246,13 @@ def test_GIVEN_sensor_matrix_with_only_one_nonzero_row_THEN_corrected_field_has_ self.ca.process_pv("TAKEDATA") # THEN - for component in AXES.keys(): + for component in AXES: if component == hw_axis: expected_value = sum(input_field.values()) else: expected_value = 0 - self.ca.assert_that_pv_is_number("CORRECTEDFIELD:{}".format(component), expected_value) + self.ca.assert_that_pv_is_number(f"CORRECTEDFIELD:{component}", expected_value) def test_GIVEN_test_input_field_strengths_WHEN_corrections_applied_THEN_corrected_fields_agree_with_labview( self, @@ -273,8 +269,8 @@ def test_GIVEN_test_input_field_strengths_WHEN_corrections_applied_THEN_correcte self.write_simulated_field_values(input_field) self.write_sensor_matrix(sensor_matrix) - for axis in input_offsets.keys(): - self.ca.set_pv_value("OFFSET:{}".format(axis), input_offsets[axis], sleep_after_set=0.0) + for axis_name, axis_value in input_offsets.items(): + self.ca.set_pv_value(f"OFFSET:{axis_name}", axis_value, sleep_after_set=0.0) # WHEN self.ca.process_pv("TAKEDATA") @@ -282,9 +278,9 @@ def test_GIVEN_test_input_field_strengths_WHEN_corrections_applied_THEN_correcte # THEN labview_result = {"X": -6.58, "Y": -18.9542, "Z": -0.21857} - for component in AXES.keys(): + for component in AXES: self.ca.assert_that_pv_is_number( - "CORRECTEDFIELD:{}".format(component), labview_result[component], tolerance=1e-4 + f"CORRECTEDFIELD:{component}", labview_result[component], tolerance=1e-4 ) def test_GIVEN_measured_data_WHEN_corrections_applied_THEN_field_magnitude_read_back(self): @@ -324,18 +320,16 @@ def test_GIVEN_no_forced_scans_WHEN_takedata_alias_processed_THEN_all_magnetomet time.sleep(1) - for component in AXES.keys(): - self.ca.assert_that_pv_is_not_number( - "DAQ:{}".format(component), test_field[component] - ) + for component in AXES: + self.ca.assert_that_pv_is_not_number(f"DAQ:{component}", test_field[component]) # WHEN self.ca.process_pv("TAKEDATA") # THEN - for component in AXES.keys(): + for component in AXES: self.ca.assert_that_pv_is_number( - "DAQ:{}".format(component), + f"DAQ:{component}", test_field[component], tolerance=0.1 * test_field[component], ) @@ -352,9 +346,9 @@ def test_GIVEN_forced_scans_WHEN_fields_change_THEN_all_magnetometer_axes_read_a self.write_simulated_field_values(test_field) # THEN - for component in AXES.keys(): + for component in AXES: self.ca.assert_that_pv_is_number( - "DAQ:{}".format(component), + f"DAQ:{component}", test_field[component], tolerance=0.1 * test_field[component], ) @@ -373,9 +367,9 @@ def test_GIVEN_magnetometer_scaling_factor_WHEN_data_read_THEN_inputs_scaled_by_ self.ca.process_pv("TAKEDATA") # THEN - for component in AXES.keys(): + for component in AXES: self.ca.assert_that_pv_is_number( - "MEASURED:{}".format(component), test_field[component] * factor + f"MEASURED:{component}", test_field[component] * factor ) @parameterized.expand(parameterized_list(AXES.keys())) @@ -421,8 +415,8 @@ def test_GIVEN_field_overloaded_THEN_output_PVs_in_major_alarm(self): # THEN self.ca.assert_that_pv_alarm_is("FIELDSTRENGTH", self.ca.Alarms.MAJOR) - for axis in AXES.keys(): - self.ca.assert_that_pv_alarm_is("CORRECTEDFIELD:{}".format(axis), self.ca.Alarms.MAJOR) + for axis in AXES: + self.ca.assert_that_pv_alarm_is(f"CORRECTEDFIELD:{axis}", self.ca.Alarms.MAJOR) @parameterized.expand( parameterized_list( @@ -440,14 +434,14 @@ def test_GIVEN_raw_daq_pvs_in_alarm_WHEN_PVs_processed_THEN_alarm_copied_to_down self, _, alarm, pv ): # GIVEN - self.ca.assert_that_pv_alarm_is("{}.SEVR".format(pv), self.ca.Alarms.NONE) + self.ca.assert_that_pv_alarm_is(f"{pv}.SEVR", self.ca.Alarms.NONE) self.write_simulated_alarm_level(alarm) self.ca.process_pv("TAKEDATA") # THEN - self.ca.assert_that_pv_alarm_is("{}.SEVR".format(pv), alarm) + self.ca.assert_that_pv_alarm_is(f"{pv}.SEVR", alarm) @parameterized.expand(parameterized_list(AXES.keys())) def test_GIVEN_smoothing_samples_WHEN_setting_field_THEN_average_field_is_given(self, _, axis): @@ -458,13 +452,14 @@ def test_GIVEN_smoothing_samples_WHEN_setting_field_THEN_average_field_is_given( full_averaging_time = number_samples * 0.1 # 0.1s is the update rate in sim mode. field_number = 100 - pv = "DAQ:{}".format(axis) - with self._ioc.start_with_macros({"NUM_SAMPLES": number_samples}, pv_to_wait_for=pv): + pv = f"DAQ:{axis}" + assert isinstance(self._ioc, ProcServLauncher), "_ioc must be ProcServLauncher" + with self._ioc.start_with_macros({"NUM_SAMPLES": str(number_samples)}, pv_to_wait_for=pv): field = {"X": 0, "Y": 0, "Z": 0} self.write_simulated_field_values(field) # make sure the field is 0 - self.ca.assert_that_pv_is_number("DAQ:{}:_RAW".format(axis), 0, full_averaging_time + 5) + self.ca.assert_that_pv_is_number(f"DAQ:{axis}:_RAW", 0, full_averaging_time + 5) self.ca.process_pv("TAKEDATA") self.ca.assert_that_pv_is_number(pv, 0) @@ -473,7 +468,7 @@ def test_GIVEN_smoothing_samples_WHEN_setting_field_THEN_average_field_is_given( self.write_simulated_field_values(field) self.ca.assert_that_pv_value_is_increasing( - "DAQ:{}:_AVERAGE".format(axis), wait=full_averaging_time + 5 + f"DAQ:{axis}:_AVERAGE", wait=full_averaging_time + 5 ) # Check the final value is correct diff --git a/utils/calibration_utils.py b/utils/calibration_utils.py index ad8035cc..c33a668a 100644 --- a/utils/calibration_utils.py +++ b/utils/calibration_utils.py @@ -28,9 +28,7 @@ def set_calibration_file(channel_access: "ChannelAccess", filename: str, prefix: if channel_access.get_pv_value(f"{prefix}CAL:RBV") == filename: break else: - raise Exception( - "Couldn't set calibration file to '{}' after {} tries".format(filename, max_retries) - ) + raise ValueError(f"Couldn't set calibration file to '{filename}' after {max_retries} tries") def reset_calibration_file( diff --git a/utils/channel_access.py b/utils/channel_access.py index c9d19ff4..c3df3309 100644 --- a/utils/channel_access.py +++ b/utils/channel_access.py @@ -8,9 +8,9 @@ import os import time from abc import abstractmethod +from collections.abc import Callable, Generator from contextlib import contextmanager from functools import partial, partialmethod -from typing import Callable, Generator, Optional from genie_python.genie import PVValue from genie_python.genie_cachannel_wrapper import ( @@ -37,7 +37,7 @@ class _MonitorAssertion(_ValueSource): """ def __init__( - self, channel_access: "ChannelAccess", pv: str, pv_access: Optional[bool] = None + self, channel_access: "ChannelAccess", pv: str, pv_access: bool | None = None ) -> None: """ Initialise. @@ -71,12 +71,12 @@ def value(self) -> PVValue: return self.latest_value -class ChannelAccess(object): +class ChannelAccess: """ Provides the required channel access commands. """ - class Alarms(object): + class Alarms: """ Possible alarm states that a PV can be in. """ @@ -90,9 +90,9 @@ class Alarms(object): def __init__( self, default_timeout: float = 5, - device_prefix: Optional[str] = None, + device_prefix: str | None = None, default_wait_time: float = 1.0, - pv_access: Optional[bool] = None, + pv_access: bool | None = None, ) -> None: """ Initializes this ChannelAccess object. @@ -121,7 +121,7 @@ def __init__( try: hcom = ctypes.cdll.LoadLibrary("COM.DLL") hcom.eltc(ctypes.c_int(0)) - except Exception as e: + except Exception as e: # noqa: BLE001 print("Unable to disable CA errors: ", e) self.host_prefix = os.environ["testing_prefix"] @@ -137,9 +137,9 @@ def set_pv_value( self, pv: str, value: PVValue, - prefix: Optional[str] = None, + prefix: str | None = None, wait: bool = False, - sleep_after_set: Optional[float] = None, + sleep_after_set: float | None = None, ) -> None: """ Sets the specified PV to the supplied value. @@ -196,7 +196,7 @@ def process_pv(self, pv: str) -> None: Args: pv: the EPICS PV name """ - pv_proc = "{}.PROC".format(self.create_pv_with_prefix(pv)) + pv_proc = f"{self.create_pv_with_prefix(pv)}.PROC" return self.ca.set_pv_value(pv_proc, 1) @contextmanager @@ -213,8 +213,8 @@ def put_simulated_record_into_alarm(self, pv: str, alarm: str) -> Generator[None """ def _set_and_check_simulated_alarm(set_check_pv: str, set_check_alarm: str) -> None: - self.set_pv_value("{}.SIMS".format(set_check_pv), set_check_alarm) - self.assert_that_pv_alarm_is("{}".format(set_check_pv), set_check_alarm) + self.set_pv_value(f"{set_check_pv}.SIMS", set_check_alarm) + self.assert_that_pv_alarm_is(f"{set_check_pv}", set_check_alarm) try: _set_and_check_simulated_alarm(pv, alarm) @@ -231,10 +231,10 @@ def create_pv_with_prefix(self, pv: str) -> str: Returns: pv name with prefix """ - return "{prefix}{pv}".format(prefix=self.prefix, pv=pv) + return f"{self.prefix}{pv}" def _wait_for_pv_lambda( - self, wait_for_lambda: Callable[[], PVValue], timeout: Optional[float] = None + self, wait_for_lambda: Callable[[], PVValue], timeout: float | None = None ) -> PVValue: """ Wait for a lambda containing a pv to become None; return value or timeout and return actual @@ -270,9 +270,9 @@ def assert_that_pv_value_causes_func_to_return_true( self, pv: str, func: Callable[[PVValue], bool], - timeout: Optional[float] = None, - message: Optional[str] = None, - pv_value_source: Optional[_ValueSource] = None, + timeout: float | None = None, + message: str | None = None, + pv_value_source: _ValueSource | None = None, ) -> None: """ Check that a PV satisfies a given function within some timeout. @@ -296,7 +296,7 @@ def _wrapper(message: str) -> str | None: value = pv_value_source.value try: return_value = func(value) - except Exception as e: + except Exception as e: # noqa: BLE001 return ( f"Exception was thrown while evaluating function '{func.__name__}' on pv" f" value {format_value(value)}. Exception was: {e.__class__.__name__} {e}" @@ -305,16 +305,17 @@ def _wrapper(message: str) -> str | None: return None else: return "Exception date time: {}{}{}{}{}".format( - datetime.datetime.now(), + datetime.datetime.now(tz=datetime.timezone.utc), os.linesep, message, os.linesep, - "Final PV value was {}".format(format_value(value)), + f"Final PV value was {format_value(value)}", ) if message is None: - message = "Expected function '{}' to evaluate to True when reading PV '{}'.".format( - func.__name__, self.create_pv_with_prefix(pv) + message = ( + f"Expected function '{func.__name__}' to evaluate to True " + f"when reading PV '{self.create_pv_with_prefix(pv)}'." ) err = self._wait_for_pv_lambda(partial(_wrapper, message), timeout) @@ -325,9 +326,9 @@ def assert_that_pv_is( self, pv: str, expected_value: PVValue, - timeout: Optional[float] = None, - msg: Optional[str] = None, - pv_value_source: Optional[_ValueSource] | None = None, + timeout: float | None = None, + msg: str | None = None, + pv_value_source: _ValueSource | None = None, ) -> None: """ Assert that the pv has the expected value or that it becomes the expected value within the @@ -346,8 +347,9 @@ def assert_that_pv_is( """ if msg is None: - msg = "Expected PV, '{}' to have value {}.".format( - self.create_pv_with_prefix(pv), format_value(expected_value) + msg = ( + f"Expected PV, '{self.create_pv_with_prefix(pv)}' to " + f"have value {format_value(expected_value)}." ) return self.assert_that_pv_value_causes_func_to_return_true( @@ -375,9 +377,9 @@ def assert_that_pv_is_path( self, pv: str, expected_path: str, - timeout: Optional[float] = None, - msg: Optional[str] = None, - pv_value_source: Optional[_ValueSource] = None, + timeout: float | None = None, + msg: str | None = None, + pv_value_source: _ValueSource | None = None, ) -> None: """ Assert that a pv is a path that when normalised matches the expected path. @@ -395,8 +397,9 @@ def assert_that_pv_is_path( """ normalised_expected_path = self._normalise_path(expected_path) if msg is None: - msg = "Expected PV, '{}' to have path {}.".format( - self.create_pv_with_prefix(pv), format_value(normalised_expected_path) + msg = ( + f"Expected PV, '{self.create_pv_with_prefix(pv)}' to have " + f"path {format_value(normalised_expected_path)}." ) return self.assert_that_pv_value_causes_func_to_return_true( @@ -411,8 +414,8 @@ def assert_that_pv_after_processing_is( self, pv: str, expected_value: PVValue, - timeout: Optional[float] = None, - msg: Optional[str] = None, + timeout: float | None = None, + msg: str | None = None, ) -> None: """ Assert that the pv has the expected value after the pv is processed @@ -435,8 +438,8 @@ def assert_that_pv_is_not( self, pv: str, restricted_value: PVValue, - timeout: Optional[float] = None, - msg: Optional[str] = None, + timeout: float | None = None, + msg: str | None = None, ) -> None: """ Assert that the pv does not have a particular value and optionally it does not become that @@ -452,7 +455,7 @@ def assert_that_pv_is_not( UnableToConnectToPVException: if pv does not exist within timeout """ if msg is None: - msg = "Expected PV to not have value {}.".format(format_value(restricted_value)) + msg = f"Expected PV to not have value {format_value(restricted_value)}." return self.assert_that_pv_value_causes_func_to_return_true( pv, lambda val: val != restricted_value, timeout, message=msg @@ -482,8 +485,8 @@ def assert_that_pv_is_number( pv: str, expected: float, tolerance: float = 0.0, - timeout: Optional[float] = None, - pv_value_source: Optional[_ValueSource] = None, + timeout: float | None = None, + pv_value_source: _ValueSource | None = None, ) -> None: """ Assert that the pv has the expected value or that it becomes the expected value within the @@ -499,8 +502,9 @@ def assert_that_pv_is_number( AssertionError: if value does not become requested value UnableToConnectToPVException: if pv does not exist within timeout """ - message = "Expected PV '{}' value to be equal to {} (tolerance: {})".format( - self.create_pv_with_prefix(pv), format_value(expected), format_value(tolerance) + message = ( + f"Expected PV '{self.create_pv_with_prefix(pv)}' value to be equal " + f"to {format_value(expected)} (tolerance: {format_value(tolerance)})" ) return self.assert_that_pv_value_causes_func_to_return_true( @@ -512,7 +516,7 @@ def assert_that_pv_is_number( ) def assert_that_pv_is_not_number( - self, pv: str, restricted: float, tolerance: float = 0, timeout: Optional[float] = None + self, pv: str, restricted: float, tolerance: float = 0, timeout: float | None = None ) -> None: """ Assert that the pv is at least tolerance from the restricted value within the timeout @@ -526,8 +530,9 @@ def assert_that_pv_is_not_number( AssertionError: if value does not enter the desired range UnableToConnectToPVException: if pv does not exist within timeout """ - message = "Expected PV value to be not equal to {} (tolerance: {})".format( - format_value(restricted), format_value(tolerance) + message = ( + f"Expected PV value to be not equal to {format_value(restricted)} " + f"(tolerance: {format_value(tolerance)})" ) return self.assert_that_pv_value_causes_func_to_return_true( @@ -542,7 +547,7 @@ def assert_that_pv_after_processing_is_number( pv: str, expected_value: float, tolerance: float = 0.0, - timeout: Optional[float] = None, + timeout: float | None = None, ) -> None: """ Assert that the pv has the expected number value after the pv is processed @@ -563,7 +568,7 @@ def assert_that_pv_after_processing_is_number( return self.assert_that_pv_is_number(pv, expected_value, tolerance=tolerance, timeout=None) def assert_that_pv_is_one_of( - self, pv: str, expected_values: list[PVValue], timeout: Optional[float] = None + self, pv: str, expected_values: list[PVValue], timeout: float | None = None ) -> None: """ Assert that the pv has one of the expected values or that it becomes one of the expected @@ -581,7 +586,7 @@ def assert_that_pv_is_one_of( def _condition(val: PVValue) -> bool: return val in expected_values - message = "Expected PV value to be in {}".format(expected_values) + message = f"Expected PV value to be in {expected_values}" return self.assert_that_pv_value_causes_func_to_return_true( pv, _condition, timeout, message ) @@ -589,9 +594,9 @@ def _condition(val: PVValue) -> bool: def assert_that_pv_is_within_range( self, pv: str, - min_value: int | float, - max_value: int | float, - timeout: Optional[float] = None, + min_value: float, + max_value: float, + timeout: float | None = None, ) -> None: """ Assert that the pv is within or at the bounds of the ranges between a minimum and maximum @@ -611,12 +616,12 @@ def _condition(val: PVValue) -> bool: assert isinstance(val, (int, float, str)) return min_value <= float(val) <= max_value - message = "Expected PV value to between {} and {}".format(min_value, max_value) + message = f"Expected PV value to between {min_value} and {max_value}" return self.assert_that_pv_value_causes_func_to_return_true( pv, _condition, timeout, message ) - def assert_that_pv_exists(self, pv: str, timeout: Optional[float] = None) -> None: + def assert_that_pv_exists(self, pv: str, timeout: float | None = None) -> None: """ Wait for pv to be available or timeout and throw UnableToConnectToPVException. @@ -638,10 +643,8 @@ def assert_that_pv_exists(self, pv: str, timeout: Optional[float] = None) -> Non # Last try. if not self.ca.pv_exists(pv, timeout=1.0): raise AssertionError( - "Exception date time: {time}\n" - "PV {pv} does not exist after {timeout} seconds".format( - time=datetime.datetime.now(), pv=pv, timeout=timeout - ) + f"Exception date time: {datetime.datetime.now(tz=datetime.timezone.utc)}\n" + f"PV {pv} does not exist after {timeout} seconds" ) def assert_that_pv_does_not_exist(self, pv: str, timeout: float = 2) -> None: @@ -659,10 +662,10 @@ def assert_that_pv_does_not_exist(self, pv: str, timeout: float = 2) -> None: except AssertionError: return else: - raise AssertionError("PV {pv} exists".format(pv=self.create_pv_with_prefix(pv))) + raise AssertionError(f"PV {self.create_pv_with_prefix(pv)} exists") def assert_that_pv_alarm_is_not( - self, pv: str, alarm: str, timeout: Optional[float] = None + self, pv: str, alarm: str, timeout: float | None = None ) -> None: """ Assert that a pv is not in alarm state given or timeout. @@ -675,9 +678,9 @@ def assert_that_pv_alarm_is_not( AssertionError: if alarm is requested value UnableToConnectToPVException: if pv does not exist within timeout """ - return self.assert_that_pv_is_not("{}.SEVR".format(pv), alarm, timeout=timeout) + return self.assert_that_pv_is_not(f"{pv}.SEVR", alarm, timeout=timeout) - def assert_that_pv_alarm_is(self, pv: str, alarm: str, timeout: Optional[float] = None) -> None: + def assert_that_pv_alarm_is(self, pv: str, alarm: str, timeout: float | None = None) -> None: """ Assert that a pv is in alarm state given or timeout. Checks the SERV of the pv name with any field name removed. @@ -691,16 +694,16 @@ def assert_that_pv_alarm_is(self, pv: str, alarm: str, timeout: Optional[float] UnableToConnectToPVException: if pv does not exist within timeout """ pv_no_field = pv.rsplit(".", 1)[0] - return self.assert_that_pv_is("{}.SEVR".format(pv_no_field), alarm, timeout=timeout) + return self.assert_that_pv_is(f"{pv_no_field}.SEVR", alarm, timeout=timeout) def assert_setting_setpoint_sets_readback( self, value: PVValue, readback_pv: str, - set_point_pv: Optional[str] = None, + set_point_pv: str | None = None, expected_value: PVValue = None, - expected_alarm: Optional[str] = Alarms.NONE, - timeout: Optional[float] = None, + expected_alarm: str | None = Alarms.NONE, + timeout: float | None = None, ) -> None: """ Set a pv to a value and check that the readback has the expected value and alarm state. @@ -718,7 +721,7 @@ def assert_setting_setpoint_sets_readback( UnableToConnectToPVException: if a pv does not exist within timeout """ if set_point_pv is None: - set_point_pv = "{}:SP".format(readback_pv) + set_point_pv = f"{readback_pv}:SP" if expected_value is None: expected_value = value @@ -745,8 +748,9 @@ def assert_that_pv_value_over_time_satisfies_comparator( initial_value = self.get_pv_value(pv) time.sleep(wait) - message = "Expected value trend to satisfy comparator '{}'. Initial value was {}.".format( - comparator.__name__, format_value(initial_value) + message = ( + f"Expected value trend to satisfy comparator '{comparator.__name__}'. " + f"Initial value was {format_value(initial_value)}." ) def _condition(val: PVValue) -> bool: @@ -868,7 +872,7 @@ def value(self) -> str: pv=pv_with_prefix, func=lambda val: val != time_before, pv_value_source=PvUpdateTimeValueSource(), - message="PV {} was not processed".format(pv), + message=f"PV {pv} was not processed", ) @contextmanager @@ -899,7 +903,7 @@ def value(self) -> str: pv=pv_with_prefix, func=lambda val: val == time_before, pv_value_source=PvUpdateTimeValueSource(), - message="PV {} was processed".format(pv), + message=f"PV {pv} was processed", ) def assert_dict_of_pvs_have_given_values(self, pvs_and_values_dict: dict[str, PVValue]) -> None: diff --git a/utils/device_launcher.py b/utils/device_launcher.py index fbaa2fbd..6e0209b0 100644 --- a/utils/device_launcher.py +++ b/utils/device_launcher.py @@ -1,10 +1,10 @@ -from contextlib import ExitStack, contextmanager -from typing import ContextManager, Generator, Optional +from collections.abc import Generator +from contextlib import AbstractContextManager, ExitStack, contextmanager @contextmanager def device_launcher( - ioc: ContextManager, lewis: Optional[ContextManager] + ioc: AbstractContextManager, lewis: AbstractContextManager | None ) -> Generator[None, None, None]: """ Context manager that launches an ioc and emulator pair @@ -20,7 +20,9 @@ def device_launcher( @contextmanager -def device_collection_launcher(devices: list[ContextManager]) -> Generator[None, None, None]: +def device_collection_launcher( + devices: list[AbstractContextManager], +) -> Generator[None, None, None]: """ Context manager that launches a list of devices :param devices: list of context managers representing the devices to launch diff --git a/utils/emulator_exceptions.py b/utils/emulator_exceptions.py index 6f181b66..ab3b17c1 100644 --- a/utils/emulator_exceptions.py +++ b/utils/emulator_exceptions.py @@ -4,6 +4,4 @@ class UnableToConnectToEmulatorException(IOError): # noqa: N818 (historic name) """ def __init__(self, emulator_name: str, err: str | BaseException) -> None: - super(UnableToConnectToEmulatorException, self).__init__( - "Unable to connect to Emnulator {0}: {1}".format(emulator_name, err) - ) + super().__init__(f"Unable to connect to Emnulator {emulator_name}: {err}") diff --git a/utils/emulator_launcher.py b/utils/emulator_launcher.py index 8a204f7a..b0352d58 100644 --- a/utils/emulator_launcher.py +++ b/utils/emulator_launcher.py @@ -7,12 +7,13 @@ import os import subprocess import sys +from collections.abc import Callable, Generator from dataclasses import dataclass -from datetime import datetime +from datetime import datetime, timezone from functools import partial from time import sleep, time from types import TracebackType -from typing import Any, Callable, Dict, Generator, List, Optional, Self, Type, TypeAlias, TypeVar +from typing import Any, ClassVar, Self, TypeAlias, TypeVar import psutil @@ -23,7 +24,7 @@ from utils.log_file import log_filename from utils.test_modes import TestModes -DEVICE_EMULATOR_PATH = os.path.join(EPICS_TOP, "support", "DeviceEmulator", "master") +DEVICE_EMULATOR_PATH = EPICS_TOP / "support" / "DeviceEmulator" / "master" DEFAULT_PY_PATH = os.path.join("C:\\", "Instrument", "Apps", "Python3") @@ -32,13 +33,13 @@ T = TypeVar("T") -class EmulatorRegister(object): +class EmulatorRegister: """ A way of registering running emulators. """ # Static dictionary of running emulators - RunningEmulators = {} + RunningEmulators: ClassVar[dict[str]] = {} @classmethod def get_running(cls, name: str | None) -> "EmulatorLauncher | MultiLewisLauncher | None": @@ -70,14 +71,14 @@ def remove_emulator(cls, name: str) -> None: del cls.RunningEmulators[name] -class EmulatorLauncher(object, metaclass=abc.ABCMeta): +class EmulatorLauncher(metaclass=abc.ABCMeta): def __init__( self, test_name: str, device: str, emulator_path: str, var_dir: str, - port: Optional[int], + port: int | None, options: dict[str, Any], ) -> None: """ @@ -104,7 +105,7 @@ def __enter__(self) -> Self: def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> None: @@ -323,17 +324,16 @@ def wrapper(msg: str) -> str | None: value = self.backdoor_get_from_device(emulator_property) try: return_value = func(value) - except Exception as e: + except Exception as e: # noqa: BLE001 try: exception_message = e.message # type: ignore except AttributeError: exception_message = "" return ( - "Exception was thrown while evaluating function '{}' on emulator property {}. " - "Exception was: {} {}".format( - func.__name__, format_value(value), e.__class__.__name__, exception_message - ) + f"Exception was thrown while evaluating function '{func.__name__}' " + f"on emulator property {format_value(value)}. " + f"Exception was: {e.__class__.__name__} {exception_message}" ) if return_value: return None @@ -341,13 +341,14 @@ def wrapper(msg: str) -> str | None: return "{}{}{}".format( msg, os.linesep, - "Final emulator property value was {}".format(format_value(value)), + f"Final emulator property value was {format_value(value)}", ) if msg is None: msg = ( - "Expected function '{}' to evaluate to True when reading emulator property '{}'." - ).format(func.__name__, emulator_property) + f"Expected function '{func.__name__}' to evaluate to True " + f"when reading emulator property '{emulator_property}'." + ) err = self._wait_for_emulator_lambda(partial(wrapper, msg), timeout) @@ -378,30 +379,30 @@ def wrapper(msg: str) -> str | None: value = self.backdoor_get_from_device(emulator_property) try: return_value = func(value) - except Exception as e: + except Exception as e: # noqa: BLE001 try: exception_message = e.message # type: ignore except AttributeError: exception_message = "" return ( - "Exception was thrown while evaluating function '{}' on emulator property {}. " - "Exception was: {} {}".format( - func.__name__, format_value(value), e.__class__.__name__, exception_message - ) + f"Exception was thrown while evaluating function '{func.__name__}' " + f"on emulator property {format_value(value)}. " + f"Exception was: {e.__class__.__name__} {exception_message}" ) if return_value: return "{}{}{}".format( msg, os.linesep, - "Final emulator property value was {}".format(format_value(value)), + f"Final emulator property value was {format_value(value)}", ) else: return None if msg is None: msg = ( - "Expected function '{}' to evaluate to False when reading emulator property '{}'." - ).format(func.__name__, emulator_property) + f"Expected function '{func.__name__}' to evaluate to False " + f"when reading emulator property '{emulator_property}'." + ) err = self._wait_for_emulator_lambda(partial(wrapper, msg), timeout) @@ -458,9 +459,8 @@ def assert_that_emulator_value_is_greater_than( """ message = ( - "Expected emulator property {} to have a value greater than or equal to {}".format( - emulator_property, min_value - ) + f"Expected emulator property {emulator_property} to " + f"have a value greater than or equal to {min_value}" ) return self.assert_that_emulator_value_causes_func_to_return_true( emulator_property, lambda value: min_value <= float(value), timeout, message @@ -529,7 +529,7 @@ def backdoor_run_function_on_device( @dataclass -class Emulator(object): +class Emulator: """ A utility class to capture data required to create a MultiLewisLauncher """ @@ -538,11 +538,11 @@ class Emulator(object): device: str var_dir: str port: Any - options: Dict + options: dict @dataclass -class TestEmulatorData(object): +class TestEmulatorData: """ A utility class to capture the required data from a test to create a MultiLewisLauncher. """ @@ -578,9 +578,7 @@ def __init__( var_dir: location of directory to write log file and macros directories port: the port to use """ - super(LewisLauncher, self).__init__( - test_name, device, emulator_path, var_dir, port, options - ) + super().__init__(test_name, device, emulator_path, var_dir, port, options) self._lewis_path: str = options.get("lewis_path", LewisLauncher._DEFAULT_LEWIS_PATH) self._python_path: str = options.get( @@ -613,12 +611,12 @@ def _close(self) -> None: """ Closes the Lewis session by killing the process. """ - print("Terminating Lewis Emulator ({0})".format(self._device)) + print(f"Terminating Lewis Emulator ({self._device})") if self._process is not None: self._process.terminate() if self._logFile is not None: self._logFile.close() - print("Lewis log written to {0}".format(self._log_filename())) + print(f"Lewis log written to {self._log_filename()}") def _open(self) -> None: """ @@ -627,7 +625,7 @@ def _open(self) -> None: :param port: the port on which to run lewis :return: """ - self._logFile = open(self._log_filename(), "a") + self._logFile = open(self._log_filename(), "a") # noqa: SIM115 self._control_port = str(get_free_ports(1)[0]) lewis_command_line = [ self._python_path, @@ -635,14 +633,12 @@ def _open(self) -> None: "-m", "lewis", "-r", - "127.0.0.1:{control_port}".format(control_port=self._control_port), + f"127.0.0.1:{self._control_port}", ] lewis_command_line.extend( [ "-p", - "{protocol}: {{bind_address: 127.0.0.1, port: {port}}}".format( - protocol=self._lewis_protocol, port=self._port - ), + f"{self._lewis_protocol}: {{bind_address: 127.0.0.1, port: {self._port}}}", ] ) if self._lewis_additional_path is not None: @@ -655,9 +651,9 @@ def _open(self) -> None: print( f"Started Lewis Emulator ({self._device}), Lewis log file is {self._log_filename()}\n" ) - self._logFile.write("Started Lewis with '{0}'\n".format(" ".join(lewis_command_line))) + self._logFile.write("Started Lewis with '{}'\n".format(" ".join(lewis_command_line))) self._logFile.flush() - print("Started Lewis with '{0}'\n".format(" ".join(lewis_command_line))) + print("Started Lewis with '{}'\n".format(" ".join(lewis_command_line))) self._process = subprocess.Popen( lewis_command_line, creationflags=subprocess.CREATE_NEW_CONSOLE, @@ -697,7 +693,7 @@ def _convert_to_string_for_backdoor(self, value: EmulatorValue) -> str: Returns: value as a string for the backdoor """ - return "'{}'".format(value) if isinstance(value, str) else str(value) + return f"'{value}'" if isinstance(value, str) else str(value) def backdoor_set_on_device( self, variable: str, value: EmulatorValue, *args: list[Any], **kwargs: dict[str, Any] @@ -744,14 +740,14 @@ def backdoor_command(self, command: list[str]) -> list[bytes]: lewis_command_line = [ os.path.join(self._lewis_path, "lewis-control.exe"), "-r", - "127.0.0.1:{control_port}".format(control_port=self._control_port), + f"127.0.0.1:{self._control_port}", ] lewis_command_line.extend(command) - time_stamp = datetime.fromtimestamp(time()).strftime("%Y-%m-%d %H:%M:%S") + time_stamp = datetime.fromtimestamp(time(), tz=timezone.utc).strftime("%Y-%m-%d %H:%M:%S") log_file = self._logFile assert log_file is not None log_file.write( - "{0}: lewis backdoor command: {1}\n".format(time_stamp, " ".join(lewis_command_line)) + "{}: lewis backdoor command: {}\n".format(time_stamp, " ".join(lewis_command_line)) ) log_file.flush() try: @@ -775,7 +771,7 @@ def backdoor_command(self, command: list[str]) -> list[bytes]: for line in output: if b"failed to create process" in line.lower(): - raise IOError(f"Failed to spawn lewis-control.exe for backdoor set {command}.") + raise OSError(f"Failed to spawn lewis-control.exe for backdoor set {command}.") return [line.strip() for line in output] except subprocess.CalledProcessError as ex: @@ -783,7 +779,7 @@ def backdoor_command(self, command: list[str]) -> list[bytes]: loc.write(f"Error using backdoor: {ex.output}\n") loc.write(f"Error code {ex.returncode}\n") log_file.flush() - raise ex + raise def backdoor_emulator_disconnect_device( self, *args: list[Any], **kwargs: dict[str, Any] @@ -819,14 +815,14 @@ def backdoor_get_from_device( return "".join(i.decode("utf-8") for i in self.backdoor_command(["device", str(variable)])) -class MultiLewisLauncher(object): +class MultiLewisLauncher: """ Launch multiple lewis emulators. """ - def __init__(self, test_name: str, emulators: List[Emulator]) -> None: + def __init__(self, test_name: str, emulators: list[Emulator]) -> None: self.test_name: str = test_name - self.emulator_launchers: Dict[int, LewisLauncher] = { + self.emulator_launchers: dict[int, LewisLauncher] = { emulator.launcher_address: LewisLauncher.from_emulator(test_name, emulator) for emulator in emulators } @@ -838,7 +834,7 @@ def __enter__(self) -> Self: def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> None: @@ -930,9 +926,7 @@ def __init__( port: int, options: dict[str, Any], ) -> None: - super(CommandLineEmulatorLauncher, self).__init__( - test_name, device, emulator_path, var_dir, port, options - ) + super().__init__(test_name, device, emulator_path, var_dir, port, options) try: self.command_line = options["emulator_command_line"] except KeyError: @@ -956,7 +950,7 @@ def __init__( def _open(self) -> None: print(f"Launching commandline emulator ({self._device}).") - self._log_file = open( + self._log_file = open( # noqa: SIM115 log_filename( self._test_name, "cmdemulator", self._device, TestModes.RECSIM, self._var_dir ), @@ -1060,11 +1054,9 @@ def __init__( if os.path.exists(run_bat_file): options["emulator_command_line"] = run_bat_file options["emulator_wait_to_finish"] = True - super(BeckhoffEmulatorLauncher, self).__init__( - test_name, device, emulator_path, var_dir, port, options - ) + super().__init__(test_name, device, emulator_path, var_dir, port, options) else: - raise IOError("Unable to find run.bat. Trying to run {} \n".format(run_bat_file)) + raise OSError(f"Unable to find run.bat. Trying to run {run_bat_file} \n") class DAQMxEmulatorLauncher(CommandLineEmulatorLauncher): @@ -1077,18 +1069,16 @@ def __init__( port: int, options: dict[str, Any], ) -> None: - labview_scripts_dir = os.path.join(DEVICE_EMULATOR_PATH, "other_emulators", "DAQmx") - self.start_command = os.path.join(labview_scripts_dir, "start_sim.bat") - self.stop_command = os.path.join(labview_scripts_dir, "stop_sim.bat") + labview_scripts_dir = DEVICE_EMULATOR_PATH / "other_emulators" / "DAQmx" + self.start_command = str(labview_scripts_dir / "start_sim.bat") + self.stop_command = str(labview_scripts_dir / "stop_sim.bat") options["emulator_command_line"] = self.start_command options["emulator_wait_to_finish"] = True - super(DAQMxEmulatorLauncher, self).__init__( - test_name, device, emulator_path, var_dir, port, options - ) + super().__init__(test_name, device, emulator_path, var_dir, port, options) def _close(self) -> None: self.disconnect_device() - super(DAQMxEmulatorLauncher, self)._close() + super()._close() def disconnect_device(self) -> None: self._call_command_line(self.stop_command) diff --git a/utils/formatters.py b/utils/formatters.py index 9f6f19c5..241abede 100644 --- a/utils/formatters.py +++ b/utils/formatters.py @@ -14,4 +14,4 @@ def format_value(value: Any) -> str: # noqa: ANN401 Returns: string: The formatted value. """ - return "'{}' (type: '{}')".format(value, value.__class__.__name__) + return f"'{value}' (type: '{value.__class__.__name__}')" diff --git a/utils/free_ports.py b/utils/free_ports.py index c912cf13..00d29814 100644 --- a/utils/free_ports.py +++ b/utils/free_ports.py @@ -8,9 +8,9 @@ def get_free_ports(n: int) -> tuple[int, ...]: :param n: the number of ports required :return: a tuple containing n free port numbers """ - socks = list() - ports = list() - for i in range(0, n): + socks = [] + ports = [] + for i in range(n): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) s.bind(("", 0)) @@ -30,9 +30,9 @@ def get_free_ports_from_list(n: int, port_low: int, port_high: int) -> tuple[int :param port_high: the maximum of the port range :return: a tuple containing n free port numbers """ - socks = list() - ports = list() - for i in range(0, n): + socks = [] + ports = [] + for i in range(n): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) for j in range(port_low, port_high): @@ -41,8 +41,9 @@ def get_free_ports_from_list(n: int, port_low: int, port_high: int) -> tuple[int ports.append(s.getsockname()[1]) socks.append(s) break - except socket.error: - pass + except OSError: + # Port is unavailable or cannot be bound; try next candidate port. + continue for s in socks: s.close() return tuple(ports) diff --git a/utils/ioc_launcher.py b/utils/ioc_launcher.py index 00a7bc9a..fb326b28 100644 --- a/utils/ioc_launcher.py +++ b/utils/ioc_launcher.py @@ -3,16 +3,18 @@ """ import abc +import datetime import os +import pathlib import subprocess import time from abc import ABCMeta +from collections.abc import Callable, Generator from contextlib import contextmanager -from datetime import date from signal import SIGTERM from time import sleep from types import TracebackType -from typing import Any, Callable, Generator, Self, Type +from typing import Any, ClassVar, Self import psutil import telnetlib3 @@ -22,10 +24,10 @@ from utils.log_file import LogFileManager, log_filename from utils.test_modes import TestModes -APPS_BASE = os.path.join("C:\\", "Instrument", "Apps") -EPICS_TOP = os.environ.get("EPICS_KIT_ROOT", os.path.join(APPS_BASE, "EPICS")) -IOCS_DIR = os.path.join(EPICS_TOP, "ioc", "master") -PYTHON3 = os.environ.get("PYTHON3", os.path.join(APPS_BASE, "Python3", "python.exe")) +APPS_BASE = pathlib.Path("C:\\", "Instrument", "Apps") +EPICS_TOP = pathlib.Path(os.environ.get("EPICS_KIT_ROOT", str(APPS_BASE / "EPICS"))) +IOCS_DIR = EPICS_TOP / "ioc" / "master" +PYTHON3 = os.environ.get("PYTHON3", str(APPS_BASE / "Python3" / "python.exe")) DEFAULT_IOC_START_TEXT = "epics>" # DEFAULT_IOC_START_TEXT = "iocRun: All initialization complete" @@ -47,12 +49,12 @@ def get_default_ioc_dir(iocname: str, iocnum: int = 1) -> str: Returns: the path """ - return os.path.join( - EPICS_TOP, "ioc", "master", iocname, "iocBoot", "ioc{}-IOC-{:02d}".format(iocname, iocnum) + return str( + EPICS_TOP / "ioc" / "master" / iocname / "iocBoot" / f"ioc{iocname}-IOC-{iocnum:02d}" ) -class CheckExistencePv(object): +class CheckExistencePv: """ Checks to see if a IOC has been started correctly by asserting that a pv does not exist on entry and does on exit @@ -77,13 +79,11 @@ def __enter__(self) -> None: print("Check that IOC is not running") self.ca.assert_that_pv_does_not_exist(self.test_pv) except AssertionError as ex: - raise AssertionError( - "IOC '{}' appears to already be running: {}".format(self.device, ex) - ) + raise AssertionError(f"IOC '{self.device}' appears to already be running: {ex}") def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> None: @@ -94,20 +94,18 @@ def __exit__( self.ca.assert_that_pv_exists(self.test_pv, timeout=30) except AssertionError as ex: full_pv = self.ca.create_pv_with_prefix(self.test_pv) - raise AssertionError( - "PV '{}' still does not exist after IOC start: {}".format(full_pv, ex) - ) + raise AssertionError(f"PV '{full_pv}' still does not exist after IOC start: {ex}") -class IOCRegister(object): +class IOCRegister: """ A way of registering running iocs. """ # Static dictionary of running iocs - RunningIOCs: dict[str, "BaseLauncher"] = {} + RunningIOCs: ClassVar[dict[str, "BaseLauncher"]] = {} - uses_rec_sim = False + uses_rec_sim: ClassVar[bool] = False test_mode = TestModes.DEVSIM @classmethod @@ -134,7 +132,7 @@ def add_ioc(cls, name: str, ioc: "BaseLauncher") -> None: cls.RunningIOCs[name] = ioc -class BaseLauncher(object, metaclass=ABCMeta): +class BaseLauncher(metaclass=ABCMeta): """ Launcher base, this is the base class for a launcher of application under test. """ @@ -196,7 +194,7 @@ def open(self) -> None: st_cmd_path = os.path.join(self._directory, "st.cmd") if not os.path.isfile(st_cmd_path): - print("St.cmd path not found: '{0}'".format(st_cmd_path)) + print(f"St.cmd path not found: '{st_cmd_path}'") ca = self._get_channel_access() @@ -209,7 +207,7 @@ def open(self) -> None: self.log_file_manager = LogFileManager(self.log_file_name, "a") self.log_file_manager.log_file_w.write( - "Started IOC with '{0}'".format(" ".join(self.command_line)) + "Started IOC with '{}'".format(" ".join(self.command_line)) ) # To be able to see the IOC output for debugging, remove the redirection of stdin, @@ -229,14 +227,14 @@ def open(self) -> None: # Write a return so that an epics terminal will appear after boot stdin = self._process.stdin assert stdin is not None - stdin.write("\n".encode("utf-8")) + stdin.write(b"\n") stdin.flush() self.log_file_manager.wait_for_console( MAX_TIME_TO_WAIT_FOR_IOC_TO_START, self._ioc_started_text ) for key, value in self._init_values.items(): - print("Initialising PV {} to {}".format(key, value)) + print(f"Initialising PV {key} to {value}") ca.set_pv_value(key, value) IOCRegister.add_ioc(self._device, self) @@ -253,7 +251,6 @@ def close(self) -> None: """ Exits the application under test """ - pass def __enter__(self) -> Self: self.open() @@ -261,7 +258,7 @@ def __enter__(self) -> Self: def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> None: @@ -286,12 +283,10 @@ def create_macros_file(self) -> None: os.makedirs(full_dir) with open(os.path.join(full_dir, "test_macros.txt"), mode="w") as f: - for macro, value in self.macros.items(): - f.write( - '{ioc_name}__{macro}="{value}"\n'.format( - ioc_name=self._device_icp_config_name, macro=macro, value=value - ) - ) + f.writelines( + f'{self._device_icp_config_name}__{macro}="{value}"\n' + for macro, value in self.macros.items() + ) def get_environment_vars(self) -> dict[str, str]: """ @@ -324,7 +319,7 @@ def get_environment_vars(self) -> dict[str, str]: return settings - def set_simulated_value(self, pv_name: str, value: float | int | str | bool) -> None: + def set_simulated_value(self, pv_name: str, value: float | str | bool) -> None: """ If this IOC is in rec sim set the PV value. @@ -341,7 +336,7 @@ class ProcServLauncher(BaseLauncher): Launches an IOC from procServ.exe """ - ICPTOOLS = os.path.join(EPICS_TOP, "tools", "master") + ICPTOOLS = str(EPICS_TOP / "tools" / "master") def __init__( self, test_name: str, ioc: dict[str, Any], test_mode: TestModes, var_dir: str @@ -359,7 +354,7 @@ def __init__( test_mode: TestModes.RECSIM or TestModes.DEVSIM depending on IOC test mode var_dir: The directory into which the launcher will save log files. """ - super(ProcServLauncher, self).__init__(test_name, ioc, test_mode, var_dir) + super().__init__(test_name, ioc, test_mode, var_dir) self.logport = int(self.macros["LOG_PORT"]) self.procserv_port = get_free_ports(1)[0] @@ -375,16 +370,16 @@ def _get_telnet(self) -> telnetlib3.Telnet: return tn def get_environment_vars(self) -> dict[str, str]: - settings = super(ProcServLauncher, self).get_environment_vars() + settings = super().get_environment_vars() settings["CYGWIN"] = "disable_pcon" - settings["MYDIRPROCSV"] = os.path.join(EPICS_TOP, "iocstartup") + settings["MYDIRPROCSV"] = str(EPICS_TOP / "iocstartup") settings["EPICS_CAS_INTF_ADDR_LIST"] = "127.0.0.1" settings["EPICS_CAS_BEACON_ADDR_LIST"] = "127.255.255.255" settings["IOCLOGROOT"] = os.path.join("C:", "Instrument", "var", "logs", "ioc") settings["IOCCYGLOGROOT"] = self.to_cygwin_address(settings["IOCLOGROOT"]) settings["IOCSH_SHOWWIN"] = "H" - settings["LOGTIME"] = date.today().strftime("%Y%m%d") + settings["LOGTIME"] = datetime.datetime.now(tz=datetime.timezone.utc).strftime("%Y%m%d") return settings @@ -408,20 +403,20 @@ def _command_line(self) -> list[str]: comspec = os.getenv("ComSpec") cygwin_dir = self.to_cygwin_address(self._directory) return [ - "{}\\cygwin\\bin\\procServ.exe".format(self.ICPTOOLS), + f"{self.ICPTOOLS}\\cygwin\\bin\\procServ.exe", "--logstamp", - '--logfile="{}"'.format(self.to_cygwin_address(self.log_file_name)), + f'--logfile="{self.to_cygwin_address(self.log_file_name)}"', '--timefmt="%Y-%m-%d %H:%M:%S"', "--restrict", '--ignore="^D^C"', "--autorestart", "--wait", - "--name={}".format(self._device.upper()), - '--pidfile="/cygdrive/c/instrument/var/run/EPICS_{}.pid"'.format(self._device), - "--logport={:d}".format(self.logport), - '--chdir="{}"'.format(cygwin_dir), - "{:d}".format(self.procserv_port), - "{}".format(comspec), + f"--name={self._device.upper()}", + f'--pidfile="/cygdrive/c/instrument/var/run/EPICS_{self._device}.pid"', + f"--logport={self.logport:d}", + f'--chdir="{cygwin_dir}"', + f"{self.procserv_port:d}", + f"{comspec}", "/c", "runIOC.bat", "st.cmd", @@ -435,7 +430,7 @@ def open(self) -> None: OSError if procServ connection could not be made """ - super(ProcServLauncher, self).open() + super().open() pids = ",".join([str(s) for s in self._find_processes()]) print( f"IOC started, connecting to procserv pids {pids} at telnet port {self.procserv_port}" @@ -480,9 +475,7 @@ def send_telnet_command_and_retry_if_not_detected_condition_for_success( self._get_telnet().close() self._get_telnet().open("localhost", self.procserv_port, timeout=20) else: # If condition for success not detected, raise an assertion error - raise AssertionError( - "Sending telnet command {} failed {} times".format(command, retry_limit) - ) + raise AssertionError(f"Sending telnet command {command} failed {retry_limit} times") def send_telnet_command(self, command: str) -> None: """ @@ -490,14 +483,14 @@ def send_telnet_command(self, command: str) -> None: Args: command: command to set """ - self._get_telnet().write("{cmd}\n".format(cmd=command).encode("ascii")) + self._get_telnet().write(f"{command}\n".encode("ascii")) def force_manual_save(self) -> None: """ Force a manual save by sending requests to save the settings and positions files """ - self.send_telnet_command("manual_save({}_info_settings.req)".format(self._device)) - self.send_telnet_command("manual_save({}_info_positions.req)".format(self._device)) + self.send_telnet_command(f"manual_save({self._device}_info_settings.req)") + self.send_telnet_command(f"manual_save({self._device}_info_positions.req)") def start_ioc(self, wait: bool = False) -> None: """ @@ -558,7 +551,7 @@ def close(self) -> None: Shuts telnet connection and kills IOC. Identifies the spawned procServ processes and kills them """ - print("\nTerminating IOC ({})".format(self._device)) + print(f"\nTerminating IOC ({self._device})") if self._telnet is not None: self._get_telnet().close() @@ -584,9 +577,8 @@ def close(self) -> None: if not at_least_one_killed: print( - "No process with name procServ.exe found that matched command line {}".format( - self.command_line - ) + "No process with name procServ.exe found that " + f"matched command line {self.command_line}" ) def _find_processes(self) -> list[int]: @@ -621,7 +613,7 @@ def process_arguments_match_this_ioc(self, process_arguments: list[str]) -> bool # so we must remove them to compare with our ioc_run_command ioc_start_arguments = [args.replace('"', "") for args in self.command_line] - arguments_match = all([args in process_arguments for args in ioc_start_arguments]) + arguments_match = all(args in process_arguments for args in ioc_start_arguments) return arguments_match @@ -691,16 +683,16 @@ def __init__( :param test_mode: TestModes.RECSIM or TestModes.DEVSIM depending on IOC test mode :param var_dir: The directory into which the launcher will save log files. """ - super(IocLauncher, self).__init__(test_name, ioc, test_mode, var_dir) + super().__init__(test_name, ioc, test_mode, var_dir) def _command_line(self) -> list[str]: run_ioc_path = os.path.join(self._directory, "runIOC.bat") st_cmd_path = os.path.join(self._directory, "st.cmd") if not os.path.isfile(run_ioc_path): - print("Run IOC path not found: '{0}'".format(run_ioc_path)) + print(f"Run IOC path not found: '{run_ioc_path}'") if not os.path.isfile(st_cmd_path): - print("St.cmd path not found: '{0}'".format(st_cmd_path)) + print(f"St.cmd path not found: '{st_cmd_path}'") return [run_ioc_path, st_cmd_path] @@ -708,13 +700,13 @@ def close(self) -> None: """ Closes the IOC. """ - print("\nTerminating IOC ({})".format(self._device)) + print(f"\nTerminating IOC ({self._device})") if self._process is not None: # use write not communicate so that we don't wait for exit before continuing stdin = self._process.stdin assert stdin is not None - stdin.write("exit\n".encode("utf-8")) + stdin.write(b"exit\n") stdin.flush() max_wait_for_ioc_to_die = 60 @@ -727,13 +719,12 @@ def close(self) -> None: except AssertionError: sleep(wait_per_loop) if loop_count % 100 == 99: - print(" waited {}".format(loop_count * wait_per_loop)) + print(f" waited {loop_count * wait_per_loop}") else: print( - "IOC process did not die after {} seconds after killing with `exit` in iocsh. " - "Killing process and waiting another {} seconds".format( - max_wait_for_ioc_to_die, max_wait_for_ioc_to_die - ) + f"IOC process did not die after {max_wait_for_ioc_to_die} " + "seconds after killing with `exit` in iocsh. " + f"Killing process and waiting another {max_wait_for_ioc_to_die} seconds" ) self._process.kill() sleep(max_wait_for_ioc_to_die) @@ -752,7 +743,7 @@ def close(self) -> None: def _print_log_file_location(self) -> None: if self.log_file_manager is not None: self.log_file_manager.close() - print("IOC log written to {0}".format(self.log_file_name)) + print(f"IOC log written to {self.log_file_name}") class PythonIOCLauncher(IocLauncher): @@ -763,13 +754,13 @@ class PythonIOCLauncher(IocLauncher): def __init__( self, test_name: str, ioc: dict[str, Any], test_mode: TestModes, var_dir: str ) -> None: - super(PythonIOCLauncher, self).__init__(test_name, ioc, test_mode, var_dir) + super().__init__(test_name, ioc, test_mode, var_dir) self._python_script_commandline = ioc.get("python_script_commandline", None) def _command_line(self) -> list[str]: run_ioc_path = self._python_script_commandline[0] if not os.path.isfile(run_ioc_path): - print("Command first argument path not found: '{0}'".format(run_ioc_path)) + print(f"Command first argument path not found: '{run_ioc_path}'") command_line = [PYTHON3] command_line.extend(self._python_script_commandline) return command_line @@ -778,7 +769,7 @@ def close(self) -> None: """ Closes the IOC. """ - print("\nTerminating python IOC ({})".format(self._device)) + print(f"\nTerminating python IOC ({self._device})") if self._process is not None: # just kill a process if this is the only way to stop it diff --git a/utils/log_file.py b/utils/log_file.py index 7befc05b..aac9b7ea 100644 --- a/utils/log_file.py +++ b/utils/log_file.py @@ -36,14 +36,14 @@ def log_filename(test_name: str, what: str, device: str, test_mode: TestModes, v ) -class LogFileManager(object): +class LogFileManager: """ Class to manage the access of log files """ def __init__(self, filename: str, write_mode: str = "w") -> None: - self.log_file_w = open(filename, write_mode, 1) - self.log_file_r = open(filename, "r") + self.log_file_w = open(filename, write_mode, 1) # noqa: SIM115 + self.log_file_r = open(filename, "r") # noqa: SIM115 def read_log(self) -> list[str]: """ @@ -84,9 +84,8 @@ def wait_for_console(self, timeout: int, ioc_started_text: str) -> None: sleep(1) else: raise AssertionError( - "IOC appears not to have started after {} seconds. Looking for '{}'".format( - timeout, ioc_started_text - ) + f"IOC appears not to have started after {timeout} " + f"seconds. Looking for '{ioc_started_text}'" ) def close(self) -> None: diff --git a/utils/testing.py b/utils/testing.py index 19b16a54..51b51ac0 100644 --- a/utils/testing.py +++ b/utils/testing.py @@ -1,8 +1,9 @@ import functools import unittest +from collections.abc import Callable from time import sleep from types import TracebackType -from typing import TYPE_CHECKING, Callable, Concatenate, ParamSpec, Self, Type, TypeVar, overload +from typing import TYPE_CHECKING, ClassVar, Concatenate, ParamSpec, Self, TypeVar, overload from utils.emulator_launcher import EmulatorRegister from utils.ioc_launcher import IOCRegister @@ -19,7 +20,7 @@ from utils.log_file import LogFileManager -class ManagerMode(object): +class ManagerMode: """A context manager for switching manager mode on.""" MANAGER_MODE_PV = "CS:MANAGER" @@ -34,7 +35,7 @@ def __enter__(self) -> None: def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> None: @@ -42,10 +43,10 @@ def __exit__( self.channel_access.assert_that_pv_is(self.MANAGER_MODE_PV, "No", timeout=5) -class _AssertLogContext(object): +class _AssertLogContext: """A context manager used to implement assert_log_messages.""" - messages = [] + messages: ClassVar[list[str]] = [] first_message = 0 def __init__( @@ -82,7 +83,7 @@ def __enter__(self) -> Self: def __exit__( self, - exc_type: Type[BaseException] | None, + exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None, ) -> bool: @@ -149,13 +150,11 @@ def get_running_lewis_and_ioc( ioc = IOCRegister.get_running(ioc_name) if ioc is None and (lewis is None and emulator_name is not None): - raise AssertionError( - "Emulator ({}) and IOC ({}) are not running".format(emulator_name, ioc_name) - ) + raise AssertionError(f"Emulator ({emulator_name}) and IOC ({ioc_name}) are not running") if ioc is None: - raise AssertionError("IOC ({}) is not running".format(ioc_name)) + raise AssertionError(f"IOC ({ioc_name}) is not running") if lewis is None and emulator_name is not None: - raise AssertionError("Emulator ({}) is not running".format(emulator_name)) + raise AssertionError(f"Emulator ({emulator_name}) is not running") return lewis, ioc @@ -250,7 +249,7 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> T: skip_always = functools.partial(skip_if_condition, lambda: True) -def add_method(method: Callable[P, T]) -> Callable[[Type[CT]], Type[CT]]: +def add_method(method: Callable[P, T]) -> Callable[[type[CT]], type[CT]]: """ Class decorator which adds the method to the decorated class. @@ -263,7 +262,7 @@ def add_method(method: Callable[P, T]) -> Callable[[Type[CT]], Type[CT]]: method (func): The method to add to the class decorated. Should be callable. """ - def wrapper(class_to_decorate: Type[CT]) -> Type[CT]: + def wrapper(class_to_decorate: type[CT]) -> type[CT]: setattr(class_to_decorate, method.__name__, method) return class_to_decorate @@ -299,7 +298,7 @@ def parameterized_list(cases: list[T]) -> list[tuple[str, T]]: def unstable_test( max_retries: int = 2, - error_class: Type[BaseException] | tuple[Type[BaseException], ...] = AssertionError, + error_class: type[BaseException] | tuple[type[BaseException], ...] = AssertionError, wait_between_runs: float = 0, ) -> Callable[ [Callable[Concatenate[unittest.TestCase, P], T]], Callable[Concatenate[unittest.TestCase, P], T] @@ -333,8 +332,11 @@ def wrapper(self: unittest.TestCase, *args: P.args, **kwargs: P.kwargs) -> T: last_error = e finally: self.tearDown() # Rerun tearDown regardless of success or not - else: + if last_error is not None: raise last_error + raise AssertionError( + "Retry decorator exhausted without capturing a retryable exception" + ) return wrapper