opentrons 8.2.0a3__py2.py3-none-any.whl → 8.3.0__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 (238) 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/config/defaults_ot3.py +1 -0
  9. opentrons/drivers/asyncio/communication/__init__.py +2 -0
  10. opentrons/drivers/asyncio/communication/errors.py +16 -3
  11. opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
  12. opentrons/drivers/command_builder.py +2 -2
  13. opentrons/drivers/flex_stacker/__init__.py +9 -0
  14. opentrons/drivers/flex_stacker/abstract.py +89 -0
  15. opentrons/drivers/flex_stacker/driver.py +260 -0
  16. opentrons/drivers/flex_stacker/simulator.py +109 -0
  17. opentrons/drivers/flex_stacker/types.py +138 -0
  18. opentrons/drivers/heater_shaker/driver.py +18 -3
  19. opentrons/drivers/temp_deck/driver.py +13 -3
  20. opentrons/drivers/thermocycler/driver.py +17 -3
  21. opentrons/execute.py +3 -1
  22. opentrons/hardware_control/__init__.py +1 -2
  23. opentrons/hardware_control/api.py +33 -21
  24. opentrons/hardware_control/backends/flex_protocol.py +17 -7
  25. opentrons/hardware_control/backends/ot3controller.py +213 -63
  26. opentrons/hardware_control/backends/ot3simulator.py +18 -9
  27. opentrons/hardware_control/backends/ot3utils.py +43 -15
  28. opentrons/hardware_control/dev_types.py +4 -0
  29. opentrons/hardware_control/emulation/heater_shaker.py +4 -0
  30. opentrons/hardware_control/emulation/module_server/client.py +1 -1
  31. opentrons/hardware_control/emulation/module_server/server.py +5 -3
  32. opentrons/hardware_control/emulation/settings.py +3 -4
  33. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
  34. opentrons/hardware_control/instruments/ot2/pipette.py +15 -22
  35. opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
  36. opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
  37. opentrons/hardware_control/instruments/ot3/pipette.py +23 -22
  38. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
  39. opentrons/hardware_control/modules/mod_abc.py +2 -2
  40. opentrons/hardware_control/motion_utilities.py +68 -0
  41. opentrons/hardware_control/nozzle_manager.py +39 -41
  42. opentrons/hardware_control/ot3_calibration.py +1 -1
  43. opentrons/hardware_control/ot3api.py +78 -31
  44. opentrons/hardware_control/protocols/gripper_controller.py +3 -0
  45. opentrons/hardware_control/protocols/hardware_manager.py +5 -1
  46. opentrons/hardware_control/protocols/liquid_handler.py +22 -1
  47. opentrons/hardware_control/protocols/motion_controller.py +7 -0
  48. opentrons/hardware_control/robot_calibration.py +1 -1
  49. opentrons/hardware_control/types.py +61 -0
  50. opentrons/legacy_commands/commands.py +37 -0
  51. opentrons/legacy_commands/types.py +39 -0
  52. opentrons/protocol_api/__init__.py +20 -1
  53. opentrons/protocol_api/_liquid.py +24 -49
  54. opentrons/protocol_api/_liquid_properties.py +754 -0
  55. opentrons/protocol_api/_types.py +24 -0
  56. opentrons/protocol_api/core/common.py +2 -0
  57. opentrons/protocol_api/core/engine/instrument.py +191 -10
  58. opentrons/protocol_api/core/engine/labware.py +29 -7
  59. opentrons/protocol_api/core/engine/protocol.py +130 -5
  60. opentrons/protocol_api/core/engine/robot.py +139 -0
  61. opentrons/protocol_api/core/engine/well.py +4 -1
  62. opentrons/protocol_api/core/instrument.py +73 -4
  63. opentrons/protocol_api/core/labware.py +13 -4
  64. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +87 -3
  65. opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
  66. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
  67. opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
  68. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +61 -3
  69. opentrons/protocol_api/core/protocol.py +34 -1
  70. opentrons/protocol_api/core/robot.py +51 -0
  71. opentrons/protocol_api/instrument_context.py +299 -44
  72. opentrons/protocol_api/labware.py +248 -9
  73. opentrons/protocol_api/module_contexts.py +21 -17
  74. opentrons/protocol_api/protocol_context.py +125 -4
  75. opentrons/protocol_api/robot_context.py +204 -32
  76. opentrons/protocol_api/validation.py +262 -3
  77. opentrons/protocol_engine/__init__.py +4 -0
  78. opentrons/protocol_engine/actions/actions.py +2 -3
  79. opentrons/protocol_engine/clients/sync_client.py +18 -0
  80. opentrons/protocol_engine/commands/__init__.py +121 -0
  81. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +1 -3
  82. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +20 -6
  83. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +1 -2
  84. opentrons/protocol_engine/commands/absorbance_reader/read.py +40 -10
  85. opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
  86. opentrons/protocol_engine/commands/aspirate.py +103 -53
  87. opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
  88. opentrons/protocol_engine/commands/blow_out.py +44 -39
  89. opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
  90. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
  91. opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
  92. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
  93. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
  94. opentrons/protocol_engine/commands/command.py +73 -66
  95. opentrons/protocol_engine/commands/command_unions.py +140 -1
  96. opentrons/protocol_engine/commands/comment.py +1 -1
  97. opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
  98. opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
  99. opentrons/protocol_engine/commands/custom.py +6 -12
  100. opentrons/protocol_engine/commands/dispense.py +82 -48
  101. opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
  102. opentrons/protocol_engine/commands/drop_tip.py +52 -31
  103. opentrons/protocol_engine/commands/drop_tip_in_place.py +79 -8
  104. opentrons/protocol_engine/commands/evotip_dispense.py +156 -0
  105. opentrons/protocol_engine/commands/evotip_seal_pipette.py +331 -0
  106. opentrons/protocol_engine/commands/evotip_unseal_pipette.py +160 -0
  107. opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
  108. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  109. opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
  110. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
  111. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
  112. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
  113. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
  114. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
  115. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
  116. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
  117. opentrons/protocol_engine/commands/home.py +13 -4
  118. opentrons/protocol_engine/commands/liquid_probe.py +125 -31
  119. opentrons/protocol_engine/commands/load_labware.py +33 -6
  120. opentrons/protocol_engine/commands/load_lid.py +146 -0
  121. opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
  122. opentrons/protocol_engine/commands/load_liquid.py +12 -4
  123. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  124. opentrons/protocol_engine/commands/load_module.py +31 -10
  125. opentrons/protocol_engine/commands/load_pipette.py +19 -8
  126. opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
  127. opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
  128. opentrons/protocol_engine/commands/move_labware.py +28 -6
  129. opentrons/protocol_engine/commands/move_relative.py +35 -25
  130. opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
  131. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
  132. opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
  133. opentrons/protocol_engine/commands/move_to_well.py +40 -24
  134. opentrons/protocol_engine/commands/movement_common.py +338 -0
  135. opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
  136. opentrons/protocol_engine/commands/pipetting_common.py +169 -87
  137. opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
  138. opentrons/protocol_engine/commands/reload_labware.py +1 -1
  139. opentrons/protocol_engine/commands/retract_axis.py +1 -1
  140. opentrons/protocol_engine/commands/robot/__init__.py +69 -0
  141. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
  142. opentrons/protocol_engine/commands/robot/common.py +18 -0
  143. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  144. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  145. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  146. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
  147. opentrons/protocol_engine/commands/save_position.py +14 -5
  148. opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
  149. opentrons/protocol_engine/commands/set_status_bar.py +1 -1
  150. opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
  151. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
  152. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
  153. opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
  154. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
  155. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
  156. opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
  157. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +9 -3
  158. opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
  159. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
  160. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
  161. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
  162. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
  163. opentrons/protocol_engine/commands/touch_tip.py +65 -16
  164. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +5 -2
  165. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +13 -4
  166. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +2 -5
  167. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +1 -1
  168. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +4 -2
  169. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +2 -5
  170. opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
  171. opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
  172. opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
  173. opentrons/protocol_engine/errors/__init__.py +12 -0
  174. opentrons/protocol_engine/errors/error_occurrence.py +19 -20
  175. opentrons/protocol_engine/errors/exceptions.py +76 -0
  176. opentrons/protocol_engine/execution/command_executor.py +1 -1
  177. opentrons/protocol_engine/execution/equipment.py +73 -5
  178. opentrons/protocol_engine/execution/gantry_mover.py +369 -8
  179. opentrons/protocol_engine/execution/hardware_stopper.py +7 -7
  180. opentrons/protocol_engine/execution/movement.py +27 -0
  181. opentrons/protocol_engine/execution/pipetting.py +5 -1
  182. opentrons/protocol_engine/execution/tip_handler.py +34 -15
  183. opentrons/protocol_engine/notes/notes.py +1 -1
  184. opentrons/protocol_engine/protocol_engine.py +7 -6
  185. opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
  186. opentrons/protocol_engine/resources/labware_validation.py +18 -0
  187. opentrons/protocol_engine/resources/module_data_provider.py +1 -1
  188. opentrons/protocol_engine/resources/pipette_data_provider.py +26 -0
  189. opentrons/protocol_engine/slot_standardization.py +9 -9
  190. opentrons/protocol_engine/state/_move_types.py +9 -5
  191. opentrons/protocol_engine/state/_well_math.py +193 -0
  192. opentrons/protocol_engine/state/addressable_areas.py +25 -61
  193. opentrons/protocol_engine/state/command_history.py +12 -0
  194. opentrons/protocol_engine/state/commands.py +22 -14
  195. opentrons/protocol_engine/state/files.py +10 -12
  196. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  197. opentrons/protocol_engine/state/frustum_helpers.py +63 -69
  198. opentrons/protocol_engine/state/geometry.py +47 -1
  199. opentrons/protocol_engine/state/labware.py +92 -26
  200. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  201. opentrons/protocol_engine/state/liquids.py +16 -4
  202. opentrons/protocol_engine/state/modules.py +56 -71
  203. opentrons/protocol_engine/state/motion.py +6 -1
  204. opentrons/protocol_engine/state/pipettes.py +149 -58
  205. opentrons/protocol_engine/state/state.py +21 -2
  206. opentrons/protocol_engine/state/state_summary.py +4 -2
  207. opentrons/protocol_engine/state/tips.py +11 -44
  208. opentrons/protocol_engine/state/update_types.py +343 -48
  209. opentrons/protocol_engine/state/wells.py +19 -11
  210. opentrons/protocol_engine/types.py +176 -28
  211. opentrons/protocol_reader/extract_labware_definitions.py +5 -2
  212. opentrons/protocol_reader/file_format_validator.py +5 -5
  213. opentrons/protocol_runner/json_file_reader.py +9 -3
  214. opentrons/protocol_runner/json_translator.py +51 -25
  215. opentrons/protocol_runner/legacy_command_mapper.py +66 -64
  216. opentrons/protocol_runner/protocol_runner.py +35 -4
  217. opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
  218. opentrons/protocol_runner/run_orchestrator.py +13 -3
  219. opentrons/protocols/advanced_control/common.py +38 -0
  220. opentrons/protocols/advanced_control/mix.py +1 -1
  221. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  222. opentrons/protocols/advanced_control/transfers/common.py +56 -0
  223. opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
  224. opentrons/protocols/api_support/definitions.py +1 -1
  225. opentrons/protocols/api_support/instrument.py +1 -1
  226. opentrons/protocols/api_support/util.py +10 -0
  227. opentrons/protocols/labware.py +70 -8
  228. opentrons/protocols/models/json_protocol.py +5 -9
  229. opentrons/simulate.py +3 -1
  230. opentrons/types.py +162 -2
  231. opentrons/util/entrypoint_util.py +2 -5
  232. opentrons/util/logging_config.py +1 -1
  233. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
  234. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
  235. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
  236. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
  237. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.2.0a3.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,23 @@
1
1
  """Load pipette command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
+ from typing import TYPE_CHECKING, Optional, Type, Any
4
+
5
+ from pydantic import BaseModel, Field
6
+ from pydantic.json_schema import SkipJsonSchema
7
+ from typing_extensions import Literal
3
8
 
4
- from opentrons.protocol_engine.state.update_types import StateUpdate
5
9
  from opentrons_shared_data.pipette.pipette_load_name_conversions import (
6
10
  convert_to_pipette_name_type,
7
11
  )
8
12
  from opentrons_shared_data.pipette.types import PipetteGenerationType
9
13
  from opentrons_shared_data.robot import user_facing_robot_type
10
14
  from opentrons_shared_data.robot.types import RobotTypeEnum
11
- from pydantic import BaseModel, Field
12
- from typing import TYPE_CHECKING, Optional, Type
13
- from typing_extensions import Literal
15
+
14
16
 
15
17
  from opentrons_shared_data.pipette.types import PipetteNameType
16
18
  from opentrons.types import MountType
17
19
 
20
+ from opentrons.protocol_engine.state.update_types import StateUpdate
18
21
  from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
19
22
  from ..errors.error_occurrence import ErrorOccurrence
20
23
  from ..errors import InvalidSpecificationForRobotTypeError, InvalidLoadPipetteSpecsError
@@ -27,6 +30,10 @@ if TYPE_CHECKING:
27
30
  LoadPipetteCommandType = Literal["loadPipette"]
28
31
 
29
32
 
33
+ def _remove_default(s: dict[str, Any]) -> None:
34
+ s.pop("default", None)
35
+
36
+
30
37
  class LoadPipetteParams(BaseModel):
31
38
  """Payload needed to load a pipette on to a mount."""
32
39
 
@@ -38,21 +45,24 @@ class LoadPipetteParams(BaseModel):
38
45
  ...,
39
46
  description="The mount the pipette should be present on.",
40
47
  )
41
- pipetteId: Optional[str] = Field(
48
+ pipetteId: str | SkipJsonSchema[None] = Field(
42
49
  None,
43
50
  description="An optional ID to assign to this pipette. If None, an ID "
44
51
  "will be generated.",
52
+ json_schema_extra=_remove_default,
45
53
  )
46
- tipOverlapNotAfterVersion: Optional[str] = Field(
54
+ tipOverlapNotAfterVersion: str | SkipJsonSchema[None] = Field(
47
55
  None,
48
56
  description="A version of tip overlap data to not exceed. The highest-versioned "
49
57
  "tip overlap data that does not exceed this version will be used. Versions are "
50
58
  "expressed as vN where N is an integer, counting up from v0. If None, the current "
51
59
  "highest version will be used.",
60
+ json_schema_extra=_remove_default,
52
61
  )
53
- liquidPresenceDetection: Optional[bool] = Field(
62
+ liquidPresenceDetection: bool | SkipJsonSchema[None] = Field(
54
63
  None,
55
64
  description="Enable liquid presence detection for this pipette. Defaults to False.",
65
+ json_schema_extra=_remove_default,
56
66
  )
57
67
 
58
68
 
@@ -127,6 +137,7 @@ class LoadPipetteImplementation(
127
137
  serial_number=loaded_pipette.serial_number,
128
138
  config=loaded_pipette.static_config,
129
139
  )
140
+ state_update.set_fluid_unknown(pipette_id=loaded_pipette.pipette_id)
130
141
 
131
142
  return SuccessData(
132
143
  public=LoadPipetteResult(pipetteId=loaded_pipette.pipette_id),
@@ -139,7 +150,7 @@ class LoadPipette(BaseCommand[LoadPipetteParams, LoadPipetteResult, ErrorOccurre
139
150
 
140
151
  commandType: LoadPipetteCommandType = "loadPipette"
141
152
  params: LoadPipetteParams
142
- result: Optional[LoadPipetteResult]
153
+ result: Optional[LoadPipetteResult] = None
143
154
 
144
155
  _ImplementationCls: Type[LoadPipetteImplementation] = LoadPipetteImplementation
145
156
 
@@ -83,7 +83,7 @@ class Disengage(BaseCommand[DisengageParams, DisengageResult, ErrorOccurrence]):
83
83
 
84
84
  commandType: DisengageCommandType = "magneticModule/disengage"
85
85
  params: DisengageParams
86
- result: Optional[DisengageResult]
86
+ result: Optional[DisengageResult] = None
87
87
 
88
88
  _ImplementationCls: Type[DisengageImplementation] = DisengageImplementation
89
89
 
@@ -105,7 +105,7 @@ class Engage(BaseCommand[EngageParams, EngageResult, ErrorOccurrence]):
105
105
 
106
106
  commandType: EngageCommandType = "magneticModule/engage"
107
107
  params: EngageParams
108
- result: Optional[EngageResult]
108
+ result: Optional[EngageResult] = None
109
109
 
110
110
  _ImplementationCls: Type[EngageImplementation] = EngageImplementation
111
111
 
@@ -1,14 +1,17 @@
1
1
  """Models and implementation for the ``moveLabware`` command."""
2
2
 
3
3
  from __future__ import annotations
4
+ from typing import TYPE_CHECKING, Optional, Type, Any
5
+
6
+ from pydantic.json_schema import SkipJsonSchema
7
+ from pydantic import BaseModel, Field
8
+ from typing_extensions import Literal
9
+
4
10
  from opentrons_shared_data.errors.exceptions import (
5
11
  FailedGripperPickupError,
6
12
  LabwareDroppedError,
7
13
  StallOrCollisionDetectedError,
8
14
  )
9
- from pydantic import BaseModel, Field
10
- from typing import TYPE_CHECKING, Optional, Type
11
- from typing_extensions import Literal
12
15
 
13
16
  from opentrons.protocol_engine.resources.model_utils import ModelUtils
14
17
  from opentrons.types import Point
@@ -49,6 +52,10 @@ if TYPE_CHECKING:
49
52
  MoveLabwareCommandType = Literal["moveLabware"]
50
53
 
51
54
 
55
+ def _remove_default(s: dict[str, Any]) -> None:
56
+ s.pop("default", None)
57
+
58
+
52
59
  # Extra buffer on top of minimum distance to move to the right
53
60
  _TRASH_CHUTE_DROP_BUFFER_MM = 8
54
61
 
@@ -63,15 +70,17 @@ class MoveLabwareParams(BaseModel):
63
70
  description="Whether to use the gripper to perform the labware movement"
64
71
  " or to perform a manual movement with an option to pause.",
65
72
  )
66
- pickUpOffset: Optional[LabwareOffsetVector] = Field(
73
+ pickUpOffset: LabwareOffsetVector | SkipJsonSchema[None] = Field(
67
74
  None,
68
75
  description="Offset to use when picking up labware. "
69
76
  "Experimental param, subject to change",
77
+ json_schema_extra=_remove_default,
70
78
  )
71
- dropOffset: Optional[LabwareOffsetVector] = Field(
79
+ dropOffset: LabwareOffsetVector | SkipJsonSchema[None] = Field(
72
80
  None,
73
81
  description="Offset to use when dropping off labware. "
74
82
  "Experimental param, subject to change",
83
+ json_schema_extra=_remove_default,
75
84
  )
76
85
 
77
86
 
@@ -156,6 +165,7 @@ class MoveLabwareImplementation(AbstractCommandImpl[MoveLabwareParams, _ExecuteR
156
165
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
157
166
  area_name
158
167
  )
168
+ state_update.set_addressable_area_used(addressable_area_name=area_name)
159
169
 
160
170
  if fixture_validation.is_gripper_waste_chute(area_name):
161
171
  # When dropping off labware in the waste chute, some bigger pieces
@@ -201,6 +211,9 @@ class MoveLabwareImplementation(AbstractCommandImpl[MoveLabwareParams, _ExecuteR
201
211
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
202
212
  params.newLocation.slotName.id
203
213
  )
214
+ state_update.set_addressable_area_used(
215
+ addressable_area_name=params.newLocation.slotName.id
216
+ )
204
217
 
205
218
  available_new_location = self._state_view.geometry.ensure_location_not_occupied(
206
219
  location=params.newLocation
@@ -210,6 +223,15 @@ class MoveLabwareImplementation(AbstractCommandImpl[MoveLabwareParams, _ExecuteR
210
223
  self._state_view.labware.raise_if_labware_has_labware_on_top(
211
224
  labware_id=params.labwareId
212
225
  )
226
+
227
+ if isinstance(available_new_location, DeckSlotLocation):
228
+ self._state_view.labware.raise_if_labware_cannot_be_ondeck(
229
+ location=available_new_location,
230
+ labware_definition=self._state_view.labware.get_definition(
231
+ params.labwareId
232
+ ),
233
+ )
234
+
213
235
  if isinstance(available_new_location, OnLabwareLocation):
214
236
  self._state_view.labware.raise_if_labware_has_labware_on_top(
215
237
  available_new_location.labwareId
@@ -355,7 +377,7 @@ class MoveLabware(
355
377
 
356
378
  commandType: MoveLabwareCommandType = "moveLabware"
357
379
  params: MoveLabwareParams
358
- result: Optional[MoveLabwareResult]
380
+ result: Optional[MoveLabwareResult] = None
359
381
 
360
382
  _ImplementationCls: Type[MoveLabwareImplementation] = MoveLabwareImplementation
361
383
 
@@ -5,14 +5,23 @@ from typing import TYPE_CHECKING, Optional, Type
5
5
  from typing_extensions import Literal
6
6
 
7
7
 
8
- from ..state import update_types
9
- from ..types import MovementAxis, DeckPoint
10
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
11
- from ..errors.error_occurrence import ErrorOccurrence
12
- from .pipetting_common import DestinationPositionResult
8
+ from ..types import MovementAxis
9
+ from .command import (
10
+ AbstractCommandImpl,
11
+ BaseCommand,
12
+ BaseCommandCreate,
13
+ SuccessData,
14
+ DefinedErrorData,
15
+ )
16
+ from .movement_common import (
17
+ DestinationPositionResult,
18
+ move_relative,
19
+ StallOrCollisionError,
20
+ )
13
21
 
14
22
  if TYPE_CHECKING:
15
23
  from ..execution import MovementHandler
24
+ from ..resources.model_utils import ModelUtils
16
25
 
17
26
 
18
27
  MoveRelativeCommandType = Literal["moveRelative"]
@@ -39,46 +48,47 @@ class MoveRelativeResult(DestinationPositionResult):
39
48
 
40
49
 
41
50
  class MoveRelativeImplementation(
42
- AbstractCommandImpl[MoveRelativeParams, SuccessData[MoveRelativeResult]]
51
+ AbstractCommandImpl[
52
+ MoveRelativeParams,
53
+ SuccessData[MoveRelativeResult] | DefinedErrorData[StallOrCollisionError],
54
+ ]
43
55
  ):
44
56
  """Move relative command implementation."""
45
57
 
46
- def __init__(self, movement: MovementHandler, **kwargs: object) -> None:
58
+ def __init__(
59
+ self, movement: MovementHandler, model_utils: ModelUtils, **kwargs: object
60
+ ) -> None:
47
61
  self._movement = movement
62
+ self._model_utils = model_utils
48
63
 
49
64
  async def execute(
50
65
  self, params: MoveRelativeParams
51
- ) -> SuccessData[MoveRelativeResult]:
66
+ ) -> SuccessData[MoveRelativeResult] | DefinedErrorData[StallOrCollisionError]:
52
67
  """Move (jog) a given pipette a relative distance."""
53
- state_update = update_types.StateUpdate()
54
-
55
- x, y, z = await self._movement.move_relative(
68
+ result = await move_relative(
69
+ movement=self._movement,
70
+ model_utils=self._model_utils,
56
71
  pipette_id=params.pipetteId,
57
72
  axis=params.axis,
58
73
  distance=params.distance,
59
74
  )
60
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
61
- state_update.pipette_location = update_types.PipetteLocationUpdate(
62
- pipette_id=params.pipetteId,
63
- # TODO(jbl 2023-02-14): Need to investigate whether move relative should clear current location
64
- new_location=update_types.NO_CHANGE,
65
- new_deck_point=deck_point,
66
- )
67
-
68
- return SuccessData(
69
- public=MoveRelativeResult(position=deck_point),
70
- state_update=state_update,
71
- )
75
+ if isinstance(result, DefinedErrorData):
76
+ return result
77
+ else:
78
+ return SuccessData(
79
+ public=MoveRelativeResult(position=result.public.position),
80
+ state_update=result.state_update,
81
+ )
72
82
 
73
83
 
74
84
  class MoveRelative(
75
- BaseCommand[MoveRelativeParams, MoveRelativeResult, ErrorOccurrence]
85
+ BaseCommand[MoveRelativeParams, MoveRelativeResult, StallOrCollisionError]
76
86
  ):
77
87
  """Command to move (jog) a given pipette a relative distance."""
78
88
 
79
89
  commandType: MoveRelativeCommandType = "moveRelative"
80
90
  params: MoveRelativeParams
81
- result: Optional[MoveRelativeResult]
91
+ result: Optional[MoveRelativeResult] = None
82
92
 
83
93
  _ImplementationCls: Type[MoveRelativeImplementation] = MoveRelativeImplementation
84
94
 
@@ -7,20 +7,29 @@ from typing_extensions import Literal
7
7
  from opentrons_shared_data.pipette.types import PipetteNameType
8
8
 
9
9
  from ..errors import LocationNotAccessibleByPipetteError
10
- from ..state import update_types
11
- from ..types import DeckPoint, AddressableOffsetVector
10
+ from ..types import AddressableOffsetVector
12
11
  from ..resources import fixture_validation
13
12
  from .pipetting_common import (
14
13
  PipetteIdMixin,
14
+ )
15
+ from .movement_common import (
15
16
  MovementMixin,
16
17
  DestinationPositionResult,
18
+ move_to_addressable_area,
19
+ StallOrCollisionError,
20
+ )
21
+ from .command import (
22
+ AbstractCommandImpl,
23
+ BaseCommand,
24
+ BaseCommandCreate,
25
+ SuccessData,
26
+ DefinedErrorData,
17
27
  )
18
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
19
- from ..errors.error_occurrence import ErrorOccurrence
20
28
 
21
29
  if TYPE_CHECKING:
22
30
  from ..execution import MovementHandler
23
31
  from ..state.state import StateView
32
+ from ..resources.model_utils import ModelUtils
24
33
 
25
34
  MoveToAddressableAreaCommandType = Literal["moveToAddressableArea"]
26
35
 
@@ -74,25 +83,29 @@ class MoveToAddressableAreaResult(DestinationPositionResult):
74
83
  pass
75
84
 
76
85
 
86
+ _ExecuteReturn = (
87
+ SuccessData[MoveToAddressableAreaResult] | DefinedErrorData[StallOrCollisionError]
88
+ )
89
+
90
+
77
91
  class MoveToAddressableAreaImplementation(
78
- AbstractCommandImpl[
79
- MoveToAddressableAreaParams, SuccessData[MoveToAddressableAreaResult]
80
- ]
92
+ AbstractCommandImpl[MoveToAddressableAreaParams, _ExecuteReturn]
81
93
  ):
82
94
  """Move to addressable area command implementation."""
83
95
 
84
96
  def __init__(
85
- self, movement: MovementHandler, state_view: StateView, **kwargs: object
97
+ self,
98
+ movement: MovementHandler,
99
+ state_view: StateView,
100
+ model_utils: ModelUtils,
101
+ **kwargs: object,
86
102
  ) -> None:
87
103
  self._movement = movement
88
104
  self._state_view = state_view
105
+ self._model_utils = model_utils
89
106
 
90
- async def execute(
91
- self, params: MoveToAddressableAreaParams
92
- ) -> SuccessData[MoveToAddressableAreaResult]:
107
+ async def execute(self, params: MoveToAddressableAreaParams) -> _ExecuteReturn:
93
108
  """Move the requested pipette to the requested addressable area."""
94
- state_update = update_types.StateUpdate()
95
-
96
109
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
97
110
  params.addressableAreaName
98
111
  )
@@ -115,7 +128,9 @@ class MoveToAddressableAreaImplementation(
115
128
  f"Cannot move pipette to staging slot {params.addressableAreaName}"
116
129
  )
117
130
 
118
- x, y, z = await self._movement.move_to_addressable_area(
131
+ result = await move_to_addressable_area(
132
+ movement=self._movement,
133
+ model_utils=self._model_utils,
119
134
  pipette_id=params.pipetteId,
120
135
  addressable_area_name=params.addressableAreaName,
121
136
  offset=params.offset,
@@ -125,29 +140,27 @@ class MoveToAddressableAreaImplementation(
125
140
  stay_at_highest_possible_z=params.stayAtHighestPossibleZ,
126
141
  highest_possible_z_extra_offset=extra_z_offset,
127
142
  )
128
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
129
- state_update.set_pipette_location(
130
- pipette_id=params.pipetteId,
131
- new_addressable_area_name=params.addressableAreaName,
132
- new_deck_point=deck_point,
133
- )
134
-
135
- return SuccessData(
136
- public=MoveToAddressableAreaResult(position=DeckPoint(x=x, y=y, z=z)),
137
- state_update=state_update,
138
- )
143
+ if isinstance(result, DefinedErrorData):
144
+ return result
145
+ else:
146
+ return SuccessData(
147
+ public=MoveToAddressableAreaResult(position=result.public.position),
148
+ state_update=result.state_update,
149
+ )
139
150
 
140
151
 
141
152
  class MoveToAddressableArea(
142
153
  BaseCommand[
143
- MoveToAddressableAreaParams, MoveToAddressableAreaResult, ErrorOccurrence
154
+ MoveToAddressableAreaParams,
155
+ MoveToAddressableAreaResult,
156
+ StallOrCollisionError,
144
157
  ]
145
158
  ):
146
159
  """Move to addressable area command model."""
147
160
 
148
161
  commandType: MoveToAddressableAreaCommandType = "moveToAddressableArea"
149
162
  params: MoveToAddressableAreaParams
150
- result: Optional[MoveToAddressableAreaResult]
163
+ result: Optional[MoveToAddressableAreaResult] = None
151
164
 
152
165
  _ImplementationCls: Type[
153
166
  MoveToAddressableAreaImplementation
@@ -1,28 +1,43 @@
1
1
  """Move to addressable area for drop tip command request, result, and implementation models."""
2
2
  from __future__ import annotations
3
- from pydantic import Field
4
- from typing import TYPE_CHECKING, Optional, Type
3
+ from typing import TYPE_CHECKING, Optional, Type, Any
5
4
  from typing_extensions import Literal
6
5
 
6
+ from pydantic import Field
7
+ from pydantic.json_schema import SkipJsonSchema
8
+
7
9
  from ..errors import LocationNotAccessibleByPipetteError
8
- from ..state import update_types
9
- from ..types import DeckPoint, AddressableOffsetVector
10
+ from ..types import AddressableOffsetVector
10
11
  from ..resources import fixture_validation
11
12
  from .pipetting_common import (
12
13
  PipetteIdMixin,
14
+ )
15
+ from .movement_common import (
13
16
  MovementMixin,
14
17
  DestinationPositionResult,
18
+ move_to_addressable_area,
19
+ StallOrCollisionError,
20
+ )
21
+ from .command import (
22
+ AbstractCommandImpl,
23
+ BaseCommand,
24
+ BaseCommandCreate,
25
+ SuccessData,
26
+ DefinedErrorData,
15
27
  )
16
- from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
17
- from ..errors.error_occurrence import ErrorOccurrence
18
28
 
19
29
  if TYPE_CHECKING:
20
30
  from ..execution import MovementHandler
21
31
  from ..state.state import StateView
32
+ from ..resources.model_utils import ModelUtils
22
33
 
23
34
  MoveToAddressableAreaForDropTipCommandType = Literal["moveToAddressableAreaForDropTip"]
24
35
 
25
36
 
37
+ def _remove_default(s: dict[str, Any]) -> None:
38
+ s.pop("default", None)
39
+
40
+
26
41
  class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
27
42
  """Payload required to move a pipette to a specific addressable area.
28
43
 
@@ -56,7 +71,7 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
56
71
  AddressableOffsetVector(x=0, y=0, z=0),
57
72
  description="Relative offset of addressable area to move pipette's critical point.",
58
73
  )
59
- alternateDropLocation: Optional[bool] = Field(
74
+ alternateDropLocation: bool | SkipJsonSchema[None] = Field(
60
75
  False,
61
76
  description=(
62
77
  "Whether to alternate location where tip is dropped within the addressable area."
@@ -65,8 +80,9 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
65
80
  " labware well."
66
81
  " If False, the tip will be dropped at the top center of the area."
67
82
  ),
83
+ json_schema_extra=_remove_default,
68
84
  )
69
- ignoreTipConfiguration: Optional[bool] = Field(
85
+ ignoreTipConfiguration: bool | SkipJsonSchema[None] = Field(
70
86
  True,
71
87
  description=(
72
88
  "Whether to utilize the critical point of the tip configuraiton when moving to an addressable area."
@@ -74,6 +90,7 @@ class MoveToAddressableAreaForDropTipParams(PipetteIdMixin, MovementMixin):
74
90
  " as the critical point for movement."
75
91
  " If False, this command will use the critical point provided by the current tip configuration."
76
92
  ),
93
+ json_schema_extra=_remove_default,
77
94
  )
78
95
 
79
96
 
@@ -83,26 +100,32 @@ class MoveToAddressableAreaForDropTipResult(DestinationPositionResult):
83
100
  pass
84
101
 
85
102
 
103
+ _ExecuteReturn = (
104
+ SuccessData[MoveToAddressableAreaForDropTipResult]
105
+ | DefinedErrorData[StallOrCollisionError]
106
+ )
107
+
108
+
86
109
  class MoveToAddressableAreaForDropTipImplementation(
87
- AbstractCommandImpl[
88
- MoveToAddressableAreaForDropTipParams,
89
- SuccessData[MoveToAddressableAreaForDropTipResult],
90
- ]
110
+ AbstractCommandImpl[MoveToAddressableAreaForDropTipParams, _ExecuteReturn]
91
111
  ):
92
112
  """Move to addressable area for drop tip command implementation."""
93
113
 
94
114
  def __init__(
95
- self, movement: MovementHandler, state_view: StateView, **kwargs: object
115
+ self,
116
+ movement: MovementHandler,
117
+ state_view: StateView,
118
+ model_utils: ModelUtils,
119
+ **kwargs: object,
96
120
  ) -> None:
97
121
  self._movement = movement
98
122
  self._state_view = state_view
123
+ self._model_utils = model_utils
99
124
 
100
125
  async def execute(
101
126
  self, params: MoveToAddressableAreaForDropTipParams
102
- ) -> SuccessData[MoveToAddressableAreaForDropTipResult]:
127
+ ) -> _ExecuteReturn:
103
128
  """Move the requested pipette to the requested addressable area in preperation of a drop tip."""
104
- state_update = update_types.StateUpdate()
105
-
106
129
  self._state_view.addressable_areas.raise_if_area_not_in_deck_configuration(
107
130
  params.addressableAreaName
108
131
  )
@@ -120,7 +143,9 @@ class MoveToAddressableAreaForDropTipImplementation(
120
143
  else:
121
144
  offset = params.offset
122
145
 
123
- x, y, z = await self._movement.move_to_addressable_area(
146
+ result = await move_to_addressable_area(
147
+ movement=self._movement,
148
+ model_utils=self._model_utils,
124
149
  pipette_id=params.pipetteId,
125
150
  addressable_area_name=params.addressableAreaName,
126
151
  offset=offset,
@@ -129,26 +154,22 @@ class MoveToAddressableAreaForDropTipImplementation(
129
154
  speed=params.speed,
130
155
  ignore_tip_configuration=params.ignoreTipConfiguration,
131
156
  )
132
- deck_point = DeckPoint.construct(x=x, y=y, z=z)
133
- state_update.set_pipette_location(
134
- pipette_id=params.pipetteId,
135
- new_addressable_area_name=params.addressableAreaName,
136
- new_deck_point=deck_point,
137
- )
138
-
139
- return SuccessData(
140
- public=MoveToAddressableAreaForDropTipResult(
141
- position=DeckPoint(x=x, y=y, z=z)
142
- ),
143
- state_update=state_update,
144
- )
157
+ if isinstance(result, DefinedErrorData):
158
+ return result
159
+ else:
160
+ return SuccessData(
161
+ public=MoveToAddressableAreaForDropTipResult(
162
+ position=result.public.position,
163
+ ),
164
+ state_update=result.state_update,
165
+ )
145
166
 
146
167
 
147
168
  class MoveToAddressableAreaForDropTip(
148
169
  BaseCommand[
149
170
  MoveToAddressableAreaForDropTipParams,
150
171
  MoveToAddressableAreaForDropTipResult,
151
- ErrorOccurrence,
172
+ StallOrCollisionError,
152
173
  ]
153
174
  ):
154
175
  """Move to addressable area for drop tip command model."""
@@ -157,7 +178,7 @@ class MoveToAddressableAreaForDropTip(
157
178
  "moveToAddressableAreaForDropTip"
158
179
  )
159
180
  params: MoveToAddressableAreaForDropTipParams
160
- result: Optional[MoveToAddressableAreaForDropTipResult]
181
+ result: Optional[MoveToAddressableAreaForDropTipResult] = None
161
182
 
162
183
  _ImplementationCls: Type[
163
184
  MoveToAddressableAreaForDropTipImplementation