opentrons 8.2.0a4__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 +36 -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 +1 -1
  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 +52 -70
  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.0a4.dist-info → opentrons-8.3.0.dist-info}/METADATA +16 -15
  234. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/RECORD +238 -208
  235. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/WHEEL +1 -1
  236. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/LICENSE +0 -0
  237. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.2.0a4.dist-info → opentrons-8.3.0.dist-info}/top_level.txt +0 -0
@@ -244,6 +244,19 @@ class LiquidDoesNotExistError(ProtocolEngineError):
244
244
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
245
245
 
246
246
 
247
+ class InvalidLiquidError(ProtocolEngineError):
248
+ """Raised when attempting to add a liquid with an invalid property."""
249
+
250
+ def __init__(
251
+ self,
252
+ message: Optional[str] = None,
253
+ details: Optional[Dict[str, Any]] = None,
254
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
255
+ ) -> None:
256
+ """Build an InvalidLiquidError."""
257
+ super().__init__(ErrorCodes.INVALID_PROTOCOL_DATA, message, details, wrapping)
258
+
259
+
247
260
  class LabwareDefinitionDoesNotExistError(ProtocolEngineError):
248
261
  """Raised when referencing a labware definition that does not exist."""
249
262
 
@@ -270,6 +283,19 @@ class LabwareCannotBeStackedError(ProtocolEngineError):
270
283
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
271
284
 
272
285
 
286
+ class LabwareCannotSitOnDeckError(ProtocolEngineError):
287
+ """Raised when a labware is incompatible with a deck slot."""
288
+
289
+ def __init__(
290
+ self,
291
+ message: Optional[str] = None,
292
+ details: Optional[Dict[str, Any]] = None,
293
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
294
+ ) -> None:
295
+ """Build a LabwareCannotSitOnDeckError."""
296
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
297
+
298
+
273
299
  class LabwareIsInStackError(ProtocolEngineError):
274
300
  """Raised when trying to move to or physically interact with a labware that has another labware on top."""
275
301
 
@@ -348,6 +374,32 @@ class TouchTipDisabledError(ProtocolEngineError):
348
374
  super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
349
375
 
350
376
 
377
+ class TouchTipIncompatibleArgumentsError(ProtocolEngineError):
378
+ """Raised when touch tip is used with both a custom radius and a mmFromEdge argument."""
379
+
380
+ def __init__(
381
+ self,
382
+ message: Optional[str] = None,
383
+ details: Optional[Dict[str, Any]] = None,
384
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
385
+ ) -> None:
386
+ """Build a TouchTipIncompatibleArgumentsError."""
387
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
388
+
389
+
390
+ class UnsupportedLabwareForActionError(ProtocolEngineError):
391
+ """Raised when trying to use an unsupported labware for a command."""
392
+
393
+ def __init__(
394
+ self,
395
+ message: Optional[str] = None,
396
+ details: Optional[Dict[str, Any]] = None,
397
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
398
+ ) -> None:
399
+ """Build a UnsupportedLabwareForActionError."""
400
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
401
+
402
+
351
403
  class WellDoesNotExistError(ProtocolEngineError):
352
404
  """Raised when referencing a well that does not exist."""
353
405
 
@@ -1155,3 +1207,27 @@ class StorageLimitReachedError(ProtocolEngineError):
1155
1207
  ) -> None:
1156
1208
  """Build an StorageLimitReached."""
1157
1209
  super().__init__(ErrorCodes.GENERAL_ERROR, message, detail, wrapping)
1210
+
1211
+
1212
+ class LiquidClassDoesNotExistError(ProtocolEngineError):
1213
+ """Raised when referencing a liquid class that has not been loaded."""
1214
+
1215
+ def __init__(
1216
+ self,
1217
+ message: Optional[str] = None,
1218
+ details: Optional[Dict[str, Any]] = None,
1219
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
1220
+ ) -> None:
1221
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
1222
+
1223
+
1224
+ class LiquidClassRedefinitionError(ProtocolEngineError):
1225
+ """Raised when attempting to load a liquid class that conflicts with a liquid class already loaded."""
1226
+
1227
+ def __init__(
1228
+ self,
1229
+ message: Optional[str] = None,
1230
+ details: Optional[Dict[str, Any]] = None,
1231
+ wrapping: Optional[Sequence[EnumeratedError]] = None,
1232
+ ) -> None:
1233
+ super().__init__(ErrorCodes.GENERAL_ERROR, message, details, wrapping)
@@ -188,7 +188,7 @@ class CommandExecutor:
188
188
  "completedAt": self._model_utils.get_timestamp(),
189
189
  "notes": note_tracker.get_notes(),
190
190
  }
191
- succeeded_command = running_command.copy(update=update)
191
+ succeeded_command = running_command.model_copy(update=update)
192
192
  self._action_dispatcher.dispatch(
193
193
  SucceedCommandAction(
194
194
  command=succeeded_command,
@@ -1,6 +1,6 @@
1
1
  """Equipment command side-effect logic."""
2
2
  from dataclasses import dataclass
3
- from typing import Optional, overload, Union
3
+ from typing import Optional, overload, Union, List
4
4
 
5
5
  from opentrons_shared_data.pipette.types import PipetteNameType
6
6
 
@@ -152,10 +152,6 @@ class EquipmentHandler:
152
152
  Returns:
153
153
  A LoadedLabwareData object.
154
154
  """
155
- labware_id = (
156
- labware_id if labware_id is not None else self._model_utils.generate_id()
157
- )
158
-
159
155
  definition_uri = uri_from_details(
160
156
  load_name=load_name,
161
157
  namespace=namespace,
@@ -172,6 +168,10 @@ class EquipmentHandler:
172
168
  version=version,
173
169
  )
174
170
 
171
+ labware_id = (
172
+ labware_id if labware_id is not None else self._model_utils.generate_id()
173
+ )
174
+
175
175
  # Allow propagation of ModuleNotLoadedError.
176
176
  offset_id = self.find_applicable_labware_offset_id(
177
177
  labware_definition_uri=definition_uri,
@@ -379,6 +379,74 @@ class EquipmentHandler:
379
379
  definition=attached_module.definition,
380
380
  )
381
381
 
382
+ async def load_lids(
383
+ self,
384
+ load_name: str,
385
+ namespace: str,
386
+ version: int,
387
+ location: LabwareLocation,
388
+ quantity: int,
389
+ ) -> List[LoadedLabwareData]:
390
+ """Load one or many lid labware by assigning an identifier and pulling required data.
391
+
392
+ Args:
393
+ load_name: The lid labware's load name.
394
+ namespace: The lid labware's namespace.
395
+ version: The lid labware's version.
396
+ location: The deck location at which lid(s) will be placed.
397
+ labware_ids: An optional list of identifiers to assign the labware. If None,
398
+ an identifier will be generated.
399
+
400
+ Raises:
401
+ ModuleNotLoadedError: If `location` references a module ID
402
+ that doesn't point to a valid loaded module.
403
+
404
+ Returns:
405
+ A list of LoadedLabwareData objects.
406
+ """
407
+ definition_uri = uri_from_details(
408
+ load_name=load_name,
409
+ namespace=namespace,
410
+ version=version,
411
+ )
412
+ try:
413
+ # Try to use existing definition in state.
414
+ definition = self._state_store.labware.get_definition_by_uri(definition_uri)
415
+ except LabwareDefinitionDoesNotExistError:
416
+ definition = await self._labware_data_provider.get_labware_definition(
417
+ load_name=load_name,
418
+ namespace=namespace,
419
+ version=version,
420
+ )
421
+
422
+ stack_limit = definition.stackLimit if definition.stackLimit is not None else 1
423
+ if quantity > stack_limit:
424
+ raise ValueError(
425
+ f"Requested quantity {quantity} is greater than the stack limit of {stack_limit} provided by definition for {load_name}."
426
+ )
427
+
428
+ # Allow propagation of ModuleNotLoadedError.
429
+ if (
430
+ isinstance(location, DeckSlotLocation)
431
+ and definition.parameters.isDeckSlotCompatible is not None
432
+ and not definition.parameters.isDeckSlotCompatible
433
+ ):
434
+ raise ValueError(
435
+ f"Lid Labware {load_name} cannot be loaded onto a Deck Slot."
436
+ )
437
+
438
+ load_labware_data_list = []
439
+ for i in range(quantity):
440
+ load_labware_data_list.append(
441
+ LoadedLabwareData(
442
+ labware_id=self._model_utils.generate_id(),
443
+ definition=definition,
444
+ offsetId=None,
445
+ )
446
+ )
447
+
448
+ return load_labware_data_list
449
+
382
450
  async def configure_for_volume(
383
451
  self, pipette_id: str, volume: float, tip_overlap_version: Optional[str]
384
452
  ) -> LoadedConfigureForVolumeData: