opentrons 8.3.0a2__py2.py3-none-any.whl → 8.3.0a5__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. opentrons/hardware_control/api.py +5 -1
  2. opentrons/hardware_control/ot3api.py +18 -8
  3. opentrons/hardware_control/protocols/liquid_handler.py +4 -1
  4. opentrons/hardware_control/protocols/motion_controller.py +1 -0
  5. opentrons/legacy_commands/commands.py +37 -0
  6. opentrons/legacy_commands/types.py +39 -0
  7. opentrons/protocol_api/core/engine/instrument.py +109 -0
  8. opentrons/protocol_api/core/instrument.py +27 -0
  9. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +50 -0
  10. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +24 -0
  11. opentrons/protocol_api/instrument_context.py +141 -0
  12. opentrons/protocol_api/labware.py +17 -2
  13. opentrons/protocol_engine/commands/__init__.py +40 -0
  14. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +1 -1
  15. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +1 -1
  16. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +1 -1
  17. opentrons/protocol_engine/commands/absorbance_reader/read.py +4 -1
  18. opentrons/protocol_engine/commands/air_gap_in_place.py +1 -1
  19. opentrons/protocol_engine/commands/command_unions.py +39 -0
  20. opentrons/protocol_engine/commands/evotip_dispense.py +156 -0
  21. opentrons/protocol_engine/commands/evotip_seal_pipette.py +331 -0
  22. opentrons/protocol_engine/commands/evotip_unseal_pipette.py +160 -0
  23. opentrons/protocol_engine/commands/get_next_tip.py +1 -1
  24. opentrons/protocol_engine/commands/liquid_probe.py +63 -12
  25. opentrons/protocol_engine/commands/load_labware.py +5 -0
  26. opentrons/protocol_engine/commands/load_lid.py +1 -1
  27. opentrons/protocol_engine/commands/load_lid_stack.py +1 -1
  28. opentrons/protocol_engine/commands/load_liquid_class.py +1 -1
  29. opentrons/protocol_engine/commands/move_labware.py +9 -0
  30. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +1 -1
  31. opentrons/protocol_engine/commands/robot/move_axes_relative.py +1 -1
  32. opentrons/protocol_engine/commands/robot/move_axes_to.py +1 -1
  33. opentrons/protocol_engine/commands/robot/move_to.py +1 -1
  34. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +1 -1
  35. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +1 -1
  36. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +1 -1
  37. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +1 -1
  38. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -1
  39. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +1 -1
  40. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +1 -1
  41. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -1
  42. opentrons/protocol_engine/errors/__init__.py +4 -0
  43. opentrons/protocol_engine/errors/exceptions.py +26 -0
  44. opentrons/protocol_engine/execution/gantry_mover.py +5 -0
  45. opentrons/protocol_engine/execution/hardware_stopper.py +7 -7
  46. opentrons/protocol_engine/execution/tip_handler.py +30 -9
  47. opentrons/protocol_engine/resources/labware_validation.py +13 -0
  48. opentrons/protocol_engine/state/commands.py +6 -2
  49. opentrons/protocol_engine/state/frustum_helpers.py +13 -44
  50. opentrons/protocol_engine/state/labware.py +13 -1
  51. opentrons/protocol_engine/state/pipettes.py +5 -0
  52. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/METADATA +4 -4
  53. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/RECORD +57 -54
  54. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/LICENSE +0 -0
  55. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/WHEEL +0 -0
  56. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/entry_points.txt +0 -0
  57. {opentrons-8.3.0a2.dist-info → opentrons-8.3.0a5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,160 @@
1
+ """Unseal evotip resin tip command request, result, and implementation models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import Field
6
+ from typing import TYPE_CHECKING, Optional, Type
7
+ from typing_extensions import Literal
8
+
9
+ from opentrons.protocol_engine.resources.model_utils import ModelUtils
10
+ from opentrons.protocol_engine.errors import UnsupportedLabwareForActionError
11
+ from opentrons.protocol_engine.types import MotorAxis
12
+ from opentrons.types import MountType
13
+
14
+ from ..types import DropTipWellLocation
15
+ from .pipetting_common import (
16
+ PipetteIdMixin,
17
+ )
18
+ from .movement_common import (
19
+ DestinationPositionResult,
20
+ move_to_well,
21
+ StallOrCollisionError,
22
+ )
23
+ from .command import (
24
+ AbstractCommandImpl,
25
+ BaseCommand,
26
+ BaseCommandCreate,
27
+ DefinedErrorData,
28
+ SuccessData,
29
+ )
30
+ from ..resources import labware_validation
31
+
32
+ if TYPE_CHECKING:
33
+ from ..state.state import StateView
34
+ from ..execution import MovementHandler, TipHandler, GantryMover
35
+
36
+
37
+ EvotipUnsealPipetteCommandType = Literal["evotipUnsealPipette"]
38
+
39
+
40
+ class EvotipUnsealPipetteParams(PipetteIdMixin):
41
+ """Payload required to drop a tip in a specific well."""
42
+
43
+ labwareId: str = Field(..., description="Identifier of labware to use.")
44
+ wellName: str = Field(..., description="Name of well to use in labware.")
45
+ wellLocation: DropTipWellLocation = Field(
46
+ default_factory=DropTipWellLocation,
47
+ description="Relative well location at which to drop the tip.",
48
+ )
49
+
50
+
51
+ class EvotipUnsealPipetteResult(DestinationPositionResult):
52
+ """Result data from the execution of a DropTip command."""
53
+
54
+ pass
55
+
56
+
57
+ _ExecuteReturn = (
58
+ SuccessData[EvotipUnsealPipetteResult] | DefinedErrorData[StallOrCollisionError]
59
+ )
60
+
61
+
62
+ class EvotipUnsealPipetteImplementation(
63
+ AbstractCommandImpl[EvotipUnsealPipetteParams, _ExecuteReturn]
64
+ ):
65
+ """Drop tip command implementation."""
66
+
67
+ def __init__(
68
+ self,
69
+ state_view: StateView,
70
+ tip_handler: TipHandler,
71
+ movement: MovementHandler,
72
+ model_utils: ModelUtils,
73
+ gantry_mover: GantryMover,
74
+ **kwargs: object,
75
+ ) -> None:
76
+ self._state_view = state_view
77
+ self._tip_handler = tip_handler
78
+ self._movement_handler = movement
79
+ self._model_utils = model_utils
80
+ self._gantry_mover = gantry_mover
81
+
82
+ async def execute(self, params: EvotipUnsealPipetteParams) -> _ExecuteReturn:
83
+ """Move to and drop a tip using the requested pipette."""
84
+ pipette_id = params.pipetteId
85
+ labware_id = params.labwareId
86
+ well_name = params.wellName
87
+
88
+ well_location = params.wellLocation
89
+ labware_definition = self._state_view.labware.get_definition(params.labwareId)
90
+ if not labware_validation.is_evotips(labware_definition.parameters.loadName):
91
+ raise UnsupportedLabwareForActionError(
92
+ f"Cannot use command: `EvotipUnsealPipette` with labware: {labware_definition.parameters.loadName}"
93
+ )
94
+ is_partially_configured = self._state_view.pipettes.get_is_partially_configured(
95
+ pipette_id=pipette_id
96
+ )
97
+ tip_drop_location = self._state_view.geometry.get_checked_tip_drop_location(
98
+ pipette_id=pipette_id,
99
+ labware_id=labware_id,
100
+ well_location=well_location,
101
+ partially_configured=is_partially_configured,
102
+ )
103
+
104
+ move_result = await move_to_well(
105
+ movement=self._movement_handler,
106
+ model_utils=self._model_utils,
107
+ pipette_id=pipette_id,
108
+ labware_id=labware_id,
109
+ well_name=well_name,
110
+ well_location=tip_drop_location,
111
+ )
112
+ if isinstance(move_result, DefinedErrorData):
113
+ return move_result
114
+
115
+ # Move to an appropriate position
116
+ mount = self._state_view.pipettes.get_mount(pipette_id)
117
+
118
+ mount_axis = MotorAxis.LEFT_Z if mount == MountType.LEFT else MotorAxis.RIGHT_Z
119
+ await self._gantry_mover.move_axes(
120
+ axis_map={mount_axis: -14}, speed=10, relative_move=True
121
+ )
122
+
123
+ await self._tip_handler.drop_tip(
124
+ pipette_id=pipette_id,
125
+ home_after=None,
126
+ do_not_ignore_tip_presence=False,
127
+ ignore_plunger=True,
128
+ )
129
+
130
+ return SuccessData(
131
+ public=EvotipUnsealPipetteResult(position=move_result.public.position),
132
+ state_update=move_result.state_update.set_fluid_unknown(
133
+ pipette_id=pipette_id
134
+ ).update_pipette_tip_state(pipette_id=params.pipetteId, tip_geometry=None),
135
+ )
136
+
137
+
138
+ class EvotipUnsealPipette(
139
+ BaseCommand[
140
+ EvotipUnsealPipetteParams, EvotipUnsealPipetteResult, StallOrCollisionError
141
+ ]
142
+ ):
143
+ """Evotip unseal command model."""
144
+
145
+ commandType: EvotipUnsealPipetteCommandType = "evotipUnsealPipette"
146
+ params: EvotipUnsealPipetteParams
147
+ result: Optional[EvotipUnsealPipetteResult] = None
148
+
149
+ _ImplementationCls: Type[
150
+ EvotipUnsealPipetteImplementation
151
+ ] = EvotipUnsealPipetteImplementation
152
+
153
+
154
+ class EvotipUnsealPipetteCreate(BaseCommandCreate[EvotipUnsealPipetteParams]):
155
+ """Evotip unseal command creation request model."""
156
+
157
+ commandType: EvotipUnsealPipetteCommandType = "evotipUnsealPipette"
158
+ params: EvotipUnsealPipetteParams
159
+
160
+ _CommandCls: Type[EvotipUnsealPipette] = EvotipUnsealPipette
@@ -120,7 +120,7 @@ class GetNextTip(BaseCommand[GetNextTipParams, GetNextTipResult, ErrorOccurrence
120
120
 
121
121
  commandType: GetNextTipCommandType = "getNextTip"
122
122
  params: GetNextTipParams
123
- result: Optional[GetNextTipResult]
123
+ result: Optional[GetNextTipResult] = None
124
124
 
125
125
  _ImplementationCls: Type[GetNextTipImplementation] = GetNextTipImplementation
126
126
 
@@ -19,12 +19,14 @@ from opentrons.types import MountType
19
19
  from opentrons_shared_data.errors.exceptions import (
20
20
  PipetteLiquidNotFoundError,
21
21
  UnsupportedHardwareCommand,
22
+ PipetteOverpressureError,
22
23
  )
23
24
 
24
25
  from ..types import DeckPoint
25
26
  from .pipetting_common import (
26
27
  LiquidNotFoundError,
27
28
  PipetteIdMixin,
29
+ OverpressureError,
28
30
  )
29
31
  from .movement_common import (
30
32
  WellLocationMixin,
@@ -43,7 +45,7 @@ from .command import (
43
45
  from ..errors.error_occurrence import ErrorOccurrence
44
46
 
45
47
  if TYPE_CHECKING:
46
- from ..execution import MovementHandler, PipettingHandler
48
+ from ..execution import MovementHandler, PipettingHandler, GantryMover
47
49
  from ..resources import ModelUtils
48
50
  from ..state.state import StateView
49
51
 
@@ -99,10 +101,14 @@ class TryLiquidProbeResult(DestinationPositionResult):
99
101
 
100
102
  _LiquidProbeExecuteReturn = Union[
101
103
  SuccessData[LiquidProbeResult],
102
- DefinedErrorData[LiquidNotFoundError] | DefinedErrorData[StallOrCollisionError],
104
+ DefinedErrorData[LiquidNotFoundError]
105
+ | DefinedErrorData[StallOrCollisionError]
106
+ | DefinedErrorData[OverpressureError],
103
107
  ]
104
108
  _TryLiquidProbeExecuteReturn = (
105
- SuccessData[TryLiquidProbeResult] | DefinedErrorData[StallOrCollisionError]
109
+ SuccessData[TryLiquidProbeResult]
110
+ | DefinedErrorData[StallOrCollisionError]
111
+ | DefinedErrorData[OverpressureError]
106
112
  )
107
113
 
108
114
 
@@ -110,19 +116,22 @@ class _ExecuteCommonResult(NamedTuple):
110
116
  # If the probe succeeded, the z_pos that it returned.
111
117
  # Or, if the probe found no liquid, the error representing that,
112
118
  # so calling code can propagate those details up.
113
- z_pos_or_error: float | PipetteLiquidNotFoundError
119
+ z_pos_or_error: float | PipetteLiquidNotFoundError | PipetteOverpressureError
114
120
 
115
121
  state_update: update_types.StateUpdate
116
122
  deck_point: DeckPoint
117
123
 
118
124
 
119
- async def _execute_common(
125
+ async def _execute_common( # noqa: C901
120
126
  state_view: StateView,
121
127
  movement: MovementHandler,
128
+ gantry_mover: GantryMover,
122
129
  pipetting: PipettingHandler,
123
130
  model_utils: ModelUtils,
124
131
  params: _CommonParams,
125
- ) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError]:
132
+ ) -> _ExecuteCommonResult | DefinedErrorData[StallOrCollisionError] | DefinedErrorData[
133
+ OverpressureError
134
+ ]:
126
135
  pipette_id = params.pipetteId
127
136
  labware_id = params.labwareId
128
137
  well_name = params.wellName
@@ -173,6 +182,7 @@ async def _execute_common(
173
182
  if isinstance(move_result, DefinedErrorData):
174
183
  return move_result
175
184
  try:
185
+ current_position = await gantry_mover.get_position(params.pipetteId)
176
186
  z_pos = await pipetting.liquid_probe_in_place(
177
187
  pipette_id=pipette_id,
178
188
  labware_id=labware_id,
@@ -185,6 +195,33 @@ async def _execute_common(
185
195
  state_update=move_result.state_update,
186
196
  deck_point=move_result.public.position,
187
197
  )
198
+ except PipetteOverpressureError as e:
199
+ return DefinedErrorData(
200
+ public=OverpressureError(
201
+ id=model_utils.generate_id(),
202
+ createdAt=model_utils.get_timestamp(),
203
+ wrappedErrors=[
204
+ ErrorOccurrence.from_failed(
205
+ id=model_utils.generate_id(),
206
+ createdAt=model_utils.get_timestamp(),
207
+ error=e,
208
+ )
209
+ ],
210
+ errorInfo=(
211
+ {
212
+ # This is here bc its not optional in the type but we are not using the retry location for this case
213
+ "retryLocation": (
214
+ current_position.x,
215
+ current_position.y,
216
+ current_position.z,
217
+ )
218
+ }
219
+ ),
220
+ ),
221
+ state_update=move_result.state_update.set_fluid_unknown(
222
+ pipette_id=pipette_id
223
+ ),
224
+ )
188
225
  else:
189
226
  return _ExecuteCommonResult(
190
227
  z_pos_or_error=z_pos,
@@ -202,12 +239,14 @@ class LiquidProbeImplementation(
202
239
  self,
203
240
  state_view: StateView,
204
241
  movement: MovementHandler,
242
+ gantry_mover: GantryMover,
205
243
  pipetting: PipettingHandler,
206
244
  model_utils: ModelUtils,
207
245
  **kwargs: object,
208
246
  ) -> None:
209
247
  self._state_view = state_view
210
248
  self._movement = movement
249
+ self._gantry_mover = gantry_mover
211
250
  self._pipetting = pipetting
212
251
  self._model_utils = model_utils
213
252
 
@@ -230,6 +269,7 @@ class LiquidProbeImplementation(
230
269
  result = await _execute_common(
231
270
  state_view=self._state_view,
232
271
  movement=self._movement,
272
+ gantry_mover=self._gantry_mover,
233
273
  pipetting=self._pipetting,
234
274
  model_utils=self._model_utils,
235
275
  params=params,
@@ -237,7 +277,9 @@ class LiquidProbeImplementation(
237
277
  if isinstance(result, DefinedErrorData):
238
278
  return result
239
279
  z_pos_or_error, state_update, deck_point = result
240
- if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
280
+ if isinstance(
281
+ z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError)
282
+ ):
241
283
  state_update.set_liquid_probed(
242
284
  labware_id=params.labwareId,
243
285
  well_name=params.wellName,
@@ -294,12 +336,14 @@ class TryLiquidProbeImplementation(
294
336
  self,
295
337
  state_view: StateView,
296
338
  movement: MovementHandler,
339
+ gantry_mover: GantryMover,
297
340
  pipetting: PipettingHandler,
298
341
  model_utils: ModelUtils,
299
342
  **kwargs: object,
300
343
  ) -> None:
301
344
  self._state_view = state_view
302
345
  self._movement = movement
346
+ self._gantry_mover = gantry_mover
303
347
  self._pipetting = pipetting
304
348
  self._model_utils = model_utils
305
349
 
@@ -313,6 +357,7 @@ class TryLiquidProbeImplementation(
313
357
  result = await _execute_common(
314
358
  state_view=self._state_view,
315
359
  movement=self._movement,
360
+ gantry_mover=self._gantry_mover,
316
361
  pipetting=self._pipetting,
317
362
  model_utils=self._model_utils,
318
363
  params=params,
@@ -321,7 +366,9 @@ class TryLiquidProbeImplementation(
321
366
  return result
322
367
  z_pos_or_error, state_update, deck_point = result
323
368
 
324
- if isinstance(z_pos_or_error, PipetteLiquidNotFoundError):
369
+ if isinstance(
370
+ z_pos_or_error, (PipetteLiquidNotFoundError, PipetteOverpressureError)
371
+ ):
325
372
  z_pos = None
326
373
  well_volume: float | update_types.ClearType = update_types.CLEAR
327
374
  else:
@@ -354,26 +401,30 @@ class LiquidProbe(
354
401
  BaseCommand[
355
402
  LiquidProbeParams,
356
403
  LiquidProbeResult,
357
- LiquidNotFoundError | StallOrCollisionError,
404
+ LiquidNotFoundError | StallOrCollisionError | OverpressureError,
358
405
  ]
359
406
  ):
360
407
  """The model for a full `liquidProbe` command."""
361
408
 
362
409
  commandType: LiquidProbeCommandType = "liquidProbe"
363
410
  params: LiquidProbeParams
364
- result: Optional[LiquidProbeResult]
411
+ result: Optional[LiquidProbeResult] = None
365
412
 
366
413
  _ImplementationCls: Type[LiquidProbeImplementation] = LiquidProbeImplementation
367
414
 
368
415
 
369
416
  class TryLiquidProbe(
370
- BaseCommand[TryLiquidProbeParams, TryLiquidProbeResult, StallOrCollisionError]
417
+ BaseCommand[
418
+ TryLiquidProbeParams,
419
+ TryLiquidProbeResult,
420
+ StallOrCollisionError | OverpressureError,
421
+ ]
371
422
  ):
372
423
  """The model for a full `tryLiquidProbe` command."""
373
424
 
374
425
  commandType: TryLiquidProbeCommandType = "tryLiquidProbe"
375
426
  params: TryLiquidProbeParams
376
- result: Optional[TryLiquidProbeResult]
427
+ result: Optional[TryLiquidProbeResult] = None
377
428
 
378
429
  _ImplementationCls: Type[
379
430
  TryLiquidProbeImplementation
@@ -192,6 +192,11 @@ class LoadLabwareImplementation(
192
192
  self._state_view.labware.raise_if_labware_incompatible_with_plate_reader(
193
193
  loaded_labware.definition
194
194
  )
195
+
196
+ self._state_view.labware.raise_if_labware_cannot_be_ondeck(
197
+ location=params.location, labware_definition=loaded_labware.definition
198
+ )
199
+
195
200
  return SuccessData(
196
201
  public=LoadLabwareResult(
197
202
  labwareId=loaded_labware.labware_id,
@@ -132,7 +132,7 @@ class LoadLid(BaseCommand[LoadLidParams, LoadLidResult, ErrorOccurrence]):
132
132
 
133
133
  commandType: LoadLidCommandType = "loadLid"
134
134
  params: LoadLidParams
135
- result: Optional[LoadLidResult]
135
+ result: Optional[LoadLidResult] = None
136
136
 
137
137
  _ImplementationCls: Type[LoadLidImplementation] = LoadLidImplementation
138
138
 
@@ -175,7 +175,7 @@ class LoadLidStack(
175
175
 
176
176
  commandType: LoadLidStackCommandType = "loadLidStack"
177
177
  params: LoadLidStackParams
178
- result: Optional[LoadLidStackResult]
178
+ result: Optional[LoadLidStackResult] = None
179
179
 
180
180
  _ImplementationCls: Type[LoadLidStackImplementation] = LoadLidStackImplementation
181
181
 
@@ -128,7 +128,7 @@ class LoadLiquidClass(
128
128
 
129
129
  commandType: LoadLiquidClassCommandType = "loadLiquidClass"
130
130
  params: LoadLiquidClassParams
131
- result: Optional[LoadLiquidClassResult]
131
+ result: Optional[LoadLiquidClassResult] = None
132
132
 
133
133
  _ImplementationCls: Type[
134
134
  LoadLiquidClassImplementation
@@ -223,6 +223,15 @@ class MoveLabwareImplementation(AbstractCommandImpl[MoveLabwareParams, _ExecuteR
223
223
  self._state_view.labware.raise_if_labware_has_labware_on_top(
224
224
  labware_id=params.labwareId
225
225
  )
226
+
227
+ if isinstance(available_new_location, DeckSlotLocation):
228
+ self._state_view.labware.raise_if_labware_cannot_be_ondeck(
229
+ location=available_new_location,
230
+ labware_definition=self._state_view.labware.get_definition(
231
+ params.labwareId
232
+ ),
233
+ )
234
+
226
235
  if isinstance(available_new_location, OnLabwareLocation):
227
236
  self._state_view.labware.raise_if_labware_has_labware_on_top(
228
237
  available_new_location.labwareId
@@ -70,7 +70,7 @@ class closeGripperJaw(
70
70
 
71
71
  commandType: closeGripperJawCommandType = "robot/closeGripperJaw"
72
72
  params: closeGripperJawParams
73
- result: Optional[closeGripperJawResult]
73
+ result: Optional[closeGripperJawResult] = None
74
74
 
75
75
  _ImplementationCls: Type[
76
76
  closeGripperJawImplementation
@@ -85,7 +85,7 @@ class MoveAxesRelative(
85
85
 
86
86
  commandType: MoveAxesRelativeCommandType = "robot/moveAxesRelative"
87
87
  params: MoveAxesRelativeParams
88
- result: Optional[MoveAxesRelativeResult]
88
+ result: Optional[MoveAxesRelativeResult] = None
89
89
 
90
90
  _ImplementationCls: Type[
91
91
  MoveAxesRelativeImplementation
@@ -86,7 +86,7 @@ class MoveAxesTo(BaseCommand[MoveAxesToParams, MoveAxesToResult, ErrorOccurrence
86
86
 
87
87
  commandType: MoveAxesToCommandType = "robot/moveAxesTo"
88
88
  params: MoveAxesToParams
89
- result: Optional[MoveAxesToResult]
89
+ result: Optional[MoveAxesToResult] = None
90
90
 
91
91
  _ImplementationCls: Type[MoveAxesToImplementation] = MoveAxesToImplementation
92
92
 
@@ -80,7 +80,7 @@ class MoveTo(BaseCommand[MoveToParams, MoveToResult, ErrorOccurrence]):
80
80
 
81
81
  commandType: MoveToCommandType = "robot/moveTo"
82
82
  params: MoveToParams
83
- result: Optional[MoveToResult]
83
+ result: Optional[MoveToResult] = None
84
84
 
85
85
  _ImplementationCls: Type[MoveToImplementation] = MoveToImplementation
86
86
 
@@ -61,7 +61,7 @@ class openGripperJaw(
61
61
 
62
62
  commandType: openGripperJawCommandType = "robot/openGripperJaw"
63
63
  params: openGripperJawParams
64
- result: Optional[openGripperJawResult]
64
+ result: Optional[openGripperJawResult] = None
65
65
 
66
66
  _ImplementationCls: Type[
67
67
  openGripperJawImplementation
@@ -157,7 +157,7 @@ class RunExtendedProfile(
157
157
 
158
158
  commandType: RunExtendedProfileCommandType = "thermocycler/runExtendedProfile"
159
159
  params: RunExtendedProfileParams
160
- result: Optional[RunExtendedProfileResult]
160
+ result: Optional[RunExtendedProfileResult] = None
161
161
 
162
162
  _ImplementationCls: Type[RunExtendedProfileImpl] = RunExtendedProfileImpl
163
163
 
@@ -82,7 +82,7 @@ class UnsafeBlowOutInPlace(
82
82
 
83
83
  commandType: UnsafeBlowOutInPlaceCommandType = "unsafe/blowOutInPlace"
84
84
  params: UnsafeBlowOutInPlaceParams
85
- result: Optional[UnsafeBlowOutInPlaceResult]
85
+ result: Optional[UnsafeBlowOutInPlaceResult] = None
86
86
 
87
87
  _ImplementationCls: Type[
88
88
  UnsafeBlowOutInPlaceImplementation
@@ -99,7 +99,7 @@ class UnsafeDropTipInPlace(
99
99
 
100
100
  commandType: UnsafeDropTipInPlaceCommandType = "unsafe/dropTipInPlace"
101
101
  params: UnsafeDropTipInPlaceParams
102
- result: Optional[UnsafeDropTipInPlaceResult]
102
+ result: Optional[UnsafeDropTipInPlaceResult] = None
103
103
 
104
104
  _ImplementationCls: Type[
105
105
  UnsafeDropTipInPlaceImplementation
@@ -66,7 +66,7 @@ class UnsafeEngageAxes(
66
66
 
67
67
  commandType: UnsafeEngageAxesCommandType = "unsafe/engageAxes"
68
68
  params: UnsafeEngageAxesParams
69
- result: Optional[UnsafeEngageAxesResult]
69
+ result: Optional[UnsafeEngageAxesResult] = None
70
70
 
71
71
  _ImplementationCls: Type[
72
72
  UnsafeEngageAxesImplementation
@@ -192,7 +192,7 @@ class UnsafePlaceLabware(
192
192
 
193
193
  commandType: UnsafePlaceLabwareCommandType = "unsafe/placeLabware"
194
194
  params: UnsafePlaceLabwareParams
195
- result: Optional[UnsafePlaceLabwareResult]
195
+ result: Optional[UnsafePlaceLabwareResult] = None
196
196
 
197
197
  _ImplementationCls: Type[
198
198
  UnsafePlaceLabwareImplementation
@@ -61,7 +61,7 @@ class UnsafeUngripLabware(
61
61
 
62
62
  commandType: UnsafeUngripLabwareCommandType = "unsafe/ungripLabware"
63
63
  params: UnsafeUngripLabwareParams
64
- result: Optional[UnsafeUngripLabwareResult]
64
+ result: Optional[UnsafeUngripLabwareResult] = None
65
65
 
66
66
  _ImplementationCls: Type[
67
67
  UnsafeUngripLabwareImplementation
@@ -74,7 +74,7 @@ class UpdatePositionEstimators(
74
74
 
75
75
  commandType: UpdatePositionEstimatorsCommandType = "unsafe/updatePositionEstimators"
76
76
  params: UpdatePositionEstimatorsParams
77
- result: Optional[UpdatePositionEstimatorsResult]
77
+ result: Optional[UpdatePositionEstimatorsResult] = None
78
78
 
79
79
  _ImplementationCls: Type[
80
80
  UpdatePositionEstimatorsImplementation
@@ -11,6 +11,7 @@ from .exceptions import (
11
11
  PickUpTipTipNotAttachedError,
12
12
  TipAttachedError,
13
13
  CommandDoesNotExistError,
14
+ UnsupportedLabwareForActionError,
14
15
  LabwareNotLoadedError,
15
16
  LabwareNotLoadedOnModuleError,
16
17
  LabwareNotLoadedOnLabwareError,
@@ -18,6 +19,7 @@ from .exceptions import (
18
19
  LiquidDoesNotExistError,
19
20
  LabwareDefinitionDoesNotExistError,
20
21
  LabwareCannotBeStackedError,
22
+ LabwareCannotSitOnDeckError,
21
23
  LabwareIsInStackError,
22
24
  LabwareOffsetDoesNotExistError,
23
25
  LabwareIsNotTipRackError,
@@ -103,8 +105,10 @@ __all__ = [
103
105
  "LabwareNotLoadedOnLabwareError",
104
106
  "LabwareNotOnDeckError",
105
107
  "LiquidDoesNotExistError",
108
+ "UnsupportedLabwareForActionError",
106
109
  "LabwareDefinitionDoesNotExistError",
107
110
  "LabwareCannotBeStackedError",
111
+ "LabwareCannotSitOnDeckError",
108
112
  "LabwareIsInStackError",
109
113
  "LabwareOffsetDoesNotExistError",
110
114
  "LabwareIsNotTipRackError",
@@ -283,6 +283,19 @@ class LabwareCannotBeStackedError(ProtocolEngineError):
283
283
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
284
284
 
285
285
 
286
+ class LabwareCannotSitOnDeckError(ProtocolEngineError):
287
+ """Raised when a labware is incompatible with a deck slot."""
288
+
289
+ def __init__(
290
+ self,
291
+ message: Optional[str] = None,
292
+ details: Optional[Dict[str, Any]] = None,
293
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
294
+ ) -> None:
295
+ """Build a LabwareCannotSitOnDeckError."""
296
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
297
+
298
+
286
299
  class LabwareIsInStackError(ProtocolEngineError):
287
300
  """Raised when trying to move to or physically interact with a labware that has another labware on top."""
288
301
 
@@ -374,6 +387,19 @@ class TouchTipIncompatibleArgumentsError(ProtocolEngineError):
374
387
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
375
388
 
376
389
 
390
+ class UnsupportedLabwareForActionError(ProtocolEngineError):
391
+ """Raised when trying to use an unsupported labware for a command."""
392
+
393
+ def __init__(
394
+ self,
395
+ message: Optional[str] = None,
396
+ details: Optional[Dict[str, Any]] = None,
397
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
398
+ ) -> None:
399
+ """Build a UnsupportedLabwareForActionError."""
400
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
401
+
402
+
377
403
  class WellDoesNotExistError(ProtocolEngineError):
378
404
  """Raised when referencing a well that does not exist."""
379
405
 
@@ -114,6 +114,7 @@ class GantryMover(TypingProtocol):
114
114
  critical_point: Optional[Dict[MotorAxis, float]] = None,
115
115
  speed: Optional[float] = None,
116
116
  relative_move: bool = False,
117
+ expect_stalls: bool = False,
117
118
  ) -> Dict[MotorAxis, float]:
118
119
  """Move a set of axes a given distance."""
119
120
  ...
@@ -341,6 +342,7 @@ class HardwareGantryMover(GantryMover):
341
342
  critical_point: Optional[Dict[MotorAxis, float]] = None,
342
343
  speed: Optional[float] = None,
343
344
  relative_move: bool = False,
345
+ expect_stalls: bool = False,
344
346
  ) -> Dict[MotorAxis, float]:
345
347
  """Move a set of axes a given distance.
346
348
 
@@ -349,6 +351,7 @@ class HardwareGantryMover(GantryMover):
349
351
  critical_point: A critical point override for axes
350
352
  speed: Optional speed parameter for the move.
351
353
  relative_move: Whether the axis map needs to be converted from a relative to absolute move.
354
+ expect_stalls: Whether it is expected that the move triggers a stall error.
352
355
  """
353
356
  try:
354
357
  pos_hw = self._convert_axis_map_for_hw(axis_map)
@@ -385,6 +388,7 @@ class HardwareGantryMover(GantryMover):
385
388
  await self._hardware_api.move_axes(
386
389
  position=absolute_pos,
387
390
  speed=speed,
391
+ expect_stalls=expect_stalls,
388
392
  )
389
393
 
390
394
  except PositionUnknownError as e:
@@ -588,6 +592,7 @@ class VirtualGantryMover(GantryMover):
588
592
  critical_point: Optional[Dict[MotorAxis, float]] = None,
589
593
  speed: Optional[float] = None,
590
594
  relative_move: bool = False,
595
+ expect_stalls: bool = False,
591
596
  ) -> Dict[MotorAxis, float]:
592
597
  """Move the give axes map. No-op in virtual implementation."""
593
598
  mount = self.pick_mount_from_axis_map(axis_map)