opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.0a0__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.

Potentially problematic release.


This version of opentrons might be problematic. Click here for more details.

Files changed (230) hide show
  1. opentrons/cli/analyze.py +71 -7
  2. opentrons/config/__init__.py +9 -0
  3. opentrons/config/advanced_settings.py +22 -0
  4. opentrons/config/defaults_ot3.py +14 -36
  5. opentrons/config/feature_flags.py +4 -0
  6. opentrons/config/types.py +6 -17
  7. opentrons/drivers/absorbance_reader/abstract.py +27 -3
  8. opentrons/drivers/absorbance_reader/async_byonoy.py +207 -154
  9. opentrons/drivers/absorbance_reader/driver.py +24 -15
  10. opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
  11. opentrons/drivers/absorbance_reader/simulator.py +32 -6
  12. opentrons/drivers/types.py +23 -1
  13. opentrons/execute.py +2 -2
  14. opentrons/hardware_control/api.py +18 -10
  15. opentrons/hardware_control/backends/controller.py +3 -2
  16. opentrons/hardware_control/backends/flex_protocol.py +11 -5
  17. opentrons/hardware_control/backends/ot3controller.py +18 -50
  18. opentrons/hardware_control/backends/ot3simulator.py +7 -6
  19. opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
  20. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  21. opentrons/hardware_control/module_control.py +43 -2
  22. opentrons/hardware_control/modules/__init__.py +7 -1
  23. opentrons/hardware_control/modules/absorbance_reader.py +230 -83
  24. opentrons/hardware_control/modules/errors.py +7 -0
  25. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  26. opentrons/hardware_control/modules/magdeck.py +12 -3
  27. opentrons/hardware_control/modules/mod_abc.py +27 -2
  28. opentrons/hardware_control/modules/tempdeck.py +15 -7
  29. opentrons/hardware_control/modules/thermocycler.py +69 -3
  30. opentrons/hardware_control/modules/types.py +11 -5
  31. opentrons/hardware_control/modules/update.py +11 -5
  32. opentrons/hardware_control/modules/utils.py +3 -1
  33. opentrons/hardware_control/ot3_calibration.py +6 -6
  34. opentrons/hardware_control/ot3api.py +126 -89
  35. opentrons/hardware_control/poller.py +15 -11
  36. opentrons/hardware_control/protocols/__init__.py +1 -7
  37. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  38. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  39. opentrons/motion_planning/__init__.py +2 -0
  40. opentrons/motion_planning/waypoints.py +32 -0
  41. opentrons/protocol_api/__init__.py +2 -1
  42. opentrons/protocol_api/_liquid.py +87 -1
  43. opentrons/protocol_api/_parameter_context.py +10 -1
  44. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  45. opentrons/protocol_api/core/engine/instrument.py +29 -25
  46. opentrons/protocol_api/core/engine/labware.py +10 -2
  47. opentrons/protocol_api/core/engine/module_core.py +129 -17
  48. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +355 -0
  49. opentrons/protocol_api/core/engine/protocol.py +55 -2
  50. opentrons/protocol_api/core/instrument.py +2 -0
  51. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  52. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +5 -2
  53. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  54. opentrons/protocol_api/core/module.py +22 -4
  55. opentrons/protocol_api/core/protocol.py +5 -2
  56. opentrons/protocol_api/instrument_context.py +52 -20
  57. opentrons/protocol_api/labware.py +13 -1
  58. opentrons/protocol_api/module_contexts.py +68 -13
  59. opentrons/protocol_api/protocol_context.py +38 -4
  60. opentrons/protocol_api/validation.py +5 -3
  61. opentrons/protocol_engine/__init__.py +10 -9
  62. opentrons/protocol_engine/actions/__init__.py +5 -0
  63. opentrons/protocol_engine/actions/actions.py +42 -25
  64. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  65. opentrons/protocol_engine/clients/sync_client.py +7 -1
  66. opentrons/protocol_engine/clients/transports.py +1 -1
  67. opentrons/protocol_engine/commands/__init__.py +0 -4
  68. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  69. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +161 -0
  70. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +53 -9
  71. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +160 -0
  72. opentrons/protocol_engine/commands/absorbance_reader/read.py +196 -0
  73. opentrons/protocol_engine/commands/aspirate.py +29 -16
  74. opentrons/protocol_engine/commands/aspirate_in_place.py +32 -15
  75. opentrons/protocol_engine/commands/blow_out.py +63 -14
  76. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  77. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  78. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  79. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  80. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  81. opentrons/protocol_engine/commands/command.py +28 -17
  82. opentrons/protocol_engine/commands/command_unions.py +37 -24
  83. opentrons/protocol_engine/commands/comment.py +5 -3
  84. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  85. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  86. opentrons/protocol_engine/commands/custom.py +5 -3
  87. opentrons/protocol_engine/commands/dispense.py +42 -20
  88. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  89. opentrons/protocol_engine/commands/drop_tip.py +68 -15
  90. opentrons/protocol_engine/commands/drop_tip_in_place.py +52 -11
  91. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  92. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  93. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  94. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  95. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  96. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  97. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  98. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  99. opentrons/protocol_engine/commands/home.py +11 -5
  100. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  101. opentrons/protocol_engine/commands/load_labware.py +19 -5
  102. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  103. opentrons/protocol_engine/commands/load_module.py +43 -6
  104. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  105. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  106. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  107. opentrons/protocol_engine/commands/move_labware.py +106 -19
  108. opentrons/protocol_engine/commands/move_relative.py +15 -3
  109. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  110. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  111. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  112. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  113. opentrons/protocol_engine/commands/pick_up_tip.py +50 -29
  114. opentrons/protocol_engine/commands/pipetting_common.py +39 -15
  115. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  116. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  117. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  118. opentrons/protocol_engine/commands/save_position.py +2 -3
  119. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  120. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  121. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  122. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  123. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  124. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  125. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  126. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  127. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  128. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  129. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  130. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  131. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  132. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  133. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  135. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  136. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  137. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  138. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  139. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  140. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +194 -0
  141. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +75 -0
  142. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +5 -3
  143. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  144. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  145. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  146. opentrons/protocol_engine/create_protocol_engine.py +41 -8
  147. opentrons/protocol_engine/engine_support.py +2 -1
  148. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  149. opentrons/protocol_engine/errors/__init__.py +18 -0
  150. opentrons/protocol_engine/errors/exceptions.py +114 -2
  151. opentrons/protocol_engine/execution/__init__.py +2 -0
  152. opentrons/protocol_engine/execution/command_executor.py +22 -13
  153. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  154. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  155. opentrons/protocol_engine/execution/equipment.py +2 -1
  156. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  157. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  158. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  159. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  160. opentrons/protocol_engine/execution/labware_movement.py +6 -3
  161. opentrons/protocol_engine/execution/movement.py +8 -3
  162. opentrons/protocol_engine/execution/pipetting.py +7 -4
  163. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  164. opentrons/protocol_engine/execution/run_control.py +1 -1
  165. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  166. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  167. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  168. opentrons/protocol_engine/notes/__init__.py +14 -2
  169. opentrons/protocol_engine/notes/notes.py +18 -1
  170. opentrons/protocol_engine/plugins.py +1 -1
  171. opentrons/protocol_engine/protocol_engine.py +54 -31
  172. opentrons/protocol_engine/resources/__init__.py +2 -0
  173. opentrons/protocol_engine/resources/deck_data_provider.py +58 -5
  174. opentrons/protocol_engine/resources/file_provider.py +157 -0
  175. opentrons/protocol_engine/resources/fixture_validation.py +5 -0
  176. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  177. opentrons/protocol_engine/state/__init__.py +0 -70
  178. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  179. opentrons/protocol_engine/state/command_history.py +21 -2
  180. opentrons/protocol_engine/state/commands.py +110 -31
  181. opentrons/protocol_engine/state/files.py +59 -0
  182. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  183. opentrons/protocol_engine/state/geometry.py +359 -15
  184. opentrons/protocol_engine/state/labware.py +166 -63
  185. opentrons/protocol_engine/state/liquids.py +1 -1
  186. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +19 -3
  187. opentrons/protocol_engine/state/modules.py +167 -85
  188. opentrons/protocol_engine/state/motion.py +16 -9
  189. opentrons/protocol_engine/state/pipettes.py +157 -317
  190. opentrons/protocol_engine/state/state.py +30 -1
  191. opentrons/protocol_engine/state/state_summary.py +3 -0
  192. opentrons/protocol_engine/state/tips.py +69 -114
  193. opentrons/protocol_engine/state/update_types.py +408 -0
  194. opentrons/protocol_engine/state/wells.py +236 -0
  195. opentrons/protocol_engine/types.py +90 -0
  196. opentrons/protocol_reader/file_format_validator.py +83 -15
  197. opentrons/protocol_runner/json_translator.py +21 -5
  198. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  199. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  200. opentrons/protocol_runner/protocol_runner.py +6 -3
  201. opentrons/protocol_runner/run_orchestrator.py +26 -6
  202. opentrons/protocols/advanced_control/mix.py +3 -5
  203. opentrons/protocols/advanced_control/transfers.py +125 -56
  204. opentrons/protocols/api_support/constants.py +1 -1
  205. opentrons/protocols/api_support/definitions.py +1 -1
  206. opentrons/protocols/api_support/labware_like.py +4 -4
  207. opentrons/protocols/api_support/tip_tracker.py +2 -2
  208. opentrons/protocols/api_support/types.py +15 -2
  209. opentrons/protocols/api_support/util.py +30 -42
  210. opentrons/protocols/duration/errors.py +1 -1
  211. opentrons/protocols/duration/estimator.py +50 -29
  212. opentrons/protocols/execution/dev_types.py +2 -2
  213. opentrons/protocols/execution/execute_json_v4.py +15 -10
  214. opentrons/protocols/execution/execute_python.py +8 -3
  215. opentrons/protocols/geometry/planning.py +12 -12
  216. opentrons/protocols/labware.py +17 -33
  217. opentrons/simulate.py +3 -3
  218. opentrons/types.py +30 -3
  219. opentrons/util/logging_config.py +34 -0
  220. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/METADATA +5 -4
  221. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/RECORD +227 -215
  222. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  223. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  224. opentrons/protocol_runner/thread_async_queue.py +0 -174
  225. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  226. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  227. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/LICENSE +0 -0
  228. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/WHEEL +0 -0
  229. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/entry_points.txt +0 -0
  230. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0a0.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,26 @@
1
1
  """Blow-out command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
- from typing import TYPE_CHECKING, Optional, Type
3
+ from typing import TYPE_CHECKING, Optional, Type, Union
4
+ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
4
5
  from typing_extensions import Literal
5
6
 
7
+
8
+ from ..state.update_types import StateUpdate
6
9
  from ..types import DeckPoint
7
10
  from .pipetting_common import (
11
+ OverpressureError,
8
12
  PipetteIdMixin,
9
13
  FlowRateMixin,
10
14
  WellLocationMixin,
11
15
  DestinationPositionResult,
12
16
  )
13
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
17
+ from .command import (
18
+ AbstractCommandImpl,
19
+ BaseCommand,
20
+ BaseCommandCreate,
21
+ DefinedErrorData,
22
+ SuccessData,
23
+ )
14
24
  from ..errors.error_occurrence import ErrorOccurrence
15
25
 
16
26
  from opentrons.hardware_control import HardwareControlAPI
@@ -18,7 +28,9 @@ from opentrons.hardware_control import HardwareControlAPI
18
28
 
19
29
  if TYPE_CHECKING:
20
30
  from ..execution import MovementHandler, PipettingHandler
21
- from ..state import StateView
31
+ from ..state.state import StateView
32
+ from ..resources import ModelUtils
33
+
22
34
 
23
35
  BlowOutCommandType = Literal["blowout"]
24
36
 
@@ -35,9 +47,13 @@ class BlowOutResult(DestinationPositionResult):
35
47
  pass
36
48
 
37
49
 
38
- class BlowOutImplementation(
39
- AbstractCommandImpl[BlowOutParams, SuccessData[BlowOutResult, None]]
40
- ):
50
+ _ExecuteReturn = Union[
51
+ SuccessData[BlowOutResult],
52
+ DefinedErrorData[OverpressureError],
53
+ ]
54
+
55
+
56
+ class BlowOutImplementation(AbstractCommandImpl[BlowOutParams, _ExecuteReturn]):
41
57
  """BlowOut command implementation."""
42
58
 
43
59
  def __init__(
@@ -46,29 +62,62 @@ class BlowOutImplementation(
46
62
  pipetting: PipettingHandler,
47
63
  state_view: StateView,
48
64
  hardware_api: HardwareControlAPI,
65
+ model_utils: ModelUtils,
49
66
  **kwargs: object,
50
67
  ) -> None:
51
68
  self._movement = movement
52
69
  self._pipetting = pipetting
53
70
  self._state_view = state_view
54
71
  self._hardware_api = hardware_api
72
+ self._model_utils = model_utils
55
73
 
56
- async def execute(self, params: BlowOutParams) -> SuccessData[BlowOutResult, None]:
74
+ async def execute(self, params: BlowOutParams) -> _ExecuteReturn:
57
75
  """Move to and blow-out the requested well."""
76
+ state_update = StateUpdate()
77
+
58
78
  x, y, z = await self._movement.move_to_well(
59
79
  pipette_id=params.pipetteId,
60
80
  labware_id=params.labwareId,
61
81
  well_name=params.wellName,
62
82
  well_location=params.wellLocation,
63
83
  )
64
-
65
- await self._pipetting.blow_out_in_place(
66
- pipette_id=params.pipetteId, flow_rate=params.flowRate
67
- )
68
-
69
- return SuccessData(
70
- public=BlowOutResult(position=DeckPoint(x=x, y=y, z=z)), private=None
84
+ deck_point = DeckPoint.construct(x=x, y=y, z=z)
85
+ state_update.set_pipette_location(
86
+ pipette_id=params.pipetteId,
87
+ new_labware_id=params.labwareId,
88
+ new_well_name=params.wellName,
89
+ new_deck_point=deck_point,
71
90
  )
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:
96
+ 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
+ },
114
+ ),
115
+ )
116
+ else:
117
+ return SuccessData(
118
+ public=BlowOutResult(position=deck_point),
119
+ state_update=state_update,
120
+ )
72
121
 
73
122
 
74
123
  class BlowOut(BaseCommand[BlowOutParams, BlowOutResult, ErrorOccurrence]):
@@ -1,23 +1,32 @@
1
1
  """Blow-out in place command request, result, and implementation models."""
2
2
 
3
3
  from __future__ import annotations
4
- from typing import TYPE_CHECKING, Optional, Type
4
+ from typing import TYPE_CHECKING, Optional, Type, Union
5
+ from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
5
6
  from typing_extensions import Literal
6
7
  from pydantic import BaseModel
7
8
 
8
9
  from .pipetting_common import (
10
+ OverpressureError,
9
11
  PipetteIdMixin,
10
12
  FlowRateMixin,
11
13
  )
12
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
14
+ from .command import (
15
+ AbstractCommandImpl,
16
+ BaseCommand,
17
+ BaseCommandCreate,
18
+ DefinedErrorData,
19
+ SuccessData,
20
+ )
13
21
  from ..errors.error_occurrence import ErrorOccurrence
14
22
 
15
23
  from opentrons.hardware_control import HardwareControlAPI
16
24
 
17
25
 
18
26
  if TYPE_CHECKING:
19
- from ..execution import PipettingHandler
20
- from ..state import StateView
27
+ from ..execution import PipettingHandler, GantryMover
28
+ from ..state.state import StateView
29
+ from ..resources import ModelUtils
21
30
 
22
31
 
23
32
  BlowOutInPlaceCommandType = Literal["blowOutInPlace"]
@@ -35,8 +44,14 @@ class BlowOutInPlaceResult(BaseModel):
35
44
  pass
36
45
 
37
46
 
47
+ _ExecuteReturn = Union[
48
+ SuccessData[BlowOutInPlaceResult],
49
+ DefinedErrorData[OverpressureError],
50
+ ]
51
+
52
+
38
53
  class BlowOutInPlaceImplementation(
39
- AbstractCommandImpl[BlowOutInPlaceParams, SuccessData[BlowOutInPlaceResult, None]]
54
+ AbstractCommandImpl[BlowOutInPlaceParams, _ExecuteReturn]
40
55
  ):
41
56
  """BlowOutInPlace command implementation."""
42
57
 
@@ -45,21 +60,48 @@ class BlowOutInPlaceImplementation(
45
60
  pipetting: PipettingHandler,
46
61
  state_view: StateView,
47
62
  hardware_api: HardwareControlAPI,
63
+ model_utils: ModelUtils,
64
+ gantry_mover: GantryMover,
48
65
  **kwargs: object,
49
66
  ) -> None:
50
67
  self._pipetting = pipetting
51
68
  self._state_view = state_view
52
69
  self._hardware_api = hardware_api
70
+ self._model_utils = model_utils
71
+ self._gantry_mover = gantry_mover
53
72
 
54
- async def execute(
55
- self, params: BlowOutInPlaceParams
56
- ) -> SuccessData[BlowOutInPlaceResult, None]:
73
+ async def execute(self, params: BlowOutInPlaceParams) -> _ExecuteReturn:
57
74
  """Blow-out without moving the pipette."""
58
- await self._pipetting.blow_out_in_place(
59
- pipette_id=params.pipetteId, flow_rate=params.flowRate
60
- )
61
-
62
- return SuccessData(public=BlowOutInPlaceResult(), private=None)
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
+ )
63
105
 
64
106
 
65
107
  class BlowOutInPlace(
@@ -71,9 +71,7 @@ class CalibrateGripperResult(BaseModel):
71
71
 
72
72
 
73
73
  class CalibrateGripperImplementation(
74
- AbstractCommandImpl[
75
- CalibrateGripperParams, SuccessData[CalibrateGripperResult, None]
76
- ]
74
+ AbstractCommandImpl[CalibrateGripperParams, SuccessData[CalibrateGripperResult]]
77
75
  ):
78
76
  """The implementation of a `calibrateGripper` command."""
79
77
 
@@ -87,7 +85,7 @@ class CalibrateGripperImplementation(
87
85
 
88
86
  async def execute(
89
87
  self, params: CalibrateGripperParams
90
- ) -> SuccessData[CalibrateGripperResult, None]:
88
+ ) -> SuccessData[CalibrateGripperResult]:
91
89
  """Execute a `calibrateGripper` command.
92
90
 
93
91
  1. Move from the current location to the calibration area on the deck.
@@ -126,7 +124,6 @@ class CalibrateGripperImplementation(
126
124
  ),
127
125
  savedCalibration=calibration_data,
128
126
  ),
129
- private=None,
130
127
  )
131
128
 
132
129
  @staticmethod
@@ -12,7 +12,7 @@ from ...errors.error_occurrence import ErrorOccurrence
12
12
 
13
13
  # Work around type-only circular dependencies.
14
14
  if TYPE_CHECKING:
15
- from ...state import StateView
15
+ from ...state.state import StateView
16
16
 
17
17
  from ...types import ModuleOffsetVector, DeckSlotLocation
18
18
 
@@ -49,7 +49,7 @@ class CalibrateModuleResult(BaseModel):
49
49
 
50
50
 
51
51
  class CalibrateModuleImplementation(
52
- AbstractCommandImpl[CalibrateModuleParams, SuccessData[CalibrateModuleResult, None]]
52
+ AbstractCommandImpl[CalibrateModuleParams, SuccessData[CalibrateModuleResult]]
53
53
  ):
54
54
  """CalibrateModule command implementation."""
55
55
 
@@ -64,7 +64,7 @@ class CalibrateModuleImplementation(
64
64
 
65
65
  async def execute(
66
66
  self, params: CalibrateModuleParams
67
- ) -> SuccessData[CalibrateModuleResult, None]:
67
+ ) -> SuccessData[CalibrateModuleResult]:
68
68
  """Execute calibrate-module command."""
69
69
  ot3_api = ensure_ot3_hardware(
70
70
  self._hardware_api,
@@ -91,7 +91,6 @@ class CalibrateModuleImplementation(
91
91
  ),
92
92
  location=slot,
93
93
  ),
94
- private=None,
95
94
  )
96
95
 
97
96
 
@@ -34,9 +34,7 @@ class CalibratePipetteResult(BaseModel):
34
34
 
35
35
 
36
36
  class CalibratePipetteImplementation(
37
- AbstractCommandImpl[
38
- CalibratePipetteParams, SuccessData[CalibratePipetteResult, None]
39
- ]
37
+ AbstractCommandImpl[CalibratePipetteParams, SuccessData[CalibratePipetteResult]]
40
38
  ):
41
39
  """CalibratePipette command implementation."""
42
40
 
@@ -49,7 +47,7 @@ class CalibratePipetteImplementation(
49
47
 
50
48
  async def execute(
51
49
  self, params: CalibratePipetteParams
52
- ) -> SuccessData[CalibratePipetteResult, None]:
50
+ ) -> SuccessData[CalibratePipetteResult]:
53
51
  """Execute calibrate-pipette command."""
54
52
  # TODO (tz, 20-9-22): Add a better solution to determine if a command can be executed on an OT-3/OT-2
55
53
  ot3_api = ensure_ot3_hardware(
@@ -72,7 +70,6 @@ class CalibratePipetteImplementation(
72
70
  x=pipette_offset.x, y=pipette_offset.y, z=pipette_offset.z
73
71
  )
74
72
  ),
75
- private=None,
76
73
  )
77
74
 
78
75
 
@@ -15,7 +15,7 @@ from opentrons.protocol_engine.resources.ot3_validation import ensure_ot3_hardwa
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from opentrons.hardware_control import HardwareControlAPI
18
- from ...state import StateView
18
+ from ...state.state import StateView
19
19
 
20
20
  # These offsets supplied from HW
21
21
  _ATTACH_POINT = Point(x=0, y=110)
@@ -57,7 +57,7 @@ class MoveToMaintenancePositionResult(BaseModel):
57
57
  class MoveToMaintenancePositionImplementation(
58
58
  AbstractCommandImpl[
59
59
  MoveToMaintenancePositionParams,
60
- SuccessData[MoveToMaintenancePositionResult, None],
60
+ SuccessData[MoveToMaintenancePositionResult],
61
61
  ]
62
62
  ):
63
63
  """Calibration set up position command implementation."""
@@ -73,7 +73,7 @@ class MoveToMaintenancePositionImplementation(
73
73
 
74
74
  async def execute(
75
75
  self, params: MoveToMaintenancePositionParams
76
- ) -> SuccessData[MoveToMaintenancePositionResult, None]:
76
+ ) -> SuccessData[MoveToMaintenancePositionResult]:
77
77
  """Move the requested mount to a maintenance deck slot."""
78
78
  ot3_api = ensure_ot3_hardware(
79
79
  self._hardware_api,
@@ -118,7 +118,9 @@ class MoveToMaintenancePositionImplementation(
118
118
  )
119
119
  await ot3_api.disengage_axes([Axis.Z_R])
120
120
 
121
- return SuccessData(public=MoveToMaintenancePositionResult(), private=None)
121
+ return SuccessData(
122
+ public=MoveToMaintenancePositionResult(),
123
+ )
122
124
 
123
125
 
124
126
  class MoveToMaintenancePosition(
@@ -3,8 +3,8 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
+ import dataclasses
6
7
  from abc import ABC, abstractmethod
7
- from dataclasses import dataclass
8
8
  from datetime import datetime
9
9
  from enum import Enum
10
10
  from typing import (
@@ -21,6 +21,7 @@ from pydantic import BaseModel, Field
21
21
  from pydantic.generics import GenericModel
22
22
 
23
23
  from opentrons.hardware_control import HardwareControlAPI
24
+ from opentrons.protocol_engine.state.update_types import StateUpdate
24
25
 
25
26
  from ..resources import ModelUtils
26
27
  from ..errors import ErrorOccurrence
@@ -29,7 +30,7 @@ from ..notes import CommandNote, CommandNoteAdder
29
30
  # Work around type-only circular dependencies.
30
31
  if TYPE_CHECKING:
31
32
  from .. import execution
32
- from ..state import StateView
33
+ from ..state.state import StateView
33
34
 
34
35
 
35
36
  _ParamsT = TypeVar("_ParamsT", bound=BaseModel)
@@ -38,7 +39,6 @@ _ResultT = TypeVar("_ResultT", bound=BaseModel)
38
39
  _ResultT_co = TypeVar("_ResultT_co", bound=BaseModel, covariant=True)
39
40
  _ErrorT = TypeVar("_ErrorT", bound=ErrorOccurrence)
40
41
  _ErrorT_co = TypeVar("_ErrorT_co", bound=ErrorOccurrence, covariant=True)
41
- _PrivateResultT_co = TypeVar("_PrivateResultT_co", covariant=True)
42
42
 
43
43
 
44
44
  class CommandStatus(str, Enum):
@@ -106,19 +106,23 @@ class BaseCommandCreate(
106
106
  )
107
107
 
108
108
 
109
- @dataclass(frozen=True)
110
- class SuccessData(Generic[_ResultT_co, _PrivateResultT_co]):
109
+ @dataclasses.dataclass(frozen=True)
110
+ class SuccessData(Generic[_ResultT_co]):
111
111
  """Data from the successful completion of a command."""
112
112
 
113
113
  public: _ResultT_co
114
114
  """Public result data. Exposed over HTTP and stored in databases."""
115
115
 
116
- private: _PrivateResultT_co
117
- """Additional result data, only given to `opentrons.protocol_engine` internals."""
116
+ state_update: StateUpdate = dataclasses.field(
117
+ # todo(mm, 2024-08-22): Remove the default once all command implementations
118
+ # use this, to make it harder to forget in new command implementations.
119
+ default_factory=StateUpdate
120
+ )
121
+ """How the engine state should be updated to reflect this command success."""
118
122
 
119
123
 
120
- @dataclass(frozen=True)
121
- class DefinedErrorData(Generic[_ErrorT_co, _PrivateResultT_co]):
124
+ @dataclasses.dataclass(frozen=True)
125
+ class DefinedErrorData(Generic[_ErrorT_co]):
122
126
  """Data from a command that failed with a defined error.
123
127
 
124
128
  This should only be used for "defined" errors, not any error.
@@ -128,8 +132,16 @@ class DefinedErrorData(Generic[_ErrorT_co, _PrivateResultT_co]):
128
132
  public: _ErrorT_co
129
133
  """Public error data. Exposed over HTTP and stored in databases."""
130
134
 
131
- private: _PrivateResultT_co
132
- """Additional error data, only given to `opentrons.protocol_engine` internals."""
135
+ state_update: StateUpdate = dataclasses.field(
136
+ # todo(mm, 2024-08-22): Remove the default once all command implementations
137
+ # use this, to make it harder to forget in new command implementations.
138
+ default_factory=StateUpdate
139
+ )
140
+ """How the engine state should be updated to reflect this command failure."""
141
+
142
+ state_update_if_false_positive: StateUpdate = dataclasses.field(
143
+ default_factory=StateUpdate
144
+ )
133
145
 
134
146
 
135
147
  class BaseCommand(
@@ -219,13 +231,11 @@ class BaseCommand(
219
231
  # Our _ImplementationCls must return public result data that can fit
220
232
  # in our `result` field:
221
233
  _ResultT,
222
- # But we don't care (here) what kind of private result data it returns:
223
- object,
224
234
  ],
225
235
  DefinedErrorData[
226
- # Likewise, for our `error` field:
236
+ # Our _ImplementationCls must return public error data that can fit
237
+ # in our `error` field:
227
238
  _ErrorT,
228
- object,
229
239
  ],
230
240
  ],
231
241
  ]
@@ -235,8 +245,8 @@ class BaseCommand(
235
245
  _ExecuteReturnT_co = TypeVar(
236
246
  "_ExecuteReturnT_co",
237
247
  bound=Union[
238
- SuccessData[BaseModel, object],
239
- DefinedErrorData[ErrorOccurrence, object],
248
+ SuccessData[BaseModel],
249
+ DefinedErrorData[ErrorOccurrence],
240
250
  ],
241
251
  covariant=True,
242
252
  )
@@ -258,6 +268,7 @@ class AbstractCommandImpl(
258
268
  state_view: StateView,
259
269
  hardware_api: HardwareControlAPI,
260
270
  equipment: execution.EquipmentHandler,
271
+ file_provider: execution.FileProvider,
261
272
  movement: execution.MovementHandler,
262
273
  gantry_mover: execution.GantryMover,
263
274
  labware_movement: execution.LabwareMovementHandler,
@@ -10,9 +10,8 @@ from opentrons.util.get_union_elements import get_union_elements
10
10
  from .command import DefinedErrorData
11
11
  from .pipetting_common import (
12
12
  OverpressureError,
13
- OverpressureErrorInternalData,
14
13
  LiquidNotFoundError,
15
- LiquidNotFoundErrorInternalData,
14
+ TipPhysicallyAttachedError,
16
15
  )
17
16
 
18
17
  from . import absorbance_reader
@@ -142,10 +141,10 @@ from .load_pipette import (
142
141
  LoadPipetteCreate,
143
142
  LoadPipetteResult,
144
143
  LoadPipetteCommandType,
145
- LoadPipettePrivateResult,
146
144
  )
147
145
 
148
146
  from .move_labware import (
147
+ GripperMovementError,
149
148
  MoveLabware,
150
149
  MoveLabwareParams,
151
150
  MoveLabwareCreate,
@@ -216,7 +215,6 @@ from .pick_up_tip import (
216
215
  PickUpTipResult,
217
216
  PickUpTipCommandType,
218
217
  TipPhysicallyMissingError,
219
- TipPhysicallyMissingErrorInternalData,
220
218
  )
221
219
 
222
220
  from .touch_tip import (
@@ -273,7 +271,6 @@ from .configure_for_volume import (
273
271
  ConfigureForVolumeCreate,
274
272
  ConfigureForVolumeResult,
275
273
  ConfigureForVolumeCommandType,
276
- ConfigureForVolumePrivateResult,
277
274
  )
278
275
 
279
276
  from .prepare_to_aspirate import (
@@ -290,7 +287,6 @@ from .configure_nozzle_layout import (
290
287
  ConfigureNozzleLayoutParams,
291
288
  ConfigureNozzleLayoutResult,
292
289
  ConfigureNozzleLayoutCommandType,
293
- ConfigureNozzleLayoutPrivateResult,
294
290
  )
295
291
 
296
292
  from .verify_tip_presence import (
@@ -382,8 +378,11 @@ Command = Annotated[
382
378
  thermocycler.OpenLid,
383
379
  thermocycler.CloseLid,
384
380
  thermocycler.RunProfile,
381
+ thermocycler.RunExtendedProfile,
382
+ absorbance_reader.CloseLid,
383
+ absorbance_reader.OpenLid,
385
384
  absorbance_reader.Initialize,
386
- absorbance_reader.MeasureAbsorbance,
385
+ absorbance_reader.ReadAbsorbance,
387
386
  calibration.CalibrateGripper,
388
387
  calibration.CalibratePipette,
389
388
  calibration.CalibrateModule,
@@ -392,6 +391,8 @@ Command = Annotated[
392
391
  unsafe.UnsafeDropTipInPlace,
393
392
  unsafe.UpdatePositionEstimators,
394
393
  unsafe.UnsafeEngageAxes,
394
+ unsafe.UnsafeUngripLabware,
395
+ unsafe.UnsafePlaceLabware,
395
396
  ],
396
397
  Field(discriminator="commandType"),
397
398
  ]
@@ -455,8 +456,11 @@ CommandParams = Union[
455
456
  thermocycler.OpenLidParams,
456
457
  thermocycler.CloseLidParams,
457
458
  thermocycler.RunProfileParams,
459
+ thermocycler.RunExtendedProfileParams,
460
+ absorbance_reader.CloseLidParams,
461
+ absorbance_reader.OpenLidParams,
458
462
  absorbance_reader.InitializeParams,
459
- absorbance_reader.MeasureAbsorbanceParams,
463
+ absorbance_reader.ReadAbsorbanceParams,
460
464
  calibration.CalibrateGripperParams,
461
465
  calibration.CalibratePipetteParams,
462
466
  calibration.CalibrateModuleParams,
@@ -465,6 +469,8 @@ CommandParams = Union[
465
469
  unsafe.UnsafeDropTipInPlaceParams,
466
470
  unsafe.UpdatePositionEstimatorsParams,
467
471
  unsafe.UnsafeEngageAxesParams,
472
+ unsafe.UnsafeUngripLabwareParams,
473
+ unsafe.UnsafePlaceLabwareParams,
468
474
  ]
469
475
 
470
476
  CommandType = Union[
@@ -526,8 +532,11 @@ CommandType = Union[
526
532
  thermocycler.OpenLidCommandType,
527
533
  thermocycler.CloseLidCommandType,
528
534
  thermocycler.RunProfileCommandType,
535
+ thermocycler.RunExtendedProfileCommandType,
536
+ absorbance_reader.CloseLidCommandType,
537
+ absorbance_reader.OpenLidCommandType,
529
538
  absorbance_reader.InitializeCommandType,
530
- absorbance_reader.MeasureAbsorbanceCommandType,
539
+ absorbance_reader.ReadAbsorbanceCommandType,
531
540
  calibration.CalibrateGripperCommandType,
532
541
  calibration.CalibratePipetteCommandType,
533
542
  calibration.CalibrateModuleCommandType,
@@ -536,6 +545,8 @@ CommandType = Union[
536
545
  unsafe.UnsafeDropTipInPlaceCommandType,
537
546
  unsafe.UpdatePositionEstimatorsCommandType,
538
547
  unsafe.UnsafeEngageAxesCommandType,
548
+ unsafe.UnsafeUngripLabwareCommandType,
549
+ unsafe.UnsafePlaceLabwareCommandType,
539
550
  ]
540
551
 
541
552
  CommandCreate = Annotated[
@@ -598,8 +609,11 @@ CommandCreate = Annotated[
598
609
  thermocycler.OpenLidCreate,
599
610
  thermocycler.CloseLidCreate,
600
611
  thermocycler.RunProfileCreate,
612
+ thermocycler.RunExtendedProfileCreate,
613
+ absorbance_reader.CloseLidCreate,
614
+ absorbance_reader.OpenLidCreate,
601
615
  absorbance_reader.InitializeCreate,
602
- absorbance_reader.MeasureAbsorbanceCreate,
616
+ absorbance_reader.ReadAbsorbanceCreate,
603
617
  calibration.CalibrateGripperCreate,
604
618
  calibration.CalibratePipetteCreate,
605
619
  calibration.CalibrateModuleCreate,
@@ -608,6 +622,8 @@ CommandCreate = Annotated[
608
622
  unsafe.UnsafeDropTipInPlaceCreate,
609
623
  unsafe.UpdatePositionEstimatorsCreate,
610
624
  unsafe.UnsafeEngageAxesCreate,
625
+ unsafe.UnsafeUngripLabwareCreate,
626
+ unsafe.UnsafePlaceLabwareCreate,
611
627
  ],
612
628
  Field(discriminator="commandType"),
613
629
  ]
@@ -671,8 +687,11 @@ CommandResult = Union[
671
687
  thermocycler.OpenLidResult,
672
688
  thermocycler.CloseLidResult,
673
689
  thermocycler.RunProfileResult,
690
+ thermocycler.RunExtendedProfileResult,
691
+ absorbance_reader.CloseLidResult,
692
+ absorbance_reader.OpenLidResult,
674
693
  absorbance_reader.InitializeResult,
675
- absorbance_reader.MeasureAbsorbanceResult,
694
+ absorbance_reader.ReadAbsorbanceResult,
676
695
  calibration.CalibrateGripperResult,
677
696
  calibration.CalibratePipetteResult,
678
697
  calibration.CalibrateModuleResult,
@@ -681,24 +700,18 @@ CommandResult = Union[
681
700
  unsafe.UnsafeDropTipInPlaceResult,
682
701
  unsafe.UpdatePositionEstimatorsResult,
683
702
  unsafe.UnsafeEngageAxesResult,
703
+ unsafe.UnsafeUngripLabwareResult,
704
+ unsafe.UnsafePlaceLabwareResult,
684
705
  ]
685
706
 
686
- # todo(mm, 2024-06-12): Ideally, command return types would have specific
687
- # CommandPrivateResults paired with specific CommandResults. For example,
688
- # a TouchTipResult can never be paired with a LoadPipettePrivateResult in practice,
689
- # and ideally our types would reflect that.
690
- CommandPrivateResult = Union[
691
- None,
692
- LoadPipettePrivateResult,
693
- ConfigureForVolumePrivateResult,
694
- ConfigureNozzleLayoutPrivateResult,
695
- ]
696
707
 
697
708
  # All `DefinedErrorData`s that implementations will actually return in practice.
698
709
  CommandDefinedErrorData = Union[
699
- DefinedErrorData[TipPhysicallyMissingError, TipPhysicallyMissingErrorInternalData],
700
- DefinedErrorData[OverpressureError, OverpressureErrorInternalData],
701
- DefinedErrorData[LiquidNotFoundError, LiquidNotFoundErrorInternalData],
710
+ DefinedErrorData[TipPhysicallyMissingError],
711
+ DefinedErrorData[TipPhysicallyAttachedError],
712
+ DefinedErrorData[OverpressureError],
713
+ DefinedErrorData[LiquidNotFoundError],
714
+ DefinedErrorData[GripperMovementError],
702
715
  ]
703
716
 
704
717
 
@@ -24,16 +24,18 @@ class CommentResult(BaseModel):
24
24
 
25
25
 
26
26
  class CommentImplementation(
27
- AbstractCommandImpl[CommentParams, SuccessData[CommentResult, None]]
27
+ AbstractCommandImpl[CommentParams, SuccessData[CommentResult]]
28
28
  ):
29
29
  """Comment command implementation."""
30
30
 
31
31
  def __init__(self, **kwargs: object) -> None:
32
32
  pass
33
33
 
34
- async def execute(self, params: CommentParams) -> SuccessData[CommentResult, None]:
34
+ async def execute(self, params: CommentParams) -> SuccessData[CommentResult]:
35
35
  """No operation taken other than capturing message in command."""
36
- return SuccessData(public=CommentResult(), private=None)
36
+ return SuccessData(
37
+ public=CommentResult(),
38
+ )
37
39
 
38
40
 
39
41
  class Comment(BaseCommand[CommentParams, CommentResult, ErrorOccurrence]):