From 6e94b907c342f9854d33b209c875e9411b58a068 Mon Sep 17 00:00:00 2001 From: tamarzanzouri Date: Fri, 2 Aug 2024 11:04:43 -0400 Subject: [PATCH] restructure --- api/src/opentrons/protocol_engine/__init__.py | 3 +- .../protocol_engine/state/__init__.py | 2 ++ .../protocol_engine/state/commands.py | 8 +++++ .../runs/router/commands_router.py | 13 +++++++-- .../robot_server/runs/run_data_manager.py | 3 +- .../runs/run_orchestrator_store.py | 3 +- .../tests/runs/router/test_commands_router.py | 29 ++++++++++--------- .../tests/runs/test_run_data_manager.py | 9 ++++-- 8 files changed, 49 insertions(+), 21 deletions(-) diff --git a/api/src/opentrons/protocol_engine/__init__.py b/api/src/opentrons/protocol_engine/__init__.py index 22d04749c75..f7c204aa1cb 100644 --- a/api/src/opentrons/protocol_engine/__init__.py +++ b/api/src/opentrons/protocol_engine/__init__.py @@ -18,7 +18,7 @@ CommandType, CommandIntent, ) -from .state import State, StateView, StateSummary, CommandSlice, CommandPointer, Config +from .state import State, StateView, StateSummary, CommandSlice, CommandPointer, Config, CommandErrorSlice from .plugins import AbstractPlugin from .types import ( @@ -81,6 +81,7 @@ "State", "StateView", "CommandSlice", + "CommandErrorSlice", "CommandPointer", # public value interfaces and models "LabwareOffset", diff --git a/api/src/opentrons/protocol_engine/state/__init__.py b/api/src/opentrons/protocol_engine/state/__init__.py index 80a88350263..f9705905967 100644 --- a/api/src/opentrons/protocol_engine/state/__init__.py +++ b/api/src/opentrons/protocol_engine/state/__init__.py @@ -7,6 +7,7 @@ CommandState, CommandView, CommandSlice, + CommandErrorSlice, CommandPointer, ) from .command_history import CommandEntry @@ -39,6 +40,7 @@ "CommandState", "CommandView", "CommandSlice", + "CommandErrorSlice", "CommandPointer", "CommandEntry", # labware state and values diff --git a/api/src/opentrons/protocol_engine/state/commands.py b/api/src/opentrons/protocol_engine/state/commands.py index 1ad17867450..129a374736a 100644 --- a/api/src/opentrons/protocol_engine/state/commands.py +++ b/api/src/opentrons/protocol_engine/state/commands.py @@ -116,6 +116,14 @@ class CommandSlice: cursor: int total_length: int +@dataclass(frozen=True) +class CommandErrorSlice: + """A subset of all commands errors in state.""" + + commands_errors: List[ErrorOccurrence] + cursor: int + total_length: int + @dataclass(frozen=True) class CommandPointer: diff --git a/robot-server/robot_server/runs/router/commands_router.py b/robot-server/robot_server/runs/router/commands_router.py index a101d3c97fe..7559d17a33d 100644 --- a/robot-server/robot_server/runs/router/commands_router.py +++ b/robot-server/robot_server/runs/router/commands_router.py @@ -454,7 +454,7 @@ async def get_run_commands_error( description="The maximum number of command errors in the list to return.", ), run_data_manager: RunDataManager = Depends(get_run_data_manager), -) -> PydanticResponse[SimpleBody[ResponseList[pe_errors.ErrorOccurrence]]]: +) -> PydanticResponse[SimpleMultiBody[ResponseList[pe_errors.ErrorOccurrence]]]: """Get a summary of a set of command errors in a run. Arguments: @@ -472,9 +472,16 @@ async def get_run_commands_error( except RunNotCurrentError as e: raise RunStopped(detail=str(e)).as_error(status.HTTP_409_CONFLICT) from e - commands_errors_result = ResponseList.construct(__root__=command_error_slice) + meta = MultiBodyMeta( + cursor=command_error_slice.cursor, + totalLength=command_error_slice.total_length, + ) + + commands_errors_result = ResponseList.construct( + __root__=command_error_slice.commands_errors + ) return await PydanticResponse.create( - content=SimpleBody.construct(data=commands_errors_result), + content=SimpleMultiBody.construct(data=commands_errors_result, meta=meta), status_code=status.HTTP_200_OK, ) diff --git a/robot-server/robot_server/runs/run_data_manager.py b/robot-server/robot_server/runs/run_data_manager.py index f962e66b269..b66b5912be8 100644 --- a/robot-server/robot_server/runs/run_data_manager.py +++ b/robot-server/robot_server/runs/run_data_manager.py @@ -9,6 +9,7 @@ LabwareOffsetCreate, StateSummary, CommandSlice, + CommandErrorSlice, CommandPointer, Command, ) @@ -383,7 +384,7 @@ def get_commands_slice( def get_command_error_slice( self, run_id: str, cursor: Optional[int], length: int - ) -> List[ErrorOccurrence]: + ) -> CommandErrorSlice: """Get a slice of run commands. Args: diff --git a/robot-server/robot_server/runs/run_orchestrator_store.py b/robot-server/robot_server/runs/run_orchestrator_store.py index 3c9bd413d65..4410ef6cc8a 100644 --- a/robot-server/robot_server/runs/run_orchestrator_store.py +++ b/robot-server/robot_server/runs/run_orchestrator_store.py @@ -29,6 +29,7 @@ LabwareOffsetCreate, StateSummary, CommandSlice, + CommandErrorSlice, CommandPointer, Command, CommandCreate, @@ -339,7 +340,7 @@ def get_command_error_slice( self, cursor: Optional[int], length: int, - ) -> List[ErrorOccurrence]: + ) -> CommandErrorSlice: """Get a slice of run commands error. Args: diff --git a/robot-server/tests/runs/router/test_commands_router.py b/robot-server/tests/runs/router/test_commands_router.py index 01f35aaa80d..96765a5d884 100644 --- a/robot-server/tests/runs/router/test_commands_router.py +++ b/robot-server/tests/runs/router/test_commands_router.py @@ -6,6 +6,7 @@ from opentrons.protocol_engine import ( CommandSlice, + CommandErrorSlice, CommandPointer, CommandNote, commands as pe_commands, @@ -13,7 +14,7 @@ ) from robot_server.errors.error_responses import ApiError -from robot_server.service.json_api import MultiBodyMeta, ResponseList +from robot_server.service.json_api import MultiBodyMeta, SimpleMultiBody from robot_server.runs.command_models import ( RequestModelWithCommandCreate, @@ -456,13 +457,17 @@ async def test_get_run_commands_errors( ), ) + command_error_slice = CommandErrorSlice( + cursor=1, total_length=3, commands_errors=[error] + ) + decoy.when( mock_run_data_manager.get_command_error_slice( run_id="run-id", cursor=None, length=42, ) - ).then_return([error]) + ).then_return(command_error_slice) result = await get_run_commands_error( runId="run-id", @@ -471,17 +476,15 @@ async def test_get_run_commands_errors( pageLength=42, ) - assert result.content.data == ResponseList.construct( - __root__=[ - pe_errors.ErrorOccurrence( - id="error-id", - errorType="PrettyBadError", - createdAt=datetime(year=2024, month=4, day=4), - detail="Things are not looking good.", - ) - ] - ) - # assert result.content.meta == MultiBodyMeta(cursor=1, totalLength=3) + assert result.content.data == [ + pe_errors.ErrorOccurrence( + id="error-id", + errorType="PrettyBadError", + createdAt=datetime(year=2024, month=4, day=4), + detail="Things are not looking good.", + ) + ] + assert result.content.meta == MultiBodyMeta(cursor=1, totalLength=3) assert result.status_code == 200 diff --git a/robot-server/tests/runs/test_run_data_manager.py b/robot-server/tests/runs/test_run_data_manager.py index e8d1bf799dd..3e8fbc06e28 100644 --- a/robot-server/tests/runs/test_run_data_manager.py +++ b/robot-server/tests/runs/test_run_data_manager.py @@ -10,6 +10,7 @@ commands, types as pe_types, CommandSlice, + CommandErrorSlice, CommandPointer, ErrorOccurrence, LoadedLabware, @@ -869,14 +870,18 @@ def test_get_commands_errors_slice_current_run( ErrorOccurrence.construct(id="error-id") # type: ignore[call-arg] ] + command_error_slice = CommandErrorSlice( + cursor=1, total_length=3, commands_errors=expected_commands_errors_result + ) + decoy.when(mock_run_orchestrator_store.current_run_id).then_return("run-id") decoy.when(mock_run_orchestrator_store.get_command_error_slice(1, 2)).then_return( - expected_commands_errors_result + command_error_slice ) result = subject.get_command_error_slice("run-id", 1, 2) - assert expected_commands_errors_result == result + assert command_error_slice == result def test_get_commands_slice_from_db_run_not_found(