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.

Potentially problematic release.


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

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
@@ -3,7 +3,7 @@
3
3
  from collections.abc import Collection
4
4
  from typing import Annotated, Type, Union, get_type_hints
5
5
 
6
- from pydantic import Field
6
+ from pydantic import Field, TypeAdapter
7
7
 
8
8
  from opentrons.util.get_union_elements import get_union_elements
9
9
 
@@ -13,6 +13,7 @@ from .pipetting_common import (
13
13
  LiquidNotFoundError,
14
14
  TipPhysicallyAttachedError,
15
15
  )
16
+ from .movement_common import StallOrCollisionError
16
17
 
17
18
  from . import absorbance_reader
18
19
  from . import heater_shaker
@@ -22,6 +23,7 @@ from . import thermocycler
22
23
 
23
24
  from . import calibration
24
25
  from . import unsafe
26
+ from . import robot
25
27
 
26
28
  from .set_rail_lights import (
27
29
  SetRailLights,
@@ -31,6 +33,14 @@ from .set_rail_lights import (
31
33
  SetRailLightsResult,
32
34
  )
33
35
 
36
+ from .air_gap_in_place import (
37
+ AirGapInPlace,
38
+ AirGapInPlaceParams,
39
+ AirGapInPlaceCreate,
40
+ AirGapInPlaceResult,
41
+ AirGapInPlaceCommandType,
42
+ )
43
+
34
44
  from .aspirate import (
35
45
  Aspirate,
36
46
  AspirateParams,
@@ -127,6 +137,14 @@ from .load_liquid import (
127
137
  LoadLiquidCommandType,
128
138
  )
129
139
 
140
+ from .load_liquid_class import (
141
+ LoadLiquidClass,
142
+ LoadLiquidClassParams,
143
+ LoadLiquidClassCreate,
144
+ LoadLiquidClassResult,
145
+ LoadLiquidClassCommandType,
146
+ )
147
+
130
148
  from .load_module import (
131
149
  LoadModule,
132
150
  LoadModuleParams,
@@ -143,6 +161,22 @@ from .load_pipette import (
143
161
  LoadPipetteCommandType,
144
162
  )
145
163
 
164
+ from .load_lid_stack import (
165
+ LoadLidStack,
166
+ LoadLidStackParams,
167
+ LoadLidStackCreate,
168
+ LoadLidStackResult,
169
+ LoadLidStackCommandType,
170
+ )
171
+
172
+ from .load_lid import (
173
+ LoadLid,
174
+ LoadLidParams,
175
+ LoadLidCreate,
176
+ LoadLidResult,
177
+ LoadLidCommandType,
178
+ )
179
+
146
180
  from .move_labware import (
147
181
  GripperMovementError,
148
182
  MoveLabware,
@@ -305,6 +339,14 @@ from .get_tip_presence import (
305
339
  GetTipPresenceCommandType,
306
340
  )
307
341
 
342
+ from .get_next_tip import (
343
+ GetNextTip,
344
+ GetNextTipCreate,
345
+ GetNextTipParams,
346
+ GetNextTipResult,
347
+ GetNextTipCommandType,
348
+ )
349
+
308
350
  from .liquid_probe import (
309
351
  LiquidProbe,
310
352
  LiquidProbeParams,
@@ -320,6 +362,7 @@ from .liquid_probe import (
320
362
 
321
363
  Command = Annotated[
322
364
  Union[
365
+ AirGapInPlace,
323
366
  Aspirate,
324
367
  AspirateInPlace,
325
368
  Comment,
@@ -337,8 +380,11 @@ Command = Annotated[
337
380
  LoadLabware,
338
381
  ReloadLabware,
339
382
  LoadLiquid,
383
+ LoadLiquidClass,
340
384
  LoadModule,
341
385
  LoadPipette,
386
+ LoadLidStack,
387
+ LoadLid,
342
388
  MoveLabware,
343
389
  MoveRelative,
344
390
  MoveToCoordinates,
@@ -355,6 +401,7 @@ Command = Annotated[
355
401
  SetStatusBar,
356
402
  VerifyTipPresence,
357
403
  GetTipPresence,
404
+ GetNextTip,
358
405
  LiquidProbe,
359
406
  TryLiquidProbe,
360
407
  heater_shaker.WaitForTemperature,
@@ -393,11 +440,17 @@ Command = Annotated[
393
440
  unsafe.UnsafeEngageAxes,
394
441
  unsafe.UnsafeUngripLabware,
395
442
  unsafe.UnsafePlaceLabware,
443
+ robot.MoveTo,
444
+ robot.MoveAxesRelative,
445
+ robot.MoveAxesTo,
446
+ robot.openGripperJaw,
447
+ robot.closeGripperJaw,
396
448
  ],
397
449
  Field(discriminator="commandType"),
398
450
  ]
399
451
 
400
452
  CommandParams = Union[
453
+ AirGapInPlaceParams,
401
454
  AspirateParams,
402
455
  AspirateInPlaceParams,
403
456
  CommentParams,
@@ -413,8 +466,11 @@ CommandParams = Union[
413
466
  HomeParams,
414
467
  RetractAxisParams,
415
468
  LoadLabwareParams,
469
+ LoadLidStackParams,
470
+ LoadLidParams,
416
471
  ReloadLabwareParams,
417
472
  LoadLiquidParams,
473
+ LoadLiquidClassParams,
418
474
  LoadModuleParams,
419
475
  LoadPipetteParams,
420
476
  MoveLabwareParams,
@@ -433,6 +489,7 @@ CommandParams = Union[
433
489
  SetStatusBarParams,
434
490
  VerifyTipPresenceParams,
435
491
  GetTipPresenceParams,
492
+ GetNextTipParams,
436
493
  LiquidProbeParams,
437
494
  TryLiquidProbeParams,
438
495
  heater_shaker.WaitForTemperatureParams,
@@ -471,9 +528,15 @@ CommandParams = Union[
471
528
  unsafe.UnsafeEngageAxesParams,
472
529
  unsafe.UnsafeUngripLabwareParams,
473
530
  unsafe.UnsafePlaceLabwareParams,
531
+ robot.MoveAxesRelativeParams,
532
+ robot.MoveAxesToParams,
533
+ robot.MoveToParams,
534
+ robot.openGripperJawParams,
535
+ robot.closeGripperJawParams,
474
536
  ]
475
537
 
476
538
  CommandType = Union[
539
+ AirGapInPlaceCommandType,
477
540
  AspirateCommandType,
478
541
  AspirateInPlaceCommandType,
479
542
  CommentCommandType,
@@ -491,8 +554,11 @@ CommandType = Union[
491
554
  LoadLabwareCommandType,
492
555
  ReloadLabwareCommandType,
493
556
  LoadLiquidCommandType,
557
+ LoadLiquidClassCommandType,
494
558
  LoadModuleCommandType,
495
559
  LoadPipetteCommandType,
560
+ LoadLidStackCommandType,
561
+ LoadLidCommandType,
496
562
  MoveLabwareCommandType,
497
563
  MoveRelativeCommandType,
498
564
  MoveToCoordinatesCommandType,
@@ -509,6 +575,7 @@ CommandType = Union[
509
575
  SetStatusBarCommandType,
510
576
  VerifyTipPresenceCommandType,
511
577
  GetTipPresenceCommandType,
578
+ GetNextTipCommandType,
512
579
  LiquidProbeCommandType,
513
580
  TryLiquidProbeCommandType,
514
581
  heater_shaker.WaitForTemperatureCommandType,
@@ -547,10 +614,16 @@ CommandType = Union[
547
614
  unsafe.UnsafeEngageAxesCommandType,
548
615
  unsafe.UnsafeUngripLabwareCommandType,
549
616
  unsafe.UnsafePlaceLabwareCommandType,
617
+ robot.MoveAxesRelativeCommandType,
618
+ robot.MoveAxesToCommandType,
619
+ robot.MoveToCommandType,
620
+ robot.openGripperJawCommandType,
621
+ robot.closeGripperJawCommandType,
550
622
  ]
551
623
 
552
624
  CommandCreate = Annotated[
553
625
  Union[
626
+ AirGapInPlaceCreate,
554
627
  AspirateCreate,
555
628
  AspirateInPlaceCreate,
556
629
  CommentCreate,
@@ -568,8 +641,11 @@ CommandCreate = Annotated[
568
641
  LoadLabwareCreate,
569
642
  ReloadLabwareCreate,
570
643
  LoadLiquidCreate,
644
+ LoadLiquidClassCreate,
571
645
  LoadModuleCreate,
572
646
  LoadPipetteCreate,
647
+ LoadLidStackCreate,
648
+ LoadLidCreate,
573
649
  MoveLabwareCreate,
574
650
  MoveRelativeCreate,
575
651
  MoveToCoordinatesCreate,
@@ -586,6 +662,7 @@ CommandCreate = Annotated[
586
662
  SetStatusBarCreate,
587
663
  VerifyTipPresenceCreate,
588
664
  GetTipPresenceCreate,
665
+ GetNextTipCreate,
589
666
  LiquidProbeCreate,
590
667
  TryLiquidProbeCreate,
591
668
  heater_shaker.WaitForTemperatureCreate,
@@ -624,11 +701,24 @@ CommandCreate = Annotated[
624
701
  unsafe.UnsafeEngageAxesCreate,
625
702
  unsafe.UnsafeUngripLabwareCreate,
626
703
  unsafe.UnsafePlaceLabwareCreate,
704
+ robot.MoveAxesRelativeCreate,
705
+ robot.MoveAxesToCreate,
706
+ robot.MoveToCreate,
707
+ robot.openGripperJawCreate,
708
+ robot.closeGripperJawCreate,
627
709
  ],
628
710
  Field(discriminator="commandType"),
629
711
  ]
630
712
 
713
+ # Each time a TypeAdapter is instantiated, it will construct a new validator and
714
+ # serializer. To improve performance, TypeAdapters are instantiated once.
715
+ # See https://docs.pydantic.dev/latest/concepts/performance/#typeadapter-instantiated-once
716
+ CommandCreateAdapter: TypeAdapter[CommandCreate] = TypeAdapter(CommandCreate)
717
+
718
+ CommandAdapter: TypeAdapter[Command] = TypeAdapter(Command)
719
+
631
720
  CommandResult = Union[
721
+ AirGapInPlaceResult,
632
722
  AspirateResult,
633
723
  AspirateInPlaceResult,
634
724
  CommentResult,
@@ -646,8 +736,11 @@ CommandResult = Union[
646
736
  LoadLabwareResult,
647
737
  ReloadLabwareResult,
648
738
  LoadLiquidResult,
739
+ LoadLiquidClassResult,
649
740
  LoadModuleResult,
650
741
  LoadPipetteResult,
742
+ LoadLidStackResult,
743
+ LoadLidResult,
651
744
  MoveLabwareResult,
652
745
  MoveRelativeResult,
653
746
  MoveToCoordinatesResult,
@@ -664,6 +757,7 @@ CommandResult = Union[
664
757
  SetStatusBarResult,
665
758
  VerifyTipPresenceResult,
666
759
  GetTipPresenceResult,
760
+ GetNextTipResult,
667
761
  LiquidProbeResult,
668
762
  TryLiquidProbeResult,
669
763
  heater_shaker.WaitForTemperatureResult,
@@ -702,6 +796,11 @@ CommandResult = Union[
702
796
  unsafe.UnsafeEngageAxesResult,
703
797
  unsafe.UnsafeUngripLabwareResult,
704
798
  unsafe.UnsafePlaceLabwareResult,
799
+ robot.MoveAxesRelativeResult,
800
+ robot.MoveAxesToResult,
801
+ robot.MoveToResult,
802
+ robot.openGripperJawResult,
803
+ robot.closeGripperJawResult,
705
804
  ]
706
805
 
707
806
 
@@ -712,6 +811,7 @@ CommandDefinedErrorData = Union[
712
811
  DefinedErrorData[OverpressureError],
713
812
  DefinedErrorData[LiquidNotFoundError],
714
813
  DefinedErrorData[GripperMovementError],
814
+ DefinedErrorData[StallOrCollisionError],
715
815
  ]
716
816
 
717
817
 
@@ -43,7 +43,7 @@ class Comment(BaseCommand[CommentParams, CommentResult, ErrorOccurrence]):
43
43
 
44
44
  commandType: CommentCommandType = "comment"
45
45
  params: CommentParams
46
- result: Optional[CommentResult]
46
+ result: Optional[CommentResult] = None
47
47
 
48
48
  _ImplementationCls: Type[CommentImplementation] = CommentImplementation
49
49
 
@@ -1,7 +1,9 @@
1
1
  """Configure for volume command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
+ from typing import TYPE_CHECKING, Optional, Type, Any
4
+
3
5
  from pydantic import BaseModel, Field
4
- from typing import TYPE_CHECKING, Optional, Type
6
+ from pydantic.json_schema import SkipJsonSchema
5
7
  from typing_extensions import Literal
6
8
 
7
9
  from .pipetting_common import PipetteIdMixin
@@ -16,6 +18,10 @@ if TYPE_CHECKING:
16
18
  ConfigureForVolumeCommandType = Literal["configureForVolume"]
17
19
 
18
20
 
21
+ def _remove_default(s: dict[str, Any]) -> None:
22
+ s.pop("default", None)
23
+
24
+
19
25
  class ConfigureForVolumeParams(PipetteIdMixin):
20
26
  """Parameters required to configure volume for a specific pipette."""
21
27
 
@@ -25,12 +31,13 @@ class ConfigureForVolumeParams(PipetteIdMixin):
25
31
  "than a pipette-specific maximum volume.",
26
32
  ge=0,
27
33
  )
28
- tipOverlapNotAfterVersion: Optional[str] = Field(
34
+ tipOverlapNotAfterVersion: str | SkipJsonSchema[None] = Field(
29
35
  None,
30
36
  description="A version of tip overlap data to not exceed. The highest-versioned "
31
37
  "tip overlap data that does not exceed this version will be used. Versions are "
32
38
  "expressed as vN where N is an integer, counting up from v0. If None, the current "
33
39
  "highest version will be used.",
40
+ json_schema_extra=_remove_default,
34
41
  )
35
42
 
36
43
 
@@ -81,7 +88,7 @@ class ConfigureForVolume(
81
88
 
82
89
  commandType: ConfigureForVolumeCommandType = "configureForVolume"
83
90
  params: ConfigureForVolumeParams
84
- result: Optional[ConfigureForVolumeResult]
91
+ result: Optional[ConfigureForVolumeResult] = None
85
92
 
86
93
  _ImplementationCls: Type[
87
94
  ConfigureForVolumeImplementation
@@ -61,9 +61,11 @@ class ConfigureNozzleLayoutImplementation(
61
61
  self, params: ConfigureNozzleLayoutParams
62
62
  ) -> SuccessData[ConfigureNozzleLayoutResult]:
63
63
  """Check that requested pipette can support the requested nozzle layout."""
64
- primary_nozzle = params.configurationParams.dict().get("primaryNozzle")
65
- front_right_nozzle = params.configurationParams.dict().get("frontRightNozzle")
66
- back_left_nozzle = params.configurationParams.dict().get("backLeftNozzle")
64
+ primary_nozzle = params.configurationParams.model_dump().get("primaryNozzle")
65
+ front_right_nozzle = params.configurationParams.model_dump().get(
66
+ "frontRightNozzle"
67
+ )
68
+ back_left_nozzle = params.configurationParams.model_dump().get("backLeftNozzle")
67
69
  nozzle_params = await self._tip_handler.available_for_nozzle_layout(
68
70
  pipette_id=params.pipetteId,
69
71
  style=params.configurationParams.style,
@@ -97,7 +99,7 @@ class ConfigureNozzleLayout(
97
99
 
98
100
  commandType: ConfigureNozzleLayoutCommandType = "configureNozzleLayout"
99
101
  params: ConfigureNozzleLayoutParams
100
- result: Optional[ConfigureNozzleLayoutResult]
102
+ result: Optional[ConfigureNozzleLayoutResult] = None
101
103
 
102
104
  _ImplementationCls: Type[
103
105
  ConfigureNozzleLayoutImplementation
@@ -10,7 +10,7 @@ data still adheres to the shapes that ProtocolEngine expects.
10
10
  If you are implementing a custom command, you should probably
11
11
  put your own disambiguation identifier in the payload.
12
12
  """
13
- from pydantic import BaseModel, Extra
13
+ from pydantic import ConfigDict, BaseModel, SerializeAsAny
14
14
  from typing import Optional, Type
15
15
  from typing_extensions import Literal
16
16
 
@@ -24,19 +24,13 @@ CustomCommandType = Literal["custom"]
24
24
  class CustomParams(BaseModel):
25
25
  """Payload used by a custom command."""
26
26
 
27
- class Config:
28
- """Allow arbitrary fields."""
29
-
30
- extra = Extra.allow
27
+ model_config = ConfigDict(extra="allow")
31
28
 
32
29
 
33
30
  class CustomResult(BaseModel):
34
31
  """Result data from a custom command."""
35
32
 
36
- class Config:
37
- """Allow arbitrary fields."""
38
-
39
- extra = Extra.allow
33
+ model_config = ConfigDict(extra="allow")
40
34
 
41
35
 
42
36
  class CustomImplementation(
@@ -50,7 +44,7 @@ class CustomImplementation(
50
44
  async def execute(self, params: CustomParams) -> SuccessData[CustomResult]:
51
45
  """A custom command does nothing when executed directly."""
52
46
  return SuccessData(
53
- public=CustomResult.construct(),
47
+ public=CustomResult.model_construct(),
54
48
  )
55
49
 
56
50
 
@@ -58,8 +52,8 @@ class Custom(BaseCommand[CustomParams, CustomResult, ErrorOccurrence]):
58
52
  """Custom command model."""
59
53
 
60
54
  commandType: CustomCommandType = "custom"
61
- params: CustomParams
62
- result: Optional[CustomResult]
55
+ params: SerializeAsAny[CustomParams]
56
+ result: Optional[CustomResult] = None
63
57
 
64
58
  _ImplementationCls: Type[CustomImplementation] = CustomImplementation
65
59
 
@@ -1,22 +1,27 @@
1
1
  """Dispense command request, result, and implementation models."""
2
+
2
3
  from __future__ import annotations
3
- from typing import TYPE_CHECKING, Optional, Type, Union
4
+ from typing import TYPE_CHECKING, Optional, Type, Union, Any
4
5
  from typing_extensions import Literal
5
6
 
6
- from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
7
7
 
8
8
  from pydantic import Field
9
+ from pydantic.json_schema import SkipJsonSchema
9
10
 
10
- from ..types import DeckPoint
11
11
  from ..state.update_types import StateUpdate, CLEAR
12
12
  from .pipetting_common import (
13
13
  PipetteIdMixin,
14
14
  DispenseVolumeMixin,
15
15
  FlowRateMixin,
16
- LiquidHandlingWellLocationMixin,
17
16
  BaseLiquidHandlingResult,
18
- DestinationPositionResult,
19
17
  OverpressureError,
18
+ dispense_in_place,
19
+ )
20
+ from .movement_common import (
21
+ LiquidHandlingWellLocationMixin,
22
+ DestinationPositionResult,
23
+ StallOrCollisionError,
24
+ move_to_well,
20
25
  )
21
26
  from .command import (
22
27
  AbstractCommandImpl,
@@ -25,7 +30,6 @@ from .command import (
25
30
  DefinedErrorData,
26
31
  SuccessData,
27
32
  )
28
- from ..errors.error_occurrence import ErrorOccurrence
29
33
 
30
34
  if TYPE_CHECKING:
31
35
  from ..execution import MovementHandler, PipettingHandler
@@ -36,14 +40,19 @@ if TYPE_CHECKING:
36
40
  DispenseCommandType = Literal["dispense"]
37
41
 
38
42
 
43
+ def _remove_default(s: dict[str, Any]) -> None:
44
+ s.pop("default", None)
45
+
46
+
39
47
  class DispenseParams(
40
48
  PipetteIdMixin, DispenseVolumeMixin, FlowRateMixin, LiquidHandlingWellLocationMixin
41
49
  ):
42
50
  """Payload required to dispense to a specific well."""
43
51
 
44
- pushOut: Optional[float] = Field(
52
+ pushOut: float | SkipJsonSchema[None] = Field(
45
53
  None,
46
54
  description="push the plunger a small amount farther than necessary for accurate low-volume dispensing",
55
+ json_schema_extra=_remove_default,
47
56
  )
48
57
 
49
58
 
@@ -55,7 +64,7 @@ class DispenseResult(BaseLiquidHandlingResult, DestinationPositionResult):
55
64
 
56
65
  _ExecuteReturn = Union[
57
66
  SuccessData[DispenseResult],
58
- DefinedErrorData[OverpressureError],
67
+ DefinedErrorData[OverpressureError] | DefinedErrorData[StallOrCollisionError],
59
68
  ]
60
69
 
61
70
 
@@ -77,7 +86,6 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
77
86
 
78
87
  async def execute(self, params: DispenseParams) -> _ExecuteReturn:
79
88
  """Move to and dispense to the requested well."""
80
- state_update = StateUpdate()
81
89
  well_location = params.wellLocation
82
90
  labware_id = params.labwareId
83
91
  well_name = params.wellName
@@ -85,66 +93,92 @@ class DispenseImplementation(AbstractCommandImpl[DispenseParams, _ExecuteReturn]
85
93
 
86
94
  # TODO(pbm, 10-15-24): call self._state_view.geometry.validate_dispense_volume_into_well()
87
95
 
88
- position = await self._movement.move_to_well(
96
+ move_result = await move_to_well(
97
+ movement=self._movement,
98
+ model_utils=self._model_utils,
89
99
  pipette_id=params.pipetteId,
90
100
  labware_id=labware_id,
91
101
  well_name=well_name,
92
102
  well_location=well_location,
93
103
  )
94
- deck_point = DeckPoint.construct(x=position.x, y=position.y, z=position.z)
95
- state_update.set_pipette_location(
104
+ if isinstance(move_result, DefinedErrorData):
105
+ return move_result
106
+ dispense_result = await dispense_in_place(
96
107
  pipette_id=params.pipetteId,
97
- new_labware_id=labware_id,
98
- new_well_name=well_name,
99
- new_deck_point=deck_point,
108
+ volume=volume,
109
+ flow_rate=params.flowRate,
110
+ push_out=params.pushOut,
111
+ location_if_error={
112
+ "retryLocation": (
113
+ move_result.public.position.x,
114
+ move_result.public.position.y,
115
+ move_result.public.position.z,
116
+ )
117
+ },
118
+ pipetting=self._pipetting,
119
+ model_utils=self._model_utils,
100
120
  )
101
121
 
102
- try:
103
- volume = await self._pipetting.dispense_in_place(
104
- pipette_id=params.pipetteId,
105
- volume=volume,
106
- flow_rate=params.flowRate,
107
- push_out=params.pushOut,
108
- )
109
- except PipetteOverpressureError as e:
110
- state_update.set_liquid_operated(
111
- labware_id=labware_id,
112
- well_name=well_name,
113
- volume_added=CLEAR,
114
- )
122
+ if isinstance(dispense_result, DefinedErrorData):
115
123
  return DefinedErrorData(
116
- public=OverpressureError(
117
- id=self._model_utils.generate_id(),
118
- createdAt=self._model_utils.get_timestamp(),
119
- wrappedErrors=[
120
- ErrorOccurrence.from_failed(
121
- id=self._model_utils.generate_id(),
122
- createdAt=self._model_utils.get_timestamp(),
123
- error=e,
124
- )
125
- ],
126
- errorInfo={"retryLocation": (position.x, position.y, position.z)},
124
+ public=dispense_result.public,
125
+ state_update=(
126
+ StateUpdate.reduce(
127
+ move_result.state_update, dispense_result.state_update
128
+ ).set_liquid_operated(
129
+ labware_id=labware_id,
130
+ well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
131
+ labware_id, well_name, params.pipetteId
132
+ ),
133
+ volume_added=CLEAR,
134
+ )
135
+ ),
136
+ state_update_if_false_positive=StateUpdate.reduce(
137
+ move_result.state_update,
138
+ dispense_result.state_update_if_false_positive,
127
139
  ),
128
- state_update=state_update,
129
140
  )
130
141
  else:
131
- state_update.set_liquid_operated(
132
- labware_id=labware_id,
133
- well_name=well_name,
134
- volume_added=volume,
142
+ volume_added = (
143
+ self._state_view.pipettes.get_liquid_dispensed_by_ejecting_volume(
144
+ pipette_id=params.pipetteId, volume=dispense_result.public.volume
145
+ )
135
146
  )
147
+ if volume_added is not None:
148
+ volume_added *= self._state_view.geometry.get_nozzles_per_well(
149
+ labware_id, well_name, params.pipetteId
150
+ )
136
151
  return SuccessData(
137
- public=DispenseResult(volume=volume, position=deck_point),
138
- state_update=state_update,
152
+ public=DispenseResult(
153
+ volume=dispense_result.public.volume,
154
+ position=move_result.public.position,
155
+ ),
156
+ state_update=(
157
+ StateUpdate.reduce(
158
+ move_result.state_update, dispense_result.state_update
159
+ ).set_liquid_operated(
160
+ labware_id=labware_id,
161
+ well_names=self._state_view.geometry.get_wells_covered_by_pipette_with_active_well(
162
+ labware_id, well_name, params.pipetteId
163
+ ),
164
+ volume_added=volume_added
165
+ if volume_added is not None
166
+ else CLEAR,
167
+ )
168
+ ),
139
169
  )
140
170
 
141
171
 
142
- class Dispense(BaseCommand[DispenseParams, DispenseResult, OverpressureError]):
172
+ class Dispense(
173
+ BaseCommand[
174
+ DispenseParams, DispenseResult, OverpressureError | StallOrCollisionError
175
+ ]
176
+ ):
143
177
  """Dispense command model."""
144
178
 
145
179
  commandType: DispenseCommandType = "dispense"
146
180
  params: DispenseParams
147
- result: Optional[DispenseResult]
181
+ result: Optional[DispenseResult] = None
148
182
 
149
183
  _ImplementationCls: Type[DispenseImplementation] = DispenseImplementation
150
184