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.
- opentrons/__init__.py +150 -0
- opentrons/_version.py +34 -0
- opentrons/calibration_storage/__init__.py +54 -0
- opentrons/calibration_storage/deck_configuration.py +62 -0
- opentrons/calibration_storage/encoder_decoder.py +31 -0
- opentrons/calibration_storage/file_operators.py +142 -0
- opentrons/calibration_storage/helpers.py +103 -0
- opentrons/calibration_storage/ot2/__init__.py +34 -0
- opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
- opentrons/calibration_storage/ot2/models/__init__.py +0 -0
- opentrons/calibration_storage/ot2/models/v1.py +149 -0
- opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
- opentrons/calibration_storage/ot2/tip_length.py +281 -0
- opentrons/calibration_storage/ot3/__init__.py +31 -0
- opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
- opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
- opentrons/calibration_storage/ot3/models/__init__.py +0 -0
- opentrons/calibration_storage/ot3/models/v1.py +122 -0
- opentrons/calibration_storage/ot3/module_offset.py +138 -0
- opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
- opentrons/calibration_storage/types.py +45 -0
- opentrons/cli/__init__.py +21 -0
- opentrons/cli/__main__.py +5 -0
- opentrons/cli/analyze.py +557 -0
- opentrons/config/__init__.py +631 -0
- opentrons/config/advanced_settings.py +871 -0
- opentrons/config/defaults_ot2.py +214 -0
- opentrons/config/defaults_ot3.py +499 -0
- opentrons/config/feature_flags.py +86 -0
- opentrons/config/gripper_config.py +55 -0
- opentrons/config/reset.py +203 -0
- opentrons/config/robot_configs.py +187 -0
- opentrons/config/types.py +183 -0
- opentrons/drivers/__init__.py +0 -0
- opentrons/drivers/absorbance_reader/__init__.py +11 -0
- opentrons/drivers/absorbance_reader/abstract.py +72 -0
- opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
- opentrons/drivers/absorbance_reader/driver.py +81 -0
- opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
- opentrons/drivers/absorbance_reader/simulator.py +84 -0
- opentrons/drivers/asyncio/__init__.py +0 -0
- opentrons/drivers/asyncio/communication/__init__.py +22 -0
- opentrons/drivers/asyncio/communication/async_serial.py +187 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +557 -0
- opentrons/drivers/command_builder.py +102 -0
- opentrons/drivers/flex_stacker/__init__.py +13 -0
- opentrons/drivers/flex_stacker/abstract.py +214 -0
- opentrons/drivers/flex_stacker/driver.py +768 -0
- opentrons/drivers/flex_stacker/errors.py +68 -0
- opentrons/drivers/flex_stacker/simulator.py +309 -0
- opentrons/drivers/flex_stacker/types.py +367 -0
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/drivers/heater_shaker/__init__.py +5 -0
- opentrons/drivers/heater_shaker/abstract.py +76 -0
- opentrons/drivers/heater_shaker/driver.py +204 -0
- opentrons/drivers/heater_shaker/simulator.py +94 -0
- opentrons/drivers/mag_deck/__init__.py +6 -0
- opentrons/drivers/mag_deck/abstract.py +44 -0
- opentrons/drivers/mag_deck/driver.py +208 -0
- opentrons/drivers/mag_deck/simulator.py +63 -0
- opentrons/drivers/rpi_drivers/__init__.py +33 -0
- opentrons/drivers/rpi_drivers/dev_types.py +94 -0
- opentrons/drivers/rpi_drivers/gpio.py +282 -0
- opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
- opentrons/drivers/rpi_drivers/interfaces.py +15 -0
- opentrons/drivers/rpi_drivers/types.py +364 -0
- opentrons/drivers/rpi_drivers/usb.py +102 -0
- opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
- opentrons/drivers/serial_communication.py +151 -0
- opentrons/drivers/smoothie_drivers/__init__.py +4 -0
- opentrons/drivers/smoothie_drivers/connection.py +51 -0
- opentrons/drivers/smoothie_drivers/constants.py +121 -0
- opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
- opentrons/drivers/smoothie_drivers/errors.py +49 -0
- opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
- opentrons/drivers/smoothie_drivers/simulator.py +99 -0
- opentrons/drivers/smoothie_drivers/types.py +16 -0
- opentrons/drivers/temp_deck/__init__.py +10 -0
- opentrons/drivers/temp_deck/abstract.py +54 -0
- opentrons/drivers/temp_deck/driver.py +197 -0
- opentrons/drivers/temp_deck/simulator.py +57 -0
- opentrons/drivers/thermocycler/__init__.py +12 -0
- opentrons/drivers/thermocycler/abstract.py +99 -0
- opentrons/drivers/thermocycler/driver.py +395 -0
- opentrons/drivers/thermocycler/simulator.py +126 -0
- opentrons/drivers/types.py +107 -0
- opentrons/drivers/utils.py +222 -0
- opentrons/execute.py +742 -0
- opentrons/hardware_control/__init__.py +65 -0
- opentrons/hardware_control/__main__.py +77 -0
- opentrons/hardware_control/adapters.py +98 -0
- opentrons/hardware_control/api.py +1347 -0
- opentrons/hardware_control/backends/__init__.py +7 -0
- opentrons/hardware_control/backends/controller.py +400 -0
- opentrons/hardware_control/backends/errors.py +9 -0
- opentrons/hardware_control/backends/estop_state.py +164 -0
- opentrons/hardware_control/backends/flex_protocol.py +497 -0
- opentrons/hardware_control/backends/ot3controller.py +1930 -0
- opentrons/hardware_control/backends/ot3simulator.py +900 -0
- opentrons/hardware_control/backends/ot3utils.py +664 -0
- opentrons/hardware_control/backends/simulator.py +442 -0
- opentrons/hardware_control/backends/status_bar_state.py +240 -0
- opentrons/hardware_control/backends/subsystem_manager.py +431 -0
- opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
- opentrons/hardware_control/backends/types.py +14 -0
- opentrons/hardware_control/constants.py +6 -0
- opentrons/hardware_control/dev_types.py +125 -0
- opentrons/hardware_control/emulation/__init__.py +0 -0
- opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
- opentrons/hardware_control/emulation/app.py +56 -0
- opentrons/hardware_control/emulation/connection_handler.py +38 -0
- opentrons/hardware_control/emulation/heater_shaker.py +150 -0
- opentrons/hardware_control/emulation/magdeck.py +60 -0
- opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
- opentrons/hardware_control/emulation/module_server/client.py +78 -0
- opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
- opentrons/hardware_control/emulation/module_server/models.py +31 -0
- opentrons/hardware_control/emulation/module_server/server.py +110 -0
- opentrons/hardware_control/emulation/parser.py +74 -0
- opentrons/hardware_control/emulation/proxy.py +241 -0
- opentrons/hardware_control/emulation/run_emulator.py +68 -0
- opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
- opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
- opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
- opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
- opentrons/hardware_control/emulation/settings.py +119 -0
- opentrons/hardware_control/emulation/simulations.py +133 -0
- opentrons/hardware_control/emulation/smoothie.py +192 -0
- opentrons/hardware_control/emulation/tempdeck.py +69 -0
- opentrons/hardware_control/emulation/thermocycler.py +128 -0
- opentrons/hardware_control/emulation/types.py +10 -0
- opentrons/hardware_control/emulation/util.py +38 -0
- opentrons/hardware_control/errors.py +43 -0
- opentrons/hardware_control/execution_manager.py +164 -0
- opentrons/hardware_control/instruments/__init__.py +5 -0
- opentrons/hardware_control/instruments/instrument_abc.py +39 -0
- opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
- opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
- opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
- opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
- opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
- opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
- opentrons/hardware_control/module_control.py +332 -0
- opentrons/hardware_control/modules/__init__.py +69 -0
- opentrons/hardware_control/modules/absorbance_reader.py +373 -0
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/flex_stacker.py +948 -0
- opentrons/hardware_control/modules/heater_shaker.py +426 -0
- opentrons/hardware_control/modules/lid_temp_status.py +35 -0
- opentrons/hardware_control/modules/magdeck.py +233 -0
- opentrons/hardware_control/modules/mod_abc.py +245 -0
- opentrons/hardware_control/modules/module_calibration.py +93 -0
- opentrons/hardware_control/modules/plate_temp_status.py +61 -0
- opentrons/hardware_control/modules/tempdeck.py +299 -0
- opentrons/hardware_control/modules/thermocycler.py +731 -0
- opentrons/hardware_control/modules/types.py +417 -0
- opentrons/hardware_control/modules/update.py +255 -0
- opentrons/hardware_control/modules/utils.py +73 -0
- opentrons/hardware_control/motion_utilities.py +318 -0
- opentrons/hardware_control/nozzle_manager.py +422 -0
- opentrons/hardware_control/ot3_calibration.py +1171 -0
- opentrons/hardware_control/ot3api.py +3227 -0
- opentrons/hardware_control/pause_manager.py +31 -0
- opentrons/hardware_control/poller.py +112 -0
- opentrons/hardware_control/protocols/__init__.py +106 -0
- opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
- opentrons/hardware_control/protocols/calibratable.py +45 -0
- opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
- opentrons/hardware_control/protocols/configurable.py +48 -0
- opentrons/hardware_control/protocols/event_sourcer.py +18 -0
- opentrons/hardware_control/protocols/execution_controllable.py +33 -0
- opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
- opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
- opentrons/hardware_control/protocols/gripper_controller.py +55 -0
- opentrons/hardware_control/protocols/hardware_manager.py +51 -0
- opentrons/hardware_control/protocols/identifiable.py +16 -0
- opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
- opentrons/hardware_control/protocols/liquid_handler.py +266 -0
- opentrons/hardware_control/protocols/module_provider.py +16 -0
- opentrons/hardware_control/protocols/motion_controller.py +243 -0
- opentrons/hardware_control/protocols/position_estimator.py +45 -0
- opentrons/hardware_control/protocols/simulatable.py +10 -0
- opentrons/hardware_control/protocols/stoppable.py +9 -0
- opentrons/hardware_control/protocols/types.py +27 -0
- opentrons/hardware_control/robot_calibration.py +224 -0
- opentrons/hardware_control/scripts/README.md +28 -0
- opentrons/hardware_control/scripts/__init__.py +1 -0
- opentrons/hardware_control/scripts/gripper_control.py +208 -0
- opentrons/hardware_control/scripts/ot3gripper +7 -0
- opentrons/hardware_control/scripts/ot3repl +7 -0
- opentrons/hardware_control/scripts/repl.py +187 -0
- opentrons/hardware_control/scripts/tc_control.py +97 -0
- opentrons/hardware_control/scripts/update_module_fw.py +274 -0
- opentrons/hardware_control/simulator_setup.py +260 -0
- opentrons/hardware_control/thread_manager.py +431 -0
- opentrons/hardware_control/threaded_async_lock.py +97 -0
- opentrons/hardware_control/types.py +792 -0
- opentrons/hardware_control/util.py +234 -0
- opentrons/legacy_broker.py +53 -0
- opentrons/legacy_commands/__init__.py +1 -0
- opentrons/legacy_commands/commands.py +483 -0
- opentrons/legacy_commands/helpers.py +153 -0
- opentrons/legacy_commands/module_commands.py +276 -0
- opentrons/legacy_commands/protocol_commands.py +54 -0
- opentrons/legacy_commands/publisher.py +155 -0
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +1186 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +501 -0
- opentrons/motion_planning/errors.py +35 -0
- opentrons/motion_planning/types.py +42 -0
- opentrons/motion_planning/waypoints.py +218 -0
- opentrons/ordered_set.py +138 -0
- opentrons/protocol_api/__init__.py +105 -0
- opentrons/protocol_api/_liquid.py +157 -0
- opentrons/protocol_api/_liquid_properties.py +814 -0
- opentrons/protocol_api/_nozzle_layout.py +31 -0
- opentrons/protocol_api/_parameter_context.py +300 -0
- opentrons/protocol_api/_parameters.py +31 -0
- opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
- opentrons/protocol_api/_types.py +43 -0
- opentrons/protocol_api/config.py +23 -0
- opentrons/protocol_api/core/__init__.py +23 -0
- opentrons/protocol_api/core/common.py +33 -0
- opentrons/protocol_api/core/core_map.py +74 -0
- opentrons/protocol_api/core/engine/__init__.py +22 -0
- opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
- opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
- opentrons/protocol_api/core/engine/exceptions.py +19 -0
- opentrons/protocol_api/core/engine/instrument.py +2391 -0
- opentrons/protocol_api/core/engine/labware.py +238 -0
- opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
- opentrons/protocol_api/core/engine/module_core.py +1027 -0
- opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
- opentrons/protocol_api/core/engine/point_calculations.py +64 -0
- opentrons/protocol_api/core/engine/protocol.py +1153 -0
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/stringify.py +74 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
- opentrons/protocol_api/core/engine/well.py +241 -0
- opentrons/protocol_api/core/instrument.py +459 -0
- opentrons/protocol_api/core/labware.py +151 -0
- opentrons/protocol_api/core/legacy/__init__.py +11 -0
- opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
- opentrons/protocol_api/core/legacy/deck.py +369 -0
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
- opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
- opentrons/protocol_api/core/legacy/load_info.py +67 -0
- opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
- opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
- opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
- opentrons/protocol_api/core/module.py +484 -0
- opentrons/protocol_api/core/protocol.py +311 -0
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/core/well.py +116 -0
- opentrons/protocol_api/core/well_grid.py +45 -0
- opentrons/protocol_api/create_protocol_context.py +177 -0
- opentrons/protocol_api/deck.py +223 -0
- opentrons/protocol_api/disposal_locations.py +244 -0
- opentrons/protocol_api/instrument_context.py +3272 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1447 -0
- opentrons/protocol_api/module_validation_and_errors.py +61 -0
- opentrons/protocol_api/protocol_context.py +1688 -0
- opentrons/protocol_api/robot_context.py +303 -0
- opentrons/protocol_api/validation.py +761 -0
- opentrons/protocol_engine/__init__.py +155 -0
- opentrons/protocol_engine/actions/__init__.py +65 -0
- opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
- opentrons/protocol_engine/actions/action_handler.py +13 -0
- opentrons/protocol_engine/actions/actions.py +302 -0
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/__init__.py +5 -0
- opentrons/protocol_engine/clients/sync_client.py +174 -0
- opentrons/protocol_engine/clients/transports.py +197 -0
- opentrons/protocol_engine/commands/__init__.py +757 -0
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
- opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
- opentrons/protocol_engine/commands/aspirate.py +244 -0
- opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
- opentrons/protocol_engine/commands/blow_out.py +146 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
- opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
- opentrons/protocol_engine/commands/command.py +308 -0
- opentrons/protocol_engine/commands/command_unions.py +974 -0
- opentrons/protocol_engine/commands/comment.py +57 -0
- opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
- opentrons/protocol_engine/commands/custom.py +67 -0
- opentrons/protocol_engine/commands/dispense.py +194 -0
- opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +232 -0
- opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
- opentrons/protocol_engine/commands/hash_command_params.py +38 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
- opentrons/protocol_engine/commands/home.py +100 -0
- opentrons/protocol_engine/commands/identify_module.py +86 -0
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +464 -0
- opentrons/protocol_engine/commands/load_labware.py +210 -0
- opentrons/protocol_engine/commands/load_lid.py +154 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
- opentrons/protocol_engine/commands/load_liquid.py +95 -0
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +223 -0
- opentrons/protocol_engine/commands/load_pipette.py +167 -0
- opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
- opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
- opentrons/protocol_engine/commands/move_labware.py +546 -0
- opentrons/protocol_engine/commands/move_relative.py +102 -0
- opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
- opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
- opentrons/protocol_engine/commands/move_to_well.py +119 -0
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
- opentrons/protocol_engine/commands/pipetting_common.py +443 -0
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
- opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
- opentrons/protocol_engine/commands/reload_labware.py +90 -0
- opentrons/protocol_engine/commands/retract_axis.py +75 -0
- opentrons/protocol_engine/commands/robot/__init__.py +70 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/save_position.py +109 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
- opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
- opentrons/protocol_engine/commands/set_status_bar.py +89 -0
- opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
- opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
- opentrons/protocol_engine/commands/touch_tip.py +189 -0
- opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
- opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
- opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
- opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
- opentrons/protocol_engine/create_protocol_engine.py +193 -0
- opentrons/protocol_engine/engine_support.py +28 -0
- opentrons/protocol_engine/error_recovery_policy.py +81 -0
- opentrons/protocol_engine/errors/__init__.py +191 -0
- opentrons/protocol_engine/errors/error_occurrence.py +182 -0
- opentrons/protocol_engine/errors/exceptions.py +1308 -0
- opentrons/protocol_engine/execution/__init__.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +216 -0
- opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
- opentrons/protocol_engine/execution/door_watcher.py +119 -0
- opentrons/protocol_engine/execution/equipment.py +819 -0
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +686 -0
- opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
- opentrons/protocol_engine/execution/labware_movement.py +297 -0
- opentrons/protocol_engine/execution/movement.py +350 -0
- opentrons/protocol_engine/execution/pipetting.py +607 -0
- opentrons/protocol_engine/execution/queue_worker.py +86 -0
- opentrons/protocol_engine/execution/rail_lights.py +25 -0
- opentrons/protocol_engine/execution/run_control.py +33 -0
- opentrons/protocol_engine/execution/status_bar.py +34 -0
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
- opentrons/protocol_engine/execution/tip_handler.py +550 -0
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/notes/__init__.py +17 -0
- opentrons/protocol_engine/notes/notes.py +59 -0
- opentrons/protocol_engine/plugins.py +104 -0
- opentrons/protocol_engine/protocol_engine.py +683 -0
- opentrons/protocol_engine/resources/__init__.py +26 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +68 -0
- opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
- opentrons/protocol_engine/resources/labware_validation.py +73 -0
- opentrons/protocol_engine/resources/model_utils.py +32 -0
- opentrons/protocol_engine/resources/module_data_provider.py +44 -0
- opentrons/protocol_engine/resources/ot3_validation.py +21 -0
- opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
- opentrons/protocol_engine/slot_standardization.py +128 -0
- opentrons/protocol_engine/state/__init__.py +1 -0
- opentrons/protocol_engine/state/_abstract_store.py +27 -0
- opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_move_types.py +83 -0
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +699 -0
- opentrons/protocol_engine/state/command_history.py +309 -0
- opentrons/protocol_engine/state/commands.py +1164 -0
- opentrons/protocol_engine/state/config.py +39 -0
- opentrons/protocol_engine/state/files.py +57 -0
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/geometry.py +2408 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1432 -0
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +73 -0
- opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
- opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
- opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
- opentrons/protocol_engine/state/modules.py +1515 -0
- opentrons/protocol_engine/state/motion.py +373 -0
- opentrons/protocol_engine/state/pipettes.py +905 -0
- opentrons/protocol_engine/state/state.py +421 -0
- opentrons/protocol_engine/state/state_summary.py +36 -0
- opentrons/protocol_engine/state/tips.py +420 -0
- opentrons/protocol_engine/state/update_types.py +904 -0
- opentrons/protocol_engine/state/wells.py +290 -0
- opentrons/protocol_engine/types/__init__.py +310 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +81 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +131 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +310 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/__init__.py +37 -0
- opentrons/protocol_reader/extract_labware_definitions.py +66 -0
- opentrons/protocol_reader/file_format_validator.py +152 -0
- opentrons/protocol_reader/file_hasher.py +27 -0
- opentrons/protocol_reader/file_identifier.py +284 -0
- opentrons/protocol_reader/file_reader_writer.py +90 -0
- opentrons/protocol_reader/input_file.py +16 -0
- opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
- opentrons/protocol_reader/protocol_reader.py +188 -0
- opentrons/protocol_reader/protocol_source.py +124 -0
- opentrons/protocol_reader/role_analyzer.py +86 -0
- opentrons/protocol_runner/__init__.py +26 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
- opentrons/protocol_runner/json_file_reader.py +55 -0
- opentrons/protocol_runner/json_translator.py +314 -0
- opentrons/protocol_runner/legacy_command_mapper.py +852 -0
- opentrons/protocol_runner/legacy_context_plugin.py +116 -0
- opentrons/protocol_runner/protocol_runner.py +530 -0
- opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
- opentrons/protocol_runner/run_orchestrator.py +496 -0
- opentrons/protocol_runner/task_queue.py +95 -0
- opentrons/protocols/__init__.py +6 -0
- opentrons/protocols/advanced_control/__init__.py +0 -0
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +60 -0
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +180 -0
- opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
- opentrons/protocols/api_support/__init__.py +0 -0
- opentrons/protocols/api_support/constants.py +8 -0
- opentrons/protocols/api_support/deck_type.py +110 -0
- opentrons/protocols/api_support/definitions.py +18 -0
- opentrons/protocols/api_support/instrument.py +151 -0
- opentrons/protocols/api_support/labware_like.py +233 -0
- opentrons/protocols/api_support/tip_tracker.py +175 -0
- opentrons/protocols/api_support/types.py +32 -0
- opentrons/protocols/api_support/util.py +403 -0
- opentrons/protocols/bundle.py +89 -0
- opentrons/protocols/duration/__init__.py +4 -0
- opentrons/protocols/duration/errors.py +5 -0
- opentrons/protocols/duration/estimator.py +628 -0
- opentrons/protocols/execution/__init__.py +0 -0
- opentrons/protocols/execution/dev_types.py +181 -0
- opentrons/protocols/execution/errors.py +40 -0
- opentrons/protocols/execution/execute.py +84 -0
- opentrons/protocols/execution/execute_json_v3.py +275 -0
- opentrons/protocols/execution/execute_json_v4.py +359 -0
- opentrons/protocols/execution/execute_json_v5.py +28 -0
- opentrons/protocols/execution/execute_python.py +169 -0
- opentrons/protocols/execution/json_dispatchers.py +87 -0
- opentrons/protocols/execution/types.py +7 -0
- opentrons/protocols/geometry/__init__.py +0 -0
- opentrons/protocols/geometry/planning.py +297 -0
- opentrons/protocols/labware.py +312 -0
- opentrons/protocols/models/__init__.py +0 -0
- opentrons/protocols/models/json_protocol.py +679 -0
- opentrons/protocols/parameters/__init__.py +0 -0
- opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
- opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
- opentrons/protocols/parameters/exceptions.py +34 -0
- opentrons/protocols/parameters/parameter_definition.py +272 -0
- opentrons/protocols/parameters/types.py +17 -0
- opentrons/protocols/parameters/validation.py +267 -0
- opentrons/protocols/parse.py +671 -0
- opentrons/protocols/types.py +159 -0
- opentrons/py.typed +0 -0
- opentrons/resources/scripts/lpc21isp +0 -0
- opentrons/resources/smoothie-edge-8414642.hex +23010 -0
- opentrons/simulate.py +1065 -0
- opentrons/system/__init__.py +6 -0
- opentrons/system/camera.py +51 -0
- opentrons/system/log_control.py +59 -0
- opentrons/system/nmcli.py +856 -0
- opentrons/system/resin.py +24 -0
- opentrons/system/smoothie_update.py +15 -0
- opentrons/system/wifi.py +204 -0
- opentrons/tools/__init__.py +0 -0
- opentrons/tools/args_handler.py +22 -0
- opentrons/tools/write_pipette_memory.py +157 -0
- opentrons/types.py +618 -0
- opentrons/util/__init__.py +1 -0
- opentrons/util/async_helpers.py +166 -0
- opentrons/util/broker.py +84 -0
- opentrons/util/change_notifier.py +47 -0
- opentrons/util/entrypoint_util.py +278 -0
- opentrons/util/get_union_elements.py +26 -0
- opentrons/util/helpers.py +6 -0
- opentrons/util/linal.py +178 -0
- opentrons/util/logging_config.py +265 -0
- opentrons/util/logging_queue_handler.py +61 -0
- opentrons/util/performance_helpers.py +157 -0
- opentrons-8.6.0.dist-info/METADATA +37 -0
- opentrons-8.6.0.dist-info/RECORD +601 -0
- opentrons-8.6.0.dist-info/WHEEL +4 -0
- opentrons-8.6.0.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""Command models to retrieve a labware from a Flex Stacker."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import Optional, Literal, TYPE_CHECKING, Type, Union, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
9
|
+
from opentrons_shared_data.labware.labware_definition import LabwareDefinition
|
|
10
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
11
|
+
FlexStackerStallError,
|
|
12
|
+
FlexStackerShuttleMissingError,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from ..command import (
|
|
16
|
+
AbstractCommandImpl,
|
|
17
|
+
BaseCommand,
|
|
18
|
+
BaseCommandCreate,
|
|
19
|
+
SuccessData,
|
|
20
|
+
DefinedErrorData,
|
|
21
|
+
)
|
|
22
|
+
from ..flex_stacker.common import (
|
|
23
|
+
FlexStackerStallOrCollisionError,
|
|
24
|
+
FlexStackerShuttleError,
|
|
25
|
+
labware_locations_for_group,
|
|
26
|
+
labware_location_base_sequence,
|
|
27
|
+
primary_location_sequence,
|
|
28
|
+
adapter_location_sequence,
|
|
29
|
+
lid_location_sequence,
|
|
30
|
+
)
|
|
31
|
+
from ...errors import (
|
|
32
|
+
ErrorOccurrence,
|
|
33
|
+
CannotPerformModuleAction,
|
|
34
|
+
LabwareNotLoadedOnModuleError,
|
|
35
|
+
FlexStackerLabwarePoolNotYetDefinedError,
|
|
36
|
+
)
|
|
37
|
+
from ...resources import ModelUtils
|
|
38
|
+
from ...state import update_types
|
|
39
|
+
from ...types import (
|
|
40
|
+
LabwareLocationSequence,
|
|
41
|
+
InStackerHopperLocation,
|
|
42
|
+
StackerStoredLabwareGroup,
|
|
43
|
+
ModuleLocation,
|
|
44
|
+
StackerLabwareMovementStrategy,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from opentrons.protocol_engine.state.state import StateView
|
|
49
|
+
from opentrons.protocol_engine.state.module_substates import FlexStackerSubState
|
|
50
|
+
from opentrons.protocol_engine.execution import EquipmentHandler
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
StoreCommandType = Literal["flexStacker/store"]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class StoreParams(BaseModel):
|
|
57
|
+
"""Input parameters for a labware storage command."""
|
|
58
|
+
|
|
59
|
+
moduleId: str = Field(
|
|
60
|
+
...,
|
|
61
|
+
description="Unique ID of the flex stacker.",
|
|
62
|
+
)
|
|
63
|
+
strategy: StackerLabwareMovementStrategy = Field(
|
|
64
|
+
...,
|
|
65
|
+
description=(
|
|
66
|
+
"If manual, indicates that labware has been moved to the hopper "
|
|
67
|
+
"manually by the user, as required in error recovery."
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class StoreResult(BaseModel):
|
|
73
|
+
"""Result data from a labware storage command."""
|
|
74
|
+
|
|
75
|
+
eventualDestinationLocationSequence: (
|
|
76
|
+
LabwareLocationSequence | SkipJsonSchema[None]
|
|
77
|
+
) = Field(
|
|
78
|
+
None,
|
|
79
|
+
description=(
|
|
80
|
+
"The full location in which all labware moved by this command will eventually reside."
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
primaryOriginLocationSequence: LabwareLocationSequence | SkipJsonSchema[
|
|
84
|
+
None
|
|
85
|
+
] = Field(None, description=("The origin location of the primary labware."))
|
|
86
|
+
primaryLabwareId: str | SkipJsonSchema[None] = Field(
|
|
87
|
+
None, description="The primary labware in the stack that was stored."
|
|
88
|
+
)
|
|
89
|
+
adapterOriginLocationSequence: LabwareLocationSequence | SkipJsonSchema[
|
|
90
|
+
None
|
|
91
|
+
] = Field(None, description=("The origin location of the adapter labware, if any."))
|
|
92
|
+
adapterLabwareId: str | SkipJsonSchema[None] = Field(
|
|
93
|
+
None, description="The adapter in the stack that was stored, if any."
|
|
94
|
+
)
|
|
95
|
+
lidOriginLocationSequence: LabwareLocationSequence | SkipJsonSchema[None] = Field(
|
|
96
|
+
None, description=("The origin location of the lid labware, if any.")
|
|
97
|
+
)
|
|
98
|
+
lidLabwareId: str | SkipJsonSchema[None] = Field(
|
|
99
|
+
None, description="The lid in the stack that was stored, if any."
|
|
100
|
+
)
|
|
101
|
+
primaryLabwareURI: str = Field(
|
|
102
|
+
...,
|
|
103
|
+
description="The labware definition URI of the primary labware.",
|
|
104
|
+
)
|
|
105
|
+
adapterLabwareURI: str | SkipJsonSchema[None] = Field(
|
|
106
|
+
None,
|
|
107
|
+
description="The labware definition URI of the adapter labware.",
|
|
108
|
+
)
|
|
109
|
+
lidLabwareURI: str | SkipJsonSchema[None] = Field(
|
|
110
|
+
None,
|
|
111
|
+
description="The labware definition URI of the lid labware.",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
_ExecuteReturn = Union[
|
|
116
|
+
SuccessData[StoreResult],
|
|
117
|
+
DefinedErrorData[FlexStackerStallOrCollisionError]
|
|
118
|
+
| DefinedErrorData[FlexStackerShuttleError],
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class StoreImpl(AbstractCommandImpl[StoreParams, _ExecuteReturn]):
|
|
123
|
+
"""Implementation of a labware storage command."""
|
|
124
|
+
|
|
125
|
+
def __init__(
|
|
126
|
+
self,
|
|
127
|
+
state_view: StateView,
|
|
128
|
+
equipment: EquipmentHandler,
|
|
129
|
+
model_utils: ModelUtils,
|
|
130
|
+
**kwargs: object,
|
|
131
|
+
) -> None:
|
|
132
|
+
self._state_view = state_view
|
|
133
|
+
self._equipment = equipment
|
|
134
|
+
self._model_utils = model_utils
|
|
135
|
+
|
|
136
|
+
def _verify_labware_to_store(
|
|
137
|
+
self, params: StoreParams, stacker_state: FlexStackerSubState
|
|
138
|
+
) -> tuple[str, str | None, str | None]:
|
|
139
|
+
location = self._state_view.modules.get_location(params.moduleId)
|
|
140
|
+
try:
|
|
141
|
+
bottom_id = self._state_view.labware.get_id_by_module(params.moduleId)
|
|
142
|
+
except LabwareNotLoadedOnModuleError:
|
|
143
|
+
raise CannotPerformModuleAction(
|
|
144
|
+
f"Flex Stacker in {location} cannot store labware because its carriage is empty"
|
|
145
|
+
)
|
|
146
|
+
labware_ids = self._state_view.labware.get_labware_stack_from_parent(bottom_id)
|
|
147
|
+
labware_defs = [
|
|
148
|
+
self._state_view.labware.get_definition(id) for id in labware_ids
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
lid_id: str | None = None
|
|
152
|
+
|
|
153
|
+
pool_list = stacker_state.get_pool_definition_ordered_list()
|
|
154
|
+
assert pool_list is not None
|
|
155
|
+
if len(labware_ids) != len(pool_list):
|
|
156
|
+
raise CannotPerformModuleAction(
|
|
157
|
+
f"Cannot store labware stack that does not correspond with the configuration of Flex Stacker in {location}"
|
|
158
|
+
)
|
|
159
|
+
if stacker_state.pool_lid_definition is not None:
|
|
160
|
+
if labware_defs[-1] != stacker_state.pool_lid_definition:
|
|
161
|
+
raise CannotPerformModuleAction(
|
|
162
|
+
f"Cannot store labware stack that does not correspond with the configuration of Flex Stacker in {location}"
|
|
163
|
+
)
|
|
164
|
+
lid_id = labware_ids[-1]
|
|
165
|
+
|
|
166
|
+
if stacker_state.pool_adapter_definition is not None:
|
|
167
|
+
if (
|
|
168
|
+
labware_defs[0] != stacker_state.pool_adapter_definition
|
|
169
|
+
or labware_defs[1] != stacker_state.pool_primary_definition
|
|
170
|
+
):
|
|
171
|
+
raise CannotPerformModuleAction(
|
|
172
|
+
f"Cannot store labware stack that does not correspond with the configuration of Flex Stacker in {location}"
|
|
173
|
+
)
|
|
174
|
+
else:
|
|
175
|
+
return labware_ids[1], labware_ids[0], lid_id
|
|
176
|
+
else:
|
|
177
|
+
if labware_defs[0] != stacker_state.pool_primary_definition:
|
|
178
|
+
raise CannotPerformModuleAction(
|
|
179
|
+
f"Cannot store labware stack that does not correspond with the configuration of Flex Stacker in {location}"
|
|
180
|
+
)
|
|
181
|
+
return labware_ids[0], None, lid_id
|
|
182
|
+
|
|
183
|
+
async def execute(self, params: StoreParams) -> _ExecuteReturn:
|
|
184
|
+
"""Execute the labware storage command."""
|
|
185
|
+
stacker_state = self._state_view.modules.get_flex_stacker_substate(
|
|
186
|
+
params.moduleId
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
location = self._state_view.modules.get_location(params.moduleId)
|
|
190
|
+
pool_definitions = stacker_state.get_pool_definition_ordered_list()
|
|
191
|
+
if pool_definitions is None:
|
|
192
|
+
raise FlexStackerLabwarePoolNotYetDefinedError(
|
|
193
|
+
message=f"The Flex Stacker in {location} has not been configured yet and cannot be filled."
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
len(stacker_state.contained_labware_bottom_first)
|
|
198
|
+
== stacker_state.max_pool_count
|
|
199
|
+
):
|
|
200
|
+
raise CannotPerformModuleAction(
|
|
201
|
+
f"Cannot store labware in Flex Stacker in {location} because it is full"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
primary_id, maybe_adapter_id, maybe_lid_id = self._verify_labware_to_store(
|
|
205
|
+
params, stacker_state
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# Allow propagation of ModuleNotAttachedError.
|
|
209
|
+
stacker_hw = self._equipment.get_module_hardware_api(stacker_state.module_id)
|
|
210
|
+
|
|
211
|
+
state_update = update_types.StateUpdate()
|
|
212
|
+
if stacker_hw is not None:
|
|
213
|
+
stacker_hw.set_stacker_identify(True)
|
|
214
|
+
|
|
215
|
+
if (
|
|
216
|
+
params.strategy is StackerLabwareMovementStrategy.AUTOMATIC
|
|
217
|
+
and stacker_hw is not None
|
|
218
|
+
):
|
|
219
|
+
try:
|
|
220
|
+
await stacker_hw.store_labware(
|
|
221
|
+
labware_height=stacker_state.get_pool_height_minus_overlap()
|
|
222
|
+
)
|
|
223
|
+
except FlexStackerStallError as e:
|
|
224
|
+
return DefinedErrorData(
|
|
225
|
+
public=FlexStackerStallOrCollisionError(
|
|
226
|
+
id=self._model_utils.generate_id(),
|
|
227
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
228
|
+
wrappedErrors=[
|
|
229
|
+
ErrorOccurrence.from_failed(
|
|
230
|
+
id=self._model_utils.generate_id(),
|
|
231
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
232
|
+
error=e,
|
|
233
|
+
)
|
|
234
|
+
],
|
|
235
|
+
errorInfo={"labwareId": primary_id},
|
|
236
|
+
),
|
|
237
|
+
)
|
|
238
|
+
except FlexStackerShuttleMissingError as e:
|
|
239
|
+
return DefinedErrorData(
|
|
240
|
+
public=FlexStackerShuttleError(
|
|
241
|
+
id=self._model_utils.generate_id(),
|
|
242
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
243
|
+
wrappedErrors=[
|
|
244
|
+
ErrorOccurrence.from_failed(
|
|
245
|
+
id=self._model_utils.generate_id(),
|
|
246
|
+
createdAt=self._model_utils.get_timestamp(),
|
|
247
|
+
error=e,
|
|
248
|
+
)
|
|
249
|
+
],
|
|
250
|
+
errorInfo={"labwareId": primary_id},
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
id_list = [
|
|
255
|
+
id for id in (primary_id, maybe_adapter_id, maybe_lid_id) if id is not None
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
group = StackerStoredLabwareGroup(
|
|
259
|
+
primaryLabwareId=primary_id,
|
|
260
|
+
adapterLabwareId=maybe_adapter_id,
|
|
261
|
+
lidLabwareId=maybe_lid_id,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
state_update.set_batch_labware_location(
|
|
265
|
+
new_locations_by_id={
|
|
266
|
+
id: InStackerHopperLocation(moduleId=params.moduleId) for id in id_list
|
|
267
|
+
},
|
|
268
|
+
new_offset_ids_by_id={id: None for id in id_list},
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
state_update.update_flex_stacker_contained_labware(
|
|
272
|
+
module_id=params.moduleId,
|
|
273
|
+
contained_labware_bottom_first=(
|
|
274
|
+
[group] + stacker_state.contained_labware_bottom_first
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
original_location_sequences = labware_locations_for_group(
|
|
279
|
+
group,
|
|
280
|
+
labware_location_base_sequence(
|
|
281
|
+
group,
|
|
282
|
+
self._state_view,
|
|
283
|
+
self._state_view.geometry.get_predicted_location_sequence(
|
|
284
|
+
ModuleLocation(moduleId=params.moduleId)
|
|
285
|
+
),
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
if stacker_hw is not None:
|
|
290
|
+
stacker_hw.set_stacker_identify(False)
|
|
291
|
+
|
|
292
|
+
return SuccessData(
|
|
293
|
+
public=StoreResult.model_construct(
|
|
294
|
+
eventualDestinationLocationSequence=[
|
|
295
|
+
InStackerHopperLocation(moduleId=params.moduleId)
|
|
296
|
+
],
|
|
297
|
+
primaryOriginLocationSequence=primary_location_sequence(
|
|
298
|
+
original_location_sequences
|
|
299
|
+
),
|
|
300
|
+
primaryLabwareId=primary_id,
|
|
301
|
+
adapterOriginLocationSequence=adapter_location_sequence(
|
|
302
|
+
original_location_sequences
|
|
303
|
+
),
|
|
304
|
+
adapterLabwareId=maybe_adapter_id,
|
|
305
|
+
lidOriginLocationSequence=lid_location_sequence(
|
|
306
|
+
original_location_sequences
|
|
307
|
+
),
|
|
308
|
+
lidLabwareId=maybe_lid_id,
|
|
309
|
+
primaryLabwareURI=self._state_view.labware.get_uri_from_definition_unless_none(
|
|
310
|
+
cast(LabwareDefinition, stacker_state.pool_primary_definition)
|
|
311
|
+
),
|
|
312
|
+
adapterLabwareURI=self._state_view.labware.get_uri_from_definition_unless_none(
|
|
313
|
+
stacker_state.pool_adapter_definition
|
|
314
|
+
),
|
|
315
|
+
lidLabwareURI=self._state_view.labware.get_uri_from_definition_unless_none(
|
|
316
|
+
stacker_state.pool_lid_definition
|
|
317
|
+
),
|
|
318
|
+
),
|
|
319
|
+
state_update=state_update,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
class Store(BaseCommand[StoreParams, StoreResult, ErrorOccurrence]):
|
|
324
|
+
"""A command to store a labware in a Flex Stacker."""
|
|
325
|
+
|
|
326
|
+
commandType: StoreCommandType = "flexStacker/store"
|
|
327
|
+
params: StoreParams
|
|
328
|
+
result: Optional[StoreResult] = None
|
|
329
|
+
|
|
330
|
+
_ImplementationCls: Type[StoreImpl] = StoreImpl
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class StoreCreate(BaseCommandCreate[StoreParams]):
|
|
334
|
+
"""A request to execute a Flex Stacker store command."""
|
|
335
|
+
|
|
336
|
+
commandType: StoreCommandType = "flexStacker/store"
|
|
337
|
+
params: StoreParams
|
|
338
|
+
|
|
339
|
+
_CommandCls: Type[Store] = Store
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Generate a JSON schema against which all create commands statically validate."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from opentrons.protocol_engine.commands.command_unions import CommandCreateAdapter
|
|
7
|
+
|
|
8
|
+
from opentrons_shared_data.command import get_newest_schema_version
|
|
9
|
+
from opentrons_shared_data.load import get_shared_data_root
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def generate_command_schema(version: str) -> str:
|
|
13
|
+
"""Generate a JSON Schema that all valid create commands can validate against."""
|
|
14
|
+
schema_as_dict = CommandCreateAdapter.json_schema(mode="validation", by_alias=False)
|
|
15
|
+
schema_as_dict["$id"] = f"opentronsCommandSchemaV{version}"
|
|
16
|
+
schema_as_dict["$schema"] = "http://json-schema.org/draft-07/schema#"
|
|
17
|
+
return json.dumps(schema_as_dict, indent=2, sort_keys=True)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def write_command_schema(json_string: str, version: str) -> None:
|
|
21
|
+
"""Write a JSON command schema to the shared-data command schema directory."""
|
|
22
|
+
path = get_shared_data_root() / "command" / "schemas" / f"{version}.json"
|
|
23
|
+
with open(path, "w") as schema_file:
|
|
24
|
+
schema_file.write(json_string)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
parser = argparse.ArgumentParser(
|
|
29
|
+
prog="generate_command_schema",
|
|
30
|
+
description="Generate A JSON-schema of all possible Create-Commands accepted by the current Protocol Engine",
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"version",
|
|
34
|
+
type=str,
|
|
35
|
+
nargs="?",
|
|
36
|
+
help="The command schema version. This is a single integer (e.g. 7) that will be used to name the generated"
|
|
37
|
+
" schema file. If not included, it will automatically use the latest version in shared-data.",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--overwrite-shared-data",
|
|
41
|
+
action="store_true",
|
|
42
|
+
help="If used, overwrites the specified or automatically chosen command schema version in shared-data."
|
|
43
|
+
" If not included, the generated schema will be printed to stdout.",
|
|
44
|
+
)
|
|
45
|
+
args = parser.parse_args()
|
|
46
|
+
|
|
47
|
+
if args.version is None:
|
|
48
|
+
version_string = get_newest_schema_version()
|
|
49
|
+
else:
|
|
50
|
+
version_string = args.version
|
|
51
|
+
|
|
52
|
+
command_schema = generate_command_schema(version_string)
|
|
53
|
+
|
|
54
|
+
if args.overwrite_shared_data:
|
|
55
|
+
write_command_schema(command_schema, version_string)
|
|
56
|
+
else:
|
|
57
|
+
print(command_schema)
|
|
58
|
+
|
|
59
|
+
sys.exit()
|
|
60
|
+
|
|
61
|
+
__all__ = ["generate_command_schema"]
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Get next tip command request, result, and implementation models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Optional, Type, List, Literal, Union
|
|
6
|
+
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
9
|
+
from opentrons.types import NozzleConfigurationType
|
|
10
|
+
|
|
11
|
+
from ..errors import ErrorOccurrence
|
|
12
|
+
from ..types import NextTipInfo, NoTipAvailable, NoTipReason
|
|
13
|
+
from .pipetting_common import PipetteIdMixin
|
|
14
|
+
|
|
15
|
+
from .command import (
|
|
16
|
+
AbstractCommandImpl,
|
|
17
|
+
BaseCommand,
|
|
18
|
+
BaseCommandCreate,
|
|
19
|
+
SuccessData,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from ..state.state import StateView
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
27
|
+
s.pop("default", None)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
GetNextTipCommandType = Literal["getNextTip"]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class GetNextTipParams(PipetteIdMixin):
|
|
34
|
+
"""Payload needed to resolve the next available tip."""
|
|
35
|
+
|
|
36
|
+
labwareIds: List[str] = Field(
|
|
37
|
+
...,
|
|
38
|
+
description="Labware ID(s) of tip racks to resolve next available tip(s) from"
|
|
39
|
+
" Labware IDs will be resolved sequentially",
|
|
40
|
+
)
|
|
41
|
+
startingTipWell: str | SkipJsonSchema[None] = Field(
|
|
42
|
+
None,
|
|
43
|
+
description="Name of starting tip rack 'well'."
|
|
44
|
+
" This only applies to the first tip rack in the list provided in labwareIDs",
|
|
45
|
+
json_schema_extra=_remove_default,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GetNextTipResult(BaseModel):
|
|
50
|
+
"""Result data from the execution of a GetNextTip."""
|
|
51
|
+
|
|
52
|
+
nextTipInfo: Union[NextTipInfo, NoTipAvailable] = Field(
|
|
53
|
+
...,
|
|
54
|
+
description="Labware ID and well name of next available tip for a pipette,"
|
|
55
|
+
" or information why no tip could be resolved.",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class GetNextTipImplementation(
|
|
60
|
+
AbstractCommandImpl[GetNextTipParams, SuccessData[GetNextTipResult]]
|
|
61
|
+
):
|
|
62
|
+
"""Get next tip command implementation."""
|
|
63
|
+
|
|
64
|
+
def __init__(
|
|
65
|
+
self,
|
|
66
|
+
state_view: StateView,
|
|
67
|
+
**kwargs: object,
|
|
68
|
+
) -> None:
|
|
69
|
+
self._state_view = state_view
|
|
70
|
+
|
|
71
|
+
async def execute(self, params: GetNextTipParams) -> SuccessData[GetNextTipResult]:
|
|
72
|
+
"""Get the next available tip for the requested pipette."""
|
|
73
|
+
pipette_id = params.pipetteId
|
|
74
|
+
starting_tip_name = params.startingTipWell
|
|
75
|
+
|
|
76
|
+
num_tips = self._state_view.pipettes.get_active_channels(pipette_id)
|
|
77
|
+
nozzle_map = self._state_view.pipettes.get_nozzle_configuration(pipette_id)
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
starting_tip_name is not None
|
|
81
|
+
and nozzle_map.configuration != NozzleConfigurationType.FULL
|
|
82
|
+
):
|
|
83
|
+
# This is to match the behavior found in PAPI, but also because we don't have logic to automatically find
|
|
84
|
+
# the next tip with partial configuration and a starting tip. This will never work for a 96-channel due to
|
|
85
|
+
# x-axis overlap, but could eventually work with 8-channel if we better define starting tip USED or CLEAN
|
|
86
|
+
# state when starting a protocol to prevent accidental tip pick-up with starting non-full tip racks.
|
|
87
|
+
return SuccessData(
|
|
88
|
+
public=GetNextTipResult(
|
|
89
|
+
nextTipInfo=NoTipAvailable(
|
|
90
|
+
noTipReason=NoTipReason.STARTING_TIP_WITH_PARTIAL,
|
|
91
|
+
message="Cannot automatically resolve next tip with starting tip and partial tip configuration.",
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
next_tip: Union[NextTipInfo, NoTipAvailable]
|
|
97
|
+
for labware_id in params.labwareIds:
|
|
98
|
+
well_name = self._state_view.tips.get_next_tip(
|
|
99
|
+
labware_id=labware_id,
|
|
100
|
+
num_tips=num_tips,
|
|
101
|
+
starting_tip_name=starting_tip_name,
|
|
102
|
+
nozzle_map=nozzle_map,
|
|
103
|
+
)
|
|
104
|
+
if well_name is not None:
|
|
105
|
+
next_tip = NextTipInfo(labwareId=labware_id, tipStartingWell=well_name)
|
|
106
|
+
break
|
|
107
|
+
# After the first tip rack is exhausted, starting tip no longer applies
|
|
108
|
+
starting_tip_name = None
|
|
109
|
+
else:
|
|
110
|
+
next_tip = NoTipAvailable(
|
|
111
|
+
noTipReason=NoTipReason.NO_AVAILABLE_TIPS,
|
|
112
|
+
message="No available tips for given pipette, nozzle configuration and provided tip racks.",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
return SuccessData(public=GetNextTipResult(nextTipInfo=next_tip))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class GetNextTip(BaseCommand[GetNextTipParams, GetNextTipResult, ErrorOccurrence]):
|
|
119
|
+
"""Get next tip command model."""
|
|
120
|
+
|
|
121
|
+
commandType: GetNextTipCommandType = "getNextTip"
|
|
122
|
+
params: GetNextTipParams
|
|
123
|
+
result: Optional[GetNextTipResult] = None
|
|
124
|
+
|
|
125
|
+
_ImplementationCls: Type[GetNextTipImplementation] = GetNextTipImplementation
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class GetNextTipCreate(BaseCommandCreate[GetNextTipParams]):
|
|
129
|
+
"""Get next tip command creation request model."""
|
|
130
|
+
|
|
131
|
+
commandType: GetNextTipCommandType = "getNextTip"
|
|
132
|
+
params: GetNextTipParams
|
|
133
|
+
|
|
134
|
+
_CommandCls: Type[GetNextTip] = GetNextTip
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Get tip presence command request, result and implementation models."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pydantic import Field, BaseModel
|
|
5
|
+
from typing import TYPE_CHECKING, Optional, Type
|
|
6
|
+
from typing_extensions import Literal
|
|
7
|
+
|
|
8
|
+
from .pipetting_common import PipetteIdMixin
|
|
9
|
+
from .command import AbstractCommandImpl, BaseCommand, BaseCommandCreate, SuccessData
|
|
10
|
+
from ..errors.error_occurrence import ErrorOccurrence
|
|
11
|
+
|
|
12
|
+
from ..types import TipPresenceStatus
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ..execution import TipHandler
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
GetTipPresenceCommandType = Literal["getTipPresence"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class GetTipPresenceParams(PipetteIdMixin):
|
|
22
|
+
"""Payload required for a GetTipPresence command."""
|
|
23
|
+
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GetTipPresenceResult(BaseModel):
|
|
28
|
+
"""Result data from the execution of a GetTipPresence command."""
|
|
29
|
+
|
|
30
|
+
status: TipPresenceStatus = Field(
|
|
31
|
+
...,
|
|
32
|
+
description=(
|
|
33
|
+
"Whether or not a tip is attached on the pipette. This only works on"
|
|
34
|
+
" on FLEX because OT-2 pipettes do not possess tip presence sensors,"
|
|
35
|
+
" hence, will always return TipPresenceStatus.UNKNOWN."
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GetTipPresenceImplementation(
|
|
41
|
+
AbstractCommandImpl[GetTipPresenceParams, SuccessData[GetTipPresenceResult]]
|
|
42
|
+
):
|
|
43
|
+
"""GetTipPresence command implementation."""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
tip_handler: TipHandler,
|
|
48
|
+
**kwargs: object,
|
|
49
|
+
) -> None:
|
|
50
|
+
self._tip_handler = tip_handler
|
|
51
|
+
|
|
52
|
+
async def execute(
|
|
53
|
+
self, params: GetTipPresenceParams
|
|
54
|
+
) -> SuccessData[GetTipPresenceResult]:
|
|
55
|
+
"""Verify if tip presence is as expected for the requested pipette."""
|
|
56
|
+
pipette_id = params.pipetteId
|
|
57
|
+
|
|
58
|
+
result = await self._tip_handler.get_tip_presence(
|
|
59
|
+
pipette_id=pipette_id,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return SuccessData(
|
|
63
|
+
public=GetTipPresenceResult(status=result),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class GetTipPresence(
|
|
68
|
+
BaseCommand[GetTipPresenceParams, GetTipPresenceResult, ErrorOccurrence]
|
|
69
|
+
):
|
|
70
|
+
"""GetTipPresence command model."""
|
|
71
|
+
|
|
72
|
+
commandType: GetTipPresenceCommandType = "getTipPresence"
|
|
73
|
+
params: GetTipPresenceParams
|
|
74
|
+
result: Optional[GetTipPresenceResult] = None
|
|
75
|
+
|
|
76
|
+
_ImplementationCls: Type[
|
|
77
|
+
GetTipPresenceImplementation
|
|
78
|
+
] = GetTipPresenceImplementation
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class GetTipPresenceCreate(BaseCommandCreate[GetTipPresenceParams]):
|
|
82
|
+
"""GetTipPresence command creation request model."""
|
|
83
|
+
|
|
84
|
+
commandType: GetTipPresenceCommandType = "getTipPresence"
|
|
85
|
+
params: GetTipPresenceParams
|
|
86
|
+
|
|
87
|
+
_CommandCls: Type[GetTipPresence] = GetTipPresence
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Hash command params into idempotent keys to track commands from analysis to run."""
|
|
2
|
+
from hashlib import md5
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .command import CommandIntent
|
|
6
|
+
from .command_unions import CommandCreate
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# TODO(mm, 2023-04-28):
|
|
10
|
+
# This implementation will not notice that commands are different if they have different params
|
|
11
|
+
# but share the same commandType. We should also hash command params. (Jira RCORE-326.)
|
|
12
|
+
def hash_protocol_command_params(
|
|
13
|
+
create: CommandCreate, last_hash: Optional[str]
|
|
14
|
+
) -> Optional[str]:
|
|
15
|
+
"""Given a command create object, return a hash.
|
|
16
|
+
|
|
17
|
+
The hash is based on three things:
|
|
18
|
+
- The command parameters
|
|
19
|
+
- The latest hash (yo dawg I heard you like blockchains)
|
|
20
|
+
- Whether the command is a setup command or a protocol command;
|
|
21
|
+
setup commands are not hashed
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
create: The command create request.
|
|
25
|
+
last_hash: The last command hash, if it exists.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
The command hash, if the command is a protocol command.
|
|
29
|
+
`None` if the command is a setup command.
|
|
30
|
+
"""
|
|
31
|
+
if create.intent in [CommandIntent.SETUP, CommandIntent.FIXIT]:
|
|
32
|
+
return None
|
|
33
|
+
# We avoid Python's built-in hash() function because it's not stable across
|
|
34
|
+
# runs of the Python interpreter. (Jira RSS-215.)
|
|
35
|
+
last_contribution = b"" if last_hash is None else last_hash.encode("ascii")
|
|
36
|
+
this_contribution = md5(create.commandType.encode("ascii")).digest()
|
|
37
|
+
to_hash = last_contribution + this_contribution
|
|
38
|
+
return md5(to_hash).hexdigest()
|