diff --git a/src/hyperion/external_interaction/ispyb/ispyb_store.py b/src/hyperion/external_interaction/ispyb/ispyb_store.py index 6f90a8330..21e558e9c 100755 --- a/src/hyperion/external_interaction/ispyb/ispyb_store.py +++ b/src/hyperion/external_interaction/ispyb/ispyb_store.py @@ -87,9 +87,7 @@ def _begin_or_update_deposition( ) ) else: - assert ( - ispyb_ids.data_collection_group_id - ), "Attempt to update data collection without a data collection group ID" + assert ispyb_ids.data_collection_group_id, "Attempt to update data collection without a data collection group ID" grid_ids = list(ispyb_ids.grid_ids) data_collection_ids_out = list(ispyb_ids.data_collection_ids) diff --git a/tests/conftest.py b/tests/conftest.py index 63ca1d6f6..562361410 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,12 +5,13 @@ import sys import threading from functools import partial -from typing import Any, Callable, Generator, Optional, Sequence +from typing import Any, Generator, Sequence from unittest.mock import MagicMock, patch import bluesky.plan_stubs as bps import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator from bluesky.utils import Msg from dodal.beamlines import i03 from dodal.common.beamlines import beamline_utils @@ -721,155 +722,6 @@ def extract_metafile(input_filename, output_filename): output_fo.write(metafile_fo.read()) -class RunEngineSimulator: - """This class simulates a Bluesky RunEngine by recording and injecting responses to messages according to the - bluesky Message Protocol (see bluesky docs for details). - Basic usage consists of - 1) Registering various handlers to respond to anticipated messages in the experiment plan and fire any - needed callbacks. - 2) Calling simulate_plan() - 3) Examining the returned message list and making asserts against them""" - - def __init__(self): - self.message_handlers = [] - self.callbacks = {} - self.next_callback_token = 0 - - def add_handler_for_callback_subscribes(self): - """Add a handler that registers all the callbacks from subscribe messages so we can call them later. - You probably want to call this as one of the first things unless you have a good reason not to. - """ - self.message_handlers.append( - MessageHandler( - lambda msg: msg.command == "subscribe", - lambda msg: self._add_callback(msg.args), - ) - ) - - def add_handler( - self, - commands: Sequence[str], - obj_name: Optional[str], - handler: Callable[[Msg], object], - ): - """Add the specified handler for a particular message - Args: - commands: the command name for the message as defined in bluesky Message Protocol, or a sequence if more - than one matches - obj_name: the name property of the obj to match, can be None as not all messages have a name - handler: a lambda that accepts a Msg and returns an object; the object is sent to the current yield statement - in the generator, and is used when reading values from devices, the structure of the object depends on device - hinting. - """ - if isinstance(commands, str): - commands = [commands] - - self.message_handlers.append( - MessageHandler( - lambda msg: msg.command in commands - and (obj_name is None or (msg.obj and msg.obj.name == obj_name)), - handler, - ) - ) - - def add_wait_handler( - self, handler: Callable[[Msg], None], group: str = "any" - ) -> None: - """Add a wait handler for a particular message - Args: - handler: a lambda that accepts a Msg, use this to execute any code that simulates something that's - supposed to complete when a group finishes - group: name of the group to wait for, default is any which matches them all - """ - self.message_handlers.append( - MessageHandler( - lambda msg: msg.command == "wait" - and (group == "any" or msg.kwargs["group"] == group), - handler, - ) - ) - - def fire_callback(self, document_name, document) -> None: - """Fire all the callbacks registered for this document type in order to simulate something happening - Args: - document_name: document name as defined in the Bluesky Message Protocol 'subscribe' call, - all subscribers filtering on this document name will be called - document: the document to send - """ - for callback_func, callback_docname in self.callbacks.values(): - if callback_docname == "all" or callback_docname == document_name: - callback_func(document_name, document) - - def simulate_plan(self, gen: Generator[Msg, object, object]) -> list[Msg]: - """Simulate the RunEngine executing the plan - Args: - gen: the generator function that executes the plan - Returns: - a list of the messages generated by the plan - """ - messages = [] - send_value = None - try: - while msg := gen.send(send_value): - send_value = None - messages.append(msg) - LOGGER.debug(f"<{msg}") - if handler := next( - (h for h in self.message_handlers if h.predicate(msg)), None - ): - send_value = handler.runnable(msg) - - if send_value: - LOGGER.debug(f">send {send_value}") - except StopIteration: - pass - return messages - - def _add_callback(self, msg_args): - self.callbacks[self.next_callback_token] = msg_args - self.next_callback_token += 1 - - def assert_message_and_return_remaining( - self, - messages: list[Msg], - predicate: Callable[[Msg], bool], - group: Optional[str] = None, - ): - """Find the next message matching the predicate, assert that we found it - Return: all the remaining messages starting from the matched message""" - indices = [ - i - for i in range(len(messages)) - if ( - not group - or (messages[i].kwargs and messages[i].kwargs.get("group") == group) - ) - and predicate(messages[i]) - ] - assert indices, f"Nothing matched predicate {predicate}" - return messages[indices[0] :] - - def mock_message_generator( - self, - function_name: str, - ) -> Callable[..., Generator[Msg, object, object]]: - """Returns a callable that returns a generator yielding a Msg object recording the call arguments. - This can be used to mock methods returning a bluesky plan or portion thereof, call it from within a unit test - using the RunEngineSimulator, and then perform asserts on the message to verify in-order execution of the plan - """ - - def mock_method(*args, **kwargs): - yield Msg(function_name, None, *args, **kwargs) - - return mock_method - - -class MessageHandler: - def __init__(self, p: Callable[[Msg], bool], r: Callable[[Msg], object]): - self.predicate = p - self.runnable = r - - @pytest.fixture def sim_run_engine(): return RunEngineSimulator() diff --git a/tests/unit_tests/device_setup_plans/test_dcm_pitch_roll_mirror_adjuster.py b/tests/unit_tests/device_setup_plans/test_dcm_pitch_roll_mirror_adjuster.py index 4a9715f75..11fe41a2e 100644 --- a/tests/unit_tests/device_setup_plans/test_dcm_pitch_roll_mirror_adjuster.py +++ b/tests/unit_tests/device_setup_plans/test_dcm_pitch_roll_mirror_adjuster.py @@ -3,6 +3,7 @@ import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining from dodal.common.beamlines.beamline_parameters import GDABeamlineParameters from dodal.devices.focusing_mirror import ( FocusingMirrorWithStripes, @@ -165,51 +166,51 @@ def test_adjust_dcm_pitch_roll_vfm_from_lut( vfm: FocusingMirrorWithStripes, vfm_mirror_voltages: VFMMirrorVoltages, beamline_parameters: GDABeamlineParameters, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): sim_run_engine.add_handler_for_callback_subscribes() sim_run_engine.add_handler( "read", - "dcm-bragg_in_degrees", lambda msg: {"dcm-bragg_in_degrees": {"value": 5.0}}, + "dcm-bragg_in_degrees", ) messages = sim_run_engine.simulate_plan( adjust_dcm_pitch_roll_vfm_from_lut(undulator_dcm, vfm, vfm_mirror_voltages, 7.5) ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages, lambda msg: msg.command == "set" and msg.obj.name == "dcm-pitch_in_mrad" and abs(msg.args[0] - -0.75859) < 1e-5 and msg.kwargs["group"] == "DCM_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "dcm-roll_in_mrad" and abs(msg.args[0] - 4.0) < 1e-5 and msg.kwargs["group"] == "DCM_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "dcm-offset_in_mm" and msg.args == (25.6,) and msg.kwargs["group"] == "DCM_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "vfm-stripe" and msg.args == (MirrorStripe.RHODIUM,), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "wait", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "trigger" and msg.obj.name == "vfm-apply_stripe", ) @@ -223,17 +224,17 @@ def test_adjust_dcm_pitch_roll_vfm_from_lut( (6, 4), (7, -46), ): - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == f"vfm_mirror_voltages-voltage_channels-{channel}" and msg.args == (expected_voltage,), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "wait" and msg.kwargs["group"] == "DCM_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "vfm-x_mm" diff --git a/tests/unit_tests/device_setup_plans/test_setup_panda.py b/tests/unit_tests/device_setup_plans/test_setup_panda.py index de7a8e15c..407a89607 100644 --- a/tests/unit_tests/device_setup_plans/test_setup_panda.py +++ b/tests/unit_tests/device_setup_plans/test_setup_panda.py @@ -5,6 +5,7 @@ import pytest from bluesky.plan_stubs import null from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator from dodal.devices.fast_grid_scan import PandAGridScanParams from ophyd_async.panda import SeqTrigger @@ -16,14 +17,14 @@ setup_panda_for_flyscan, ) -from ...conftest import RunEngineSimulator - def get_smargon_speed(x_step_size_mm: float, time_between_x_steps_ms: float) -> float: return x_step_size_mm / time_between_x_steps_ms -def run_simulating_setup_panda_functions(plan: str, mock_load_device=MagicMock): +def run_simulating_setup_panda_functions( + plan: str, sim_run_engine: RunEngineSimulator, mock_load_device=MagicMock +): num_of_sets = 0 num_of_waits = 0 mock_panda = MagicMock() @@ -37,11 +38,7 @@ def count_commands(msg): num_of_waits += 1 sim = RunEngineSimulator() - sim.add_handler( - ["set", "wait"], - None, - count_commands, - ) + sim.add_handler(["set", "wait"], count_commands) if plan == "setup": smargon_speed = get_smargon_speed(0.1, 1) @@ -63,9 +60,9 @@ def count_commands(msg): @patch("hyperion.device_setup_plans.setup_panda.load_device") -def test_setup_panda_performs_correct_plans(mock_load_device): +def test_setup_panda_performs_correct_plans(mock_load_device, sim_run_engine): num_of_sets, num_of_waits = run_simulating_setup_panda_functions( - "setup", mock_load_device + "setup", sim_run_engine, mock_load_device ) mock_load_device.assert_called_once() assert num_of_sets == 9 @@ -181,9 +178,7 @@ def assert_set_table_has_been_waited_on(*args, **kwargs): ), patch( "hyperion.device_setup_plans.setup_panda.bps.wait", MagicMock(side_effect=handle_wait), - ), patch( - "hyperion.device_setup_plans.setup_panda.load_device" - ), patch( + ), patch("hyperion.device_setup_plans.setup_panda.load_device"), patch( "hyperion.device_setup_plans.setup_panda.bps.abs_set" ): RE( @@ -201,8 +196,10 @@ def assert_set_table_has_been_waited_on(*args, **kwargs): # It also would be useful to have some system tests which check that (at least) # all the blocks which were enabled on setup are also disabled on tidyup -def test_disarm_panda_disables_correct_blocks(): - num_of_sets, num_of_waits = run_simulating_setup_panda_functions("disarm") +def test_disarm_panda_disables_correct_blocks(sim_run_engine): + num_of_sets, num_of_waits = run_simulating_setup_panda_functions( + "disarm", sim_run_engine + ) assert num_of_sets == 6 assert num_of_waits == 1 diff --git a/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py b/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py index e5801af88..aecf97970 100644 --- a/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py +++ b/tests/unit_tests/experiment_plans/test_flyscan_xray_centre_plan.py @@ -8,6 +8,7 @@ import numpy as np import pytest from bluesky.run_engine import RunEngine, RunEngineResult +from bluesky.simulators import assert_message_and_return_remaining from bluesky.utils import FailedStatus, Msg from dodal.beamlines import i03 from dodal.common.beamlines.beamline_utils import clear_device @@ -998,30 +999,30 @@ def test_read_hardware_during_collection_occurs_after_eiger_arm( ) sim_run_engine.add_handler( "read", - "synchrotron-synchrotron_mode", lambda msg: {"values": {"value": SynchrotronMode.USER}}, + "synchrotron-synchrotron_mode", ) msgs = sim_run_engine.simulate_plan( run_gridscan( fake_fgs_composite, test_fgs_params_panda_zebra, feature_controlled ) ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "stage" and msg.obj.name == "eiger" ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "kickoff" and msg.obj == feature_controlled.fgs_motors, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "create" ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "read" and msg.obj.name == "eiger_bit_depth", ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "save" ) diff --git a/tests/unit_tests/experiment_plans/test_grid_detection_plan.py b/tests/unit_tests/experiment_plans/test_grid_detection_plan.py index ac122d3ad..774ff4378 100644 --- a/tests/unit_tests/experiment_plans/test_grid_detection_plan.py +++ b/tests/unit_tests/experiment_plans/test_grid_detection_plan.py @@ -4,6 +4,7 @@ import numpy as np import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator from bluesky.utils import Msg from dodal.beamlines import i03 from dodal.devices.backlight import Backlight @@ -345,11 +346,11 @@ def decorated(): def test_when_detected_grid_has_odd_y_steps_then_add_a_y_step_and_shift_grid( fake_logger: MagicMock, fake_devices, + sim_run_engine: RunEngineSimulator, test_config_files, odd, ): composite, _ = fake_devices - sim = RunEngineSimulator() params = OAVParameters("loopCentring", test_config_files["oav_config_json"]) grid_width_microns = 161.2 box_size_um = 20 @@ -382,19 +383,9 @@ def record_set(msg: Msg): if msg.obj.dotted_name in abs_sets.keys(): abs_sets[msg.obj.dotted_name].append(msg.args[0]) - sim.add_handler( - "set", - None, - record_set, - ) - - sim.add_handler( - "read", - None, - handle_read, - ) - - sim.simulate_plan( + sim_run_engine.add_handler("set", record_set) + sim_run_engine.add_handler("read", handle_read) + sim_run_engine.simulate_plan( grid_detection_plan( composite, parameters=params, diff --git a/tests/unit_tests/experiment_plans/test_oav_snapshot_plan.py b/tests/unit_tests/experiment_plans/test_oav_snapshot_plan.py index 81b77c747..71fd0626e 100644 --- a/tests/unit_tests/experiment_plans/test_oav_snapshot_plan.py +++ b/tests/unit_tests/experiment_plans/test_oav_snapshot_plan.py @@ -2,6 +2,7 @@ from unittest.mock import patch import pytest +from bluesky.simulators import assert_message_and_return_remaining from dodal.devices.oav.oav_parameters import OAVParameters from dodal.devices.oav.utils import ColorMode @@ -44,37 +45,37 @@ def test_oav_snapshot_plan_issues_rotations_and_generates_events( ) ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_cam_color_mode" and msg.args[0] == ColorMode.RGB1, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_cam_acquire_period" and msg.args[0] == 0.05, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_cam_acquire_time" and msg.args[0] == 0.075, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_cam_gain" and msg.args[0] == 1, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_zoom_controller" and msg.args[0] == "5.0x", ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_snapshot_directory" @@ -86,39 +87,39 @@ def test_oav_snapshot_plan_issues_rotations_and_generates_events( {"omega": 180, "filename": "100623_oav_snapshot_180"}, {"omega": 270, "filename": "100623_oav_snapshot_270"}, ]: - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "smargon-omega" and msg.args[0] == expected["omega"] and msg.kwargs["group"] == OAV_SNAPSHOT_GROUP, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "set" and msg.obj.name == "oav_snapshot_filename" and msg.args[0] == expected["filename"], ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "trigger" and msg.obj.name == "oav_snapshot" and msg.kwargs["group"] == OAV_SNAPSHOT_GROUP, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "wait" and msg.kwargs["group"] == OAV_SNAPSHOT_GROUP, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "create" and msg.kwargs["name"] == DocDescriptorNames.OAV_ROTATION_SNAPSHOT_TRIGGERED, ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "read" and msg.obj.name == "oav_snapshot" ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "save" ) diff --git a/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py b/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py index 2f3f476ac..7ff6571a7 100644 --- a/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py +++ b/tests/unit_tests/experiment_plans/test_pin_centre_then_xray_centre_plan.py @@ -2,6 +2,7 @@ import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining from bluesky.utils import Msg from dodal.devices.detector.detector_motion import ShutterState from dodal.devices.synchrotron import SynchrotronMode @@ -78,7 +79,7 @@ def test_when_pin_centre_xray_centre_called_then_detector_positioned( test_pin_centre_then_xray_centre_params: PinTipCentreThenXrayCentre, simple_beamline, test_config_files, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): mock_grid_callback.return_value.get_grid_parameters.return_value = { "transmission_frac": 1.0, @@ -100,20 +101,20 @@ def test_when_pin_centre_xray_centre_called_then_detector_positioned( sim_run_engine.add_handler( "read", - "synchrotron-synchrotron_mode", lambda msg_: {"values": {"value": SynchrotronMode.SHUTDOWN}}, + "synchrotron-synchrotron_mode", ) def add_handlers_to_simulate_detector_motion(msg: Msg): sim_run_engine.add_handler( "read", - "detector_motion_shutter", lambda msg_: {"values": {"value": int(ShutterState.OPEN)}}, + "detector_motion_shutter", ) sim_run_engine.add_handler( "read", - "detector_motion_z_motor_done_move", lambda msg_: {"values": {"value": 1}}, + "detector_motion_z_motor_done_move", ) sim_run_engine.add_wait_handler( @@ -128,7 +129,7 @@ def add_handlers_to_simulate_detector_motion(msg: Msg): ), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages, lambda msg: msg.obj is simple_beamline.detector_motion.z ) assert messages[0].args[0] == 100 @@ -136,12 +137,12 @@ def add_handlers_to_simulate_detector_motion(msg: Msg): assert messages[1].obj is simple_beamline.detector_motion.shutter assert messages[1].args[0] == 1 assert messages[1].kwargs["group"] == CONST.WAIT.GRID_READY_FOR_DC - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[2:], lambda msg: msg.command == "wait" and msg.kwargs["group"] == CONST.WAIT.GRID_READY_FOR_DC, ) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( messages[2:], lambda msg: msg.command == "open_run" and msg.kwargs["subplan_name"] == "do_fgs", diff --git a/tests/unit_tests/experiment_plans/test_rotation_scan_plan.py b/tests/unit_tests/experiment_plans/test_rotation_scan_plan.py index 5fb16eb5a..699b681a6 100644 --- a/tests/unit_tests/experiment_plans/test_rotation_scan_plan.py +++ b/tests/unit_tests/experiment_plans/test_rotation_scan_plan.py @@ -6,6 +6,7 @@ import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining from dodal.devices.aperturescatterguard import ApertureScatterguard from dodal.devices.synchrotron import SynchrotronMode from dodal.devices.zebra import Zebra @@ -272,20 +273,20 @@ def test_rotation_plan_reads_hardware( fake_create_rotation_devices: RotationScanComposite, test_rotation_params, motion_values, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): sim_run_engine.add_handler( "read", - "synchrotron-synchrotron_mode", lambda msg: {"values": {"value": SynchrotronMode.USER}}, + "synchrotron-synchrotron_mode", ) sim_run_engine.add_handler( "read", - "synchrotron-top_up_start_countdown", lambda msg: {"values": {"value": -1}}, + "synchrotron-top_up_start_countdown", ) sim_run_engine.add_handler( - "read", "smargon-omega", lambda msg: {"smargon-omega": {"value": -1}} + "read", lambda msg: {"smargon-omega": {"value": -1}}, "smargon-omega" ) msgs = sim_run_engine.simulate_plan( @@ -294,18 +295,18 @@ def test_rotation_plan_reads_hardware( ) ) - msgs = sim_run_engine.assert_message_and_return_remaining( + msgs = assert_message_and_return_remaining( msgs, lambda msg: msg.command == "create" and msg.kwargs["name"] == CONST.DESCRIPTORS.HARDWARE_READ_PRE, ) msgs_in_event = list(takewhile(lambda msg: msg.command != "save", msgs)) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( msgs_in_event, lambda msg: msg.command == "read" and msg.obj.name == "smargon-x" ) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( msgs_in_event, lambda msg: msg.command == "read" and msg.obj.name == "smargon-y" ) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( msgs_in_event, lambda msg: msg.command == "read" and msg.obj.name == "smargon-z" ) diff --git a/tests/unit_tests/experiment_plans/test_set_energy_plan.py b/tests/unit_tests/experiment_plans/test_set_energy_plan.py index 52eff1052..6d256c164 100644 --- a/tests/unit_tests/experiment_plans/test_set_energy_plan.py +++ b/tests/unit_tests/experiment_plans/test_set_energy_plan.py @@ -1,6 +1,7 @@ from unittest.mock import patch import pytest +from bluesky.simulators import assert_message_and_return_remaining from bluesky.utils import Msg from dodal.devices.xbpm_feedback import Pause @@ -35,39 +36,39 @@ def test_set_energy( set_energy_composite, ): messages = sim_run_engine.simulate_plan(set_energy_plan(11.1, set_energy_composite)) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages, lambda msg: msg.command == "set" and msg.obj.name == "xbpm_feedback-pause_feedback" and msg.args == (Pause.PAUSE,), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "attenuator" and msg.args == (0.1,), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "undulator_dcm" and msg.args == (11.1,) and msg.kwargs["group"] == "UNDULATOR_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "adjust_dcm_pitch_roll_vfm_from_lut" ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "wait" and msg.kwargs["group"] == "UNDULATOR_GROUP", ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "xbpm_feedback-pause_feedback" and msg.args == (Pause.RUN,), ) - messages = sim_run_engine.assert_message_and_return_remaining( + messages = assert_message_and_return_remaining( messages[1:], lambda msg: msg.command == "set" and msg.obj.name == "attenuator" diff --git a/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py b/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py index 93884b968..c1e52ec2d 100644 --- a/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py +++ b/tests/unit_tests/experiment_plans/test_wait_for_robot_load_then_centre.py @@ -3,6 +3,7 @@ import pytest from bluesky.run_engine import RunEngine +from bluesky.simulators import RunEngineSimulator, assert_message_and_return_remaining from bluesky.utils import Msg from dodal.devices.aperturescatterguard import AperturePositions from dodal.devices.eiger import EigerDetector @@ -98,17 +99,17 @@ def test_when_plan_run_with_requested_energy_specified_energy_change_executes( mock_centring_plan: MagicMock, robot_load_composite: RobotLoadThenCentreComposite, robot_load_then_centre_params: RobotLoadThenCentre, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): sim_run_engine.add_handler( "read", - "dcm-energy_in_kev", lambda msg: {"dcm-energy_in_kev": {"value": 11.105}}, + "dcm-energy_in_kev", ) messages = sim_run_engine.simulate_plan( robot_load_then_centre(robot_load_composite, robot_load_then_centre_params) ) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( messages, lambda msg: msg.command == "set_energy_plan" ) params_passed: PinTipCentreThenXrayCentre = mock_centring_plan.call_args[0][1] @@ -126,12 +127,12 @@ def test_when_plan_run_with_requested_energy_specified_energy_change_executes( def test_robot_load_then_centre_doesnt_set_energy_if_not_specified_and_current_energy_set_on_eiger( robot_load_composite: RobotLoadThenCentreComposite, robot_load_then_centre_params_no_energy: RobotLoadThenCentre, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): sim_run_engine.add_handler( "read", - "dcm-energy_in_kev", lambda msg: {"dcm-energy_in_kev": {"value": 11.105}}, + "dcm-energy_in_kev", ) messages = sim_run_engine.simulate_plan( robot_load_then_centre( @@ -148,7 +149,7 @@ def run_simulating_smargon_wait( robot_load_then_centre_params, robot_load_composite, total_disabled_reads, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): robot_load_composite.smargon = instantiate_fake_device(Smargon, name="smargon") robot_load_composite.eiger = instantiate_fake_device(EigerDetector, name="eiger") @@ -162,13 +163,11 @@ def return_not_disabled_after_reads(_): sim_run_engine.add_handler( "read", - "dcm-energy_in_kev", lambda msg: {"dcm-energy_in_kev": {"value": 11.105}}, + "dcm-energy_in_kev", ) sim_run_engine.add_handler( - "read", - "smargon-disabled", - return_not_disabled_after_reads, + "read", return_not_disabled_after_reads, "smargon-disabled" ) return sim_run_engine.simulate_plan( @@ -367,14 +366,14 @@ def test_when_plan_run_then_thawing_turned_on_for_expected_time( mock_centring_plan: MagicMock, robot_load_composite: RobotLoadThenCentreComposite, robot_load_then_centre_params_no_energy: RobotLoadThenCentre, - sim_run_engine, + sim_run_engine: RunEngineSimulator, ): robot_load_then_centre_params_no_energy.thawing_time = (thaw_time := 50) sim_run_engine.add_handler( "read", - "dcm-energy_in_kev", lambda msg: {"dcm-energy_in_kev": {"value": 11.105}}, + "dcm-energy_in_kev", ) messages = sim_run_engine.simulate_plan( @@ -384,7 +383,7 @@ def test_when_plan_run_then_thawing_turned_on_for_expected_time( ) ) - sim_run_engine.assert_message_and_return_remaining( + assert_message_and_return_remaining( messages, lambda msg: msg.command == "set" and msg.obj.name == "thawer-thaw_for_time_s" diff --git a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py index da764f44d..cd9c99703 100644 --- a/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py +++ b/tests/unit_tests/external_interaction/callbacks/rotation/test_ispyb_callback.py @@ -218,9 +218,7 @@ def test_oav_rotation_snapshot_triggered_event( mock_ispyb_conn, dummy_rotation_params, rotation_start_outer_doc_without_snapshots ): callback = RotationISPyBCallback() - callback.activity_gated_start( - rotation_start_outer_doc_without_snapshots - ) # pyright: ignore + callback.activity_gated_start(rotation_start_outer_doc_without_snapshots) # pyright: ignore callback.activity_gated_start( TestData.test_rotation_start_main_document # pyright: ignore ) @@ -301,9 +299,9 @@ def test_comment_correct_after_hardware_read( ): callback = RotationISPyBCallback() test_rotation_start_outer_document["hyperion_parameters"] = ( - test_rotation_start_outer_document["hyperion_parameters"].replace( - '"comment": "test"', '"comment": "a lovely unit test"' - ) + test_rotation_start_outer_document[ + "hyperion_parameters" + ].replace('"comment": "test"', '"comment": "a lovely unit test"') ) callback.activity_gated_start(test_rotation_start_outer_document) # pyright: ignore callback.activity_gated_start( diff --git a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py index 9c1fcdd7f..5328e2c24 100644 --- a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py +++ b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_callback.py @@ -51,9 +51,7 @@ class TestXrayCentreISPyBCallback: def test_activity_gated_start_3d(self, mock_ispyb_conn): callback = GridscanISPyBCallback() - callback.activity_gated_start( - TestData.test_gridscan3d_start_document - ) # pyright: ignore + callback.activity_gated_start(TestData.test_gridscan3d_start_document) # pyright: ignore mx_acq = mx_acquisition_from_conn(mock_ispyb_conn) assert_upsert_call_with( mx_acq.upsert_data_collection_group.mock_calls[0], # pyright: ignore @@ -79,9 +77,7 @@ def test_activity_gated_start_3d(self, mock_ispyb_conn): def test_hardware_read_event_3d(self, mock_ispyb_conn): callback = GridscanISPyBCallback() - callback.activity_gated_start( - TestData.test_gridscan3d_start_document - ) # pyright: ignore + callback.activity_gated_start(TestData.test_gridscan3d_start_document) # pyright: ignore mx_acq = mx_acquisition_from_conn(mock_ispyb_conn) mx_acq.upsert_data_collection_group.reset_mock() mx_acq.upsert_data_collection.reset_mock() @@ -117,9 +113,7 @@ def test_hardware_read_event_3d(self, mock_ispyb_conn): def test_flux_read_events_3d(self, mock_ispyb_conn): callback = GridscanISPyBCallback() - callback.activity_gated_start( - TestData.test_gridscan3d_start_document - ) # pyright: ignore + callback.activity_gated_start(TestData.test_gridscan3d_start_document) # pyright: ignore mx_acq = mx_acquisition_from_conn(mock_ispyb_conn) callback.activity_gated_descriptor( TestData.test_descriptor_document_pre_data_collection @@ -172,9 +166,7 @@ def test_flux_read_events_3d(self, mock_ispyb_conn): def test_activity_gated_event_oav_snapshot_triggered(self, mock_ispyb_conn): callback = GridscanISPyBCallback() - callback.activity_gated_start( - TestData.test_gridscan3d_start_document - ) # pyright: ignore + callback.activity_gated_start(TestData.test_gridscan3d_start_document) # pyright: ignore mx_acq = mx_acquisition_from_conn(mock_ispyb_conn) mx_acq.upsert_data_collection_group.reset_mock() mx_acq.upsert_data_collection.reset_mock() diff --git a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_handler.py b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_handler.py index e8d8713ed..0a90ae894 100644 --- a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_handler.py +++ b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_handler.py @@ -167,9 +167,7 @@ def test_given_fgs_plan_finished_when_zocalo_results_event_then_expected_comment ): ispyb_handler = GridscanISPyBCallback() - ispyb_handler.activity_gated_start( - td.test_gridscan3d_start_document - ) # type:ignore + ispyb_handler.activity_gated_start(td.test_gridscan3d_start_document) # type:ignore ispyb_handler.activity_gated_start(td.test_do_fgs_start_document) # type:ignore ispyb_handler.activity_gated_stop(td.test_do_fgs_gridscan_stop_document) diff --git a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py index 0a273043e..36bc3ebe1 100644 --- a/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py +++ b/tests/unit_tests/external_interaction/callbacks/xray_centre/test_ispyb_mapping.py @@ -28,22 +28,25 @@ def test_ispyb_deposition_rounds_position_to_int( mock_ispyb_conn: MagicMock, dummy_params, ): - assert construct_comment_for_gridscan( - DataCollectionGridInfo( - 0.1, - 0.1, - 40, - 20, - 1.25, - 1.25, - 0.01, # type: ignore - 100, - Orientation.HORIZONTAL, - True, # type: ignore - ), - ) == ( - "Hyperion: Xray centring - Diffraction grid scan of 40 by 20 images " - "in 100.0 um by 100.0 um steps. Top left (px): [0,100], bottom right (px): [3200,1700]." + assert ( + construct_comment_for_gridscan( + DataCollectionGridInfo( + 0.1, + 0.1, + 40, + 20, + 1.25, + 1.25, + 0.01, # type: ignore + 100, + Orientation.HORIZONTAL, + True, # type: ignore + ), + ) + == ( + "Hyperion: Xray centring - Diffraction grid scan of 40 by 20 images " + "in 100.0 um by 100.0 um steps. Top left (px): [0,100], bottom right (px): [3200,1700]." + ) ) diff --git a/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py b/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py index 5f4751482..bd75916d2 100644 --- a/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py +++ b/tests/unit_tests/external_interaction/ispyb/test_rotation_ispyb_store.py @@ -482,9 +482,7 @@ def test_store_rotation_scan_uses_supplied_dcgid( scan_data_info_for_begin, scan_data_info_for_update, ): - mock_ispyb_conn.return_value.mx_acquisition.upsert_data_collection_group.return_value = ( - dcgid - ) + mock_ispyb_conn.return_value.mx_acquisition.upsert_data_collection_group.return_value = dcgid store_in_ispyb = StoreInIspyb(CONST.SIM.ISPYB_CONFIG) scan_data_info_for_begin.data_collection_info.parent_id = dcgid ispyb_ids = store_in_ispyb.begin_deposition(