opentrons 8.3.0a0__py2.py3-none-any.whl → 8.3.0a1__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 (228) hide show
  1. opentrons/calibration_storage/deck_configuration.py +3 -3
  2. opentrons/calibration_storage/file_operators.py +3 -3
  3. opentrons/calibration_storage/helpers.py +3 -1
  4. opentrons/calibration_storage/ot2/models/v1.py +16 -29
  5. opentrons/calibration_storage/ot2/tip_length.py +7 -4
  6. opentrons/calibration_storage/ot3/models/v1.py +14 -23
  7. opentrons/cli/analyze.py +18 -6
  8. opentrons/drivers/asyncio/communication/__init__.py +2 -0
  9. opentrons/drivers/asyncio/communication/errors.py +16 -3
  10. opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
  11. opentrons/drivers/command_builder.py +2 -2
  12. opentrons/drivers/flex_stacker/__init__.py +9 -0
  13. opentrons/drivers/flex_stacker/abstract.py +89 -0
  14. opentrons/drivers/flex_stacker/driver.py +260 -0
  15. opentrons/drivers/flex_stacker/simulator.py +109 -0
  16. opentrons/drivers/flex_stacker/types.py +138 -0
  17. opentrons/drivers/heater_shaker/driver.py +18 -3
  18. opentrons/drivers/temp_deck/driver.py +13 -3
  19. opentrons/drivers/thermocycler/driver.py +17 -3
  20. opentrons/execute.py +3 -1
  21. opentrons/hardware_control/__init__.py +1 -2
  22. opentrons/hardware_control/api.py +28 -20
  23. opentrons/hardware_control/backends/flex_protocol.py +4 -6
  24. opentrons/hardware_control/backends/ot3controller.py +177 -59
  25. opentrons/hardware_control/backends/ot3simulator.py +10 -8
  26. opentrons/hardware_control/backends/ot3utils.py +3 -13
  27. opentrons/hardware_control/dev_types.py +2 -0
  28. opentrons/hardware_control/emulation/heater_shaker.py +4 -0
  29. opentrons/hardware_control/emulation/module_server/client.py +1 -1
  30. opentrons/hardware_control/emulation/module_server/server.py +5 -3
  31. opentrons/hardware_control/emulation/settings.py +3 -4
  32. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
  33. opentrons/hardware_control/instruments/ot2/pipette.py +9 -21
  34. opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
  35. opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
  36. opentrons/hardware_control/instruments/ot3/pipette.py +13 -22
  37. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
  38. opentrons/hardware_control/modules/mod_abc.py +2 -2
  39. opentrons/hardware_control/motion_utilities.py +68 -0
  40. opentrons/hardware_control/nozzle_manager.py +39 -41
  41. opentrons/hardware_control/ot3_calibration.py +1 -1
  42. opentrons/hardware_control/ot3api.py +34 -22
  43. opentrons/hardware_control/protocols/gripper_controller.py +3 -0
  44. opentrons/hardware_control/protocols/hardware_manager.py +5 -1
  45. opentrons/hardware_control/protocols/liquid_handler.py +18 -0
  46. opentrons/hardware_control/protocols/motion_controller.py +6 -0
  47. opentrons/hardware_control/robot_calibration.py +1 -1
  48. opentrons/hardware_control/types.py +61 -0
  49. opentrons/protocol_api/__init__.py +20 -1
  50. opentrons/protocol_api/_liquid.py +24 -49
  51. opentrons/protocol_api/_liquid_properties.py +754 -0
  52. opentrons/protocol_api/_types.py +24 -0
  53. opentrons/protocol_api/core/common.py +2 -0
  54. opentrons/protocol_api/core/engine/instrument.py +67 -10
  55. opentrons/protocol_api/core/engine/labware.py +29 -7
  56. opentrons/protocol_api/core/engine/protocol.py +130 -5
  57. opentrons/protocol_api/core/engine/robot.py +139 -0
  58. opentrons/protocol_api/core/engine/well.py +4 -1
  59. opentrons/protocol_api/core/instrument.py +42 -4
  60. opentrons/protocol_api/core/labware.py +13 -4
  61. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +34 -3
  62. opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
  63. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
  64. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  65. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +34 -3
  66. opentrons/protocol_api/core/protocol.py +34 -1
  67. opentrons/protocol_api/core/robot.py +51 -0
  68. opentrons/protocol_api/instrument_context.py +145 -43
  69. opentrons/protocol_api/labware.py +231 -7
  70. opentrons/protocol_api/module_contexts.py +21 -17
  71. opentrons/protocol_api/protocol_context.py +125 -4
  72. opentrons/protocol_api/robot_context.py +204 -32
  73. opentrons/protocol_api/validation.py +261 -3
  74. opentrons/protocol_engine/__init__.py +4 -0
  75. opentrons/protocol_engine/actions/actions.py +2 -3
  76. opentrons/protocol_engine/clients/sync_client.py +18 -0
  77. opentrons/protocol_engine/commands/__init__.py +81 -0
  78. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +0 -2
  79. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +19 -5
  80. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +0 -1
  81. opentrons/protocol_engine/commands/absorbance_reader/read.py +32 -9
  82. opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
  83. opentrons/protocol_engine/commands/aspirate.py +103 -53
  84. opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
  85. opentrons/protocol_engine/commands/blow_out.py +44 -39
  86. opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
  87. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
  88. opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
  89. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
  90. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
  91. opentrons/protocol_engine/commands/command.py +73 -66
  92. opentrons/protocol_engine/commands/command_unions.py +101 -1
  93. opentrons/protocol_engine/commands/comment.py +1 -1
  94. opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
  95. opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
  96. opentrons/protocol_engine/commands/custom.py +6 -12
  97. opentrons/protocol_engine/commands/dispense.py +82 -48
  98. opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
  99. opentrons/protocol_engine/commands/drop_tip.py +52 -31
  100. opentrons/protocol_engine/commands/drop_tip_in_place.py +13 -3
  101. opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
  102. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  103. opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
  104. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
  105. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
  106. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
  107. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
  108. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
  109. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
  110. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
  111. opentrons/protocol_engine/commands/home.py +13 -4
  112. opentrons/protocol_engine/commands/liquid_probe.py +60 -25
  113. opentrons/protocol_engine/commands/load_labware.py +29 -7
  114. opentrons/protocol_engine/commands/load_lid.py +146 -0
  115. opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
  116. opentrons/protocol_engine/commands/load_liquid.py +12 -4
  117. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  118. opentrons/protocol_engine/commands/load_module.py +31 -10
  119. opentrons/protocol_engine/commands/load_pipette.py +19 -8
  120. opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
  121. opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
  122. opentrons/protocol_engine/commands/move_labware.py +19 -6
  123. opentrons/protocol_engine/commands/move_relative.py +35 -25
  124. opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
  125. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
  126. opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
  127. opentrons/protocol_engine/commands/move_to_well.py +40 -24
  128. opentrons/protocol_engine/commands/movement_common.py +338 -0
  129. opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
  130. opentrons/protocol_engine/commands/pipetting_common.py +169 -87
  131. opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
  132. opentrons/protocol_engine/commands/reload_labware.py +1 -1
  133. opentrons/protocol_engine/commands/retract_axis.py +1 -1
  134. opentrons/protocol_engine/commands/robot/__init__.py +69 -0
  135. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
  136. opentrons/protocol_engine/commands/robot/common.py +18 -0
  137. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  138. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  139. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  140. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
  141. opentrons/protocol_engine/commands/save_position.py +14 -5
  142. opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
  143. opentrons/protocol_engine/commands/set_status_bar.py +1 -1
  144. opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
  145. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
  146. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
  147. opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
  148. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
  149. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
  150. opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
  151. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +8 -2
  152. opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
  153. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
  154. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
  155. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
  156. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
  157. opentrons/protocol_engine/commands/touch_tip.py +65 -16
  158. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +4 -1
  159. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -3
  160. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -4
  161. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -4
  162. opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
  163. opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
  164. opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
  165. opentrons/protocol_engine/errors/__init__.py +8 -0
  166. opentrons/protocol_engine/errors/error_occurrence.py +19 -20
  167. opentrons/protocol_engine/errors/exceptions.py +50 -0
  168. opentrons/protocol_engine/execution/command_executor.py +1 -1
  169. opentrons/protocol_engine/execution/equipment.py +73 -5
  170. opentrons/protocol_engine/execution/gantry_mover.py +364 -8
  171. opentrons/protocol_engine/execution/movement.py +27 -0
  172. opentrons/protocol_engine/execution/pipetting.py +5 -1
  173. opentrons/protocol_engine/execution/tip_handler.py +4 -6
  174. opentrons/protocol_engine/notes/notes.py +1 -1
  175. opentrons/protocol_engine/protocol_engine.py +7 -6
  176. opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
  177. opentrons/protocol_engine/resources/labware_validation.py +5 -0
  178. opentrons/protocol_engine/resources/module_data_provider.py +1 -1
  179. opentrons/protocol_engine/resources/pipette_data_provider.py +12 -0
  180. opentrons/protocol_engine/slot_standardization.py +9 -9
  181. opentrons/protocol_engine/state/_move_types.py +9 -5
  182. opentrons/protocol_engine/state/_well_math.py +193 -0
  183. opentrons/protocol_engine/state/addressable_areas.py +25 -61
  184. opentrons/protocol_engine/state/command_history.py +12 -0
  185. opentrons/protocol_engine/state/commands.py +17 -13
  186. opentrons/protocol_engine/state/files.py +10 -12
  187. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  188. opentrons/protocol_engine/state/frustum_helpers.py +57 -32
  189. opentrons/protocol_engine/state/geometry.py +47 -1
  190. opentrons/protocol_engine/state/labware.py +79 -25
  191. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  192. opentrons/protocol_engine/state/liquids.py +16 -4
  193. opentrons/protocol_engine/state/modules.py +52 -70
  194. opentrons/protocol_engine/state/motion.py +6 -1
  195. opentrons/protocol_engine/state/pipettes.py +135 -58
  196. opentrons/protocol_engine/state/state.py +21 -2
  197. opentrons/protocol_engine/state/state_summary.py +4 -2
  198. opentrons/protocol_engine/state/tips.py +11 -44
  199. opentrons/protocol_engine/state/update_types.py +343 -48
  200. opentrons/protocol_engine/state/wells.py +19 -11
  201. opentrons/protocol_engine/types.py +176 -28
  202. opentrons/protocol_reader/extract_labware_definitions.py +5 -2
  203. opentrons/protocol_reader/file_format_validator.py +5 -5
  204. opentrons/protocol_runner/json_file_reader.py +9 -3
  205. opentrons/protocol_runner/json_translator.py +51 -25
  206. opentrons/protocol_runner/legacy_command_mapper.py +66 -64
  207. opentrons/protocol_runner/protocol_runner.py +35 -4
  208. opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
  209. opentrons/protocol_runner/run_orchestrator.py +13 -3
  210. opentrons/protocols/advanced_control/common.py +38 -0
  211. opentrons/protocols/advanced_control/mix.py +1 -1
  212. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  213. opentrons/protocols/advanced_control/transfers/common.py +56 -0
  214. opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
  215. opentrons/protocols/api_support/definitions.py +1 -1
  216. opentrons/protocols/api_support/instrument.py +1 -1
  217. opentrons/protocols/api_support/util.py +10 -0
  218. opentrons/protocols/labware.py +39 -6
  219. opentrons/protocols/models/json_protocol.py +5 -9
  220. opentrons/simulate.py +3 -1
  221. opentrons/types.py +162 -2
  222. opentrons/util/logging_config.py +1 -1
  223. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/METADATA +16 -15
  224. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/RECORD +228 -201
  225. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/WHEEL +1 -1
  226. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/LICENSE +0 -0
  227. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/entry_points.txt +0 -0
  228. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/top_level.txt +0 -0
@@ -5,14 +5,23 @@ from typing import TYPE_CHECKING, Optional, Type
5
5
  from typing_extensions import Literal
6
6
 
7
7
 
8
- from ..state import update_types
9
- from ..types import MovementAxis, DeckPoint
10
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
11
- from ..errors.error_occurrence import ErrorOccurrence
12
- from .pipetting_common import DestinationPositionResult
8
+ from ..types import MovementAxis
9
+ from .command import (
10
+ AbstractCommandImpl,
11
+ BaseCommand,
12
+ BaseCommandCreate,
13
+ SuccessData,
14
+ DefinedErrorData,
15
+ )
16
+ from .movement_common import (
17
+ DestinationPositionResult,
18
+ move_relative,
19
+ StallOrCollisionError,
20
+ )
13
21
 
14
22
  if TYPE_CHECKING:
15
23
  from ..execution import MovementHandler
24
+ from ..resources.model_utils import ModelUtils
16
25
 
17
26
 
18
27
  MoveRelativeCommandType = Literal["moveRelative"]
@@ -39,46 +48,47 @@ class MoveRelativeResult(DestinationPositionResult):
39
48
 
40
49
 
41
50
  class MoveRelativeImplementation(
42
- AbstractCommandImpl[MoveRelativeParams, SuccessData[MoveRelativeResult]]
51
+ AbstractCommandImpl[
52
+ MoveRelativeParams,
53
+ SuccessData[MoveRelativeResult] | DefinedErrorData[StallOrCollisionError],
54
+ ]
43
55
  ):
44
56
  """Move relative command implementation."""
45
57
 
46
- def __init__(self, movement: MovementHandler, **kwargs: object) -> None:
58
+ def __init__(
59
+ self, movement: MovementHandler, model_utils: ModelUtils, **kwargs: object
60
+ ) -> None:
47
61
  self._movement = movement
62
+ self._model_utils = model_utils
48
63
 
49
64
  async def execute(
50
65
  self, params: MoveRelativeParams
51
- ) -> SuccessData[MoveRelativeResult]:
66
+ ) -> SuccessData[MoveRelativeResult] | DefinedErrorData[StallOrCollisionError]:
52
67
  """Move (jog) a given pipette a relative distance."""
53
- state_update = update_types.StateUpdate()
54
-
55
- x, y, z = await self._movement.move_relative(
68
+ result = await move_relative(
69
+ movement=self._movement,
70
+ model_utils=self._model_utils,
56
71
  pipette_id=params.pipetteId,
57
72
  axis=params.axis,
58
73
  distance=params.distance,
59
74
  )
60
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
61
- state_update.pipette_location = update_types.PipetteLocationUpdate(
62
- pipette_id=params.pipetteId,
63
- # TODO(jbl 2023-02-14): Need to investigate whether move relative should clear current location
64
- new_location=update_types.NO_CHANGE,
65
- new_deck_point=deck_point,
66
- )
67
-
68
- return SuccessData(
69
- public=MoveRelativeResult(position=deck_point),
70
- state_update=state_update,
71
- )
75
+ if isinstance(result, DefinedErrorData):
76
+ return result
77
+ else:
78
+ return SuccessData(
79
+ public=MoveRelativeResult(position=result.public.position),
80
+ state_update=result.state_update,
81
+ )
72
82
 
73
83
 
74
84
  class MoveRelative(
75
- BaseCommand[MoveRelativeParams, MoveRelativeResult, ErrorOccurrence]
85
+ BaseCommand[MoveRelativeParams, MoveRelativeResult, StallOrCollisionError]
76
86
  ):
77
87
  """Command to move (jog) a given pipette a relative distance."""
78
88
 
79
89
  commandType: MoveRelativeCommandType = "moveRelative"
80
90
  params: MoveRelativeParams
81
- result: Optional[MoveRelativeResult]
91
+ result: Optional[MoveRelativeResult] = None
82
92
 
83
93
  _ImplementationCls: Type[MoveRelativeImplementation] = MoveRelativeImplementation
84
94
 
@@ -7,20 +7,29 @@ from typing_extensions import Literal
7
7
  from opentrons_shared_data.pipette.types import PipetteNameType
8
8
 
9
9
  from ..errors import LocationNotAccessibleByPipetteError
10
- from ..state import update_types
11
- from ..types import DeckPoint, AddressableOffsetVector
10
+ from ..types import AddressableOffsetVector
12
11
  from ..resources import fixture_validation
13
12
  from .pipetting_common import (
14
13
  PipetteIdMixin,
14
+ )
15
+ from .movement_common import (
15
16
  MovementMixin,
16
17
  DestinationPositionResult,
18
+ move_to_addressable_area,
19
+ StallOrCollisionError,
20
+ )
21
+ from .command import (
22
+ AbstractCommandImpl,
23
+ BaseCommand,
24
+ BaseCommandCreate,
25
+ SuccessData,
26
+ DefinedErrorData,
17
27
  )
18
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
19
- from ..errors.error_occurrence import ErrorOccurrence
20
28
 
21
29
  if TYPE_CHECKING:
22
30
  from ..execution import MovementHandler
23
31
  from ..state.state import StateView
32
+ from ..resources.model_utils import ModelUtils
24
33
 
25
34
  MoveToAddressableAreaCommandType = Literal["moveToAddressableArea"]
26
35
 
@@ -74,25 +83,29 @@ class MoveToAddressableAreaResult(DestinationPositionResult):
74
83
  pass
75
84
 
76
85
 
86
+ _ExecuteReturn = (
87
+ SuccessData[MoveToAddressableAreaResult] | DefinedErrorData[StallOrCollisionError]
88
+ )
89
+
90
+
77
91
  class MoveToAddressableAreaImplementation(
78
- AbstractCommandImpl[
79
- MoveToAddressableAreaParams, SuccessData[MoveToAddressableAreaResult]
80
- ]
92
+ AbstractCommandImpl[MoveToAddressableAreaParams, _ExecuteReturn]
81
93
  ):
82
94
  """Move to addressable area command implementation."""
83
95
 
84
96
  def __init__(
85
- self, movement: MovementHandler, state_view: StateView, **kwargs: object
97
+ self,
98
+ movement: MovementHandler,
99
+ state_view: StateView,
100
+ model_utils: ModelUtils,
101
+ **kwargs: object,
86
102
  ) -> None:
87
103
  self._movement = movement
88
104
  self._state_view = state_view
105
+ self._model_utils = model_utils
89
106
 
90
- async def execute(
91
- self, params: MoveToAddressableAreaParams
92
- ) -> SuccessData[MoveToAddressableAreaResult]:
107
+ async def execute(self, params: MoveToAddressableAreaParams) -> _ExecuteReturn:
93
108
  """Move the requested pipette to the requested addressable area."""
94
- state_update = update_types.StateUpdate()
95
-
96
109
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
97
110
  params.addressableAreaName
98
111
  )
@@ -115,7 +128,9 @@ class MoveToAddressableAreaImplementation(
115
128
  f"Cannot move pipette to staging slot {params.addressableAreaName}"
116
129
  )
117
130
 
118
- x, y, z = await self._movement.move_to_addressable_area(
131
+ result = await move_to_addressable_area(
132
+ movement=self._movement,
133
+ model_utils=self._model_utils,
119
134
  pipette_id=params.pipetteId,
120
135
  addressable_area_name=params.addressableAreaName,
121
136
  offset=params.offset,
@@ -125,29 +140,27 @@ class MoveToAddressableAreaImplementation(
125
140
  stay_at_highest_possible_z=params.stayAtHighestPossibleZ,
126
141
  highest_possible_z_extra_offset=extra_z_offset,
127
142
  )
128
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
129
- state_update.set_pipette_location(
130
- pipette_id=params.pipetteId,
131
- new_addressable_area_name=params.addressableAreaName,
132
- new_deck_point=deck_point,
133
- )
134
-
135
- return SuccessData(
136
- public=MoveToAddressableAreaResult(position=DeckPoint(x=x, y=y, z=z)),
137
- state_update=state_update,
138
- )
143
+ if isinstance(result, DefinedErrorData):
144
+ return result
145
+ else:
146
+ return SuccessData(
147
+ public=MoveToAddressableAreaResult(position=result.public.position),
148
+ state_update=result.state_update,
149
+ )
139
150
 
140
151
 
141
152
  class MoveToAddressableArea(
142
153
  BaseCommand[
143
- MoveToAddressableAreaParams, MoveToAddressableAreaResult, ErrorOccurrence
154
+ MoveToAddressableAreaParams,
155
+ MoveToAddressableAreaResult,
156
+ StallOrCollisionError,
144
157
  ]
145
158
  ):
146
159
  """Move to addressable area command model."""
147
160
 
148
161
  commandType: MoveToAddressableAreaCommandType = "moveToAddressableArea"
149
162
  params: MoveToAddressableAreaParams
150
- result: Optional[MoveToAddressableAreaResult]
163
+ result: Optional[MoveToAddressableAreaResult] = None
151
164
 
152
165
  _ImplementationCls: Type[
153
166
  MoveToAddressableAreaImplementation
@@ -1,28 +1,43 @@
1
1
  """Move to addressable area for drop tip command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
- from pydantic import Field
4
- from typing import TYPE_CHECKING, Optional, Type
3
+ from typing import TYPE_CHECKING, Optional, Type, Any
5
4
  from typing_extensions import Literal
6
5
 
6
+ from pydantic import Field
7
+ from pydantic.json_schema import SkipJsonSchema
8
+
7
9
  from ..errors import LocationNotAccessibleByPipetteError
8
- from ..state import update_types
9
- from ..types import DeckPoint, AddressableOffsetVector
10
+ from ..types import AddressableOffsetVector
10
11
  from ..resources import fixture_validation
11
12
  from .pipetting_common import (
12
13
  PipetteIdMixin,
14
+ )
15
+ from .movement_common import (
13
16
  MovementMixin,
14
17
  DestinationPositionResult,
18
+ move_to_addressable_area,
19
+ StallOrCollisionError,
20
+ )
21
+ from .command import (
22
+ AbstractCommandImpl,
23
+ BaseCommand,
24
+ BaseCommandCreate,
25
+ SuccessData,
26
+ DefinedErrorData,
15
27
  )
16
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
17
- from ..errors.error_occurrence import ErrorOccurrence
18
28
 
19
29
  if TYPE_CHECKING:
20
30
  from ..execution import MovementHandler
21
31
  from ..state.state import StateView
32
+ from ..resources.model_utils import ModelUtils
22
33
 
23
34
  MoveToAddressableAreaForDropTipCommandType = Literal["moveToAddressableAreaForDropTip"]
24
35
 
25
36
 
37
+ def _remove_default(s: dict[str, Any]) -> None:
38
+ s.pop("default", None)
39
+
40
+
26
41
  class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
27
42
  """Payload required to move a pipette to a specific addressable area.
28
43
 
@@ -56,7 +71,7 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
56
71
  AddressableOffsetVector(x=0, y=0, z=0),
57
72
  description="Relative offset of addressable area to move pipette's critical point.",
58
73
  )
59
- alternateDropLocation: Optional[bool] = Field(
74
+ alternateDropLocation: bool | SkipJsonSchema[None] = Field(
60
75
  False,
61
76
  description=(
62
77
  "Whether to alternate location where tip is dropped within the addressable area."
@@ -65,8 +80,9 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
65
80
  " labware well."
66
81
  " If False, the tip will be dropped at the top center of the area."
67
82
  ),
83
+ json_schema_extra=_remove_default,
68
84
  )
69
- ignoreTipConfiguration: Optional[bool] = Field(
85
+ ignoreTipConfiguration: bool | SkipJsonSchema[None] = Field(
70
86
  True,
71
87
  description=(
72
88
  "Whether to utilize the critical point of the tip configuraiton when moving to an addressable area."
@@ -74,6 +90,7 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
74
90
  " as the critical point for movement."
75
91
  " If False, this command will use the critical point provided by the current tip configuration."
76
92
  ),
93
+ json_schema_extra=_remove_default,
77
94
  )
78
95
 
79
96
 
@@ -83,26 +100,32 @@ class MoveToAddressableAreaForDropTipResult(DestinationPositionResult):
83
100
  pass
84
101
 
85
102
 
103
+ _ExecuteReturn = (
104
+ SuccessData[MoveToAddressableAreaForDropTipResult]
105
+ | DefinedErrorData[StallOrCollisionError]
106
+ )
107
+
108
+
86
109
  class MoveToAddressableAreaForDropTipImplementation(
87
- AbstractCommandImpl[
88
- MoveToAddressableAreaForDropTipParams,
89
- SuccessData[MoveToAddressableAreaForDropTipResult],
90
- ]
110
+ AbstractCommandImpl[MoveToAddressableAreaForDropTipParams, _ExecuteReturn]
91
111
  ):
92
112
  """Move to addressable area for drop tip command implementation."""
93
113
 
94
114
  def __init__(
95
- self, movement: MovementHandler, state_view: StateView, **kwargs: object
115
+ self,
116
+ movement: MovementHandler,
117
+ state_view: StateView,
118
+ model_utils: ModelUtils,
119
+ **kwargs: object,
96
120
  ) -> None:
97
121
  self._movement = movement
98
122
  self._state_view = state_view
123
+ self._model_utils = model_utils
99
124
 
100
125
  async def execute(
101
126
  self, params: MoveToAddressableAreaForDropTipParams
102
- ) -> SuccessData[MoveToAddressableAreaForDropTipResult]:
127
+ ) -> _ExecuteReturn:
103
128
  """Move the requested pipette to the requested addressable area in preperation of a drop tip."""
104
- state_update = update_types.StateUpdate()
105
-
106
129
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
107
130
  params.addressableAreaName
108
131
  )
@@ -120,7 +143,9 @@ class MoveToAddressableAreaForDropTipImplementation(
120
143
  else:
121
144
  offset = params.offset
122
145
 
123
- x, y, z = await self._movement.move_to_addressable_area(
146
+ result = await move_to_addressable_area(
147
+ movement=self._movement,
148
+ model_utils=self._model_utils,
124
149
  pipette_id=params.pipetteId,
125
150
  addressable_area_name=params.addressableAreaName,
126
151
  offset=offset,
@@ -129,26 +154,22 @@ class MoveToAddressableAreaForDropTipImplementation(
129
154
  speed=params.speed,
130
155
  ignore_tip_configuration=params.ignoreTipConfiguration,
131
156
  )
132
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
133
- state_update.set_pipette_location(
134
- pipette_id=params.pipetteId,
135
- new_addressable_area_name=params.addressableAreaName,
136
- new_deck_point=deck_point,
137
- )
138
-
139
- return SuccessData(
140
- public=MoveToAddressableAreaForDropTipResult(
141
- position=DeckPoint(x=x, y=y, z=z)
142
- ),
143
- state_update=state_update,
144
- )
157
+ if isinstance(result, DefinedErrorData):
158
+ return result
159
+ else:
160
+ return SuccessData(
161
+ public=MoveToAddressableAreaForDropTipResult(
162
+ position=result.public.position,
163
+ ),
164
+ state_update=result.state_update,
165
+ )
145
166
 
146
167
 
147
168
  class MoveToAddressableAreaForDropTip(
148
169
  BaseCommand[
149
170
  MoveToAddressableAreaForDropTipParams,
150
171
  MoveToAddressableAreaForDropTipResult,
151
- ErrorOccurrence,
172
+ StallOrCollisionError,
152
173
  ]
153
174
  ):
154
175
  """Move to addressable area for drop tip command model."""
@@ -157,7 +178,7 @@ class MoveToAddressableAreaForDropTip(
157
178
  "moveToAddressableAreaForDropTip"
158
179
  )
159
180
  params: MoveToAddressableAreaForDropTipParams
160
- result: Optional[MoveToAddressableAreaForDropTipResult]
181
+ result: Optional[MoveToAddressableAreaForDropTipResult] = None
161
182
 
162
183
  _ImplementationCls: Type[
163
184
  MoveToAddressableAreaForDropTipImplementation
@@ -6,14 +6,25 @@ from typing import Optional, Type, TYPE_CHECKING
6
6
  from typing_extensions import Literal
7
7
 
8
8
 
9
- from ..state import update_types
10
9
  from ..types import DeckPoint
11
- from .pipetting_common import PipetteIdMixin, MovementMixin, DestinationPositionResult
12
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
13
- from ..errors.error_occurrence import ErrorOccurrence
10
+ from .pipetting_common import PipetteIdMixin
11
+ from .movement_common import (
12
+ MovementMixin,
13
+ DestinationPositionResult,
14
+ move_to_coordinates,
15
+ StallOrCollisionError,
16
+ )
17
+ from .command import (
18
+ AbstractCommandImpl,
19
+ BaseCommand,
20
+ BaseCommandCreate,
21
+ SuccessData,
22
+ DefinedErrorData,
23
+ )
14
24
 
15
25
  if TYPE_CHECKING:
16
26
  from ..execution import MovementHandler
27
+ from ..resources.model_utils import ModelUtils
17
28
 
18
29
 
19
30
  MoveToCoordinatesCommandType = Literal["moveToCoordinates"]
@@ -34,50 +45,53 @@ class MoveToCoordinatesResult(DestinationPositionResult):
34
45
  pass
35
46
 
36
47
 
48
+ _ExecuteReturn = (
49
+ SuccessData[MoveToCoordinatesResult] | DefinedErrorData[StallOrCollisionError]
50
+ )
51
+
52
+
37
53
  class MoveToCoordinatesImplementation(
38
- AbstractCommandImpl[MoveToCoordinatesParams, SuccessData[MoveToCoordinatesResult]]
54
+ AbstractCommandImpl[MoveToCoordinatesParams, _ExecuteReturn]
39
55
  ):
40
56
  """Move to coordinates command implementation."""
41
57
 
42
58
  def __init__(
43
59
  self,
44
60
  movement: MovementHandler,
61
+ model_utils: ModelUtils,
45
62
  **kwargs: object,
46
63
  ) -> None:
47
64
  self._movement = movement
65
+ self._model_utils = model_utils
48
66
 
49
- async def execute(
50
- self, params: MoveToCoordinatesParams
51
- ) -> SuccessData[MoveToCoordinatesResult]:
67
+ async def execute(self, params: MoveToCoordinatesParams) -> _ExecuteReturn:
52
68
  """Move the requested pipette to the requested coordinates."""
53
- state_update = update_types.StateUpdate()
54
-
55
- x, y, z = await self._movement.move_to_coordinates(
69
+ result = await move_to_coordinates(
70
+ movement=self._movement,
71
+ model_utils=self._model_utils,
56
72
  pipette_id=params.pipetteId,
57
73
  deck_coordinates=params.coordinates,
58
74
  direct=params.forceDirect,
59
75
  additional_min_travel_z=params.minimumZHeight,
60
76
  speed=params.speed,
61
77
  )
62
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
63
- state_update.pipette_location = update_types.PipetteLocationUpdate(
64
- pipette_id=params.pipetteId, new_location=None, new_deck_point=deck_point
65
- )
66
-
67
- return SuccessData(
68
- public=MoveToCoordinatesResult(position=DeckPoint(x=x, y=y, z=z)),
69
- state_update=state_update,
70
- )
78
+ if isinstance(result, DefinedErrorData):
79
+ return result
80
+ else:
81
+ return SuccessData(
82
+ public=MoveToCoordinatesResult(position=result.public.position),
83
+ state_update=result.state_update,
84
+ )
71
85
 
72
86
 
73
87
  class MoveToCoordinates(
74
- BaseCommand[MoveToCoordinatesParams, MoveToCoordinatesResult, ErrorOccurrence]
88
+ BaseCommand[MoveToCoordinatesParams, MoveToCoordinatesResult, StallOrCollisionError]
75
89
  ):
76
90
  """Move to well command model."""
77
91
 
78
92
  commandType: MoveToCoordinatesCommandType = "moveToCoordinates"
79
93
  params: MoveToCoordinatesParams
80
- result: Optional[MoveToCoordinatesResult]
94
+ result: Optional[MoveToCoordinatesResult] = None
81
95
 
82
96
  _ImplementationCls: Type[
83
97
  MoveToCoordinatesImplementation
@@ -1,23 +1,32 @@
1
1
  """Move to well command request, result, and implementation models."""
2
+
2
3
  from __future__ import annotations
3
4
  from typing import TYPE_CHECKING, Optional, Type
4
5
  from typing_extensions import Literal
5
6
 
6
- from ..types import DeckPoint
7
7
  from .pipetting_common import (
8
8
  PipetteIdMixin,
9
+ )
10
+ from .movement_common import (
9
11
  WellLocationMixin,
10
12
  MovementMixin,
11
13
  DestinationPositionResult,
14
+ StallOrCollisionError,
15
+ move_to_well,
16
+ )
17
+ from .command import (
18
+ AbstractCommandImpl,
19
+ BaseCommand,
20
+ BaseCommandCreate,
21
+ SuccessData,
22
+ DefinedErrorData,
12
23
  )
13
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
14
- from ..errors.error_occurrence import ErrorOccurrence
15
- from ..state import update_types
16
24
  from ..errors import LabwareIsTipRackError
17
25
 
18
26
  if TYPE_CHECKING:
19
27
  from ..execution import MovementHandler
20
28
  from ..state.state import StateView
29
+ from ..resources.model_utils import ModelUtils
21
30
 
22
31
  MoveToWellCommandType = Literal["moveToWell"]
23
32
 
@@ -35,25 +44,33 @@ class MoveToWellResult(DestinationPositionResult):
35
44
 
36
45
 
37
46
  class MoveToWellImplementation(
38
- AbstractCommandImpl[MoveToWellParams, SuccessData[MoveToWellResult]]
47
+ AbstractCommandImpl[
48
+ MoveToWellParams,
49
+ SuccessData[MoveToWellResult] | DefinedErrorData[StallOrCollisionError],
50
+ ]
39
51
  ):
40
52
  """Move to well command implementation."""
41
53
 
42
54
  def __init__(
43
- self, state_view: StateView, movement: MovementHandler, **kwargs: object
55
+ self,
56
+ state_view: StateView,
57
+ movement: MovementHandler,
58
+ model_utils: ModelUtils,
59
+ **kwargs: object,
44
60
  ) -> None:
45
61
  self._state_view = state_view
46
62
  self._movement = movement
63
+ self._model_utils = model_utils
47
64
 
48
- async def execute(self, params: MoveToWellParams) -> SuccessData[MoveToWellResult]:
65
+ async def execute(
66
+ self, params: MoveToWellParams
67
+ ) -> SuccessData[MoveToWellResult] | DefinedErrorData[StallOrCollisionError]:
49
68
  """Move the requested pipette to the requested well."""
50
69
  pipette_id = params.pipetteId
51
70
  labware_id = params.labwareId
52
71
  well_name = params.wellName
53
72
  well_location = params.wellLocation
54
73
 
55
- state_update = update_types.StateUpdate()
56
-
57
74
  if (
58
75
  self._state_view.labware.is_tiprack(labware_id)
59
76
  and well_location.volumeOffset
@@ -62,7 +79,9 @@ class MoveToWellImplementation(
62
79
  "Cannot specify a WellLocation with a volumeOffset with movement to a tip rack"
63
80
  )
64
81
 
65
- x, y, z = await self._movement.move_to_well(
82
+ move_result = await move_to_well(
83
+ model_utils=self._model_utils,
84
+ movement=self._movement,
66
85
  pipette_id=pipette_id,
67
86
  labware_id=labware_id,
68
87
  well_name=well_name,
@@ -71,26 +90,23 @@ class MoveToWellImplementation(
71
90
  minimum_z_height=params.minimumZHeight,
72
91
  speed=params.speed,
73
92
  )
74
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
75
- state_update.set_pipette_location(
76
- pipette_id=pipette_id,
77
- new_labware_id=labware_id,
78
- new_well_name=well_name,
79
- new_deck_point=deck_point,
80
- )
81
-
82
- return SuccessData(
83
- public=MoveToWellResult(position=deck_point),
84
- state_update=state_update,
85
- )
93
+ if isinstance(move_result, DefinedErrorData):
94
+ return move_result
95
+ else:
96
+ return SuccessData(
97
+ public=MoveToWellResult(position=move_result.public.position),
98
+ state_update=move_result.state_update,
99
+ )
86
100
 
87
101
 
88
- class MoveToWell(BaseCommand[MoveToWellParams, MoveToWellResult, ErrorOccurrence]):
102
+ class MoveToWell(
103
+ BaseCommand[MoveToWellParams, MoveToWellResult, StallOrCollisionError]
104
+ ):
89
105
  """Move to well command model."""
90
106
 
91
107
  commandType: MoveToWellCommandType = "moveToWell"
92
108
  params: MoveToWellParams
93
- result: Optional[MoveToWellResult]
109
+ result: Optional[MoveToWellResult] = None
94
110
 
95
111
  _ImplementationCls: Type[MoveToWellImplementation] = MoveToWellImplementation
96
112