opentrons 8.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (601) hide show
  1. opentrons/__init__.py +150 -0
  2. opentrons/_version.py +34 -0
  3. opentrons/calibration_storage/__init__.py +54 -0
  4. opentrons/calibration_storage/deck_configuration.py +62 -0
  5. opentrons/calibration_storage/encoder_decoder.py +31 -0
  6. opentrons/calibration_storage/file_operators.py +142 -0
  7. opentrons/calibration_storage/helpers.py +103 -0
  8. opentrons/calibration_storage/ot2/__init__.py +34 -0
  9. opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
  10. opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
  11. opentrons/calibration_storage/ot2/models/__init__.py +0 -0
  12. opentrons/calibration_storage/ot2/models/v1.py +149 -0
  13. opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
  14. opentrons/calibration_storage/ot2/tip_length.py +281 -0
  15. opentrons/calibration_storage/ot3/__init__.py +31 -0
  16. opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
  17. opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
  18. opentrons/calibration_storage/ot3/models/__init__.py +0 -0
  19. opentrons/calibration_storage/ot3/models/v1.py +122 -0
  20. opentrons/calibration_storage/ot3/module_offset.py +138 -0
  21. opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
  22. opentrons/calibration_storage/types.py +45 -0
  23. opentrons/cli/__init__.py +21 -0
  24. opentrons/cli/__main__.py +5 -0
  25. opentrons/cli/analyze.py +557 -0
  26. opentrons/config/__init__.py +631 -0
  27. opentrons/config/advanced_settings.py +871 -0
  28. opentrons/config/defaults_ot2.py +214 -0
  29. opentrons/config/defaults_ot3.py +499 -0
  30. opentrons/config/feature_flags.py +86 -0
  31. opentrons/config/gripper_config.py +55 -0
  32. opentrons/config/reset.py +203 -0
  33. opentrons/config/robot_configs.py +187 -0
  34. opentrons/config/types.py +183 -0
  35. opentrons/drivers/__init__.py +0 -0
  36. opentrons/drivers/absorbance_reader/__init__.py +11 -0
  37. opentrons/drivers/absorbance_reader/abstract.py +72 -0
  38. opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
  39. opentrons/drivers/absorbance_reader/driver.py +81 -0
  40. opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
  41. opentrons/drivers/absorbance_reader/simulator.py +84 -0
  42. opentrons/drivers/asyncio/__init__.py +0 -0
  43. opentrons/drivers/asyncio/communication/__init__.py +22 -0
  44. opentrons/drivers/asyncio/communication/async_serial.py +187 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +557 -0
  47. opentrons/drivers/command_builder.py +102 -0
  48. opentrons/drivers/flex_stacker/__init__.py +13 -0
  49. opentrons/drivers/flex_stacker/abstract.py +214 -0
  50. opentrons/drivers/flex_stacker/driver.py +768 -0
  51. opentrons/drivers/flex_stacker/errors.py +68 -0
  52. opentrons/drivers/flex_stacker/simulator.py +309 -0
  53. opentrons/drivers/flex_stacker/types.py +367 -0
  54. opentrons/drivers/flex_stacker/utils.py +19 -0
  55. opentrons/drivers/heater_shaker/__init__.py +5 -0
  56. opentrons/drivers/heater_shaker/abstract.py +76 -0
  57. opentrons/drivers/heater_shaker/driver.py +204 -0
  58. opentrons/drivers/heater_shaker/simulator.py +94 -0
  59. opentrons/drivers/mag_deck/__init__.py +6 -0
  60. opentrons/drivers/mag_deck/abstract.py +44 -0
  61. opentrons/drivers/mag_deck/driver.py +208 -0
  62. opentrons/drivers/mag_deck/simulator.py +63 -0
  63. opentrons/drivers/rpi_drivers/__init__.py +33 -0
  64. opentrons/drivers/rpi_drivers/dev_types.py +94 -0
  65. opentrons/drivers/rpi_drivers/gpio.py +282 -0
  66. opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
  67. opentrons/drivers/rpi_drivers/interfaces.py +15 -0
  68. opentrons/drivers/rpi_drivers/types.py +364 -0
  69. opentrons/drivers/rpi_drivers/usb.py +102 -0
  70. opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
  71. opentrons/drivers/serial_communication.py +151 -0
  72. opentrons/drivers/smoothie_drivers/__init__.py +4 -0
  73. opentrons/drivers/smoothie_drivers/connection.py +51 -0
  74. opentrons/drivers/smoothie_drivers/constants.py +121 -0
  75. opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
  76. opentrons/drivers/smoothie_drivers/errors.py +49 -0
  77. opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
  78. opentrons/drivers/smoothie_drivers/simulator.py +99 -0
  79. opentrons/drivers/smoothie_drivers/types.py +16 -0
  80. opentrons/drivers/temp_deck/__init__.py +10 -0
  81. opentrons/drivers/temp_deck/abstract.py +54 -0
  82. opentrons/drivers/temp_deck/driver.py +197 -0
  83. opentrons/drivers/temp_deck/simulator.py +57 -0
  84. opentrons/drivers/thermocycler/__init__.py +12 -0
  85. opentrons/drivers/thermocycler/abstract.py +99 -0
  86. opentrons/drivers/thermocycler/driver.py +395 -0
  87. opentrons/drivers/thermocycler/simulator.py +126 -0
  88. opentrons/drivers/types.py +107 -0
  89. opentrons/drivers/utils.py +222 -0
  90. opentrons/execute.py +742 -0
  91. opentrons/hardware_control/__init__.py +65 -0
  92. opentrons/hardware_control/__main__.py +77 -0
  93. opentrons/hardware_control/adapters.py +98 -0
  94. opentrons/hardware_control/api.py +1347 -0
  95. opentrons/hardware_control/backends/__init__.py +7 -0
  96. opentrons/hardware_control/backends/controller.py +400 -0
  97. opentrons/hardware_control/backends/errors.py +9 -0
  98. opentrons/hardware_control/backends/estop_state.py +164 -0
  99. opentrons/hardware_control/backends/flex_protocol.py +497 -0
  100. opentrons/hardware_control/backends/ot3controller.py +1930 -0
  101. opentrons/hardware_control/backends/ot3simulator.py +900 -0
  102. opentrons/hardware_control/backends/ot3utils.py +664 -0
  103. opentrons/hardware_control/backends/simulator.py +442 -0
  104. opentrons/hardware_control/backends/status_bar_state.py +240 -0
  105. opentrons/hardware_control/backends/subsystem_manager.py +431 -0
  106. opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
  107. opentrons/hardware_control/backends/types.py +14 -0
  108. opentrons/hardware_control/constants.py +6 -0
  109. opentrons/hardware_control/dev_types.py +125 -0
  110. opentrons/hardware_control/emulation/__init__.py +0 -0
  111. opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
  112. opentrons/hardware_control/emulation/app.py +56 -0
  113. opentrons/hardware_control/emulation/connection_handler.py +38 -0
  114. opentrons/hardware_control/emulation/heater_shaker.py +150 -0
  115. opentrons/hardware_control/emulation/magdeck.py +60 -0
  116. opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
  117. opentrons/hardware_control/emulation/module_server/client.py +78 -0
  118. opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
  119. opentrons/hardware_control/emulation/module_server/models.py +31 -0
  120. opentrons/hardware_control/emulation/module_server/server.py +110 -0
  121. opentrons/hardware_control/emulation/parser.py +74 -0
  122. opentrons/hardware_control/emulation/proxy.py +241 -0
  123. opentrons/hardware_control/emulation/run_emulator.py +68 -0
  124. opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
  125. opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
  126. opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
  127. opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
  128. opentrons/hardware_control/emulation/settings.py +119 -0
  129. opentrons/hardware_control/emulation/simulations.py +133 -0
  130. opentrons/hardware_control/emulation/smoothie.py +192 -0
  131. opentrons/hardware_control/emulation/tempdeck.py +69 -0
  132. opentrons/hardware_control/emulation/thermocycler.py +128 -0
  133. opentrons/hardware_control/emulation/types.py +10 -0
  134. opentrons/hardware_control/emulation/util.py +38 -0
  135. opentrons/hardware_control/errors.py +43 -0
  136. opentrons/hardware_control/execution_manager.py +164 -0
  137. opentrons/hardware_control/instruments/__init__.py +5 -0
  138. opentrons/hardware_control/instruments/instrument_abc.py +39 -0
  139. opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
  140. opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
  141. opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
  142. opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
  143. opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
  144. opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
  145. opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
  146. opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
  147. opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
  148. opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
  149. opentrons/hardware_control/module_control.py +332 -0
  150. opentrons/hardware_control/modules/__init__.py +69 -0
  151. opentrons/hardware_control/modules/absorbance_reader.py +373 -0
  152. opentrons/hardware_control/modules/errors.py +7 -0
  153. opentrons/hardware_control/modules/flex_stacker.py +948 -0
  154. opentrons/hardware_control/modules/heater_shaker.py +426 -0
  155. opentrons/hardware_control/modules/lid_temp_status.py +35 -0
  156. opentrons/hardware_control/modules/magdeck.py +233 -0
  157. opentrons/hardware_control/modules/mod_abc.py +245 -0
  158. opentrons/hardware_control/modules/module_calibration.py +93 -0
  159. opentrons/hardware_control/modules/plate_temp_status.py +61 -0
  160. opentrons/hardware_control/modules/tempdeck.py +299 -0
  161. opentrons/hardware_control/modules/thermocycler.py +731 -0
  162. opentrons/hardware_control/modules/types.py +417 -0
  163. opentrons/hardware_control/modules/update.py +255 -0
  164. opentrons/hardware_control/modules/utils.py +73 -0
  165. opentrons/hardware_control/motion_utilities.py +318 -0
  166. opentrons/hardware_control/nozzle_manager.py +422 -0
  167. opentrons/hardware_control/ot3_calibration.py +1171 -0
  168. opentrons/hardware_control/ot3api.py +3227 -0
  169. opentrons/hardware_control/pause_manager.py +31 -0
  170. opentrons/hardware_control/poller.py +112 -0
  171. opentrons/hardware_control/protocols/__init__.py +106 -0
  172. opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
  173. opentrons/hardware_control/protocols/calibratable.py +45 -0
  174. opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
  175. opentrons/hardware_control/protocols/configurable.py +48 -0
  176. opentrons/hardware_control/protocols/event_sourcer.py +18 -0
  177. opentrons/hardware_control/protocols/execution_controllable.py +33 -0
  178. opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
  179. opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
  180. opentrons/hardware_control/protocols/gripper_controller.py +55 -0
  181. opentrons/hardware_control/protocols/hardware_manager.py +51 -0
  182. opentrons/hardware_control/protocols/identifiable.py +16 -0
  183. opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
  184. opentrons/hardware_control/protocols/liquid_handler.py +266 -0
  185. opentrons/hardware_control/protocols/module_provider.py +16 -0
  186. opentrons/hardware_control/protocols/motion_controller.py +243 -0
  187. opentrons/hardware_control/protocols/position_estimator.py +45 -0
  188. opentrons/hardware_control/protocols/simulatable.py +10 -0
  189. opentrons/hardware_control/protocols/stoppable.py +9 -0
  190. opentrons/hardware_control/protocols/types.py +27 -0
  191. opentrons/hardware_control/robot_calibration.py +224 -0
  192. opentrons/hardware_control/scripts/README.md +28 -0
  193. opentrons/hardware_control/scripts/__init__.py +1 -0
  194. opentrons/hardware_control/scripts/gripper_control.py +208 -0
  195. opentrons/hardware_control/scripts/ot3gripper +7 -0
  196. opentrons/hardware_control/scripts/ot3repl +7 -0
  197. opentrons/hardware_control/scripts/repl.py +187 -0
  198. opentrons/hardware_control/scripts/tc_control.py +97 -0
  199. opentrons/hardware_control/scripts/update_module_fw.py +274 -0
  200. opentrons/hardware_control/simulator_setup.py +260 -0
  201. opentrons/hardware_control/thread_manager.py +431 -0
  202. opentrons/hardware_control/threaded_async_lock.py +97 -0
  203. opentrons/hardware_control/types.py +792 -0
  204. opentrons/hardware_control/util.py +234 -0
  205. opentrons/legacy_broker.py +53 -0
  206. opentrons/legacy_commands/__init__.py +1 -0
  207. opentrons/legacy_commands/commands.py +483 -0
  208. opentrons/legacy_commands/helpers.py +153 -0
  209. opentrons/legacy_commands/module_commands.py +276 -0
  210. opentrons/legacy_commands/protocol_commands.py +54 -0
  211. opentrons/legacy_commands/publisher.py +155 -0
  212. opentrons/legacy_commands/robot_commands.py +51 -0
  213. opentrons/legacy_commands/types.py +1186 -0
  214. opentrons/motion_planning/__init__.py +32 -0
  215. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  216. opentrons/motion_planning/deck_conflict.py +501 -0
  217. opentrons/motion_planning/errors.py +35 -0
  218. opentrons/motion_planning/types.py +42 -0
  219. opentrons/motion_planning/waypoints.py +218 -0
  220. opentrons/ordered_set.py +138 -0
  221. opentrons/protocol_api/__init__.py +105 -0
  222. opentrons/protocol_api/_liquid.py +157 -0
  223. opentrons/protocol_api/_liquid_properties.py +814 -0
  224. opentrons/protocol_api/_nozzle_layout.py +31 -0
  225. opentrons/protocol_api/_parameter_context.py +300 -0
  226. opentrons/protocol_api/_parameters.py +31 -0
  227. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  228. opentrons/protocol_api/_types.py +43 -0
  229. opentrons/protocol_api/config.py +23 -0
  230. opentrons/protocol_api/core/__init__.py +23 -0
  231. opentrons/protocol_api/core/common.py +33 -0
  232. opentrons/protocol_api/core/core_map.py +74 -0
  233. opentrons/protocol_api/core/engine/__init__.py +22 -0
  234. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  235. opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
  236. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  237. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  238. opentrons/protocol_api/core/engine/labware.py +238 -0
  239. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  240. opentrons/protocol_api/core/engine/module_core.py +1027 -0
  241. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  242. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  243. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  244. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  245. opentrons/protocol_api/core/engine/robot.py +139 -0
  246. opentrons/protocol_api/core/engine/stringify.py +74 -0
  247. opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
  248. opentrons/protocol_api/core/engine/well.py +241 -0
  249. opentrons/protocol_api/core/instrument.py +459 -0
  250. opentrons/protocol_api/core/labware.py +151 -0
  251. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  252. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  253. opentrons/protocol_api/core/legacy/deck.py +369 -0
  254. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  255. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  256. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  257. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  258. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  259. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  260. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  261. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  262. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  263. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  265. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  266. opentrons/protocol_api/core/module.py +484 -0
  267. opentrons/protocol_api/core/protocol.py +311 -0
  268. opentrons/protocol_api/core/robot.py +51 -0
  269. opentrons/protocol_api/core/well.py +116 -0
  270. opentrons/protocol_api/core/well_grid.py +45 -0
  271. opentrons/protocol_api/create_protocol_context.py +177 -0
  272. opentrons/protocol_api/deck.py +223 -0
  273. opentrons/protocol_api/disposal_locations.py +244 -0
  274. opentrons/protocol_api/instrument_context.py +3272 -0
  275. opentrons/protocol_api/labware.py +1579 -0
  276. opentrons/protocol_api/module_contexts.py +1447 -0
  277. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  278. opentrons/protocol_api/protocol_context.py +1688 -0
  279. opentrons/protocol_api/robot_context.py +303 -0
  280. opentrons/protocol_api/validation.py +761 -0
  281. opentrons/protocol_engine/__init__.py +155 -0
  282. opentrons/protocol_engine/actions/__init__.py +65 -0
  283. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  284. opentrons/protocol_engine/actions/action_handler.py +13 -0
  285. opentrons/protocol_engine/actions/actions.py +302 -0
  286. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  287. opentrons/protocol_engine/clients/__init__.py +5 -0
  288. opentrons/protocol_engine/clients/sync_client.py +174 -0
  289. opentrons/protocol_engine/clients/transports.py +197 -0
  290. opentrons/protocol_engine/commands/__init__.py +757 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  296. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  297. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  298. opentrons/protocol_engine/commands/aspirate.py +244 -0
  299. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  300. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  301. opentrons/protocol_engine/commands/blow_out.py +146 -0
  302. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  303. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  306. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  307. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  308. opentrons/protocol_engine/commands/command.py +308 -0
  309. opentrons/protocol_engine/commands/command_unions.py +974 -0
  310. opentrons/protocol_engine/commands/comment.py +57 -0
  311. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  312. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  313. opentrons/protocol_engine/commands/custom.py +67 -0
  314. opentrons/protocol_engine/commands/dispense.py +194 -0
  315. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  316. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  317. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  318. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  319. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  320. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  321. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  322. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  323. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  324. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  325. opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
  326. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  327. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  328. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  329. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  330. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  331. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  333. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  334. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  336. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  337. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  338. opentrons/protocol_engine/commands/home.py +100 -0
  339. opentrons/protocol_engine/commands/identify_module.py +86 -0
  340. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  341. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  342. opentrons/protocol_engine/commands/load_labware.py +210 -0
  343. opentrons/protocol_engine/commands/load_lid.py +154 -0
  344. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  345. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  346. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  347. opentrons/protocol_engine/commands/load_module.py +223 -0
  348. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  349. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  350. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  351. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  352. opentrons/protocol_engine/commands/move_labware.py +546 -0
  353. opentrons/protocol_engine/commands/move_relative.py +102 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  355. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  356. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  357. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  358. opentrons/protocol_engine/commands/movement_common.py +338 -0
  359. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  360. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  361. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  362. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  363. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  364. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  365. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  366. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  367. opentrons/protocol_engine/commands/robot/common.py +18 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  369. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  370. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  371. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  372. opentrons/protocol_engine/commands/save_position.py +109 -0
  373. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  374. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  375. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  376. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  377. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  378. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  379. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  380. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  381. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  384. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  386. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  388. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  390. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  391. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  392. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  401. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  402. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  403. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  404. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  405. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  406. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  407. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  408. opentrons/protocol_engine/engine_support.py +28 -0
  409. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  410. opentrons/protocol_engine/errors/__init__.py +191 -0
  411. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  412. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  413. opentrons/protocol_engine/execution/__init__.py +50 -0
  414. opentrons/protocol_engine/execution/command_executor.py +216 -0
  415. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  416. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  417. opentrons/protocol_engine/execution/equipment.py +819 -0
  418. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  419. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  420. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  421. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  422. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  423. opentrons/protocol_engine/execution/movement.py +350 -0
  424. opentrons/protocol_engine/execution/pipetting.py +607 -0
  425. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  426. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  427. opentrons/protocol_engine/execution/run_control.py +33 -0
  428. opentrons/protocol_engine/execution/status_bar.py +34 -0
  429. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  430. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  431. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  432. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  433. opentrons/protocol_engine/notes/__init__.py +17 -0
  434. opentrons/protocol_engine/notes/notes.py +59 -0
  435. opentrons/protocol_engine/plugins.py +104 -0
  436. opentrons/protocol_engine/protocol_engine.py +683 -0
  437. opentrons/protocol_engine/resources/__init__.py +26 -0
  438. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  439. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  440. opentrons/protocol_engine/resources/file_provider.py +161 -0
  441. opentrons/protocol_engine/resources/fixture_validation.py +68 -0
  442. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  443. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  444. opentrons/protocol_engine/resources/model_utils.py +32 -0
  445. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  446. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  447. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  448. opentrons/protocol_engine/slot_standardization.py +128 -0
  449. opentrons/protocol_engine/state/__init__.py +1 -0
  450. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  451. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  452. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  453. opentrons/protocol_engine/state/_move_types.py +83 -0
  454. opentrons/protocol_engine/state/_well_math.py +193 -0
  455. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  456. opentrons/protocol_engine/state/command_history.py +309 -0
  457. opentrons/protocol_engine/state/commands.py +1164 -0
  458. opentrons/protocol_engine/state/config.py +39 -0
  459. opentrons/protocol_engine/state/files.py +57 -0
  460. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  461. opentrons/protocol_engine/state/geometry.py +2408 -0
  462. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  463. opentrons/protocol_engine/state/labware.py +1432 -0
  464. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  465. opentrons/protocol_engine/state/liquids.py +73 -0
  466. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  467. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  468. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  469. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  471. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  472. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  473. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  474. opentrons/protocol_engine/state/modules.py +1515 -0
  475. opentrons/protocol_engine/state/motion.py +373 -0
  476. opentrons/protocol_engine/state/pipettes.py +905 -0
  477. opentrons/protocol_engine/state/state.py +421 -0
  478. opentrons/protocol_engine/state/state_summary.py +36 -0
  479. opentrons/protocol_engine/state/tips.py +420 -0
  480. opentrons/protocol_engine/state/update_types.py +904 -0
  481. opentrons/protocol_engine/state/wells.py +290 -0
  482. opentrons/protocol_engine/types/__init__.py +310 -0
  483. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  484. opentrons/protocol_engine/types/command_annotations.py +53 -0
  485. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  486. opentrons/protocol_engine/types/execution.py +96 -0
  487. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  488. opentrons/protocol_engine/types/instrument.py +47 -0
  489. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  490. opentrons/protocol_engine/types/labware.py +131 -0
  491. opentrons/protocol_engine/types/labware_movement.py +22 -0
  492. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  493. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  494. opentrons/protocol_engine/types/liquid.py +40 -0
  495. opentrons/protocol_engine/types/liquid_class.py +59 -0
  496. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  497. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  498. opentrons/protocol_engine/types/location.py +194 -0
  499. opentrons/protocol_engine/types/module.py +310 -0
  500. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  501. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  502. opentrons/protocol_engine/types/tip.py +18 -0
  503. opentrons/protocol_engine/types/util.py +21 -0
  504. opentrons/protocol_engine/types/well_position.py +124 -0
  505. opentrons/protocol_reader/__init__.py +37 -0
  506. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  507. opentrons/protocol_reader/file_format_validator.py +152 -0
  508. opentrons/protocol_reader/file_hasher.py +27 -0
  509. opentrons/protocol_reader/file_identifier.py +284 -0
  510. opentrons/protocol_reader/file_reader_writer.py +90 -0
  511. opentrons/protocol_reader/input_file.py +16 -0
  512. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  513. opentrons/protocol_reader/protocol_reader.py +188 -0
  514. opentrons/protocol_reader/protocol_source.py +124 -0
  515. opentrons/protocol_reader/role_analyzer.py +86 -0
  516. opentrons/protocol_runner/__init__.py +26 -0
  517. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  518. opentrons/protocol_runner/json_file_reader.py +55 -0
  519. opentrons/protocol_runner/json_translator.py +314 -0
  520. opentrons/protocol_runner/legacy_command_mapper.py +852 -0
  521. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  522. opentrons/protocol_runner/protocol_runner.py +530 -0
  523. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  524. opentrons/protocol_runner/run_orchestrator.py +496 -0
  525. opentrons/protocol_runner/task_queue.py +95 -0
  526. opentrons/protocols/__init__.py +6 -0
  527. opentrons/protocols/advanced_control/__init__.py +0 -0
  528. opentrons/protocols/advanced_control/common.py +38 -0
  529. opentrons/protocols/advanced_control/mix.py +60 -0
  530. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  531. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  532. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  533. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  534. opentrons/protocols/api_support/__init__.py +0 -0
  535. opentrons/protocols/api_support/constants.py +8 -0
  536. opentrons/protocols/api_support/deck_type.py +110 -0
  537. opentrons/protocols/api_support/definitions.py +18 -0
  538. opentrons/protocols/api_support/instrument.py +151 -0
  539. opentrons/protocols/api_support/labware_like.py +233 -0
  540. opentrons/protocols/api_support/tip_tracker.py +175 -0
  541. opentrons/protocols/api_support/types.py +32 -0
  542. opentrons/protocols/api_support/util.py +403 -0
  543. opentrons/protocols/bundle.py +89 -0
  544. opentrons/protocols/duration/__init__.py +4 -0
  545. opentrons/protocols/duration/errors.py +5 -0
  546. opentrons/protocols/duration/estimator.py +628 -0
  547. opentrons/protocols/execution/__init__.py +0 -0
  548. opentrons/protocols/execution/dev_types.py +181 -0
  549. opentrons/protocols/execution/errors.py +40 -0
  550. opentrons/protocols/execution/execute.py +84 -0
  551. opentrons/protocols/execution/execute_json_v3.py +275 -0
  552. opentrons/protocols/execution/execute_json_v4.py +359 -0
  553. opentrons/protocols/execution/execute_json_v5.py +28 -0
  554. opentrons/protocols/execution/execute_python.py +169 -0
  555. opentrons/protocols/execution/json_dispatchers.py +87 -0
  556. opentrons/protocols/execution/types.py +7 -0
  557. opentrons/protocols/geometry/__init__.py +0 -0
  558. opentrons/protocols/geometry/planning.py +297 -0
  559. opentrons/protocols/labware.py +312 -0
  560. opentrons/protocols/models/__init__.py +0 -0
  561. opentrons/protocols/models/json_protocol.py +679 -0
  562. opentrons/protocols/parameters/__init__.py +0 -0
  563. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  564. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  565. opentrons/protocols/parameters/exceptions.py +34 -0
  566. opentrons/protocols/parameters/parameter_definition.py +272 -0
  567. opentrons/protocols/parameters/types.py +17 -0
  568. opentrons/protocols/parameters/validation.py +267 -0
  569. opentrons/protocols/parse.py +671 -0
  570. opentrons/protocols/types.py +159 -0
  571. opentrons/py.typed +0 -0
  572. opentrons/resources/scripts/lpc21isp +0 -0
  573. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  574. opentrons/simulate.py +1065 -0
  575. opentrons/system/__init__.py +6 -0
  576. opentrons/system/camera.py +51 -0
  577. opentrons/system/log_control.py +59 -0
  578. opentrons/system/nmcli.py +856 -0
  579. opentrons/system/resin.py +24 -0
  580. opentrons/system/smoothie_update.py +15 -0
  581. opentrons/system/wifi.py +204 -0
  582. opentrons/tools/__init__.py +0 -0
  583. opentrons/tools/args_handler.py +22 -0
  584. opentrons/tools/write_pipette_memory.py +157 -0
  585. opentrons/types.py +618 -0
  586. opentrons/util/__init__.py +1 -0
  587. opentrons/util/async_helpers.py +166 -0
  588. opentrons/util/broker.py +84 -0
  589. opentrons/util/change_notifier.py +47 -0
  590. opentrons/util/entrypoint_util.py +278 -0
  591. opentrons/util/get_union_elements.py +26 -0
  592. opentrons/util/helpers.py +6 -0
  593. opentrons/util/linal.py +178 -0
  594. opentrons/util/logging_config.py +265 -0
  595. opentrons/util/logging_queue_handler.py +61 -0
  596. opentrons/util/performance_helpers.py +157 -0
  597. opentrons-8.6.0.dist-info/METADATA +37 -0
  598. opentrons-8.6.0.dist-info/RECORD +601 -0
  599. opentrons-8.6.0.dist-info/WHEEL +4 -0
  600. opentrons-8.6.0.dist-info/entry_points.txt +3 -0
  601. opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,557 @@
1
+ """Opentrons analyze CLI."""
2
+
3
+ import click
4
+
5
+ from anyio import run
6
+ from contextlib import contextmanager
7
+ from dataclasses import dataclass
8
+ from datetime import datetime, timezone
9
+ from enum import Enum
10
+ from pathlib import Path
11
+ from pydantic import BaseModel
12
+ from typing import (
13
+ Any,
14
+ Dict,
15
+ List,
16
+ Optional,
17
+ Sequence,
18
+ Union,
19
+ Literal,
20
+ Callable,
21
+ IO,
22
+ TypeVar,
23
+ Iterator,
24
+ )
25
+ import logging
26
+ import sys
27
+ import json
28
+ import gc
29
+
30
+ from opentrons.protocol_engine import ProtocolEngine
31
+ from opentrons.protocol_engine.types import (
32
+ RunTimeParameter,
33
+ CSVRuntimeParamPaths,
34
+ PrimitiveRunTimeParamValuesType,
35
+ EngineStatus,
36
+ )
37
+ from opentrons.protocols.api_support.types import APIVersion
38
+ from opentrons.protocol_reader import (
39
+ ProtocolReader,
40
+ ProtocolFileRole,
41
+ ProtocolType,
42
+ JsonProtocolConfig,
43
+ ProtocolFilesInvalidError,
44
+ ProtocolSource,
45
+ )
46
+ from opentrons.protocol_runner.create_simulating_orchestrator import (
47
+ create_simulating_orchestrator,
48
+ )
49
+ from opentrons.protocol_runner import RunResult
50
+ from opentrons.protocol_runner.run_orchestrator import ParseMode
51
+
52
+ from opentrons.protocol_engine import (
53
+ Command,
54
+ ErrorOccurrence,
55
+ LoadedLabware,
56
+ LoadedPipette,
57
+ LoadedModule,
58
+ Liquid,
59
+ LiquidClassRecordWithId,
60
+ StateSummary,
61
+ )
62
+ from opentrons.protocol_engine.protocol_engine import code_in_error_tree
63
+ from opentrons.protocol_engine.types import CommandAnnotation
64
+
65
+ from opentrons_shared_data.robot.types import RobotType
66
+
67
+ from opentrons_shared_data.errors import ErrorCodes
68
+ from opentrons_shared_data.errors.exceptions import (
69
+ EnumeratedError,
70
+ PythonException,
71
+ )
72
+
73
+
74
+ OutputKind = Literal["json", "human-json"]
75
+
76
+
77
+ @dataclass(frozen=True)
78
+ class _Output:
79
+ to_file: IO[bytes]
80
+ kind: OutputKind
81
+
82
+
83
+ @click.command()
84
+ @click.argument(
85
+ "files",
86
+ nargs=-1,
87
+ required=True,
88
+ type=click.Path(exists=True, path_type=Path, file_okay=True, dir_okay=True),
89
+ )
90
+ @click.option(
91
+ "--json-output",
92
+ help="Return analysis results as machine-readable JSON. Specify --json-output=- to use stdout, but be aware that Python protocols may contain print() which will make the output JSON invalid.",
93
+ type=click.File(mode="wb"),
94
+ )
95
+ @click.option(
96
+ "--human-json-output",
97
+ help="Return analysis results as JSON, formatted for human eyes. Specify --human-json-output=- to use stdout, but be aware that Python protocols may contain print() which will make the output JSON invalid.",
98
+ type=click.File(mode="wb"),
99
+ )
100
+ @click.option(
101
+ "--leaks",
102
+ help="Fail (via exit code) if the analysis engine has not been garbage collected after analysis is complete.",
103
+ is_flag=True,
104
+ default=False,
105
+ )
106
+ @click.option(
107
+ "--leaks-debug",
108
+ help="Drop into a PDB shell if a leak is detected",
109
+ is_flag=True,
110
+ default=False,
111
+ )
112
+ @click.option(
113
+ "--check",
114
+ help="Fail (via exit code) if the protocol had an error. If not specified, always succeed.",
115
+ is_flag=True,
116
+ default=False,
117
+ )
118
+ @click.option(
119
+ "--log-output",
120
+ help="Where to send logs. Can be a path, - for stdout, or stderr for stderr.",
121
+ default="stderr",
122
+ type=str,
123
+ )
124
+ @click.option(
125
+ "--log-level",
126
+ help="Level of logs to capture.",
127
+ type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR"], case_sensitive=False),
128
+ default="WARNING",
129
+ )
130
+ @click.option(
131
+ "--rtp-values",
132
+ help="Serialized JSON of runtime parameter variable names to values.",
133
+ default="{}",
134
+ type=str,
135
+ )
136
+ @click.option(
137
+ "--rtp-files",
138
+ help="Serialized JSON of runtime parameter variable names to file paths.",
139
+ default="{}",
140
+ type=str,
141
+ )
142
+ def analyze(
143
+ files: Sequence[Path],
144
+ rtp_values: str,
145
+ rtp_files: str,
146
+ json_output: Optional[IO[bytes]],
147
+ human_json_output: Optional[IO[bytes]],
148
+ log_output: str,
149
+ log_level: str,
150
+ check: bool,
151
+ leaks: bool,
152
+ leaks_debug: bool,
153
+ ) -> int:
154
+ """Analyze a protocol.
155
+
156
+ You can use `opentrons analyze` to get a protocol's expected
157
+ equipment and commands.
158
+ """
159
+ outputs = _get_outputs(json=json_output, human_json=human_json_output)
160
+ if not outputs and not check:
161
+ raise click.UsageError(
162
+ message="Please specify at least --check or one of the output options."
163
+ )
164
+
165
+ try:
166
+ with _capture_logs(log_output, log_level):
167
+ sys.exit(
168
+ run(
169
+ _analyze,
170
+ files,
171
+ rtp_values,
172
+ rtp_files,
173
+ outputs,
174
+ check,
175
+ leaks or leaks_debug,
176
+ leaks_debug,
177
+ )
178
+ )
179
+ except click.ClickException:
180
+ raise
181
+ except Exception as e:
182
+ raise click.ClickException(str(e))
183
+
184
+
185
+ @contextmanager
186
+ def _capture_logs_to_stream(stream: IO[str]) -> Iterator[None]:
187
+ handler = logging.StreamHandler(stream)
188
+ logging.getLogger().addHandler(handler)
189
+ try:
190
+ yield
191
+ finally:
192
+ logging.getLogger().removeHandler(handler)
193
+
194
+
195
+ @contextmanager
196
+ def _capture_logs_to_file(filepath: Path) -> Iterator[None]:
197
+ handler = logging.FileHandler(filepath, mode="w")
198
+ logging.getLogger().addHandler(handler)
199
+ try:
200
+ yield
201
+ finally:
202
+ logging.getLogger().removeHandler(handler)
203
+
204
+
205
+ @contextmanager
206
+ def _capture_logs(write_to: str, log_level: str) -> Iterator[None]:
207
+ try:
208
+ level = getattr(logging, log_level)
209
+ except AttributeError:
210
+ raise click.ClickException(f"No such log level {log_level}")
211
+ logging.getLogger().setLevel(level)
212
+ if write_to in ("-", "stdout"):
213
+ with _capture_logs_to_stream(sys.stdout):
214
+ yield
215
+ elif write_to == "stderr":
216
+ with _capture_logs_to_stream(sys.stderr):
217
+ yield
218
+ else:
219
+ with _capture_logs_to_file(Path(write_to)):
220
+ yield
221
+
222
+
223
+ def _get_outputs(
224
+ json: Optional[IO[bytes]],
225
+ human_json: Optional[IO[bytes]],
226
+ ) -> List[_Output]:
227
+ outputs: List[_Output] = []
228
+ if json:
229
+ outputs.append(_Output(to_file=json, kind="json"))
230
+ if human_json:
231
+ outputs.append(_Output(to_file=human_json, kind="human-json"))
232
+ return outputs
233
+
234
+
235
+ def _get_input_files(files_and_dirs: Sequence[Path]) -> List[Path]:
236
+ results: List[Path] = []
237
+
238
+ for entry in files_and_dirs:
239
+ if entry.is_dir():
240
+ results.extend(entry.glob("**/*"))
241
+ else:
242
+ results.append(entry)
243
+
244
+ return results
245
+
246
+
247
+ def _get_runtime_parameter_values(
248
+ serialized_rtp_values: str,
249
+ ) -> PrimitiveRunTimeParamValuesType:
250
+ rtp_values = {}
251
+ try:
252
+ for variable_name, value in json.loads(serialized_rtp_values).items():
253
+ if not isinstance(value, (bool, int, float, str)):
254
+ raise click.BadParameter(
255
+ f"Runtime parameter '{value}' is not of allowed type boolean, integer, float or string",
256
+ param_hint="--rtp-values",
257
+ )
258
+ rtp_values[variable_name] = value
259
+ except json.JSONDecodeError as error:
260
+ raise click.BadParameter(
261
+ f"JSON decode error: {error}", param_hint="--rtp-values"
262
+ )
263
+ return rtp_values
264
+
265
+
266
+ def _get_runtime_parameter_paths(serialized_rtp_files: str) -> CSVRuntimeParamPaths:
267
+ try:
268
+ return {
269
+ variable_name: Path(path_string)
270
+ for variable_name, path_string in json.loads(serialized_rtp_files).items()
271
+ }
272
+ except json.JSONDecodeError as error:
273
+ raise click.BadParameter(
274
+ f"JSON decode error: {error}", param_hint="--rtp-files"
275
+ )
276
+
277
+
278
+ R = TypeVar("R")
279
+
280
+
281
+ def _call_for_output_of_kind(
282
+ kind: OutputKind, outputs: Sequence[_Output], fn: Callable[[IO[bytes]], R]
283
+ ) -> Optional[R]:
284
+ for output in outputs:
285
+ if output.kind == kind:
286
+ return fn(output.to_file)
287
+ return None
288
+
289
+
290
+ def _get_return_code(analysis: RunResult) -> int:
291
+ if analysis.state_summary.errors:
292
+ return -1
293
+ return 0
294
+
295
+
296
+ class UnexpectedAnalysisError(EnumeratedError):
297
+ """An error raised while setting up the runner for analysis."""
298
+
299
+ def __init__(
300
+ self,
301
+ message: Optional[str] = None,
302
+ wrapping: Optional[Sequence[Union[EnumeratedError, Exception]]] = None,
303
+ ) -> None:
304
+ """Build a UnexpectedAnalysisError exception."""
305
+
306
+ def _convert_exc() -> Iterator[EnumeratedError]:
307
+ if not wrapping:
308
+ return
309
+ for exc in wrapping:
310
+ if isinstance(exc, EnumeratedError):
311
+ yield exc
312
+ else:
313
+ yield PythonException(exc)
314
+
315
+ super().__init__(
316
+ code=ErrorCodes.GENERAL_ERROR,
317
+ message=message,
318
+ wrapping=[e for e in _convert_exc()],
319
+ )
320
+
321
+
322
+ async def _do_analyze(
323
+ protocol_source: ProtocolSource,
324
+ rtp_values: PrimitiveRunTimeParamValuesType,
325
+ rtp_paths: CSVRuntimeParamPaths,
326
+ ) -> RunResult:
327
+
328
+ orchestrator = await create_simulating_orchestrator(
329
+ robot_type=protocol_source.robot_type, protocol_config=protocol_source.config
330
+ )
331
+ try:
332
+ await orchestrator.load(
333
+ protocol_source=protocol_source,
334
+ parse_mode=ParseMode.NORMAL,
335
+ run_time_param_values=rtp_values,
336
+ run_time_param_paths=rtp_paths,
337
+ )
338
+ except Exception as error:
339
+ err_id = "analysis-setup-error"
340
+ err_created_at = datetime.now(tz=timezone.utc)
341
+ if isinstance(error, EnumeratedError):
342
+ error_occ = ErrorOccurrence.from_failed(
343
+ id=err_id, createdAt=err_created_at, error=error
344
+ )
345
+ else:
346
+ enumerated_wrapper = UnexpectedAnalysisError(
347
+ message=str(error),
348
+ wrapping=[error],
349
+ )
350
+ error_occ = ErrorOccurrence.from_failed(
351
+ id=err_id, createdAt=err_created_at, error=enumerated_wrapper
352
+ )
353
+ analysis = RunResult(
354
+ commands=[],
355
+ state_summary=StateSummary(
356
+ errors=[error_occ],
357
+ status=EngineStatus.IDLE,
358
+ labware=[],
359
+ pipettes=[],
360
+ modules=[],
361
+ labwareOffsets=[],
362
+ liquids=[],
363
+ wells=[],
364
+ hasEverEnteredErrorRecovery=False,
365
+ files=[],
366
+ liquidClasses=[],
367
+ ),
368
+ parameters=[],
369
+ command_annotations=[],
370
+ )
371
+ return analysis
372
+ return await orchestrator.run(deck_configuration=[])
373
+
374
+
375
+ async def _analyze( # noqa: C901
376
+ files_and_dirs: Sequence[Path],
377
+ rtp_values: str,
378
+ rtp_files: str,
379
+ outputs: Sequence[_Output],
380
+ check: bool,
381
+ fail_on_leak: bool,
382
+ debug_on_leak: bool,
383
+ ) -> int:
384
+ input_files = _get_input_files(files_and_dirs)
385
+ parsed_rtp_values = _get_runtime_parameter_values(rtp_values)
386
+ rtp_paths = _get_runtime_parameter_paths(rtp_files)
387
+
388
+ try:
389
+ protocol_source = await ProtocolReader().read_saved(
390
+ files=input_files,
391
+ directory=None,
392
+ )
393
+ except ProtocolFilesInvalidError as error:
394
+ raise click.ClickException(str(error))
395
+
396
+ analysis = await _do_analyze(protocol_source, parsed_rtp_values, rtp_paths)
397
+ return_code = _get_return_code(analysis)
398
+
399
+ # This ugly code checks to see if an engine remains past garbage collection
400
+ # after analysis is complete.
401
+ # It should be here and open coded to make it a little easier to present
402
+ # the debug option.
403
+ if fail_on_leak or debug_on_leak:
404
+ gc.collect()
405
+ leaked_engine = next(
406
+ (obj for obj in gc.get_objects() if isinstance(obj, ProtocolEngine)), None
407
+ )
408
+ if leaked_engine:
409
+ if fail_on_leak:
410
+ print(
411
+ "A ProtocolEngine instance exists even after garbage collection; "
412
+ "some thing (likely in the protocol) has caused it to be leaked, "
413
+ "likely by reference to the engine or something that refers to the "
414
+ "engine after the run function ends.",
415
+ file=sys.stderr,
416
+ )
417
+ return_code = -2
418
+ if debug_on_leak:
419
+ print(
420
+ "You are now in an interactive PDB (https://docs.python.org/3.10/library/pdb.html) "
421
+ "session; the leaked engine is bound to the variable leaked_engine."
422
+ )
423
+ breakpoint()
424
+
425
+ if not outputs:
426
+ return return_code
427
+
428
+ if len(analysis.state_summary.errors) > 0:
429
+ if any(
430
+ code_in_error_tree(
431
+ root_error=error, code=ErrorCodes.RUNTIME_PARAMETER_VALUE_REQUIRED
432
+ )
433
+ for error in analysis.state_summary.errors
434
+ ):
435
+ result = AnalysisResult.PARAMETER_VALUE_REQUIRED
436
+ else:
437
+ result = AnalysisResult.NOT_OK
438
+ else:
439
+ result = AnalysisResult.OK
440
+
441
+ results = AnalyzeResults.model_construct(
442
+ createdAt=datetime.now(tz=timezone.utc),
443
+ files=[
444
+ ProtocolFile.model_construct(name=f.path.name, role=f.role)
445
+ for f in protocol_source.files
446
+ ],
447
+ config=(
448
+ JsonConfig.model_construct(
449
+ schemaVersion=protocol_source.config.schema_version
450
+ )
451
+ if isinstance(protocol_source.config, JsonProtocolConfig)
452
+ else PythonConfig.model_construct(
453
+ apiVersion=protocol_source.config.api_version
454
+ )
455
+ ),
456
+ result=result,
457
+ metadata=protocol_source.metadata,
458
+ robotType=protocol_source.robot_type,
459
+ runTimeParameters=analysis.parameters,
460
+ commands=analysis.commands,
461
+ errors=analysis.state_summary.errors,
462
+ labware=analysis.state_summary.labware,
463
+ pipettes=analysis.state_summary.pipettes,
464
+ modules=analysis.state_summary.modules,
465
+ liquids=analysis.state_summary.liquids,
466
+ commandAnnotations=analysis.command_annotations,
467
+ liquidClasses=analysis.state_summary.liquidClasses,
468
+ )
469
+
470
+ _call_for_output_of_kind(
471
+ "json",
472
+ outputs,
473
+ lambda to_file: to_file.write(
474
+ results.model_dump_json(exclude_none=True).encode("utf-8"),
475
+ ),
476
+ )
477
+ _call_for_output_of_kind(
478
+ "human-json",
479
+ outputs,
480
+ lambda to_file: to_file.write(
481
+ results.model_dump_json(exclude_none=True, indent=2).encode("utf-8")
482
+ ),
483
+ )
484
+ if check:
485
+ return return_code
486
+ else:
487
+ return 0
488
+
489
+
490
+ class ProtocolFile(BaseModel):
491
+ """A file in a protocol analysis."""
492
+
493
+ name: str
494
+ role: ProtocolFileRole
495
+
496
+
497
+ class JsonConfig(BaseModel):
498
+ """Configuration of a JSON protocol."""
499
+
500
+ protocolType: Literal[ProtocolType.JSON] = ProtocolType.JSON
501
+ schemaVersion: int
502
+
503
+
504
+ class PythonConfig(BaseModel):
505
+ """Configuration of a Python protocol."""
506
+
507
+ protocolType: Literal[ProtocolType.PYTHON] = ProtocolType.PYTHON
508
+ apiVersion: APIVersion
509
+
510
+
511
+ class AnalysisResult(str, Enum):
512
+ """Result of a completed protocol analysis.
513
+
514
+ The result indicates whether the protocol is expected to run successfully.
515
+
516
+ Properties:
517
+ OK: No problems were found during protocol analysis.
518
+ NOT_OK: Problems were found during protocol analysis. Inspect
519
+ `analysis.errors` for error occurrences.
520
+ PARAMETER_VALUE_REQUIRED: A value is required to be set for a parameter
521
+ in order for the protocol to be analyzed/run. The absence of this does not
522
+ inherently mean there are no parameters, as there may be defaults for all
523
+ or unset parameters are not referenced or handled via try/except clauses.
524
+ """
525
+
526
+ OK = "ok"
527
+ NOT_OK = "not-ok"
528
+ PARAMETER_VALUE_REQUIRED = "parameter-value-required"
529
+
530
+
531
+ class AnalyzeResults(BaseModel):
532
+ """Results of a protocol analysis.
533
+
534
+ See robot-server's analysis models for field documentation.
535
+ """
536
+
537
+ # We want to unify this local analysis model with the one that robot-server returns.
538
+ # Until that happens, we need to keep these fields in sync manually.
539
+
540
+ # Fields that are currently unique to this local analysis module, missing from robot-server:
541
+ createdAt: datetime
542
+ files: List[ProtocolFile]
543
+ config: Union[JsonConfig, PythonConfig]
544
+ metadata: Dict[str, Any]
545
+
546
+ # Fields that should match robot-server:
547
+ result: AnalysisResult
548
+ robotType: RobotType
549
+ runTimeParameters: List[RunTimeParameter]
550
+ commands: List[Command]
551
+ labware: List[LoadedLabware]
552
+ pipettes: List[LoadedPipette]
553
+ modules: List[LoadedModule]
554
+ liquids: List[Liquid]
555
+ liquidClasses: List[LiquidClassRecordWithId]
556
+ errors: List[ErrorOccurrence]
557
+ commandAnnotations: List[CommandAnnotation]