opentrons 8.6.0a1__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 (600) 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 +501 -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 +183 -0
  45. opentrons/drivers/asyncio/communication/errors.py +88 -0
  46. opentrons/drivers/asyncio/communication/serial_connection.py +552 -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/simulator_setup.py +260 -0
  200. opentrons/hardware_control/thread_manager.py +431 -0
  201. opentrons/hardware_control/threaded_async_lock.py +97 -0
  202. opentrons/hardware_control/types.py +792 -0
  203. opentrons/hardware_control/util.py +234 -0
  204. opentrons/legacy_broker.py +53 -0
  205. opentrons/legacy_commands/__init__.py +1 -0
  206. opentrons/legacy_commands/commands.py +483 -0
  207. opentrons/legacy_commands/helpers.py +153 -0
  208. opentrons/legacy_commands/module_commands.py +215 -0
  209. opentrons/legacy_commands/protocol_commands.py +54 -0
  210. opentrons/legacy_commands/publisher.py +155 -0
  211. opentrons/legacy_commands/robot_commands.py +51 -0
  212. opentrons/legacy_commands/types.py +1115 -0
  213. opentrons/motion_planning/__init__.py +32 -0
  214. opentrons/motion_planning/adjacent_slots_getters.py +168 -0
  215. opentrons/motion_planning/deck_conflict.py +396 -0
  216. opentrons/motion_planning/errors.py +35 -0
  217. opentrons/motion_planning/types.py +42 -0
  218. opentrons/motion_planning/waypoints.py +218 -0
  219. opentrons/ordered_set.py +138 -0
  220. opentrons/protocol_api/__init__.py +105 -0
  221. opentrons/protocol_api/_liquid.py +157 -0
  222. opentrons/protocol_api/_liquid_properties.py +814 -0
  223. opentrons/protocol_api/_nozzle_layout.py +31 -0
  224. opentrons/protocol_api/_parameter_context.py +300 -0
  225. opentrons/protocol_api/_parameters.py +31 -0
  226. opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
  227. opentrons/protocol_api/_types.py +43 -0
  228. opentrons/protocol_api/config.py +23 -0
  229. opentrons/protocol_api/core/__init__.py +23 -0
  230. opentrons/protocol_api/core/common.py +33 -0
  231. opentrons/protocol_api/core/core_map.py +74 -0
  232. opentrons/protocol_api/core/engine/__init__.py +22 -0
  233. opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
  234. opentrons/protocol_api/core/engine/deck_conflict.py +348 -0
  235. opentrons/protocol_api/core/engine/exceptions.py +19 -0
  236. opentrons/protocol_api/core/engine/instrument.py +2391 -0
  237. opentrons/protocol_api/core/engine/labware.py +238 -0
  238. opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
  239. opentrons/protocol_api/core/engine/module_core.py +1025 -0
  240. opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
  241. opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
  242. opentrons/protocol_api/core/engine/point_calculations.py +64 -0
  243. opentrons/protocol_api/core/engine/protocol.py +1153 -0
  244. opentrons/protocol_api/core/engine/robot.py +139 -0
  245. opentrons/protocol_api/core/engine/stringify.py +74 -0
  246. opentrons/protocol_api/core/engine/transfer_components_executor.py +990 -0
  247. opentrons/protocol_api/core/engine/well.py +241 -0
  248. opentrons/protocol_api/core/instrument.py +459 -0
  249. opentrons/protocol_api/core/labware.py +151 -0
  250. opentrons/protocol_api/core/legacy/__init__.py +11 -0
  251. opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
  252. opentrons/protocol_api/core/legacy/deck.py +369 -0
  253. opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
  254. opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
  255. opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
  256. opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
  257. opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
  258. opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
  259. opentrons/protocol_api/core/legacy/load_info.py +67 -0
  260. opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
  261. opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
  262. opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
  263. opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
  264. opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
  265. opentrons/protocol_api/core/module.py +484 -0
  266. opentrons/protocol_api/core/protocol.py +311 -0
  267. opentrons/protocol_api/core/robot.py +51 -0
  268. opentrons/protocol_api/core/well.py +116 -0
  269. opentrons/protocol_api/core/well_grid.py +45 -0
  270. opentrons/protocol_api/create_protocol_context.py +177 -0
  271. opentrons/protocol_api/deck.py +223 -0
  272. opentrons/protocol_api/disposal_locations.py +244 -0
  273. opentrons/protocol_api/instrument_context.py +3212 -0
  274. opentrons/protocol_api/labware.py +1579 -0
  275. opentrons/protocol_api/module_contexts.py +1425 -0
  276. opentrons/protocol_api/module_validation_and_errors.py +61 -0
  277. opentrons/protocol_api/protocol_context.py +1688 -0
  278. opentrons/protocol_api/robot_context.py +303 -0
  279. opentrons/protocol_api/validation.py +761 -0
  280. opentrons/protocol_engine/__init__.py +155 -0
  281. opentrons/protocol_engine/actions/__init__.py +65 -0
  282. opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
  283. opentrons/protocol_engine/actions/action_handler.py +13 -0
  284. opentrons/protocol_engine/actions/actions.py +302 -0
  285. opentrons/protocol_engine/actions/get_state_update.py +38 -0
  286. opentrons/protocol_engine/clients/__init__.py +5 -0
  287. opentrons/protocol_engine/clients/sync_client.py +174 -0
  288. opentrons/protocol_engine/clients/transports.py +197 -0
  289. opentrons/protocol_engine/commands/__init__.py +757 -0
  290. opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
  291. opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
  292. opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
  293. opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
  294. opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
  295. opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
  296. opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
  297. opentrons/protocol_engine/commands/aspirate.py +244 -0
  298. opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
  299. opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
  300. opentrons/protocol_engine/commands/blow_out.py +146 -0
  301. opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
  302. opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
  303. opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
  304. opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
  305. opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
  306. opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
  307. opentrons/protocol_engine/commands/command.py +308 -0
  308. opentrons/protocol_engine/commands/command_unions.py +974 -0
  309. opentrons/protocol_engine/commands/comment.py +57 -0
  310. opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
  311. opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
  312. opentrons/protocol_engine/commands/custom.py +67 -0
  313. opentrons/protocol_engine/commands/dispense.py +194 -0
  314. opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
  315. opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
  316. opentrons/protocol_engine/commands/drop_tip.py +232 -0
  317. opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
  318. opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
  319. opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
  320. opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
  321. opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
  322. opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
  323. opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
  324. opentrons/protocol_engine/commands/flex_stacker/store.py +326 -0
  325. opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
  326. opentrons/protocol_engine/commands/get_next_tip.py +134 -0
  327. opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
  328. opentrons/protocol_engine/commands/hash_command_params.py +38 -0
  329. opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
  330. opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
  331. opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
  332. opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
  333. opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
  334. opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
  335. opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
  336. opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
  337. opentrons/protocol_engine/commands/home.py +100 -0
  338. opentrons/protocol_engine/commands/identify_module.py +86 -0
  339. opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
  340. opentrons/protocol_engine/commands/liquid_probe.py +464 -0
  341. opentrons/protocol_engine/commands/load_labware.py +210 -0
  342. opentrons/protocol_engine/commands/load_lid.py +154 -0
  343. opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
  344. opentrons/protocol_engine/commands/load_liquid.py +95 -0
  345. opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
  346. opentrons/protocol_engine/commands/load_module.py +223 -0
  347. opentrons/protocol_engine/commands/load_pipette.py +167 -0
  348. opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
  349. opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
  350. opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
  351. opentrons/protocol_engine/commands/move_labware.py +546 -0
  352. opentrons/protocol_engine/commands/move_relative.py +102 -0
  353. opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
  354. opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
  355. opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
  356. opentrons/protocol_engine/commands/move_to_well.py +119 -0
  357. opentrons/protocol_engine/commands/movement_common.py +338 -0
  358. opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
  359. opentrons/protocol_engine/commands/pipetting_common.py +443 -0
  360. opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
  361. opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
  362. opentrons/protocol_engine/commands/reload_labware.py +90 -0
  363. opentrons/protocol_engine/commands/retract_axis.py +75 -0
  364. opentrons/protocol_engine/commands/robot/__init__.py +70 -0
  365. opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
  366. opentrons/protocol_engine/commands/robot/common.py +18 -0
  367. opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
  368. opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
  369. opentrons/protocol_engine/commands/robot/move_to.py +94 -0
  370. opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
  371. opentrons/protocol_engine/commands/save_position.py +109 -0
  372. opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
  373. opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
  374. opentrons/protocol_engine/commands/set_status_bar.py +89 -0
  375. opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
  376. opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
  377. opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
  378. opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
  379. opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
  380. opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
  381. opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
  382. opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
  383. opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
  384. opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
  385. opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
  386. opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
  387. opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
  388. opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
  389. opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
  390. opentrons/protocol_engine/commands/touch_tip.py +189 -0
  391. opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
  392. opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
  393. opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
  394. opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
  395. opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
  396. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
  397. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
  398. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
  399. opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
  400. opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
  401. opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
  402. opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
  403. opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
  404. opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
  405. opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
  406. opentrons/protocol_engine/create_protocol_engine.py +193 -0
  407. opentrons/protocol_engine/engine_support.py +28 -0
  408. opentrons/protocol_engine/error_recovery_policy.py +81 -0
  409. opentrons/protocol_engine/errors/__init__.py +191 -0
  410. opentrons/protocol_engine/errors/error_occurrence.py +182 -0
  411. opentrons/protocol_engine/errors/exceptions.py +1308 -0
  412. opentrons/protocol_engine/execution/__init__.py +50 -0
  413. opentrons/protocol_engine/execution/command_executor.py +216 -0
  414. opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
  415. opentrons/protocol_engine/execution/door_watcher.py +119 -0
  416. opentrons/protocol_engine/execution/equipment.py +819 -0
  417. opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
  418. opentrons/protocol_engine/execution/gantry_mover.py +686 -0
  419. opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
  420. opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
  421. opentrons/protocol_engine/execution/labware_movement.py +297 -0
  422. opentrons/protocol_engine/execution/movement.py +349 -0
  423. opentrons/protocol_engine/execution/pipetting.py +607 -0
  424. opentrons/protocol_engine/execution/queue_worker.py +86 -0
  425. opentrons/protocol_engine/execution/rail_lights.py +25 -0
  426. opentrons/protocol_engine/execution/run_control.py +33 -0
  427. opentrons/protocol_engine/execution/status_bar.py +34 -0
  428. opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
  429. opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
  430. opentrons/protocol_engine/execution/tip_handler.py +550 -0
  431. opentrons/protocol_engine/labware_offset_standardization.py +194 -0
  432. opentrons/protocol_engine/notes/__init__.py +17 -0
  433. opentrons/protocol_engine/notes/notes.py +59 -0
  434. opentrons/protocol_engine/plugins.py +104 -0
  435. opentrons/protocol_engine/protocol_engine.py +683 -0
  436. opentrons/protocol_engine/resources/__init__.py +26 -0
  437. opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
  438. opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
  439. opentrons/protocol_engine/resources/file_provider.py +161 -0
  440. opentrons/protocol_engine/resources/fixture_validation.py +58 -0
  441. opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
  442. opentrons/protocol_engine/resources/labware_validation.py +73 -0
  443. opentrons/protocol_engine/resources/model_utils.py +32 -0
  444. opentrons/protocol_engine/resources/module_data_provider.py +44 -0
  445. opentrons/protocol_engine/resources/ot3_validation.py +21 -0
  446. opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
  447. opentrons/protocol_engine/slot_standardization.py +128 -0
  448. opentrons/protocol_engine/state/__init__.py +1 -0
  449. opentrons/protocol_engine/state/_abstract_store.py +27 -0
  450. opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
  451. opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
  452. opentrons/protocol_engine/state/_move_types.py +83 -0
  453. opentrons/protocol_engine/state/_well_math.py +193 -0
  454. opentrons/protocol_engine/state/addressable_areas.py +699 -0
  455. opentrons/protocol_engine/state/command_history.py +309 -0
  456. opentrons/protocol_engine/state/commands.py +1158 -0
  457. opentrons/protocol_engine/state/config.py +39 -0
  458. opentrons/protocol_engine/state/files.py +57 -0
  459. opentrons/protocol_engine/state/fluid_stack.py +138 -0
  460. opentrons/protocol_engine/state/geometry.py +2359 -0
  461. opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
  462. opentrons/protocol_engine/state/labware.py +1459 -0
  463. opentrons/protocol_engine/state/liquid_classes.py +82 -0
  464. opentrons/protocol_engine/state/liquids.py +73 -0
  465. opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
  466. opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
  467. opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
  468. opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
  469. opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
  470. opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
  471. opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
  472. opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
  473. opentrons/protocol_engine/state/modules.py +1500 -0
  474. opentrons/protocol_engine/state/motion.py +373 -0
  475. opentrons/protocol_engine/state/pipettes.py +905 -0
  476. opentrons/protocol_engine/state/state.py +421 -0
  477. opentrons/protocol_engine/state/state_summary.py +36 -0
  478. opentrons/protocol_engine/state/tips.py +420 -0
  479. opentrons/protocol_engine/state/update_types.py +904 -0
  480. opentrons/protocol_engine/state/wells.py +290 -0
  481. opentrons/protocol_engine/types/__init__.py +308 -0
  482. opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
  483. opentrons/protocol_engine/types/command_annotations.py +53 -0
  484. opentrons/protocol_engine/types/deck_configuration.py +81 -0
  485. opentrons/protocol_engine/types/execution.py +96 -0
  486. opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
  487. opentrons/protocol_engine/types/instrument.py +47 -0
  488. opentrons/protocol_engine/types/instrument_sensors.py +47 -0
  489. opentrons/protocol_engine/types/labware.py +131 -0
  490. opentrons/protocol_engine/types/labware_movement.py +22 -0
  491. opentrons/protocol_engine/types/labware_offset_location.py +111 -0
  492. opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
  493. opentrons/protocol_engine/types/liquid.py +40 -0
  494. opentrons/protocol_engine/types/liquid_class.py +59 -0
  495. opentrons/protocol_engine/types/liquid_handling.py +13 -0
  496. opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
  497. opentrons/protocol_engine/types/location.py +194 -0
  498. opentrons/protocol_engine/types/module.py +303 -0
  499. opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
  500. opentrons/protocol_engine/types/run_time_parameters.py +133 -0
  501. opentrons/protocol_engine/types/tip.py +18 -0
  502. opentrons/protocol_engine/types/util.py +21 -0
  503. opentrons/protocol_engine/types/well_position.py +124 -0
  504. opentrons/protocol_reader/__init__.py +37 -0
  505. opentrons/protocol_reader/extract_labware_definitions.py +66 -0
  506. opentrons/protocol_reader/file_format_validator.py +152 -0
  507. opentrons/protocol_reader/file_hasher.py +27 -0
  508. opentrons/protocol_reader/file_identifier.py +284 -0
  509. opentrons/protocol_reader/file_reader_writer.py +90 -0
  510. opentrons/protocol_reader/input_file.py +16 -0
  511. opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
  512. opentrons/protocol_reader/protocol_reader.py +188 -0
  513. opentrons/protocol_reader/protocol_source.py +124 -0
  514. opentrons/protocol_reader/role_analyzer.py +86 -0
  515. opentrons/protocol_runner/__init__.py +26 -0
  516. opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
  517. opentrons/protocol_runner/json_file_reader.py +55 -0
  518. opentrons/protocol_runner/json_translator.py +314 -0
  519. opentrons/protocol_runner/legacy_command_mapper.py +848 -0
  520. opentrons/protocol_runner/legacy_context_plugin.py +116 -0
  521. opentrons/protocol_runner/protocol_runner.py +530 -0
  522. opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
  523. opentrons/protocol_runner/run_orchestrator.py +496 -0
  524. opentrons/protocol_runner/task_queue.py +95 -0
  525. opentrons/protocols/__init__.py +6 -0
  526. opentrons/protocols/advanced_control/__init__.py +0 -0
  527. opentrons/protocols/advanced_control/common.py +38 -0
  528. opentrons/protocols/advanced_control/mix.py +60 -0
  529. opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
  530. opentrons/protocols/advanced_control/transfers/common.py +180 -0
  531. opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
  532. opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
  533. opentrons/protocols/api_support/__init__.py +0 -0
  534. opentrons/protocols/api_support/constants.py +8 -0
  535. opentrons/protocols/api_support/deck_type.py +110 -0
  536. opentrons/protocols/api_support/definitions.py +18 -0
  537. opentrons/protocols/api_support/instrument.py +151 -0
  538. opentrons/protocols/api_support/labware_like.py +233 -0
  539. opentrons/protocols/api_support/tip_tracker.py +175 -0
  540. opentrons/protocols/api_support/types.py +32 -0
  541. opentrons/protocols/api_support/util.py +403 -0
  542. opentrons/protocols/bundle.py +89 -0
  543. opentrons/protocols/duration/__init__.py +4 -0
  544. opentrons/protocols/duration/errors.py +5 -0
  545. opentrons/protocols/duration/estimator.py +628 -0
  546. opentrons/protocols/execution/__init__.py +0 -0
  547. opentrons/protocols/execution/dev_types.py +181 -0
  548. opentrons/protocols/execution/errors.py +40 -0
  549. opentrons/protocols/execution/execute.py +84 -0
  550. opentrons/protocols/execution/execute_json_v3.py +275 -0
  551. opentrons/protocols/execution/execute_json_v4.py +359 -0
  552. opentrons/protocols/execution/execute_json_v5.py +28 -0
  553. opentrons/protocols/execution/execute_python.py +169 -0
  554. opentrons/protocols/execution/json_dispatchers.py +87 -0
  555. opentrons/protocols/execution/types.py +7 -0
  556. opentrons/protocols/geometry/__init__.py +0 -0
  557. opentrons/protocols/geometry/planning.py +297 -0
  558. opentrons/protocols/labware.py +312 -0
  559. opentrons/protocols/models/__init__.py +0 -0
  560. opentrons/protocols/models/json_protocol.py +679 -0
  561. opentrons/protocols/parameters/__init__.py +0 -0
  562. opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
  563. opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
  564. opentrons/protocols/parameters/exceptions.py +34 -0
  565. opentrons/protocols/parameters/parameter_definition.py +272 -0
  566. opentrons/protocols/parameters/types.py +17 -0
  567. opentrons/protocols/parameters/validation.py +267 -0
  568. opentrons/protocols/parse.py +671 -0
  569. opentrons/protocols/types.py +159 -0
  570. opentrons/py.typed +0 -0
  571. opentrons/resources/scripts/lpc21isp +0 -0
  572. opentrons/resources/smoothie-edge-8414642.hex +23010 -0
  573. opentrons/simulate.py +1065 -0
  574. opentrons/system/__init__.py +6 -0
  575. opentrons/system/camera.py +51 -0
  576. opentrons/system/log_control.py +59 -0
  577. opentrons/system/nmcli.py +856 -0
  578. opentrons/system/resin.py +24 -0
  579. opentrons/system/smoothie_update.py +15 -0
  580. opentrons/system/wifi.py +204 -0
  581. opentrons/tools/__init__.py +0 -0
  582. opentrons/tools/args_handler.py +22 -0
  583. opentrons/tools/write_pipette_memory.py +157 -0
  584. opentrons/types.py +618 -0
  585. opentrons/util/__init__.py +1 -0
  586. opentrons/util/async_helpers.py +166 -0
  587. opentrons/util/broker.py +84 -0
  588. opentrons/util/change_notifier.py +47 -0
  589. opentrons/util/entrypoint_util.py +278 -0
  590. opentrons/util/get_union_elements.py +26 -0
  591. opentrons/util/helpers.py +6 -0
  592. opentrons/util/linal.py +178 -0
  593. opentrons/util/logging_config.py +265 -0
  594. opentrons/util/logging_queue_handler.py +61 -0
  595. opentrons/util/performance_helpers.py +157 -0
  596. opentrons-8.6.0a1.dist-info/METADATA +37 -0
  597. opentrons-8.6.0a1.dist-info/RECORD +600 -0
  598. opentrons-8.6.0a1.dist-info/WHEEL +4 -0
  599. opentrons-8.6.0a1.dist-info/entry_points.txt +3 -0
  600. opentrons-8.6.0a1.dist-info/licenses/LICENSE +202 -0
@@ -0,0 +1,631 @@
1
+ """
2
+ This module handles configuration management. It keeps track of where the
3
+ configuration data is found in the robot, and is able to search for data to
4
+ construct an index if an existing index is not found. All other modules that
5
+ use persistent configuration data should use this module to read and write it.
6
+
7
+ The settings file defined here is opentrons.json. This file should be located
8
+
9
+ - On the robot, in /data
10
+ - Not on the robot, either in
11
+ - the directory from which the python importing this module was launched
12
+ - ~/.opentrons for the current user (where it will be written if nothing is
13
+ found)
14
+
15
+ The keys in opentrons.json are defined by the CONFIG_ELEMENTS tuple below.
16
+ The keys in the file are the name elements of the CONFIG_ELEMENTS. They can
17
+ also be specified via environment variables, the names of which are
18
+ OT_API_${UPPERCASED_NAME_ELEMENT}. For instance, to override the
19
+ robot_settings_file option from an environment variable, you would set the
20
+ OT_API_ROBOT_CONFIG_FILE variable.
21
+
22
+ This module's interface to the rest of the system are the IS_* attributes and
23
+ the CONFIG attribute.
24
+ """
25
+ import enum
26
+ import os
27
+ import json
28
+ import logging
29
+ from pathlib import Path
30
+ import re
31
+ import shutil
32
+ import subprocess
33
+ import sys
34
+ from enum import Enum, auto
35
+ from typing import Dict, NamedTuple, Optional, cast
36
+
37
+ _CONFIG_FILENAME = "config.json"
38
+ _LEGACY_INDICES = (
39
+ Path("/mnt") / "usbdrive" / "config" / "index.json",
40
+ Path("/data") / "index.json",
41
+ )
42
+
43
+ log = logging.getLogger(__file__)
44
+
45
+ IS_WIN = sys.platform.startswith("win")
46
+ IS_OSX = sys.platform == "darwin"
47
+ IS_LINUX = sys.platform.startswith("linux")
48
+ IS_ROBOT = bool(
49
+ IS_LINUX
50
+ and (os.environ.get("RUNNING_ON_PI") or os.environ.get("RUNNING_ON_VERDIN"))
51
+ )
52
+ #: This is the correct thing to check to see if we’re running on a robot
53
+ IS_VIRTUAL = bool(os.environ.get("ENABLE_VIRTUAL_SMOOTHIE"))
54
+
55
+
56
+ class SystemArchitecture(Enum):
57
+ HOST = auto()
58
+ BUILDROOT = auto()
59
+ YOCTO = auto()
60
+
61
+
62
+ ROBOT_FIRMWARE_DIR: Optional[Path] = None
63
+ #: The path to firmware files for modules
64
+
65
+ ARCHITECTURE: SystemArchitecture = SystemArchitecture.HOST
66
+ #: The system architecture running
67
+
68
+ JUPYTER_NOTEBOOK_ROOT_DIR: Optional[Path] = None
69
+ #: The path to the root dir for Jupyter
70
+
71
+ JUPYTER_NOTEBOOK_LABWARE_DIR: Optional[Path] = None
72
+ #: The path to labware installs for jupyter
73
+
74
+ OT_SYSTEM_VERSION = "0.0.0"
75
+ #: The semver string of the system
76
+
77
+
78
+ if IS_ROBOT:
79
+ if "OT_SYSTEM_VERSION" in os.environ:
80
+ OT_SYSTEM_VERSION = os.environ["OT_SYSTEM_VERSION"]
81
+ ARCHITECTURE = SystemArchitecture.YOCTO
82
+ else:
83
+ try:
84
+ with open("/etc/VERSION.json") as vj:
85
+ contents = json.load(vj)
86
+ OT_SYSTEM_VERSION = contents["buildroot_version"]
87
+ ARCHITECTURE = SystemArchitecture.BUILDROOT
88
+ except Exception:
89
+ log.exception("Could not find version file in /etc/VERSION.json")
90
+ ROBOT_FIRMWARE_DIR = Path("/usr/lib/firmware/")
91
+ JUPYTER_NOTEBOOK_ROOT_DIR = Path("/var/lib/jupyter/notebooks/")
92
+ JUPYTER_NOTEBOOK_LABWARE_DIR = JUPYTER_NOTEBOOK_ROOT_DIR / "labware"
93
+
94
+
95
+ def name() -> str:
96
+ if IS_ROBOT and ARCHITECTURE in (
97
+ SystemArchitecture.BUILDROOT,
98
+ SystemArchitecture.YOCTO,
99
+ ):
100
+ # Read the name from the machine's pretty hostname, which is maintained
101
+ # by update-server. This retrieval logic needs to be kept in sync with
102
+ # update-server.
103
+
104
+ # NOTE: This call to hostnamectl can fail momentarily if it runs
105
+ # at the same time as a systemd-hostnamed restart.
106
+ # update-server triggers such restarts regularly, any time the name changes.
107
+ #
108
+ # We let the exception propagate so the caller (probably an HTTP client
109
+ # polling /health) can retry later.
110
+ result = subprocess.check_output(["hostnamectl", "--pretty", "status"]).decode(
111
+ "utf-8"
112
+ )
113
+
114
+ # Strip the trailing newline, since it's not part of the actual name value.
115
+ # TODO(mm, 2022-07-18): When we upgrade to systemd 249, use
116
+ # `hostnamectl --json` for CLI output that we can parse more robustly.
117
+ assert len(result) >= 1 and result[-1] == "\n"
118
+ return result[:-1]
119
+
120
+ else:
121
+ robot_name = "opentrons-dev"
122
+ if "DEV_ROBOT_NAME" in os.environ.keys():
123
+ robot_name = os.environ["DEV_ROBOT_NAME"]
124
+ return robot_name
125
+
126
+
127
+ class ConfigElementType(enum.Enum):
128
+ FILE = enum.auto()
129
+ DIR = enum.auto()
130
+
131
+
132
+ class ConfigElement(NamedTuple):
133
+ name: str
134
+ display_name: str
135
+ default: Path
136
+ kind: ConfigElementType
137
+ help: str
138
+
139
+
140
+ CONFIG_ELEMENTS = (
141
+ ConfigElement(
142
+ "labware_database_file",
143
+ "API V1 Labware Database",
144
+ Path("opentrons.db"),
145
+ ConfigElementType.FILE,
146
+ (
147
+ "A SQLite database where labware definitions and offsets were stored."
148
+ " No longer used as of v4."
149
+ ),
150
+ ),
151
+ ConfigElement(
152
+ "labware_calibration_offsets_dir_v2",
153
+ "API V2 Calibration Offsets Directory",
154
+ Path("labware") / "v2" / "offsets",
155
+ ConfigElementType.DIR,
156
+ "A location where labware offsets were stored. No longer used as of v5.",
157
+ ),
158
+ ConfigElement(
159
+ "labware_user_definitions_dir_v2",
160
+ "API V2 Custom Labware Directory",
161
+ Path("labware") / "v2" / "custom_definitions",
162
+ ConfigElementType.DIR,
163
+ (
164
+ "A location where custom labware definitions may be stored."
165
+ " Usage not recommended."
166
+ ),
167
+ ),
168
+ ConfigElement(
169
+ "feature_flags_file",
170
+ "Feature Flags",
171
+ Path("feature_flags.json"),
172
+ ConfigElementType.FILE,
173
+ "The file storing the advanced feature flags.",
174
+ ),
175
+ ConfigElement(
176
+ "robot_settings_file",
177
+ "Robot Settings",
178
+ Path("robot_settings.json"),
179
+ ConfigElementType.FILE,
180
+ "The file storing settings relevant to motion",
181
+ ),
182
+ ConfigElement(
183
+ "deck_calibration_file",
184
+ "Deck Calibration",
185
+ Path("deck_calibration.json"),
186
+ ConfigElementType.FILE,
187
+ "The file storing the deck calibration. Superseded in v4 by robot_calibration_dir.",
188
+ ),
189
+ ConfigElement(
190
+ "log_dir",
191
+ "Log Directory",
192
+ Path("logs"),
193
+ ConfigElementType.FILE,
194
+ "The location for saving log files",
195
+ ),
196
+ ConfigElement(
197
+ "api_log_file",
198
+ "API Log File",
199
+ Path("logs") / "api.log",
200
+ ConfigElementType.FILE,
201
+ "The location of the file to save API logs to. If this is an"
202
+ " absolute path, it will be used directly. If it is a "
203
+ "relative path it will be relative to log_dir",
204
+ ),
205
+ ConfigElement(
206
+ "sensor_log_file",
207
+ "Sensor Log File",
208
+ Path("logs") / "sensor.log",
209
+ ConfigElementType.FILE,
210
+ "The location of the file to save sensor logs to. If this is an"
211
+ " absolute path, it will be used directly. If it is a "
212
+ "relative path it will be relative to log_dir",
213
+ ),
214
+ ConfigElement(
215
+ "serial_log_file",
216
+ "Serial Log File",
217
+ Path("logs") / "serial.log",
218
+ ConfigElementType.FILE,
219
+ "The location of the file to save serial logs to. If this is"
220
+ " an absolute path, it will be used directly. If it is a "
221
+ "relative path it will be relative to log_dir"
222
+ "The location of the file to save serial logs to",
223
+ ),
224
+ # Unlike other config elements, the wifi keys dir is still in
225
+ # /data/user_storage/opentrons_data because these paths are fed directly to
226
+ # NetworkManager and stored in connections files there. To change this
227
+ # directory, we would have to modify those connections files, presumably on
228
+ # boot, which is a level of complexity that makes it worth having an
229
+ # annoying path.
230
+ ConfigElement(
231
+ "wifi_keys_dir",
232
+ "Wifi Keys Dir",
233
+ Path("user_storage/opentrons_data/network_keys"),
234
+ ConfigElementType.DIR,
235
+ "The directory in which to save any key material for wifi"
236
+ " auth. Not relevant outside of a robot.",
237
+ ),
238
+ ConfigElement(
239
+ "hardware_controller_lockfile",
240
+ "Hardware Controller Lockfile",
241
+ Path("hardware.lock"),
242
+ ConfigElementType.FILE,
243
+ "The file to use for a hardware controller lockfile.",
244
+ ),
245
+ ConfigElement(
246
+ "pipette_config_overrides_dir",
247
+ "Pipette Config User Overrides",
248
+ Path("pipettes"),
249
+ ConfigElementType.DIR,
250
+ "The dir where settings overrides for pipettes are stored",
251
+ ),
252
+ ConfigElement(
253
+ "tip_length_calibration_dir",
254
+ "Tip Length Calibration Directory",
255
+ Path("tip_lengths"),
256
+ ConfigElementType.DIR,
257
+ "The dir where tip length calibration of each tiprack for "
258
+ "each unique pipette is stored",
259
+ ),
260
+ ConfigElement(
261
+ "robot_calibration_dir",
262
+ "Robot Calibration Directory",
263
+ Path("robot"),
264
+ ConfigElementType.DIR,
265
+ "The dir where robot calibration is stored",
266
+ ),
267
+ ConfigElement(
268
+ "pipette_calibration_dir",
269
+ "Pipette Calibration Directory",
270
+ Path("robot") / "pipettes",
271
+ ConfigElementType.DIR,
272
+ "The dir where pipette calibration is stored",
273
+ ),
274
+ ConfigElement(
275
+ "custom_tiprack_dir",
276
+ "Custom Tiprack Directory",
277
+ Path("tip_lengths") / "custom_tiprack_definitions",
278
+ ConfigElementType.DIR,
279
+ "The dir where custom tiprack definitions for tip length "
280
+ "calibration are stored",
281
+ ),
282
+ ConfigElement(
283
+ "gripper_calibration_dir",
284
+ "Gripper Calibration Directory",
285
+ Path("robot") / "gripper",
286
+ ConfigElementType.DIR,
287
+ "The dir where gripper calibration is stored",
288
+ ),
289
+ ConfigElement(
290
+ "gripper_jaw_width_dir",
291
+ "Gripper Jaw Width Directory",
292
+ Path("robot") / "gripper_jaw_width_data",
293
+ ConfigElementType.DIR,
294
+ "The dir where gripper jaw width data is stored",
295
+ ),
296
+ ConfigElement(
297
+ "module_calibration_dir",
298
+ "Module Calibration Directory",
299
+ Path("robot") / "modules",
300
+ ConfigElementType.DIR,
301
+ "The dir where module calibration is stored",
302
+ ),
303
+ ConfigElement(
304
+ "performance_metrics_dir",
305
+ "Performance Metrics Directory",
306
+ Path("performance_metrics_data"),
307
+ ConfigElementType.DIR,
308
+ "The dir where performance metrics are stored",
309
+ ),
310
+ )
311
+ #: The available configuration file elements to modify. All of these can be
312
+ #: changed by editing opentrons.json, where the keys are the name elements,
313
+ #: or by specifying as environment variables, where the keys are uppercase
314
+ #: versions of the name elements.
315
+ #: In addition to these flags, the OT_API_CONFIG_DIR env var (if present)
316
+ #: will change where the API looks for these settings by prepending it to the
317
+ #: normal search path.
318
+
319
+
320
+ def infer_config_base_dir() -> Path:
321
+ """Return the directory to store data in.
322
+
323
+ Defaults are ~/.opentrons if not on a pi; OT_API_CONFIG_DIR is
324
+ respected here.
325
+
326
+ When this module is imported, this function is called automatically
327
+ and the result stored in :py:attr:`APP_DATA_DIR`.
328
+
329
+ This directory may not exist when the module is imported. Even if it
330
+ does exist, it may not contain data, or may require data to be moved
331
+ to it.
332
+
333
+ :return pathlib.Path: The path to the desired root settings dir.
334
+ """
335
+ if "OT_API_CONFIG_DIR" in os.environ:
336
+ return Path(os.environ["OT_API_CONFIG_DIR"])
337
+ elif IS_ROBOT:
338
+ return Path("/data")
339
+ else:
340
+ search = (Path.cwd(), Path.home() / ".opentrons")
341
+ for path in search:
342
+ if (path / _CONFIG_FILENAME).exists():
343
+ return path
344
+ else:
345
+ return search[-1]
346
+
347
+
348
+ def load_and_migrate() -> Dict[str, Path]:
349
+ """Ensure the settings directory tree is properly configured.
350
+
351
+ This function does most of its work on the actual robot. It will move
352
+ all settings files from wherever they happen to be to the proper
353
+ place. On non-robots, this mostly just loads. In addition, it writes
354
+ a default config and makes sure all directories required exist (though
355
+ the files in them may not).
356
+ """
357
+ if IS_ROBOT and ARCHITECTURE != SystemArchitecture.YOCTO:
358
+ _migrate_robot()
359
+ base = infer_config_base_dir()
360
+ base.mkdir(parents=True, exist_ok=True)
361
+ index = _load_with_overrides(base)
362
+ return _ensure_paths_and_types(index)
363
+
364
+
365
+ def _load_with_overrides(base: Path) -> Dict[str, str]:
366
+ """Load an config or write its defaults"""
367
+ should_write = False
368
+ overrides = _get_environ_overrides()
369
+ try:
370
+ with (base / _CONFIG_FILENAME).open() as file:
371
+ index = json.load(file)
372
+ except (OSError, json.JSONDecodeError):
373
+ should_write = True
374
+ index = generate_config_index(overrides)
375
+
376
+ for key in CONFIG_ELEMENTS:
377
+ if key.name not in index:
378
+ if key.kind in (ConfigElementType.DIR, ConfigElementType.FILE):
379
+ index[key.name] = base / key.default
380
+ else:
381
+ index[key.name] = key.default
382
+ should_write = True
383
+
384
+ if should_write:
385
+ try:
386
+ write_config(index, path=base)
387
+ except Exception as e:
388
+ sys.stderr.write(
389
+ "Error writing config to {}: {}\nProceeding memory-only\n".format(
390
+ str(base), e
391
+ )
392
+ )
393
+ index.update(overrides)
394
+ return cast(Dict[str, str], index)
395
+
396
+
397
+ def _ensure_paths_and_types(index: Dict[str, str]) -> Dict[str, Path]:
398
+ """Take the direct results of loading the config and make sure
399
+ the filesystem reflects them.
400
+ """
401
+ configs_by_name = {ce.name: ce for ce in CONFIG_ELEMENTS}
402
+ correct_types: Dict[str, Path] = {}
403
+ for key, item in index.items():
404
+ if key not in configs_by_name: # old config, ignore
405
+ continue
406
+ if configs_by_name[key].kind == ConfigElementType.FILE:
407
+ it = Path(item)
408
+ it.parent.mkdir(parents=True, exist_ok=True)
409
+ correct_types[key] = it
410
+ elif configs_by_name[key].kind == ConfigElementType.DIR:
411
+ it = Path(item)
412
+ it.mkdir(parents=True, exist_ok=True)
413
+ correct_types[key] = it
414
+ else:
415
+ raise RuntimeError(
416
+ f"unhandled kind in ConfigElements: {key}: "
417
+ f"{configs_by_name[key].kind}"
418
+ )
419
+ return correct_types
420
+
421
+
422
+ def _get_environ_overrides() -> Dict[str, str]:
423
+ """Pull any overrides for the config elements from the environ and return
424
+ a mapping from the names to the values (as strings). Config elements that
425
+ are not overridden will not be in the mapping.
426
+ """
427
+ return {
428
+ ce.name: os.environ["OT_API_" + ce.name.upper()]
429
+ for ce in CONFIG_ELEMENTS
430
+ if "OT_API_" + ce.name.upper() in os.environ
431
+ }
432
+
433
+
434
+ def _legacy_index() -> Optional[Dict[str, str]]:
435
+ """Try and load an index file from the various places it might exist.
436
+
437
+ If the legacy file cannot be found or cannot be parsed, return None.
438
+
439
+ This method should only be called on a robot.
440
+ """
441
+ for index in _LEGACY_INDICES:
442
+ if index.exists():
443
+ try:
444
+ with open(index) as file:
445
+ return cast(Dict[str, str], json.load(file))
446
+ except (OSError, json.JSONDecodeError):
447
+ return None
448
+ return None
449
+
450
+
451
+ def _erase_old_indices() -> None:
452
+ """Remove old index files so they don't pollute future loads.
453
+
454
+ This method should only be called on a robot.
455
+ """
456
+ for index in _LEGACY_INDICES:
457
+ if index.exists():
458
+ index.unlink()
459
+
460
+
461
+ def _find_most_recent_backup(normal_path: Optional[str]) -> Optional[str]:
462
+ """Find the most recent old settings to migrate.
463
+
464
+ The input is the path to an unqualified settings file - e.g.
465
+ /mnt/usbdrive/config/robotSettings.json
466
+
467
+ This will return
468
+ - None if the input is None (to support chaining from dict.get())
469
+ - The input if it exists, or
470
+ - The file named normal_path-TIMESTAMP.json with the highest timestamp
471
+ if one can be found, or
472
+ - None
473
+ """
474
+ if normal_path is None:
475
+ return None
476
+
477
+ if os.path.exists(normal_path):
478
+ return normal_path
479
+
480
+ dirname, basename = os.path.split(normal_path)
481
+ root, ext = os.path.splitext(basename)
482
+ backups = [
483
+ fi for fi in os.listdir(dirname) if fi.startswith(root) and fi.endswith(ext)
484
+ ]
485
+ ts_re = re.compile(r".*-([0-9]+)" + ext + "$")
486
+
487
+ def ts_compare(filename: str) -> int:
488
+ match = ts_re.match(filename)
489
+ if not match:
490
+ return -1
491
+ else:
492
+ return int(match.group(1))
493
+
494
+ backups_sorted = sorted(backups, key=ts_compare)
495
+ if not backups_sorted:
496
+ return None
497
+ return os.path.join(dirname, backups_sorted[-1])
498
+
499
+
500
+ def _do_migrate(index: Dict[str, str]) -> None:
501
+ base = infer_config_base_dir()
502
+ new_index = generate_config_index(_get_environ_overrides(), base)
503
+ moves = (
504
+ (
505
+ "/data/user_storage/opentrons_data/opentrons.db",
506
+ new_index["labware_database_file"],
507
+ ),
508
+ (
509
+ _find_most_recent_backup(index.get("robotSettingsFile")),
510
+ new_index["robot_settings_file"],
511
+ ),
512
+ (index.get("deckCalibrationFile"), new_index["deck_calibration_file"]),
513
+ (index.get("featureFlagFile"), new_index["feature_flags_file"]),
514
+ )
515
+ sys.stdout.write(f"config migration: new base {base}\n")
516
+ for old, new in moves:
517
+ if not old:
518
+ continue
519
+ old_path = Path(old)
520
+ new_path = Path(new)
521
+ if old_path.exists() and not old_path.is_symlink():
522
+ sys.stdout.write(f"config migration: {old}->{new}\n")
523
+ if new_path.is_dir():
524
+ shutil.rmtree(new_path)
525
+ shutil.move(str(old_path), str(new_path))
526
+ else:
527
+ sys.stdout.write(f"config migration: not moving {old}:")
528
+ sys.stdout.write(f" exists={old_path.exists()}")
529
+ sys.stdout.write(f" symlink={old_path.is_symlink()}\n")
530
+
531
+ write_config(new_index, base)
532
+
533
+
534
+ def _migrate_robot() -> None:
535
+ old_index = _legacy_index()
536
+ if old_index:
537
+ _do_migrate(old_index)
538
+ _erase_old_indices()
539
+
540
+
541
+ def generate_config_index(
542
+ defaults: Dict[str, str], base_dir: Optional[Path] = None
543
+ ) -> Dict[str, Path]:
544
+ """
545
+ Determines where existing info can be found in the system, and creates a
546
+ corresponding data dict that can be written to index.json in the
547
+ baseDataDir.
548
+
549
+ The information in the files defined by the config index is information
550
+ required by the API itself and nothing else - labware definitions, feature
551
+ flags, robot configurations. It does not include configuration files that
552
+ relate to the rest of the system, such as network description file
553
+ definitions.
554
+
555
+ :param defaults: A dict of defaults to write, useful for specifying part
556
+ (but not all) of the index succinctly. This is used both
557
+ when loading a configuration file from disk and when
558
+ generating a new one.
559
+ :param base_dir: If specified, a base path used if this function has to
560
+ generate defaults. If not specified, falls back to
561
+ :py:attr:`CONFIG_BASE_DIR`
562
+ :returns: The config object
563
+ """
564
+ base = Path(base_dir) if base_dir else infer_config_base_dir()
565
+
566
+ def parse_or_default(ce: ConfigElement, val: Optional[str]) -> Path:
567
+ if not val:
568
+ return base / ce.default
569
+ else:
570
+ return Path(val)
571
+
572
+ return {
573
+ ce.name: parse_or_default(ce, defaults.get(ce.name)) for ce in CONFIG_ELEMENTS
574
+ }
575
+
576
+
577
+ def write_config(config_data: Dict[str, Path], path: Optional[Path] = None) -> None:
578
+ """Save the config file.
579
+
580
+ :param config_data: The index to save
581
+ :param base_dir: The place to save the file. If ``None``,
582
+ :py:meth:`infer_config_base_dir()` will be used
583
+
584
+ Only keys that are in the config elements will be saved.
585
+ """
586
+ path = Path(path) if path else infer_config_base_dir()
587
+ valid_names = [ce.name for ce in CONFIG_ELEMENTS]
588
+ try:
589
+ os.makedirs(path, exist_ok=True)
590
+ with (path / _CONFIG_FILENAME).open("w") as base_f:
591
+ json.dump(
592
+ {k: str(v) for k, v in config_data.items() if k in valid_names},
593
+ base_f,
594
+ indent=2,
595
+ )
596
+ except OSError as e:
597
+ sys.stderr.write(
598
+ "Config index write to {} failed: {}\n".format(path / _CONFIG_FILENAME, e)
599
+ )
600
+
601
+
602
+ def reload() -> None:
603
+ global CONFIG
604
+ CONFIG.clear()
605
+ CONFIG.update(load_and_migrate())
606
+
607
+
608
+ def get_opentrons_path(path_name: str) -> Path:
609
+ # Helper function to look-up the path
610
+ # to specific configuration files for
611
+ # the Opentrons system
612
+ global CONFIG
613
+ return CONFIG[path_name]
614
+
615
+
616
+ CONFIG = load_and_migrate()
617
+ #: The currently loaded config. This should not change for the lifetime
618
+ #: of the program. This is a dict much like os.environ() where the keys
619
+ #: are config element names
620
+
621
+
622
+ def get_tip_length_cal_path() -> Path:
623
+ return get_opentrons_path("tip_length_calibration_dir")
624
+
625
+
626
+ def get_custom_tiprack_def_path() -> Path:
627
+ return get_opentrons_path("custom_tiprack_dir")
628
+
629
+
630
+ def get_performance_metrics_data_dir() -> Path:
631
+ return get_opentrons_path("performance_metrics_dir")