opentrons 8.3.0a0__py2.py3-none-any.whl → 8.3.0a2__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 (229) 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 +70 -8
  219. opentrons/protocols/models/json_protocol.py +5 -9
  220. opentrons/simulate.py +3 -1
  221. opentrons/types.py +162 -2
  222. opentrons/util/entrypoint_util.py +2 -5
  223. opentrons/util/logging_config.py +1 -1
  224. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/METADATA +16 -15
  225. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/RECORD +229 -202
  226. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/WHEEL +1 -1
  227. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/LICENSE +0 -0
  228. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/entry_points.txt +0 -0
  229. {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a2.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,21 @@
1
1
  """Blow-out command request, result, and implementation models."""
2
+
2
3
  from __future__ import annotations
3
4
  from typing import TYPE_CHECKING, Optional, Type, Union
4
- from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
5
5
  from typing_extensions import Literal
6
6
 
7
7
 
8
- from ..state.update_types import StateUpdate
9
- from ..types import DeckPoint
10
8
  from .pipetting_common import (
11
9
  OverpressureError,
12
10
  PipetteIdMixin,
13
11
  FlowRateMixin,
12
+ blow_out_in_place,
13
+ )
14
+ from .movement_common import (
14
15
  WellLocationMixin,
15
16
  DestinationPositionResult,
17
+ move_to_well,
18
+ StallOrCollisionError,
16
19
  )
17
20
  from .command import (
18
21
  AbstractCommandImpl,
@@ -21,7 +24,7 @@ from .command import (
21
24
  DefinedErrorData,
22
25
  SuccessData,
23
26
  )
24
- from ..errors.error_occurrence import ErrorOccurrence
27
+ from ..state.update_types import StateUpdate
25
28
 
26
29
  from opentrons.hardware_control import HardwareControlAPI
27
30
 
@@ -49,7 +52,7 @@ class BlowOutResult(DestinationPositionResult):
49
52
 
50
53
  _ExecuteReturn = Union[
51
54
  SuccessData[BlowOutResult],
52
- DefinedErrorData[OverpressureError],
55
+ DefinedErrorData[OverpressureError] | DefinedErrorData[StallOrCollisionError],
53
56
  ]
54
57
 
55
58
 
@@ -73,59 +76,61 @@ class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, _ExecuteReturn]):
73
76
 
74
77
  async def execute(self, params: BlowOutParams) -> _ExecuteReturn:
75
78
  """Move to and blow-out the requested well."""
76
- state_update = StateUpdate()
77
-
78
- x, y, z = await self._movement.move_to_well(
79
+ move_result = await move_to_well(
80
+ movement=self._movement,
81
+ model_utils=self._model_utils,
79
82
  pipette_id=params.pipetteId,
80
83
  labware_id=params.labwareId,
81
84
  well_name=params.wellName,
82
85
  well_location=params.wellLocation,
83
86
  )
84
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
85
- state_update.set_pipette_location(
87
+ if isinstance(move_result, DefinedErrorData):
88
+ return move_result
89
+ blow_out_result = await blow_out_in_place(
86
90
  pipette_id=params.pipetteId,
87
- new_labware_id=params.labwareId,
88
- new_well_name=params.wellName,
89
- new_deck_point=deck_point,
91
+ flow_rate=params.flowRate,
92
+ location_if_error={
93
+ "retryLocation": (
94
+ move_result.public.position.x,
95
+ move_result.public.position.y,
96
+ move_result.public.position.z,
97
+ )
98
+ },
99
+ pipetting=self._pipetting,
100
+ model_utils=self._model_utils,
90
101
  )
91
- try:
92
- await self._pipetting.blow_out_in_place(
93
- pipette_id=params.pipetteId, flow_rate=params.flowRate
94
- )
95
- except PipetteOverpressureError as e:
102
+ if isinstance(blow_out_result, DefinedErrorData):
96
103
  return DefinedErrorData(
97
- public=OverpressureError(
98
- id=self._model_utils.generate_id(),
99
- createdAt=self._model_utils.get_timestamp(),
100
- wrappedErrors=[
101
- ErrorOccurrence.from_failed(
102
- id=self._model_utils.generate_id(),
103
- createdAt=self._model_utils.get_timestamp(),
104
- error=e,
105
- )
106
- ],
107
- errorInfo={
108
- "retryLocation": (
109
- x,
110
- y,
111
- z,
112
- )
113
- },
104
+ public=blow_out_result.public,
105
+ state_update=StateUpdate.reduce(
106
+ move_result.state_update, blow_out_result.state_update
107
+ ),
108
+ state_update_if_false_positive=StateUpdate.reduce(
109
+ move_result.state_update,
110
+ blow_out_result.state_update_if_false_positive,
114
111
  ),
115
112
  )
116
113
  else:
117
114
  return SuccessData(
118
- public=BlowOutResult(position=deck_point),
119
- state_update=state_update,
115
+ public=BlowOutResult(position=move_result.public.position),
116
+ state_update=StateUpdate.reduce(
117
+ move_result.state_update, blow_out_result.state_update
118
+ ),
120
119
  )
121
120
 
122
121
 
123
- class BlowOut(BaseCommand[BlowOutParams, BlowOutResult, ErrorOccurrence]):
122
+ class BlowOut(
123
+ BaseCommand[
124
+ BlowOutParams,
125
+ BlowOutResult,
126
+ OverpressureError | StallOrCollisionError,
127
+ ]
128
+ ):
124
129
  """Blow-out command model."""
125
130
 
126
131
  commandType: BlowOutCommandType = "blowout"
127
132
  params: BlowOutParams
128
- result: Optional[BlowOutResult]
133
+ result: Optional[BlowOutResult] = None
129
134
 
130
135
  _ImplementationCls: Type[BlowOutImplementation] = BlowOutImplementation
131
136
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
  from typing import TYPE_CHECKING, Optional, Type, Union
5
- from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
6
5
  from typing_extensions import Literal
7
6
  from pydantic import BaseModel
8
7
 
@@ -10,6 +9,7 @@ from .pipetting_common import (
10
9
  OverpressureError,
11
10
  PipetteIdMixin,
12
11
  FlowRateMixin,
12
+ blow_out_in_place,
13
13
  )
14
14
  from .command import (
15
15
  AbstractCommandImpl,
@@ -72,36 +72,25 @@ class BlowOutInPlaceImplementation(
72
72
 
73
73
  async def execute(self, params: BlowOutInPlaceParams) -> _ExecuteReturn:
74
74
  """Blow-out without moving the pipette."""
75
- try:
76
- current_position = await self._gantry_mover.get_position(params.pipetteId)
77
- await self._pipetting.blow_out_in_place(
78
- pipette_id=params.pipetteId, flow_rate=params.flowRate
79
- )
80
- except PipetteOverpressureError as e:
81
- return DefinedErrorData(
82
- public=OverpressureError(
83
- id=self._model_utils.generate_id(),
84
- createdAt=self._model_utils.get_timestamp(),
85
- wrappedErrors=[
86
- ErrorOccurrence.from_failed(
87
- id=self._model_utils.generate_id(),
88
- createdAt=self._model_utils.get_timestamp(),
89
- error=e,
90
- )
91
- ],
92
- errorInfo={
93
- "retryLocation": (
94
- current_position.x,
95
- current_position.y,
96
- current_position.z,
97
- )
98
- },
99
- ),
100
- )
101
- else:
102
- return SuccessData(
103
- public=BlowOutInPlaceResult(),
104
- )
75
+ current_position = await self._gantry_mover.get_position(params.pipetteId)
76
+ result = await blow_out_in_place(
77
+ pipette_id=params.pipetteId,
78
+ flow_rate=params.flowRate,
79
+ location_if_error={
80
+ "retryLocation": (
81
+ current_position.x,
82
+ current_position.y,
83
+ current_position.z,
84
+ )
85
+ },
86
+ pipetting=self._pipetting,
87
+ model_utils=self._model_utils,
88
+ )
89
+ if isinstance(result, DefinedErrorData):
90
+ return result
91
+ return SuccessData(
92
+ public=BlowOutInPlaceResult(), state_update=result.state_update
93
+ )
105
94
 
106
95
 
107
96
  class BlowOutInPlace(
@@ -111,7 +100,7 @@ class BlowOutInPlace(
111
100
 
112
101
  commandType: BlowOutInPlaceCommandType = "blowOutInPlace"
113
102
  params: BlowOutInPlaceParams
114
- result: Optional[BlowOutInPlaceResult]
103
+ result: Optional[BlowOutInPlaceResult] = None
115
104
 
116
105
  _ImplementationCls: Type[
117
106
  BlowOutInPlaceImplementation
@@ -1,10 +1,11 @@
1
1
  """Models and implementation for the calibrateGripper command."""
2
2
 
3
3
  from enum import Enum
4
- from typing import Optional, Type
4
+ from typing import Optional, Type, Any
5
5
  from typing_extensions import Literal
6
6
 
7
7
  from pydantic import BaseModel, Field
8
+ from pydantic.json_schema import SkipJsonSchema
8
9
 
9
10
  from opentrons.types import Point
10
11
  from opentrons.hardware_control import HardwareControlAPI
@@ -22,6 +23,10 @@ from opentrons.protocol_engine.resources import ensure_ot3_hardware
22
23
  CalibrateGripperCommandType = Literal["calibration/calibrateGripper"]
23
24
 
24
25
 
26
+ def _remove_default(s: dict[str, Any]) -> None:
27
+ s.pop("default", None)
28
+
29
+
25
30
  class CalibrateGripperParamsJaw(Enum): # noqa: D101
26
31
  FRONT = "front"
27
32
  REAR = "rear"
@@ -39,7 +44,7 @@ class CalibrateGripperParams(BaseModel):
39
44
  ),
40
45
  )
41
46
 
42
- otherJawOffset: Optional[Vec3f] = Field(
47
+ otherJawOffset: Vec3f | SkipJsonSchema[None] = Field(
43
48
  None,
44
49
  description=(
45
50
  "If an offset for the other probe is already found, then specifying it here"
@@ -48,6 +53,7 @@ class CalibrateGripperParams(BaseModel):
48
53
  " If this param is not specified then the command will only find and return"
49
54
  " the offset for the specified probe."
50
55
  ),
56
+ json_schema_extra=_remove_default,
51
57
  )
52
58
 
53
59
 
@@ -62,11 +68,12 @@ class CalibrateGripperResult(BaseModel):
62
68
  ),
63
69
  )
64
70
 
65
- savedCalibration: Optional[GripperCalibrationOffset] = Field(
71
+ savedCalibration: GripperCalibrationOffset | SkipJsonSchema[None] = Field(
66
72
  None,
67
73
  description=(
68
74
  "Gripper calibration result data, when `otherJawOffset` is provided."
69
75
  ),
76
+ json_schema_extra=_remove_default,
70
77
  )
71
78
 
72
79
 
@@ -118,8 +125,8 @@ class CalibrateGripperImplementation(
118
125
  calibration_data = result
119
126
 
120
127
  return SuccessData(
121
- public=CalibrateGripperResult.construct(
122
- jawOffset=Vec3f.construct(
128
+ public=CalibrateGripperResult.model_construct(
129
+ jawOffset=Vec3f.model_construct(
123
130
  x=probe_offset.x, y=probe_offset.y, z=probe_offset.z
124
131
  ),
125
132
  savedCalibration=calibration_data,
@@ -143,7 +150,7 @@ class CalibrateGripper(
143
150
 
144
151
  commandType: CalibrateGripperCommandType = "calibration/calibrateGripper"
145
152
  params: CalibrateGripperParams
146
- result: Optional[CalibrateGripperResult]
153
+ result: Optional[CalibrateGripperResult] = None
147
154
 
148
155
  _ImplementationCls: Type[
149
156
  CalibrateGripperImplementation
@@ -101,7 +101,7 @@ class CalibrateModule(
101
101
 
102
102
  commandType: CalibrateModuleCommandType = "calibration/calibrateModule"
103
103
  params: CalibrateModuleParams
104
- result: Optional[CalibrateModuleResult]
104
+ result: Optional[CalibrateModuleResult] = None
105
105
 
106
106
  _ImplementationCls: Type[
107
107
  CalibrateModuleImplementation
@@ -65,8 +65,8 @@ class CalibratePipetteImplementation(
65
65
  await ot3_api.save_instrument_offset(mount=ot3_mount, delta=pipette_offset)
66
66
 
67
67
  return SuccessData(
68
- public=CalibratePipetteResult.construct(
69
- pipetteOffset=InstrumentOffsetVector.construct(
68
+ public=CalibratePipetteResult.model_construct(
69
+ pipetteOffset=InstrumentOffsetVector.model_construct(
70
70
  x=pipette_offset.x, y=pipette_offset.y, z=pipette_offset.z
71
71
  )
72
72
  ),
@@ -80,7 +80,7 @@ class CalibratePipette(
80
80
 
81
81
  commandType: CalibratePipetteCommandType = "calibration/calibratePipette"
82
82
  params: CalibratePipetteParams
83
- result: Optional[CalibratePipetteResult]
83
+ result: Optional[CalibratePipetteResult] = None
84
84
 
85
85
  _ImplementationCls: Type[
86
86
  CalibratePipetteImplementation
@@ -136,7 +136,7 @@ class MoveToMaintenancePosition(
136
136
  "calibration/moveToMaintenancePosition"
137
137
  )
138
138
  params: MoveToMaintenancePositionParams
139
- result: Optional[MoveToMaintenancePositionResult]
139
+ result: Optional[MoveToMaintenancePositionResult] = None
140
140
 
141
141
  _ImplementationCls: Type[
142
142
  MoveToMaintenancePositionImplementation
@@ -1,12 +1,11 @@
1
1
  """Base command data model and type definitions."""
2
2
 
3
-
4
3
  from __future__ import annotations
5
4
 
6
5
  import dataclasses
7
6
  from abc import ABC, abstractmethod
8
7
  from datetime import datetime
9
- from enum import Enum
8
+ import enum
10
9
  from typing import (
11
10
  TYPE_CHECKING,
12
11
  Generic,
@@ -15,10 +14,12 @@ from typing import (
15
14
  List,
16
15
  Type,
17
16
  Union,
17
+ Any,
18
+ Dict,
18
19
  )
19
20
 
20
21
  from pydantic import BaseModel, Field
21
- from pydantic.generics import GenericModel
22
+ from pydantic.json_schema import SkipJsonSchema
22
23
 
23
24
  from opentrons.hardware_control import HardwareControlAPI
24
25
  from opentrons.protocol_engine.state.update_types import StateUpdate
@@ -41,7 +42,7 @@ _ErrorT = TypeVar("_ErrorT", bound=ErrorOccurrence)
41
42
  _ErrorT_co = TypeVar("_ErrorT_co", bound=ErrorOccurrence, covariant=True)
42
43
 
43
44
 
44
- class CommandStatus(str, Enum):
45
+ class CommandStatus(str, enum.Enum):
45
46
  """Command execution status."""
46
47
 
47
48
  QUEUED = "queued"
@@ -50,7 +51,7 @@ class CommandStatus(str, Enum):
50
51
  FAILED = "failed"
51
52
 
52
53
 
53
- class CommandIntent(str, Enum):
54
+ class CommandIntent(str, enum.Enum):
54
55
  """Run intent for a given command.
55
56
 
56
57
  Props:
@@ -63,8 +64,12 @@ class CommandIntent(str, Enum):
63
64
  FIXIT = "fixit"
64
65
 
65
66
 
67
+ def _pop_default(s: Dict[str, Any]) -> None:
68
+ s.pop("default", None)
69
+
70
+
66
71
  class BaseCommandCreate(
67
- GenericModel,
72
+ BaseModel,
68
73
  # These type parameters need to be invariant because our fields are mutable.
69
74
  Generic[_ParamsT],
70
75
  ):
@@ -82,7 +87,7 @@ class BaseCommandCreate(
82
87
  ),
83
88
  )
84
89
  params: _ParamsT = Field(..., description="Command execution data payload")
85
- intent: Optional[CommandIntent] = Field(
90
+ intent: CommandIntent | SkipJsonSchema[None] = Field(
86
91
  None,
87
92
  description=(
88
93
  "The reason the command was added. If not specified or `protocol`,"
@@ -95,14 +100,16 @@ class BaseCommandCreate(
95
100
  "Use setup commands for activities like pre-run calibration checks"
96
101
  " and module setup, like pre-heating."
97
102
  ),
103
+ json_schema_extra=_pop_default,
98
104
  )
99
- key: Optional[str] = Field(
105
+ key: str | SkipJsonSchema[None] = Field(
100
106
  None,
101
107
  description=(
102
108
  "A key value, unique in this run, that can be used to track"
103
109
  " the same logical command across multiple runs of the same protocol."
104
110
  " If a value is not provided, one will be generated."
105
111
  ),
112
+ json_schema_extra=_pop_default,
106
113
  )
107
114
 
108
115
 
@@ -144,8 +151,65 @@ class DefinedErrorData(Generic[_ErrorT_co]):
144
151
  )
145
152
 
146
153
 
154
+ _ExecuteReturnT_co = TypeVar(
155
+ "_ExecuteReturnT_co",
156
+ bound=Union[
157
+ SuccessData[BaseModel],
158
+ DefinedErrorData[ErrorOccurrence],
159
+ ],
160
+ covariant=True,
161
+ )
162
+
163
+
164
+ class AbstractCommandImpl(
165
+ ABC,
166
+ Generic[_ParamsT_contra, _ExecuteReturnT_co],
167
+ ):
168
+ """Abstract command creation and execution implementation.
169
+
170
+ A given command request should map to a specific command implementation,
171
+ which defines how to execute the command and map data from execution into the
172
+ result model.
173
+ """
174
+
175
+ def __init__(
176
+ self,
177
+ state_view: StateView,
178
+ hardware_api: HardwareControlAPI,
179
+ equipment: execution.EquipmentHandler,
180
+ file_provider: execution.FileProvider,
181
+ movement: execution.MovementHandler,
182
+ gantry_mover: execution.GantryMover,
183
+ labware_movement: execution.LabwareMovementHandler,
184
+ pipetting: execution.PipettingHandler,
185
+ tip_handler: execution.TipHandler,
186
+ run_control: execution.RunControlHandler,
187
+ rail_lights: execution.RailLightsHandler,
188
+ model_utils: ModelUtils,
189
+ status_bar: execution.StatusBarHandler,
190
+ command_note_adder: CommandNoteAdder,
191
+ ) -> None:
192
+ """Initialize the command implementation with execution handlers."""
193
+ pass
194
+
195
+ @abstractmethod
196
+ async def execute(self, params: _ParamsT_contra) -> _ExecuteReturnT_co:
197
+ """Execute the command, mapping data from execution into a response model.
198
+
199
+ This should either:
200
+
201
+ - Return a `SuccessData`, if the command completed normally.
202
+ - Return a `DefinedErrorData`, if the command failed with a "defined error."
203
+ Defined errors are errors that are documented as part of the robot's public
204
+ API.
205
+ - Raise an exception, if the command failed with any other error
206
+ (in other words, an undefined error).
207
+ """
208
+ ...
209
+
210
+
147
211
  class BaseCommand(
148
- GenericModel,
212
+ BaseModel,
149
213
  # These type parameters need to be invariant because our fields are mutable.
150
214
  Generic[_ParamsT, _ResultT, _ErrorT],
151
215
  ):
@@ -242,60 +306,3 @@ class BaseCommand(
242
306
  ],
243
307
  ]
244
308
  ]
245
-
246
-
247
- _ExecuteReturnT_co = TypeVar(
248
- "_ExecuteReturnT_co",
249
- bound=Union[
250
- SuccessData[BaseModel],
251
- DefinedErrorData[ErrorOccurrence],
252
- ],
253
- covariant=True,
254
- )
255
-
256
-
257
- class AbstractCommandImpl(
258
- ABC,
259
- Generic[_ParamsT_contra, _ExecuteReturnT_co],
260
- ):
261
- """Abstract command creation and execution implementation.
262
-
263
- A given command request should map to a specific command implementation,
264
- which defines how to execute the command and map data from execution into the
265
- result model.
266
- """
267
-
268
- def __init__(
269
- self,
270
- state_view: StateView,
271
- hardware_api: HardwareControlAPI,
272
- equipment: execution.EquipmentHandler,
273
- file_provider: execution.FileProvider,
274
- movement: execution.MovementHandler,
275
- gantry_mover: execution.GantryMover,
276
- labware_movement: execution.LabwareMovementHandler,
277
- pipetting: execution.PipettingHandler,
278
- tip_handler: execution.TipHandler,
279
- run_control: execution.RunControlHandler,
280
- rail_lights: execution.RailLightsHandler,
281
- model_utils: ModelUtils,
282
- status_bar: execution.StatusBarHandler,
283
- command_note_adder: CommandNoteAdder,
284
- ) -> None:
285
- """Initialize the command implementation with execution handlers."""
286
- pass
287
-
288
- @abstractmethod
289
- async def execute(self, params: _ParamsT_contra) -> _ExecuteReturnT_co:
290
- """Execute the command, mapping data from execution into a response model.
291
-
292
- This should either:
293
-
294
- - Return a `SuccessData`, if the command completed normally.
295
- - Return a `DefinedErrorData`, if the command failed with a "defined error."
296
- Defined errors are errors that are documented as part of the robot's public
297
- API.
298
- - Raise an exception, if the command failed with any other error
299
- (in other words, an undefined error).
300
- """
301
- ...