opentrons 8.1.0a0__py2.py3-none-any.whl → 8.2.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/cli/analyze.py +71 -7
  2. opentrons/config/__init__.py +9 -0
  3. opentrons/config/advanced_settings.py +22 -0
  4. opentrons/config/defaults_ot3.py +14 -36
  5. opentrons/config/feature_flags.py +4 -0
  6. opentrons/config/types.py +6 -17
  7. opentrons/drivers/absorbance_reader/abstract.py +27 -3
  8. opentrons/drivers/absorbance_reader/async_byonoy.py +208 -154
  9. opentrons/drivers/absorbance_reader/driver.py +24 -15
  10. opentrons/drivers/absorbance_reader/hid_protocol.py +79 -50
  11. opentrons/drivers/absorbance_reader/simulator.py +32 -6
  12. opentrons/drivers/types.py +23 -1
  13. opentrons/execute.py +2 -2
  14. opentrons/hardware_control/api.py +18 -10
  15. opentrons/hardware_control/backends/controller.py +3 -2
  16. opentrons/hardware_control/backends/flex_protocol.py +11 -5
  17. opentrons/hardware_control/backends/ot3controller.py +18 -50
  18. opentrons/hardware_control/backends/ot3simulator.py +7 -6
  19. opentrons/hardware_control/backends/ot3utils.py +1 -0
  20. opentrons/hardware_control/instruments/ot2/pipette_handler.py +22 -82
  21. opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -2
  22. opentrons/hardware_control/module_control.py +43 -2
  23. opentrons/hardware_control/modules/__init__.py +7 -1
  24. opentrons/hardware_control/modules/absorbance_reader.py +232 -83
  25. opentrons/hardware_control/modules/errors.py +7 -0
  26. opentrons/hardware_control/modules/heater_shaker.py +8 -3
  27. opentrons/hardware_control/modules/magdeck.py +12 -3
  28. opentrons/hardware_control/modules/mod_abc.py +27 -2
  29. opentrons/hardware_control/modules/tempdeck.py +15 -7
  30. opentrons/hardware_control/modules/thermocycler.py +69 -3
  31. opentrons/hardware_control/modules/types.py +11 -5
  32. opentrons/hardware_control/modules/update.py +11 -5
  33. opentrons/hardware_control/modules/utils.py +3 -1
  34. opentrons/hardware_control/ot3_calibration.py +6 -6
  35. opentrons/hardware_control/ot3api.py +131 -94
  36. opentrons/hardware_control/poller.py +15 -11
  37. opentrons/hardware_control/protocols/__init__.py +1 -7
  38. opentrons/hardware_control/protocols/instrument_configurer.py +14 -2
  39. opentrons/hardware_control/protocols/liquid_handler.py +5 -0
  40. opentrons/hardware_control/protocols/position_estimator.py +3 -1
  41. opentrons/hardware_control/types.py +2 -0
  42. opentrons/legacy_commands/helpers.py +8 -2
  43. opentrons/motion_planning/__init__.py +2 -0
  44. opentrons/motion_planning/waypoints.py +32 -0
  45. opentrons/protocol_api/__init__.py +2 -1
  46. opentrons/protocol_api/_liquid.py +87 -1
  47. opentrons/protocol_api/_parameter_context.py +10 -1
  48. opentrons/protocol_api/core/engine/deck_conflict.py +0 -297
  49. opentrons/protocol_api/core/engine/instrument.py +29 -25
  50. opentrons/protocol_api/core/engine/labware.py +20 -4
  51. opentrons/protocol_api/core/engine/module_core.py +166 -17
  52. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +362 -0
  53. opentrons/protocol_api/core/engine/protocol.py +30 -2
  54. opentrons/protocol_api/core/instrument.py +2 -0
  55. opentrons/protocol_api/core/labware.py +4 -0
  56. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +2 -0
  57. opentrons/protocol_api/core/legacy/legacy_labware_core.py +5 -0
  58. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +6 -2
  59. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +2 -0
  60. opentrons/protocol_api/core/module.py +22 -4
  61. opentrons/protocol_api/core/protocol.py +6 -2
  62. opentrons/protocol_api/instrument_context.py +52 -20
  63. opentrons/protocol_api/labware.py +13 -1
  64. opentrons/protocol_api/module_contexts.py +115 -17
  65. opentrons/protocol_api/protocol_context.py +49 -5
  66. opentrons/protocol_api/validation.py +5 -3
  67. opentrons/protocol_engine/__init__.py +10 -9
  68. opentrons/protocol_engine/actions/__init__.py +3 -0
  69. opentrons/protocol_engine/actions/actions.py +30 -25
  70. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  71. opentrons/protocol_engine/clients/sync_client.py +1 -1
  72. opentrons/protocol_engine/clients/transports.py +1 -1
  73. opentrons/protocol_engine/commands/__init__.py +0 -4
  74. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +41 -11
  75. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +148 -0
  76. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +65 -9
  77. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +148 -0
  78. opentrons/protocol_engine/commands/absorbance_reader/read.py +200 -0
  79. opentrons/protocol_engine/commands/aspirate.py +29 -16
  80. opentrons/protocol_engine/commands/aspirate_in_place.py +33 -16
  81. opentrons/protocol_engine/commands/blow_out.py +63 -14
  82. opentrons/protocol_engine/commands/blow_out_in_place.py +55 -13
  83. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +2 -5
  84. opentrons/protocol_engine/commands/calibration/calibrate_module.py +3 -4
  85. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +2 -5
  86. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +6 -4
  87. opentrons/protocol_engine/commands/command.py +31 -18
  88. opentrons/protocol_engine/commands/command_unions.py +37 -24
  89. opentrons/protocol_engine/commands/comment.py +5 -3
  90. opentrons/protocol_engine/commands/configure_for_volume.py +11 -14
  91. opentrons/protocol_engine/commands/configure_nozzle_layout.py +9 -15
  92. opentrons/protocol_engine/commands/custom.py +5 -3
  93. opentrons/protocol_engine/commands/dispense.py +42 -20
  94. opentrons/protocol_engine/commands/dispense_in_place.py +32 -14
  95. opentrons/protocol_engine/commands/drop_tip.py +70 -16
  96. opentrons/protocol_engine/commands/drop_tip_in_place.py +59 -13
  97. opentrons/protocol_engine/commands/get_tip_presence.py +5 -3
  98. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +6 -6
  99. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +6 -6
  100. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +6 -6
  101. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +8 -6
  102. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +8 -4
  103. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +6 -4
  104. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +6 -6
  105. opentrons/protocol_engine/commands/home.py +11 -5
  106. opentrons/protocol_engine/commands/liquid_probe.py +146 -88
  107. opentrons/protocol_engine/commands/load_labware.py +28 -5
  108. opentrons/protocol_engine/commands/load_liquid.py +18 -7
  109. opentrons/protocol_engine/commands/load_module.py +4 -6
  110. opentrons/protocol_engine/commands/load_pipette.py +18 -17
  111. opentrons/protocol_engine/commands/magnetic_module/disengage.py +6 -6
  112. opentrons/protocol_engine/commands/magnetic_module/engage.py +6 -4
  113. opentrons/protocol_engine/commands/move_labware.py +155 -23
  114. opentrons/protocol_engine/commands/move_relative.py +15 -3
  115. opentrons/protocol_engine/commands/move_to_addressable_area.py +29 -4
  116. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +13 -4
  117. opentrons/protocol_engine/commands/move_to_coordinates.py +11 -5
  118. opentrons/protocol_engine/commands/move_to_well.py +37 -10
  119. opentrons/protocol_engine/commands/pick_up_tip.py +51 -30
  120. opentrons/protocol_engine/commands/pipetting_common.py +47 -16
  121. opentrons/protocol_engine/commands/prepare_to_aspirate.py +62 -15
  122. opentrons/protocol_engine/commands/reload_labware.py +13 -4
  123. opentrons/protocol_engine/commands/retract_axis.py +6 -3
  124. opentrons/protocol_engine/commands/save_position.py +2 -3
  125. opentrons/protocol_engine/commands/set_rail_lights.py +5 -3
  126. opentrons/protocol_engine/commands/set_status_bar.py +5 -3
  127. opentrons/protocol_engine/commands/temperature_module/deactivate.py +6 -4
  128. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +3 -4
  129. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +6 -6
  130. opentrons/protocol_engine/commands/thermocycler/__init__.py +19 -0
  131. opentrons/protocol_engine/commands/thermocycler/close_lid.py +8 -8
  132. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +6 -4
  133. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +6 -4
  134. opentrons/protocol_engine/commands/thermocycler/open_lid.py +8 -4
  135. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +165 -0
  136. opentrons/protocol_engine/commands/thermocycler/run_profile.py +6 -6
  137. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +3 -4
  138. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +3 -4
  139. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +6 -4
  140. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +6 -4
  141. opentrons/protocol_engine/commands/touch_tip.py +19 -7
  142. opentrons/protocol_engine/commands/unsafe/__init__.py +30 -0
  143. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +6 -4
  144. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -4
  145. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +5 -3
  146. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  147. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  148. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +10 -4
  149. opentrons/protocol_engine/commands/verify_tip_presence.py +5 -5
  150. opentrons/protocol_engine/commands/wait_for_duration.py +5 -3
  151. opentrons/protocol_engine/commands/wait_for_resume.py +5 -3
  152. opentrons/protocol_engine/create_protocol_engine.py +60 -10
  153. opentrons/protocol_engine/engine_support.py +2 -1
  154. opentrons/protocol_engine/error_recovery_policy.py +14 -3
  155. opentrons/protocol_engine/errors/__init__.py +20 -0
  156. opentrons/protocol_engine/errors/error_occurrence.py +8 -3
  157. opentrons/protocol_engine/errors/exceptions.py +127 -2
  158. opentrons/protocol_engine/execution/__init__.py +2 -0
  159. opentrons/protocol_engine/execution/command_executor.py +22 -13
  160. opentrons/protocol_engine/execution/create_queue_worker.py +5 -1
  161. opentrons/protocol_engine/execution/door_watcher.py +1 -1
  162. opentrons/protocol_engine/execution/equipment.py +2 -1
  163. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  164. opentrons/protocol_engine/execution/gantry_mover.py +4 -2
  165. opentrons/protocol_engine/execution/hardware_stopper.py +3 -3
  166. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +1 -4
  167. opentrons/protocol_engine/execution/labware_movement.py +73 -22
  168. opentrons/protocol_engine/execution/movement.py +17 -7
  169. opentrons/protocol_engine/execution/pipetting.py +7 -4
  170. opentrons/protocol_engine/execution/queue_worker.py +6 -2
  171. opentrons/protocol_engine/execution/run_control.py +1 -1
  172. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +1 -1
  173. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +2 -1
  174. opentrons/protocol_engine/execution/tip_handler.py +77 -43
  175. opentrons/protocol_engine/notes/__init__.py +14 -2
  176. opentrons/protocol_engine/notes/notes.py +18 -1
  177. opentrons/protocol_engine/plugins.py +1 -1
  178. opentrons/protocol_engine/protocol_engine.py +47 -31
  179. opentrons/protocol_engine/resources/__init__.py +2 -0
  180. opentrons/protocol_engine/resources/deck_data_provider.py +19 -5
  181. opentrons/protocol_engine/resources/file_provider.py +161 -0
  182. opentrons/protocol_engine/resources/fixture_validation.py +11 -1
  183. opentrons/protocol_engine/resources/labware_validation.py +10 -0
  184. opentrons/protocol_engine/state/__init__.py +0 -70
  185. opentrons/protocol_engine/state/addressable_areas.py +1 -1
  186. opentrons/protocol_engine/state/command_history.py +21 -2
  187. opentrons/protocol_engine/state/commands.py +110 -31
  188. opentrons/protocol_engine/state/files.py +59 -0
  189. opentrons/protocol_engine/state/frustum_helpers.py +440 -0
  190. opentrons/protocol_engine/state/geometry.py +445 -59
  191. opentrons/protocol_engine/state/labware.py +264 -84
  192. opentrons/protocol_engine/state/liquids.py +1 -1
  193. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +21 -3
  194. opentrons/protocol_engine/state/modules.py +145 -90
  195. opentrons/protocol_engine/state/motion.py +33 -14
  196. opentrons/protocol_engine/state/pipettes.py +157 -317
  197. opentrons/protocol_engine/state/state.py +30 -1
  198. opentrons/protocol_engine/state/state_summary.py +3 -0
  199. opentrons/protocol_engine/state/tips.py +69 -114
  200. opentrons/protocol_engine/state/update_types.py +424 -0
  201. opentrons/protocol_engine/state/wells.py +236 -0
  202. opentrons/protocol_engine/types.py +90 -0
  203. opentrons/protocol_reader/file_format_validator.py +83 -15
  204. opentrons/protocol_runner/json_translator.py +21 -5
  205. opentrons/protocol_runner/legacy_command_mapper.py +27 -6
  206. opentrons/protocol_runner/legacy_context_plugin.py +27 -71
  207. opentrons/protocol_runner/protocol_runner.py +6 -3
  208. opentrons/protocol_runner/run_orchestrator.py +41 -6
  209. opentrons/protocols/advanced_control/mix.py +3 -5
  210. opentrons/protocols/advanced_control/transfers.py +125 -56
  211. opentrons/protocols/api_support/constants.py +1 -1
  212. opentrons/protocols/api_support/definitions.py +1 -1
  213. opentrons/protocols/api_support/labware_like.py +4 -4
  214. opentrons/protocols/api_support/tip_tracker.py +2 -2
  215. opentrons/protocols/api_support/types.py +15 -2
  216. opentrons/protocols/api_support/util.py +30 -42
  217. opentrons/protocols/duration/errors.py +1 -1
  218. opentrons/protocols/duration/estimator.py +50 -29
  219. opentrons/protocols/execution/dev_types.py +2 -2
  220. opentrons/protocols/execution/execute_json_v4.py +15 -10
  221. opentrons/protocols/execution/execute_python.py +8 -3
  222. opentrons/protocols/geometry/planning.py +12 -12
  223. opentrons/protocols/labware.py +17 -33
  224. opentrons/protocols/parameters/csv_parameter_interface.py +3 -1
  225. opentrons/simulate.py +3 -3
  226. opentrons/types.py +30 -3
  227. opentrons/util/logging_config.py +34 -0
  228. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/METADATA +5 -4
  229. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/RECORD +235 -223
  230. opentrons/protocol_engine/commands/absorbance_reader/measure.py +0 -94
  231. opentrons/protocol_engine/commands/configuring_common.py +0 -26
  232. opentrons/protocol_runner/thread_async_queue.py +0 -174
  233. /opentrons/protocol_engine/state/{abstract_store.py → _abstract_store.py} +0 -0
  234. /opentrons/protocol_engine/state/{move_types.py → _move_types.py} +0 -0
  235. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/LICENSE +0 -0
  236. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/WHEEL +0 -0
  237. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/entry_points.txt +0 -0
  238. {opentrons-8.1.0a0.dist-info → opentrons-8.2.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,6 @@
1
1
  import logging
2
- from typing import Optional, List
2
+ from typing import Any, Optional, List, cast
3
3
  from typing_extensions import Final
4
-
5
4
  import math
6
5
  import functools
7
6
 
@@ -54,7 +53,7 @@ class DurationEstimator:
54
53
  Broker listener that calculates the duration of protocol steps.
55
54
  """
56
55
 
57
- def __init__(self):
56
+ def __init__(self) -> None:
58
57
  # Which slot the last command was in.
59
58
  self._last_deckslot = STARTING_SLOT
60
59
  # todo(mm, 2021-09-08): Support protocols with more than one
@@ -128,39 +127,50 @@ class DurationEstimator:
128
127
  # TODO (al, 2021-09-09):
129
128
  # - Make this into a map
130
129
  # - Remove "noqa: C901"
131
- # - type the payload in the on_X methods.
132
130
  if message_name == types.PICK_UP_TIP:
131
+ payload = cast(types.PickUpTipCommandPayload, payload)
133
132
  duration = self.on_pick_up_tip(payload=payload)
134
133
  elif message_name == types.DROP_TIP:
134
+ payload = cast(types.DropTipCommandPayload, payload)
135
135
  duration = self.on_drop_tip(payload=payload)
136
136
  elif message_name == types.ASPIRATE:
137
+ payload = cast(types.AspirateDispenseCommandPayload, payload)
137
138
  duration = self.on_aspirate(payload=payload)
138
139
  elif message_name == types.DISPENSE:
140
+ payload = cast(types.AspirateDispenseCommandPayload, payload)
139
141
  duration = self.on_dispense(payload=payload)
140
142
  elif message_name == types.BLOW_OUT:
143
+ payload = cast(types.BlowOutCommandPayload, payload)
141
144
  duration = self.on_blow_out(payload=payload)
142
145
  elif message_name == types.TOUCH_TIP:
143
- duration = self.on_touch_tip(payload=payload)
146
+ payload = cast(types.TouchTipCommandPayload, payload)
147
+ duration = self.on_touch_tip()
144
148
  elif message_name == types.DELAY:
149
+ payload = cast(types.DelayCommandPayload, payload)
145
150
  duration = self.on_delay(payload=payload)
146
151
  elif message_name == types.TEMPDECK_SET_TEMP:
152
+ payload = cast(types.TempdeckSetTempCommandPayload, payload)
147
153
  duration = self.on_tempdeck_set_temp(payload=payload)
148
154
  elif message_name == types.TEMPDECK_DEACTIVATE:
149
- duration = self.on_tempdeck_deactivate(payload=payload)
155
+ payload = cast(types.TempdeckDeactivateCommandPayload, payload)
156
+ duration = self.on_tempdeck_deactivate()
150
157
  elif message_name == types.TEMPDECK_AWAIT_TEMP:
151
- duration = self.on_tempdeck_await_temp(payload=payload)
158
+ payload = cast(types.TempdeckAwaitTempCommandPayload, payload)
159
+ duration = self.on_tempdeck_await_temp()
152
160
  elif message_name == types.THERMOCYCLER_SET_BLOCK_TEMP:
161
+ payload = cast(types.ThermocyclerSetBlockTempCommandPayload, payload)
153
162
  duration = self.on_thermocycler_block_temp(payload=payload)
154
163
  elif message_name == types.THERMOCYCLER_EXECUTE_PROFILE:
164
+ payload = cast(types.ThermocyclerExecuteProfileCommandPayload, payload)
155
165
  duration = self.on_execute_profile(payload=payload)
156
166
  elif message_name == types.THERMOCYCLER_SET_LID_TEMP:
157
- duration = self.on_thermocycler_set_lid_temp(payload=payload)
167
+ duration = self.on_thermocycler_set_lid_temp()
158
168
  elif message_name == types.THERMOCYCLER_CLOSE:
159
- duration = self.on_thermocycler_lid_close(payload=payload)
169
+ duration = self.on_thermocycler_lid_close()
160
170
  elif message_name == types.THERMOCYCLER_DEACTIVATE_LID:
161
- duration = self.on_thermocycler_deactivate_lid(payload=payload)
171
+ duration = self.on_thermocycler_deactivate_lid()
162
172
  elif message_name == types.THERMOCYCLER_OPEN:
163
- duration = self.on_thermocycler_lid_open(payload=payload)
173
+ duration = self.on_thermocycler_lid_open()
164
174
  elif message_name == types.TRANSFER:
165
175
  # Already accounted for in other steps
166
176
  pass
@@ -177,10 +187,10 @@ class DurationEstimator:
177
187
  )
178
188
  return duration
179
189
 
180
- def on_pick_up_tip(self, payload) -> float:
190
+ def on_pick_up_tip(self, payload: types.PickUpTipCommandPayload) -> float:
181
191
  """Handle a pick up tip event"""
182
- instrument = payload["instrument"]
183
192
 
193
+ instrument = payload["instrument"]
184
194
  location = payload["location"]
185
195
  prev_slot = self._last_deckslot
186
196
  curr_slot = self.get_slot(location)
@@ -200,7 +210,8 @@ class DurationEstimator:
200
210
  )
201
211
  return duration
202
212
 
203
- def on_drop_tip(self, payload) -> float:
213
+ def on_drop_tip(self, payload: types.DropTipCommandPayload) -> float:
214
+
204
215
  instrument = payload["instrument"]
205
216
  # We are going to once again use our "deck movement" set up. This should
206
217
  # be in pickup, drop tip, aspirate, dispense
@@ -221,7 +232,7 @@ class DurationEstimator:
221
232
  logger.info(f"{instrument.name}, drop tip duration is {duration}")
222
233
  return duration
223
234
 
224
- def on_aspirate(self, payload) -> float:
235
+ def on_aspirate(self, payload: types.AspirateDispenseCommandPayload) -> float:
225
236
  # General aspiration code
226
237
  instrument = payload["instrument"]
227
238
  volume = payload["volume"]
@@ -250,13 +261,14 @@ class DurationEstimator:
250
261
  deck_travel_time = self.calc_deck_movement_time(
251
262
  self._deck, curr_slot, prev_slot, gantry_speed
252
263
  )
264
+ assert isinstance(aspiration_time, float)
253
265
  duration = deck_travel_time + z_total_time + aspiration_time
254
266
  logger.info(
255
267
  f"{instrument.name} aspirate from {slot}, " f"the duration is {duration}"
256
268
  )
257
269
  return duration
258
270
 
259
- def on_dispense(self, payload) -> float:
271
+ def on_dispense(self, payload: types.AspirateDispenseCommandPayload) -> float:
260
272
  # General code for aspiration/dispense
261
273
  instrument = payload["instrument"]
262
274
  volume = payload["volume"]
@@ -282,6 +294,7 @@ class DurationEstimator:
282
294
  self._deck, curr_slot, prev_slot, gantry_speed
283
295
  )
284
296
 
297
+ assert isinstance(dispense_time, float)
285
298
  duration = deck_travel_time + z_total_time + dispense_time
286
299
 
287
300
  logger.info(
@@ -289,7 +302,7 @@ class DurationEstimator:
289
302
  )
290
303
  return duration
291
304
 
292
- def on_blow_out(self, payload) -> float:
305
+ def on_blow_out(self, payload: types.BlowOutCommandPayload) -> float:
293
306
  location = payload["location"]
294
307
  curr_slot = self.get_slot(location)
295
308
  # In theory, we could use instrument.flow_rate.blow_out, but we don't
@@ -299,7 +312,7 @@ class DurationEstimator:
299
312
  logger.info(f"blowing_out_for {duration} seconds, in slot {curr_slot}")
300
313
  return duration
301
314
 
302
- def on_touch_tip(self, payload) -> float:
315
+ def on_touch_tip(self) -> float:
303
316
  # base assumption. Touch_tip takes 0.5 seconds This is consistent with a
304
317
  # ~7.5mm diameter (default 60mm/s, 4 sides)
305
318
  # plate = protocol.load_labware('corning_96_wellplate_360ul_flat', '1')
@@ -311,17 +324,20 @@ class DurationEstimator:
311
324
  logger.info(f"touch_tip for {duration} seconds")
312
325
  return duration
313
326
 
314
- def on_delay(self, payload) -> float:
327
+ def on_delay(self, payload: types.DelayCommandPayload) -> float:
315
328
  # Explanation: we are gathering seconds and minutes here
316
329
  seconds_delay = payload["seconds"]
317
330
  minutes_delay = payload["minutes"]
318
331
  duration = seconds_delay + minutes_delay * 60
332
+ duration = float(duration)
319
333
  # Note will need to multiply minutes by 60
320
334
  logger.info(f"delay for {seconds_delay} seconds and {minutes_delay} minutes")
321
335
 
322
336
  return duration
323
337
 
324
- def on_thermocycler_block_temp(self, payload) -> float:
338
+ def on_thermocycler_block_temp(
339
+ self, payload: types.ThermocyclerSetBlockTempCommandPayload
340
+ ) -> float:
325
341
  temperature = payload["temperature"]
326
342
  hold_time = payload["hold_time"]
327
343
  temp0 = self._last_thermocycler_module_temperature
@@ -340,10 +356,13 @@ class DurationEstimator:
340
356
  f"hold for {hold_time} seconds and set temp for {temperature}"
341
357
  f" C total duration {duration}"
342
358
  )
359
+ duration = float(duration)
343
360
 
344
361
  return duration
345
362
 
346
- def on_execute_profile(self, payload) -> float:
363
+ def on_execute_profile(
364
+ self, payload: types.ThermocyclerExecuteProfileCommandPayload
365
+ ) -> float:
347
366
  # Overview We need to run each time a temperature change happens
348
367
  # through thermocycler_handler and multiply
349
368
  # By the cycle count. Then we also (in parallel) do the same with delays
@@ -386,35 +405,37 @@ class DurationEstimator:
386
405
  )
387
406
  return duration
388
407
 
389
- def on_thermocycler_set_lid_temp(self, payload) -> float:
408
+ def on_thermocycler_set_lid_temp(self) -> float:
390
409
  # Hardware said ~1 minute
391
410
  duration = 60
392
411
  thermoaction = "set lid temperature"
393
412
  logger.info(f"thermocation = {thermoaction}")
394
413
  return duration
395
414
 
396
- def on_thermocycler_lid_close(self, payload) -> float:
415
+ def on_thermocycler_lid_close(self) -> float:
397
416
  # Hardware said ~24 seconds
398
417
  duration = 24
399
418
  thermoaction = "closing"
400
419
  logger.info(f"thermocation = {thermoaction}")
401
420
  return duration
402
421
 
403
- def on_thermocycler_lid_open(self, payload) -> float:
422
+ def on_thermocycler_lid_open(self) -> float:
404
423
  # Hardware said ~24 seconds
405
424
  duration = 24
406
425
  thermoaction = "opening"
407
426
  logger.info(f"thermocation = {thermoaction}")
408
427
  return duration
409
428
 
410
- def on_thermocycler_deactivate_lid(self, payload) -> float:
429
+ def on_thermocycler_deactivate_lid(self) -> float:
411
430
  # Hardware said ~23 seconds
412
431
  duration = 23
413
432
  thermoaction = "Deactivating"
414
433
  logger.info(f"thermocation = {thermoaction}")
415
434
  return duration
416
435
 
417
- def on_tempdeck_set_temp(self, payload) -> float:
436
+ def on_tempdeck_set_temp(
437
+ self, payload: types.TempdeckSetTempCommandPayload
438
+ ) -> float:
418
439
  temperature_tempdeck = payload["celsius"]
419
440
  temp0 = self._last_temperature_module_temperature
420
441
  temp1 = float(temperature_tempdeck)
@@ -460,20 +481,20 @@ class DurationEstimator:
460
481
  duration = self.rate_low(temp0, temp1)
461
482
  return duration
462
483
 
463
- def on_tempdeck_deactivate(self, payload) -> float:
484
+ def on_tempdeck_deactivate(self) -> float:
464
485
  # TODO (al, 2021-09-08: Find an answer for this value.
465
486
  duration = 0.0
466
487
  logger.info("tempdeck deactivating")
467
488
  return duration
468
489
 
469
- def on_tempdeck_await_temp(self, payload) -> float:
490
+ def on_tempdeck_await_temp(self) -> float:
470
491
  # The duration is accounted for in set temperature
471
492
  duration = 0.0
472
493
  logger.info("tempdeck awaiting temperature")
473
494
  return duration
474
495
 
475
496
  @staticmethod
476
- def get_slot(location) -> Optional[str]:
497
+ def get_slot(location: Any) -> Optional[str]:
477
498
  """A utility function to extract the slot number from the location."""
478
499
  if isinstance(location, Location):
479
500
  return location.labware.first_parent()
@@ -1,4 +1,4 @@
1
- from typing import Callable, Dict, TYPE_CHECKING
1
+ from typing import Callable, Dict, TYPE_CHECKING, Any
2
2
 
3
3
  from typing_extensions import Protocol, TypedDict
4
4
 
@@ -45,7 +45,7 @@ if Protocol is not None:
45
45
  not a type (https://github.com/python/mypy/issues/3915)
46
46
  """
47
47
 
48
- async def _asdict(self):
48
+ async def _asdict(self) -> Dict[Any, Any]:
49
49
  ...
50
50
 
51
51
 
@@ -8,6 +8,11 @@ from opentrons.protocol_api import (
8
8
  ModuleContext,
9
9
  ThermocyclerContext,
10
10
  )
11
+ from opentrons_shared_data.protocol.types import (
12
+ MagneticModuleCommand,
13
+ TemperatureModuleCommand,
14
+ ThermocyclerCommand,
15
+ )
11
16
  from .execute_json_v3 import _delay, _move_to_slot
12
17
  from opentrons.protocols.execution.types import LoadedLabware, Instruments
13
18
  from opentrons_shared_data.protocol.constants import (
@@ -277,21 +282,21 @@ def dispatch_json(
277
282
  params, # type: ignore
278
283
  modules,
279
284
  command_type, # type: ignore
280
- magnetic_module_command_map,
285
+ magnetic_module_command_map, # type: ignore[arg-type]
281
286
  )
282
287
  elif command_type in temperature_module_command_map:
283
288
  handleTemperatureCommand(
284
- params, # type: ignore
289
+ params, # type: ignore[arg-type]
285
290
  modules,
286
291
  command_type, # type: ignore
287
- temperature_module_command_map,
292
+ temperature_module_command_map, # type: ignore[arg-type]
288
293
  )
289
294
  elif command_type in thermocycler_module_command_map:
290
295
  handleThermocyclerCommand(
291
296
  params, # type: ignore
292
297
  modules, # type: ignore
293
298
  command_type, # type: ignore
294
- thermocycler_module_command_map,
299
+ thermocycler_module_command_map, # type: ignore[arg-type]
295
300
  )
296
301
  elif command_item["command"] == JsonRobotCommand.delay.value:
297
302
  _delay(context, params) # type: ignore
@@ -305,12 +310,12 @@ def handleTemperatureCommand(
305
310
  params: Union["TemperatureParams", "ModuleIDParams"],
306
311
  modules: Dict[str, ModuleContext],
307
312
  command_type: "TemperatureModuleCommandId",
308
- temperature_module_command_map,
313
+ temperature_module_command_map: TemperatureModuleCommand,
309
314
  ) -> None:
310
315
  module_id = params["module"]
311
316
  module = modules[module_id]
312
317
  if isinstance(module, TemperatureModuleContext):
313
- temperature_module_command_map[command_type](module, params)
318
+ temperature_module_command_map[command_type](module, params) # type: ignore[typeddict-item]
314
319
  else:
315
320
  raise RuntimeError(
316
321
  "Temperature Module does not match " + "TemperatureModuleContext interface"
@@ -326,12 +331,12 @@ def handleThermocyclerCommand(
326
331
  ],
327
332
  modules: Dict[str, ThermocyclerContext],
328
333
  command_type: "ThermocyclerCommandId",
329
- thermocycler_module_command_map,
334
+ thermocycler_module_command_map: ThermocyclerCommand,
330
335
  ) -> None:
331
336
  module_id = params["module"]
332
337
  module = modules[module_id]
333
338
  if isinstance(module, ThermocyclerContext):
334
- thermocycler_module_command_map[command_type](module, params)
339
+ thermocycler_module_command_map[command_type](module, params) # type: ignore[typeddict-item]
335
340
  else:
336
341
  raise RuntimeError(
337
342
  "Thermocycler Module does not match ThermocyclerContext interface"
@@ -342,12 +347,12 @@ def handleMagnetCommand(
342
347
  params: Union["ModuleIDParams", "MagneticModuleEngageParams"],
343
348
  modules: Dict[str, ModuleContext],
344
349
  command_type: "MagneticModuleCommandId",
345
- magnetic_module_command_map,
350
+ magnetic_module_command_map: MagneticModuleCommand,
346
351
  ) -> None:
347
352
  module_id = params["module"]
348
353
  module = modules[module_id]
349
354
  if isinstance(module, MagneticModuleContext):
350
- magnetic_module_command_map[command_type](module, params)
355
+ magnetic_module_command_map[command_type](module, params) # type: ignore[typeddict-item]
351
356
  else:
352
357
  raise RuntimeError(
353
358
  "Magnetic Module does not match MagneticModuleContext interface"
@@ -3,6 +3,7 @@ import inspect
3
3
  import logging
4
4
  import traceback
5
5
  import sys
6
+ from types import TracebackType
6
7
  from typing import Any, Dict, Optional
7
8
 
8
9
  from opentrons.drivers.smoothie_drivers.errors import SmoothieAlarm
@@ -21,7 +22,7 @@ from opentrons_shared_data.errors.exceptions import ExecutionCancelledError
21
22
  MODULE_LOG = logging.getLogger(__name__)
22
23
 
23
24
 
24
- def _runfunc_ok(run_func: Any):
25
+ def _runfunc_ok(run_func: Any) -> None:
25
26
  if not callable(run_func):
26
27
  raise SyntaxError("No function 'run(ctx)' defined")
27
28
  sig = inspect.Signature.from_callable(run_func)
@@ -44,10 +45,14 @@ def _add_parameters_func_ok(add_parameters_func: Any) -> None:
44
45
  raise SyntaxError("Function 'add_parameters' must take exactly one argument.")
45
46
 
46
47
 
47
- def _find_protocol_error(tb, proto_name):
48
+ def _find_protocol_error(
49
+ tb: TracebackType | None, proto_name: str
50
+ ) -> traceback.FrameSummary:
48
51
  """Return the FrameInfo for the lowest frame in the traceback from the
49
52
  protocol.
50
53
  """
54
+ if tb is None:
55
+ raise KeyError
51
56
  tb_info = traceback.extract_tb(tb)
52
57
  for frame in reversed(tb_info):
53
58
  if frame.filename == proto_name:
@@ -57,7 +62,7 @@ def _find_protocol_error(tb, proto_name):
57
62
 
58
63
 
59
64
  def _raise_pretty_protocol_error(exception: Exception, filename: str) -> None:
60
- exc_type, exc_value, tb = sys.exc_info()
65
+ _, _, tb = sys.exc_info()
61
66
  try:
62
67
  frame = _find_protocol_error(tb, filename)
63
68
  except KeyError:
@@ -1,7 +1,7 @@
1
1
  import functools
2
2
  import logging
3
3
  from dataclasses import dataclass
4
- from typing import List, Optional, Tuple
4
+ from typing import Any, List, Optional, Tuple, Type
5
5
 
6
6
  from opentrons import types
7
7
  from opentrons.hardware_control.types import CriticalPoint
@@ -27,7 +27,7 @@ class LabwareHeightError(Exception):
27
27
  pass
28
28
 
29
29
 
30
- def max_many(*args):
30
+ def max_many(*args: float) -> float:
31
31
  return functools.reduce(max, args[1:], args[0])
32
32
 
33
33
 
@@ -76,7 +76,7 @@ class MoveConstraints:
76
76
  minimum_z_height: float = 0.0
77
77
 
78
78
  @classmethod
79
- def build(cls, **kwargs):
79
+ def build(cls: Type["MoveConstraints"], **kwargs: Any) -> "MoveConstraints":
80
80
  return cls(**{k: v for k, v in kwargs.items() if v is not None})
81
81
 
82
82
 
@@ -103,10 +103,10 @@ def safe_height(
103
103
  to_loc: types.Location,
104
104
  deck: Deck,
105
105
  instr_max_height: float,
106
- well_z_margin: float = None,
107
- lw_z_margin: float = None,
108
- minimum_lw_z_margin: float = None,
109
- minimum_z_height: float = None,
106
+ well_z_margin: Optional[float] = None,
107
+ lw_z_margin: Optional[float] = None,
108
+ minimum_lw_z_margin: Optional[float] = None,
109
+ minimum_z_height: Optional[float] = None,
110
110
  ) -> float:
111
111
  """
112
112
  Derive the height required to clear the current deck setup along
@@ -147,7 +147,7 @@ def _build_safe_height(
147
147
  from_point = from_loc.point
148
148
  from_lw, from_well = from_loc.labware.get_parent_labware_and_well()
149
149
 
150
- if to_lw and to_lw == from_lw:
150
+ if to_lw and from_lw and to_lw == from_lw:
151
151
  # If we know the labwares we’re moving from and to, we can calculate
152
152
  # a safe z based on their heights
153
153
  if to_well:
@@ -206,11 +206,11 @@ def plan_moves(
206
206
  to_loc: types.Location,
207
207
  deck: Deck,
208
208
  instr_max_height: float,
209
- well_z_margin: float = None,
210
- lw_z_margin: float = None,
209
+ well_z_margin: Optional[float] = None,
210
+ lw_z_margin: Optional[float] = None,
211
211
  force_direct: bool = False,
212
- minimum_lw_z_margin: float = None,
213
- minimum_z_height: float = None,
212
+ minimum_lw_z_margin: Optional[float] = None,
213
+ minimum_z_height: Optional[float] = None,
214
214
  use_experimental_waypoint_planning: bool = False,
215
215
  ) -> List[Tuple[types.Point, Optional[CriticalPoint]]]:
216
216
  """Plan moves between one :py:class:`.Location` and another.
@@ -2,14 +2,12 @@ from __future__ import annotations
2
2
 
3
3
  import logging
4
4
  import json
5
- import os
6
5
 
7
6
  from pathlib import Path
8
- from typing import Any, AnyStr, List, Dict, Optional, Union
7
+ from typing import Any, AnyStr, Dict, Optional, Union
9
8
 
10
9
  import jsonschema # type: ignore
11
10
 
12
- from opentrons.protocols.api_support.util import ModifiedList
13
11
  from opentrons_shared_data import load_shared_data, get_shared_data_root
14
12
  from opentrons.protocols.api_support.constants import (
15
13
  OPENTRONS_NAMESPACE,
@@ -63,29 +61,6 @@ def get_labware_definition(
63
61
  return _get_standard_labware_definition(load_name, namespace, version)
64
62
 
65
63
 
66
- def get_all_labware_definitions() -> List[str]:
67
- """
68
- Return a list of standard and custom labware definitions with load_name +
69
- name_space + version existing on the robot
70
- """
71
- labware_list = ModifiedList()
72
-
73
- def _check_for_subdirectories(path):
74
- with os.scandir(path) as top_path:
75
- for sub_dir in top_path:
76
- if sub_dir.is_dir():
77
- labware_list.append(sub_dir.name)
78
-
79
- # check for standard labware
80
- _check_for_subdirectories(get_shared_data_root() / STANDARD_DEFS_PATH)
81
-
82
- # check for custom labware
83
- for namespace in os.scandir(USER_DEFS_PATH):
84
- _check_for_subdirectories(namespace)
85
-
86
- return labware_list
87
-
88
-
89
64
  def save_definition(
90
65
  labware_def: LabwareDefinition, force: bool = False, location: Optional[Path] = None
91
66
  ) -> None:
@@ -114,7 +89,6 @@ def save_definition(
114
89
  f'Saving definitions to the "{OPENTRONS_NAMESPACE}" namespace '
115
90
  + "is not permitted"
116
91
  )
117
-
118
92
  def_path = _get_path_to_labware(load_name, namespace, version, location)
119
93
 
120
94
  if not force and def_path.is_file():
@@ -150,7 +124,7 @@ def verify_definition(
150
124
  jsonschema.validate(to_return, labware_schema_v2)
151
125
  # we can type ignore this because if it passes the jsonschema it has
152
126
  # the correct structure
153
- return to_return # type: ignore
127
+ return to_return # type: ignore[return-value]
154
128
 
155
129
 
156
130
  def _get_labware_definition_from_bundle(
@@ -219,7 +193,6 @@ def _get_standard_labware_definition(
219
193
  Definitions Folder from the Opentrons App before
220
194
  uploading your protocol.
221
195
  """
222
-
223
196
  if namespace is None:
224
197
  for fallback_namespace in [OPENTRONS_NAMESPACE, CUSTOM_NAMESPACE]:
225
198
  try:
@@ -244,8 +217,7 @@ def _get_standard_labware_definition(
244
217
  f'Labware "{load_name}" not found with version {checked_version} '
245
218
  f'in namespace "{namespace}".'
246
219
  )
247
-
248
- return labware_def
220
+ return labware_def # type: ignore[no-any-return]
249
221
 
250
222
 
251
223
  def _get_path_to_labware(
@@ -253,9 +225,21 @@ def _get_path_to_labware(
253
225
  ) -> Path:
254
226
  if namespace == OPENTRONS_NAMESPACE:
255
227
  # all labware in OPENTRONS_NAMESPACE is stored in shared data
256
- return (
257
- get_shared_data_root() / STANDARD_DEFS_PATH / load_name / f"{version}.json"
228
+ schema_3_path = (
229
+ get_shared_data_root()
230
+ / STANDARD_DEFS_PATH
231
+ / "3"
232
+ / load_name
233
+ / f"{version}.json"
234
+ )
235
+ schema_2_path = (
236
+ get_shared_data_root()
237
+ / STANDARD_DEFS_PATH
238
+ / "2"
239
+ / load_name
240
+ / f"{version}.json"
258
241
  )
242
+ return schema_3_path if schema_3_path.exists() else schema_2_path
259
243
  if not base_path:
260
244
  base_path = USER_DEFS_PATH
261
245
  def_path = base_path / namespace / load_name / f"{version}.json"
@@ -60,7 +60,9 @@ class CSVParameter:
60
60
  as appropriate.
61
61
 
62
62
  :param detect_dialect: If ``True``, examine the file and try to assign it a
63
- :py:class:`csv.Dialect` to improve parsing behavior.
63
+ :py:class:`csv.Dialect` to improve parsing behavior. Set this to ``False``
64
+ when using the file output of :py:meth:`.AbsorbanceReaderContext.read` as
65
+ a runtime parameter.
64
66
  :param kwargs: For advanced CSV handling, you can pass any of the
65
67
  `formatting parameters <https://docs.python.org/3/library/csv.html#csv-fmt-params>`_
66
68
  accepted by :py:func:`csv.reader` from the Python standard library.
opentrons/simulate.py CHANGED
@@ -815,6 +815,7 @@ def _create_live_context_pe(
815
815
  robot_type, use_pe_virtual_hardware=use_pe_virtual_hardware
816
816
  ),
817
817
  deck_configuration=None,
818
+ file_provider=None,
818
819
  error_recovery_policy=error_recovery_policy.never_recover,
819
820
  drop_tips_after_run=False,
820
821
  post_run_hardware_state=PostRunHardwareState.STAY_ENGAGED_IN_PLACE,
@@ -883,8 +884,6 @@ def _run_file_non_pe(
883
884
  context.home()
884
885
  with scraper.scrape():
885
886
  try:
886
- # TODO (spp, 2024-03-18): use true run-time param overrides once enabled
887
- # for cli protocol simulation/ execution
888
887
  execute.run_protocol(
889
888
  protocol, context, run_time_parameters_with_overrides=None
890
889
  )
@@ -914,6 +913,7 @@ def _run_file_pe(
914
913
  log_level: str,
915
914
  ) -> _SimulateResult:
916
915
  """Run a protocol file with Protocol Engine."""
916
+ # TODO (spp, 2024-03-18): use run-time param overrides once enabled for cli protocol simulation.
917
917
 
918
918
  async def run(protocol_source: ProtocolSource) -> _SimulateResult:
919
919
  hardware_api_wrapped = hardware_api.wrapped()
@@ -1014,7 +1014,7 @@ def main() -> int:
1014
1014
  args = parser.parse_args()
1015
1015
 
1016
1016
  # TODO(mm, 2022-12-01): Configure the DurationEstimator with the correct deck type.
1017
- duration_estimator = DurationEstimator() if args.estimate_duration else None # type: ignore[no-untyped-call]
1017
+ duration_estimator = DurationEstimator() if args.estimate_duration else None
1018
1018
 
1019
1019
  try:
1020
1020
  runlog, maybe_bundle = simulate(