Skip to content

Commit

Permalink
fix(api): inherit protocol api errors from enumerated errors (#15516)
Browse files Browse the repository at this point in the history
<!--
Thanks for taking the time to open a pull request! Please make sure
you've read the "Opening Pull Requests" section of our Contributing
Guide:


https://github.com/Opentrons/opentrons/blob/edge/CONTRIBUTING.md#opening-pull-requests

To ensure your code is reviewed quickly and thoroughly, please fill out
the sections below to the best of your ability!
-->

# Overview

<!--
Use this section to describe your pull-request at a high level. If the
PR addresses any open issues, please tag the issues here.
-->

This PR changes Protocol API APIVersionError to inherit from enumerated
error IncorrectAPIVersion and Protocol API UnsupportedAPIError to
inherit from enumerated error APIRemoved.

# Test Plan

<!--
Use this section to describe the steps that you took to test your Pull
Request.
If you did not perform any testing provide justification why.

OT-3 Developers: You should default to testing on actual physical
hardware.
Once again, if you did not perform testing against hardware, justify
why.

Note: It can be helpful to write a test plan before doing development

Example Test Plan (HTTP API Change)

- Verified that new optional argument `dance-party` causes the robot to
flash its lights, move the pipettes,
then home.
- Verified that when you omit the `dance-party` option the robot homes
normally
- Added protocol that uses `dance-party` argument to G-Code Testing
Suite
- Ran protocol that did not use `dance-party` argument and everything
was successful
- Added unit tests to validate that changes to pydantic model are
correct

-->

# Changelog

<!--
List out the changes to the code in this PR. Please try your best to
categorize your changes and describe what has changed and why.

Example changelog:
- Fixed app crash when trying to calibrate an illegal pipette
- Added state to API to track pipette usage
- Updated API docs to mention only two pipettes are supported

IMPORTANT: MAKE SURE ANY BREAKING CHANGES ARE PROPERLY COMMUNICATED
-->

# Review requests

<!--
Describe any requests for your reviewers here.
-->

# Risk assessment

<!--
Carefully go over your pull request and look at the other parts of the
codebase it may affect. Look for the possibility, even if you think it's
small, that your change may affect some other part of the system - for
instance, changing return tip behavior in protocol may also change the
behavior of labware calibration.

Identify the other parts of the system your codebase may affect, so that
in addition to your own review and testing, other people who may not
have the system internalized as much as you can focus their attention
and testing there.
-->
  • Loading branch information
pmoegenburg authored Jul 9, 2024
1 parent c40d293 commit 0e005dd
Show file tree
Hide file tree
Showing 22 changed files with 270 additions and 146 deletions.
6 changes: 3 additions & 3 deletions api/src/opentrons/protocol_api/core/engine/well.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from opentrons.protocol_engine import WellLocation, WellOrigin, WellOffset
from opentrons.protocol_engine import commands as cmd
from opentrons.protocol_engine.clients import SyncClient as EngineClient
from opentrons.protocols.api_support.util import APIVersionError
from opentrons.protocols.api_support.util import UnsupportedAPIError
from opentrons.types import Point

from . import point_calculations
Expand Down Expand Up @@ -69,8 +69,8 @@ def has_tip(self) -> bool:

def set_has_tip(self, value: bool) -> None:
"""Set the well as containing or not containing a tip."""
raise APIVersionError(
"Manually setting the tip state of a well in a tip rack has been deprecated."
raise UnsupportedAPIError(
api_element="Manually setting the tip state of a well in a tip rack",
)

def get_display_name(self) -> str:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ def dispense(
"""
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Dispense in Moveable Trash or Waste Chute are not supported in this API Version."
api_element="Dispense in Moveable Trash or Waste Chute"
)
if push_out:
raise APIVersionError("push_out is not supported in this API version.")
raise APIVersionError(api_element="push_out")
if not in_place:
self.move_to(location=location)

Expand All @@ -159,7 +159,7 @@ def blow_out(
"""
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Blow Out in Moveable Trash or Waste Chute are not supported in this API Version."
api_element="Blow Out in Moveable Trash or Waste Chute"
)

if not in_place:
Expand Down Expand Up @@ -249,9 +249,7 @@ def drop_tip(
home_after: Whether to home the pipette after the tip is dropped.
"""
if alternate_drop_location:
raise APIVersionError(
"Tip drop randomization is not supported in this API version."
)
raise APIVersionError(api_element="Tip drop randomization")
labware_core = well_core.geometry.parent

if location is None:
Expand Down Expand Up @@ -302,9 +300,7 @@ def drop_tip_in_disposal_location(
home_after: Optional[bool],
alternate_tip_drop: bool = False,
) -> None:
raise APIVersionError(
"Dropping tips in a trash bin or waste chute is not supported in this API Version."
)
raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute")

def home(self) -> None:
"""Home the mount"""
Expand Down Expand Up @@ -342,9 +338,7 @@ def move_to(
the computed safe travel height.
"""
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Move To Trash Bin and Waste Chute are not supported in this API Version."
)
raise APIVersionError(api_element="Move To Trash Bin and Waste Chute")
self.flag_unsafe_move(location)

# prevent direct movement bugs in PAPI version >= 2.10
Expand Down
25 changes: 12 additions & 13 deletions api/src/opentrons/protocol_api/core/legacy/legacy_protocol_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def append_disposal_location(
) -> None:
if isinstance(disposal_location, (TrashBin, WasteChute)):
raise APIVersionError(
"Trash Bin and Waste Chute Disposal locations are not supported in this API Version."
api_element="Trash Bin and Waste Chute Disposal locations"
)
self._disposal_locations.append(disposal_location)

Expand Down Expand Up @@ -174,14 +174,17 @@ def load_labware(
"""Load a labware using its identifying parameters."""
if isinstance(location, OffDeckType):
raise APIVersionError(
"Loading a labware off deck is only supported with apiLevel 2.15 and newer."
api_element="Loading a labware off deck", until_version="2.15"
)
elif isinstance(location, LegacyLabwareCore):
raise APIVersionError(
"Loading a labware onto another labware or adapter is only supported with api version 2.15 and above"
api_element="Loading a labware onto another labware or adapter",
until_version="2.15",
)
elif isinstance(location, StagingSlotName):
raise APIVersionError("Using a staging deck slot requires apiLevel 2.16.")
raise APIVersionError(
api_element="Using a staging deck slot", until_version="2.16"
)

deck_slot = (
location if isinstance(location, DeckSlotName) else location.get_deck_slot()
Expand Down Expand Up @@ -262,7 +265,7 @@ def load_adapter(
version: Optional[int],
) -> LegacyLabwareCore:
"""Load an adapter using its identifying parameters"""
raise APIVersionError("Loading adapter is not supported in this API version.")
raise APIVersionError(api_element="Loading adapter")

# TODO (spp, 2022-12-14): https://opentrons.atlassian.net/browse/RLAB-237
def move_labware(
Expand All @@ -282,7 +285,7 @@ def move_labware(
drop_offset: Optional[Tuple[float, float, float]],
) -> None:
"""Move labware to new location."""
raise APIVersionError("Labware movement is not supported in this API version")
raise APIVersionError(api_element="Labware movement")

def load_module(
self,
Expand Down Expand Up @@ -383,19 +386,15 @@ def load_instrument(
return new_instr

def load_trash_bin(self, slot_name: DeckSlotName, area_name: str) -> TrashBin:
raise APIVersionError(
"Loading deck configured trash bin is not supported in this API version."
)
raise APIVersionError(api_element="Loading deck configured trash bin")

def load_ot2_fixed_trash_bin(self) -> None:
raise APIVersionError(
"Loading deck configured OT-2 fixed trash bin is not supported in this API version."
api_element="Loading deck configured OT-2 fixed trash bin"
)

def load_waste_chute(self) -> WasteChute:
raise APIVersionError(
"Loading waste chute is not supported in this API version."
)
raise APIVersionError(api_element="Loading waste chute")

def get_loaded_instruments(
self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def load_liquid(
volume: float,
) -> None:
"""Load liquid into a well."""
raise APIVersionError("Loading a liquid is not supported in this API version.")
raise APIVersionError(api_element="Loading a liquid")

def from_center_cartesian(self, x: float, y: float, z: float) -> Point:
"""Gets point in deck coordinates based on percentage of the radius of each axis."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def dispense(
) -> None:
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Dispense in Moveable Trash or Waste Chute are not supported in this API Version."
api_element="Dispense in Moveable Trash or Waste Chute"
)
if not in_place:
self.move_to(location=location, well_core=well_core)
Expand All @@ -150,7 +150,7 @@ def blow_out(
) -> None:
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Blow Out in Moveable Trash or Waste Chute are not supported in this API Version."
api_element="Blow Out in Moveable Trash or Waste Chute"
)
if not in_place:
self.move_to(location=location, well_core=well_core)
Expand Down Expand Up @@ -215,9 +215,7 @@ def drop_tip(
alternate_drop_location: Optional[bool] = False,
) -> None:
if alternate_drop_location:
raise APIVersionError(
"Tip drop alternation is not supported in this API version."
)
raise APIVersionError(api_element="Tip drop alternation")
labware_core = well_core.geometry.parent

if location is None:
Expand Down Expand Up @@ -270,9 +268,7 @@ def drop_tip_in_disposal_location(
home_after: Optional[bool],
alternate_tip_drop: bool = False,
) -> None:
raise APIVersionError(
"Dropping tips in a trash bin or waste chute is not supported in this API Version."
)
raise APIVersionError(api_element="Dropping tips in a trash bin or waste chute")

def home(self) -> None:
self._protocol_interface.set_last_location(None)
Expand All @@ -290,9 +286,7 @@ def move_to(
) -> None:
"""Simulation of only the motion planning portion of move_to."""
if isinstance(location, (TrashBin, WasteChute)):
raise APIVersionError(
"Move To Trash Bin and Waste Chute are not supported in this API Version."
)
raise APIVersionError(api_element="Move To Trash Bin and Waste Chute")

self.flag_unsafe_move(location)

Expand Down
5 changes: 3 additions & 2 deletions api/src/opentrons/protocol_api/deck.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ def __delitem__(self, key: DeckLocation) -> None:
# * PAPIv2.14 (Protocol Engine): No
# * PAPIv2.15 (Protocol Engine): Yes
raise APIVersionError(
f"Deleting deck elements is not supported with apiLevel {self._api_version}."
f" Try increasing your apiLevel to {APIVersion(2, 15)}."
api_element="Deleting deck elements",
until_version="2.15",
current_version=f"{self._api_version}",
)

slot_name = _get_slot_name(
Expand Down
34 changes: 19 additions & 15 deletions api/src/opentrons/protocol_api/instrument_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
clamp_value,
requires_version,
APIVersionError,
UnsupportedAPIError,
)
from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType

Expand Down Expand Up @@ -370,7 +371,9 @@ def dispense( # noqa: C901
"""
if self.api_version < APIVersion(2, 15) and push_out:
raise APIVersionError(
"Unsupported parameter push_out. Change your API version to 2.15 or above to use this parameter."
api_element="Parameter push_out",
until_version="2.15",
current_version=f"{self.api_version}",
)
_log.debug(
"dispense {} from {} at {}".format(
Expand Down Expand Up @@ -889,21 +892,24 @@ def pick_up_tip( # noqa: C901
"""

if presses is not None and self._api_version >= _PRESSES_INCREMENT_REMOVED_IN:
raise APIVersionError(
f"presses is only available in API versions lower than {_PRESSES_INCREMENT_REMOVED_IN},"
f" but you are using API {self._api_version}."
raise UnsupportedAPIError(
api_element="presses",
since_version=f"{_PRESSES_INCREMENT_REMOVED_IN}",
current_version=f"{self._api_version}",
)

if increment is not None and self._api_version >= _PRESSES_INCREMENT_REMOVED_IN:
raise APIVersionError(
f"increment is only available in API versions lower than {_PRESSES_INCREMENT_REMOVED_IN},"
f" but you are using API {self._api_version}."
raise UnsupportedAPIError(
api_element="increment",
since_version=f"{_PRESSES_INCREMENT_REMOVED_IN}",
current_version=f"{self._api_version}",
)

if prep_after is not None and self._api_version < _PREP_AFTER_ADDED_IN:
raise APIVersionError(
f"prep_after is only available in API {_PREP_AFTER_ADDED_IN} and newer,"
f" but you are using API {self._api_version}."
api_element="prep_after",
until_version=f"{_PREP_AFTER_ADDED_IN}",
current_version=f"{self._api_version}",
)

well: labware.Well
Expand Down Expand Up @@ -1495,9 +1501,8 @@ def delay(self, *args: Any, **kwargs: Any) -> None:
# would get a TypeError if they tried to call it like delay(minutes=10).
# Without changing the ultimate behavior that such a call fails the
# protocol, we can provide a more descriptive message as a courtesy.
raise APIVersionError(
"InstrumentContext.delay() is not supported in Python Protocol API v2."
" Use ProtocolContext.delay() instead."
raise UnsupportedAPIError(
message="InstrumentContext.delay() is not supported in Python Protocol API v2. Use ProtocolContext.delay() instead."
)
else:
# Former implementations of this method, when called without any args,
Expand Down Expand Up @@ -1617,9 +1622,8 @@ def speed(self) -> "PlungerSpeeds":
:py:attr:`.flow_rate` instead.
"""
if self._api_version >= ENGINE_CORE_API_VERSION:
raise APIVersionError(
"InstrumentContext.speed has been removed."
" Use InstrumentContext.flow_rate, instead."
raise UnsupportedAPIError(
message="InstrumentContext.speed has been removed. Use InstrumentContext.flow_rate, instead."
)

# TODO(mc, 2023-02-13): this assert should be enough for mypy
Expand Down
Loading

0 comments on commit 0e005dd

Please sign in to comment.