diff --git a/api/src/opentrons/protocol_runner/run_orchestrator.py b/api/src/opentrons/protocol_runner/run_orchestrator.py index c99e9f09d20..8e03b6c6738 100644 --- a/api/src/opentrons/protocol_runner/run_orchestrator.py +++ b/api/src/opentrons/protocol_runner/run_orchestrator.py @@ -121,22 +121,9 @@ def add_command( return self._json_or_python_runner.set_command_queued(request) # TODO(tz, 2024-5-13): what runner should we return? - def get_protocol_runner(self) -> Optional[Union[protocol_runner.JsonRunner, protocol_runner.PythonAndLegacyRunner]]: - return self._json_or_python_runner + def get_protocol_runner(self) -> protocol_runner.AnyRunner: + return self._json_or_python_runner or self._setup_runner def get_protocol_engine(self) -> ProtocolEngine: return self._protocol_engine - async def load( - self, - protocol_source: ProtocolSource, - python_parse_mode: PythonParseMode, - run_time_param_values: Optional[RunTimeParamValuesType], - ) -> None: - pass - - def prepare( - self, - ) -> None: - pass - diff --git a/robot-server/robot_server/runs/engine_store.py b/robot-server/robot_server/runs/engine_store.py index 2967a29e6d7..78334c27685 100644 --- a/robot-server/robot_server/runs/engine_store.py +++ b/robot-server/robot_server/runs/engine_store.py @@ -255,13 +255,11 @@ async def create( # concurrency hazard. If two requests simultaneously call this method, # they will both "succeed" (with undefined results) instead of one # raising EngineConflictError. - if isinstance( - self._run_orchestrator.get_protocol_runner(), PythonAndLegacyRunner - ): + if isinstance(self.runner, PythonAndLegacyRunner): assert ( protocol is not None ), "A Python protocol should have a protocol source file." - await self._run_orchestrator.load( + await self.runner.load( protocol.source, # Conservatively assume that we're re-running a protocol that # was uploaded before we added stricter validation, and that @@ -269,13 +267,13 @@ async def create( python_parse_mode=PythonParseMode.ALLOW_LEGACY_METADATA_AND_REQUIREMENTS, run_time_param_values=run_time_param_values, ) - elif isinstance(self._run_orchestrator.get_protocol_runner(), JsonRunner): + elif isinstance(self.runner, JsonRunner): assert ( protocol is not None ), "A JSON protocol should have a protocol source file." - await self._run_orchestrator.load(protocol.source) + await self.runner.load(protocol.source) else: - self._run_orchestrator.prepare() + self.runner.prepare() for offset in labware_offsets: engine.add_labware_offset(offset) @@ -295,8 +293,8 @@ async def clear(self) -> RunResult: EngineConflictError: The current runner/engine pair is not idle, so they cannot be cleared. """ - engine = self._run_orchestrator.get_protocol_engine() - runner = self._run_orchestrator.get_protocol_runner() + engine = self.engine + runner = self.runner if engine.state_view.commands.get_is_okay_to_clear(): await engine.finish( drop_tips_after_run=False, diff --git a/robot-server/tests/runs/test_engine_store.py b/robot-server/tests/runs/test_engine_store.py index 330e974be9c..97631f27380 100644 --- a/robot-server/tests/runs/test_engine_store.py +++ b/robot-server/tests/runs/test_engine_store.py @@ -11,11 +11,7 @@ from opentrons.hardware_control import HardwareControlAPI, API from opentrons.hardware_control.types import EstopStateNotification, EstopState from opentrons.protocol_engine import ProtocolEngine, StateSummary, types as pe_types -from opentrons.protocol_runner import ( - RunResult, - LiveRunner, - JsonRunner, -) +from opentrons.protocol_runner import RunResult, LiveRunner, JsonRunner, RunOrchestrator from opentrons.protocol_reader import ProtocolReader, ProtocolSource from robot_server.protocols.protocol_store import ProtocolResource @@ -25,6 +21,7 @@ NoRunnerEnginePairError, handle_estop_event, ) +from robot_server.runs.run_models import Run def mock_notify_publishers() -> None: @@ -32,6 +29,12 @@ def mock_notify_publishers() -> None: return None +@pytest.fixture +async def mock_run_orchestrator(decoy: Decoy) -> RunOrchestrator: + """A mock RunOrchestrator""" + return decoy.mock(cls=RunOrchestrator) + + @pytest.fixture async def subject(decoy: Decoy, hardware_api: HardwareControlAPI) -> EngineStore: """Get a EngineStore test subject.""" @@ -53,7 +56,9 @@ async def json_protocol_source() -> ProtocolSource: return await ProtocolReader().read_saved(files=[simple_protocol], directory=None) -async def test_create_engine(subject: EngineStore) -> None: +async def test_create_engine( + decoy: Decoy, subject: EngineStore, mock_run_orchestrator: RunOrchestrator +) -> None: """It should create an engine for a run.""" result = await subject.create( run_id="run-id",