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,297 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import logging
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, List, Optional, Tuple, Type
|
|
5
|
+
|
|
6
|
+
from opentrons import types
|
|
7
|
+
from opentrons.hardware_control.types import CriticalPoint
|
|
8
|
+
from opentrons.hardware_control.util import plan_arc
|
|
9
|
+
|
|
10
|
+
from opentrons.motion_planning import (
|
|
11
|
+
DEFAULT_GENERAL_ARC_Z_MARGIN,
|
|
12
|
+
DEFAULT_IN_LABWARE_ARC_Z_MARGIN,
|
|
13
|
+
MINIMUM_Z_MARGIN,
|
|
14
|
+
MoveType,
|
|
15
|
+
get_waypoints,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from opentrons.protocols.api_support.labware_like import LabwareLike
|
|
19
|
+
from opentrons.protocol_api.core.legacy.deck import Deck
|
|
20
|
+
from opentrons.protocol_api.core.legacy.module_geometry import ModuleGeometry
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
MODULE_LOG = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LabwareHeightError(Exception):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def max_many(*args: float) -> float:
|
|
31
|
+
return functools.reduce(max, args[1:], args[0])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
BAD_PAIRS = {
|
|
35
|
+
("1", "12"),
|
|
36
|
+
("12", "1"),
|
|
37
|
+
("4", "12"),
|
|
38
|
+
("12", "4"),
|
|
39
|
+
("4", "9"),
|
|
40
|
+
("9", "4"),
|
|
41
|
+
("4", "8"),
|
|
42
|
+
("8", "4"),
|
|
43
|
+
("1", "8"),
|
|
44
|
+
("8", "1"),
|
|
45
|
+
("4", "11"),
|
|
46
|
+
("11", "4"),
|
|
47
|
+
("1", "11"),
|
|
48
|
+
("11", "1"),
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def should_dodge_thermocycler(
|
|
53
|
+
deck: Deck, from_loc: types.Location, to_loc: types.Location
|
|
54
|
+
) -> bool:
|
|
55
|
+
"""
|
|
56
|
+
Decide if the requested path would cross the thermocycler, if
|
|
57
|
+
installed.
|
|
58
|
+
|
|
59
|
+
Returns True if we need to dodge, False otherwise
|
|
60
|
+
"""
|
|
61
|
+
if deck.thermocycler_present:
|
|
62
|
+
transit = (from_loc.labware.first_parent(), to_loc.labware.first_parent())
|
|
63
|
+
# mypy doesn't like this because transit could be none, but it's
|
|
64
|
+
# checked by value in BAD_PAIRS which has only strings
|
|
65
|
+
return transit in BAD_PAIRS
|
|
66
|
+
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class MoveConstraints:
|
|
72
|
+
instr_max_height: float
|
|
73
|
+
well_z_margin: float = DEFAULT_IN_LABWARE_ARC_Z_MARGIN
|
|
74
|
+
lw_z_margin: float = DEFAULT_GENERAL_ARC_Z_MARGIN
|
|
75
|
+
minimum_lw_z_margin: float = MINIMUM_Z_MARGIN
|
|
76
|
+
minimum_z_height: float = 0.0
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def build(cls: Type["MoveConstraints"], **kwargs: Any) -> "MoveConstraints":
|
|
80
|
+
return cls(**{k: v for k, v in kwargs.items() if v is not None})
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_move_type(
|
|
84
|
+
from_loc: types.Location,
|
|
85
|
+
to_loc: types.Location,
|
|
86
|
+
force_direct: bool = False,
|
|
87
|
+
) -> MoveType:
|
|
88
|
+
"""Given two Locations, return the type of move."""
|
|
89
|
+
move_type = MoveType.GENERAL_ARC
|
|
90
|
+
from_labware, from_well = from_loc.labware.get_parent_labware_and_well()
|
|
91
|
+
to_labware, to_well = to_loc.labware.get_parent_labware_and_well()
|
|
92
|
+
same_labware = to_labware is not None and to_labware == from_labware
|
|
93
|
+
same_well = to_well is not None and to_well == from_well
|
|
94
|
+
|
|
95
|
+
if same_labware:
|
|
96
|
+
move_type = MoveType.DIRECT if same_well else MoveType.IN_LABWARE_ARC
|
|
97
|
+
|
|
98
|
+
return move_type if not force_direct else MoveType.DIRECT
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def safe_height(
|
|
102
|
+
from_loc: types.Location,
|
|
103
|
+
to_loc: types.Location,
|
|
104
|
+
deck: Deck,
|
|
105
|
+
instr_max_height: float,
|
|
106
|
+
well_z_margin: Optional[float] = None,
|
|
107
|
+
lw_z_margin: Optional[float] = None,
|
|
108
|
+
minimum_lw_z_margin: Optional[float] = None,
|
|
109
|
+
minimum_z_height: Optional[float] = None,
|
|
110
|
+
) -> float:
|
|
111
|
+
"""
|
|
112
|
+
Derive the height required to clear the current deck setup along
|
|
113
|
+
with other constraints
|
|
114
|
+
:param from_loc: The last location.
|
|
115
|
+
:param to_loc: The location to move to.
|
|
116
|
+
:param deck: The :py:class:`Deck` instance describing the robot.
|
|
117
|
+
:param float instr_max_height: The highest z location this pipette can
|
|
118
|
+
achieve
|
|
119
|
+
:param float well_z_margin: How much extra Z margin to raise the cp by over
|
|
120
|
+
the bare minimum to clear wells within the same
|
|
121
|
+
labware. Default: 5mm
|
|
122
|
+
:param float lw_z_margin: How much extra Z margin to raise the cp by over
|
|
123
|
+
the bare minimum to clear different pieces of
|
|
124
|
+
labware.
|
|
125
|
+
:param minimum_z_height: When specified, this Z margin is able to raise
|
|
126
|
+
(but never lower) the mid-arc height.
|
|
127
|
+
"""
|
|
128
|
+
constraints = MoveConstraints.build(
|
|
129
|
+
instr_max_height=instr_max_height,
|
|
130
|
+
well_z_margin=well_z_margin,
|
|
131
|
+
lw_z_margin=lw_z_margin,
|
|
132
|
+
minimum_lw_z_margin=minimum_lw_z_margin,
|
|
133
|
+
minimum_z_height=minimum_z_height,
|
|
134
|
+
)
|
|
135
|
+
assert constraints.minimum_z_height >= 0.0
|
|
136
|
+
return _build_safe_height(from_loc, to_loc, deck, constraints)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _build_safe_height(
|
|
140
|
+
from_loc: types.Location,
|
|
141
|
+
to_loc: types.Location,
|
|
142
|
+
deck: Deck,
|
|
143
|
+
constraints: MoveConstraints,
|
|
144
|
+
) -> float:
|
|
145
|
+
to_point = to_loc.point
|
|
146
|
+
to_lw, to_well = to_loc.labware.get_parent_labware_and_well()
|
|
147
|
+
from_point = from_loc.point
|
|
148
|
+
from_lw, from_well = from_loc.labware.get_parent_labware_and_well()
|
|
149
|
+
|
|
150
|
+
if to_lw and from_lw and to_lw == from_lw:
|
|
151
|
+
# If we know the labwares we’re moving from and to, we can calculate
|
|
152
|
+
# a safe z based on their heights
|
|
153
|
+
if to_well:
|
|
154
|
+
to_safety = to_well.top().point.z + constraints.well_z_margin
|
|
155
|
+
else:
|
|
156
|
+
to_safety = to_lw.highest_z + constraints.well_z_margin
|
|
157
|
+
if from_well:
|
|
158
|
+
from_safety = from_well.top().point.z + constraints.well_z_margin
|
|
159
|
+
else:
|
|
160
|
+
from_safety = from_lw.highest_z + constraints.well_z_margin
|
|
161
|
+
# if we are already at the labware, we know the instr max height would
|
|
162
|
+
# be tall enough
|
|
163
|
+
if max(from_safety, to_safety) > constraints.instr_max_height:
|
|
164
|
+
to_safety = constraints.instr_max_height
|
|
165
|
+
from_safety = 0.0 # (ignore since it's in a max())
|
|
166
|
+
else:
|
|
167
|
+
# One of our labwares is invalid so we have to just go above
|
|
168
|
+
# deck.highest_z since we don’t know where we are
|
|
169
|
+
to_safety = deck.highest_z + constraints.lw_z_margin
|
|
170
|
+
|
|
171
|
+
if to_safety > constraints.instr_max_height:
|
|
172
|
+
if constraints.instr_max_height >= (
|
|
173
|
+
deck.highest_z + constraints.minimum_lw_z_margin
|
|
174
|
+
):
|
|
175
|
+
to_safety = constraints.instr_max_height
|
|
176
|
+
else:
|
|
177
|
+
tallest_lw = list(
|
|
178
|
+
filter(
|
|
179
|
+
lambda lw: lw.highest_z == deck.highest_z,
|
|
180
|
+
[lw for lw in deck.data.values() if lw],
|
|
181
|
+
)
|
|
182
|
+
)[0]
|
|
183
|
+
if isinstance(tallest_lw, ModuleGeometry) and tallest_lw.labware:
|
|
184
|
+
tallest_lw = tallest_lw.labware
|
|
185
|
+
raise LabwareHeightError(
|
|
186
|
+
f"The {tallest_lw} has a total height of {deck.highest_z}"
|
|
187
|
+
" mm, which is too tall for your current pipette "
|
|
188
|
+
"configurations. The longest pipette on your robot can "
|
|
189
|
+
f"only be raised to {constraints.instr_max_height} mm "
|
|
190
|
+
"above the deck. "
|
|
191
|
+
"This may be because the labware is incorrectly defined, "
|
|
192
|
+
"incorrectly calibrated, or physically too tall. This "
|
|
193
|
+
"could also be caused by the pipette and its tipracks "
|
|
194
|
+
"being mismatched. Please check your protocol, labware "
|
|
195
|
+
"definitions and calibrations."
|
|
196
|
+
)
|
|
197
|
+
from_safety = 0.0 # (ignore since it’s in a max())
|
|
198
|
+
|
|
199
|
+
return max_many(
|
|
200
|
+
to_point.z, from_point.z, to_safety, from_safety, constraints.minimum_z_height
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def plan_moves(
|
|
205
|
+
from_loc: types.Location,
|
|
206
|
+
to_loc: types.Location,
|
|
207
|
+
deck: Deck,
|
|
208
|
+
instr_max_height: float,
|
|
209
|
+
well_z_margin: Optional[float] = None,
|
|
210
|
+
lw_z_margin: Optional[float] = None,
|
|
211
|
+
force_direct: bool = False,
|
|
212
|
+
minimum_lw_z_margin: Optional[float] = None,
|
|
213
|
+
minimum_z_height: Optional[float] = None,
|
|
214
|
+
use_experimental_waypoint_planning: bool = False,
|
|
215
|
+
) -> List[Tuple[types.Point, Optional[CriticalPoint]]]:
|
|
216
|
+
"""Plan moves between one :py:class:`.Location` and another.
|
|
217
|
+
|
|
218
|
+
Each :py:class:`.Location` instance might or might not have a specific
|
|
219
|
+
kind of geometry attached. This function is intended to return series
|
|
220
|
+
of moves that contain the minimum safe retractions to avoid (known)
|
|
221
|
+
labware on the specified :py:class:`Deck`.
|
|
222
|
+
:param from_loc: The last location.
|
|
223
|
+
:param to_loc: The location to move to.
|
|
224
|
+
:param deck: The :py:class:`Deck` instance describing the robot.
|
|
225
|
+
:param force_direct: If True, ignore any Z margins force a direct move
|
|
226
|
+
:param use_experimental_waypoint_planning: If True, use waypoint logic
|
|
227
|
+
from opentrons.motion_planning
|
|
228
|
+
|
|
229
|
+
The other parameters are as :py:meth:`safe_height`.
|
|
230
|
+
|
|
231
|
+
:returns: A list of tuples of :py:class:`.Point` and critical point
|
|
232
|
+
overrides to move through.
|
|
233
|
+
"""
|
|
234
|
+
constraints = MoveConstraints.build(
|
|
235
|
+
instr_max_height=instr_max_height,
|
|
236
|
+
well_z_margin=well_z_margin,
|
|
237
|
+
lw_z_margin=lw_z_margin,
|
|
238
|
+
minimum_lw_z_margin=minimum_lw_z_margin,
|
|
239
|
+
minimum_z_height=minimum_z_height,
|
|
240
|
+
)
|
|
241
|
+
assert constraints.minimum_z_height >= 0.0
|
|
242
|
+
|
|
243
|
+
to_point = to_loc.point
|
|
244
|
+
to_lw, to_well = to_loc.labware.get_parent_labware_and_well()
|
|
245
|
+
from_point = from_loc.point
|
|
246
|
+
from_lw, from_well = from_loc.labware.get_parent_labware_and_well()
|
|
247
|
+
from_center = LabwareLike(from_lw).center_multichannel_on_wells()
|
|
248
|
+
to_center = LabwareLike(to_lw).center_multichannel_on_wells()
|
|
249
|
+
dest_cp_override = CriticalPoint.XY_CENTER if to_center else None
|
|
250
|
+
origin_cp_override = CriticalPoint.XY_CENTER if from_center else None
|
|
251
|
+
extra_waypoints = []
|
|
252
|
+
|
|
253
|
+
if should_dodge_thermocycler(deck, from_loc, to_loc):
|
|
254
|
+
sc = deck.get_slot_center("5")
|
|
255
|
+
extra_waypoints = [(sc.x, sc.y)]
|
|
256
|
+
|
|
257
|
+
if use_experimental_waypoint_planning:
|
|
258
|
+
move_type = get_move_type(from_loc, to_loc, force_direct)
|
|
259
|
+
min_travel_z = deck.highest_z
|
|
260
|
+
|
|
261
|
+
if to_lw is not None and move_type == MoveType.IN_LABWARE_ARC:
|
|
262
|
+
min_travel_z = to_lw.highest_z
|
|
263
|
+
|
|
264
|
+
# TODO(mc, 2020-11-05): if this ever needs to be used, we need a
|
|
265
|
+
# story to re-create error messaging from LabwareHeightError above if
|
|
266
|
+
# this raises a MotionPlanningError
|
|
267
|
+
waypoints = get_waypoints(
|
|
268
|
+
origin=from_point,
|
|
269
|
+
dest=to_point,
|
|
270
|
+
min_travel_z=min_travel_z,
|
|
271
|
+
max_travel_z=instr_max_height,
|
|
272
|
+
move_type=move_type,
|
|
273
|
+
xy_waypoints=extra_waypoints,
|
|
274
|
+
origin_cp=origin_cp_override,
|
|
275
|
+
dest_cp=dest_cp_override,
|
|
276
|
+
)
|
|
277
|
+
return [(wp.position, wp.critical_point) for wp in waypoints]
|
|
278
|
+
|
|
279
|
+
is_same_location = (to_lw and to_lw == from_lw) and (
|
|
280
|
+
to_well and to_well == from_well
|
|
281
|
+
)
|
|
282
|
+
if force_direct or (is_same_location and not (minimum_z_height or 0) > 0):
|
|
283
|
+
# If we’re going direct, we can assume we’re already in the correct
|
|
284
|
+
# cp so we can use the override without prep
|
|
285
|
+
return [(to_point, dest_cp_override)]
|
|
286
|
+
|
|
287
|
+
# Find the safe z heights based on the destination and origin labware/well
|
|
288
|
+
safe = _build_safe_height(from_loc, to_loc, deck, constraints)
|
|
289
|
+
|
|
290
|
+
return plan_arc(
|
|
291
|
+
from_point,
|
|
292
|
+
to_point,
|
|
293
|
+
safe,
|
|
294
|
+
origin_cp_override,
|
|
295
|
+
dest_cp_override,
|
|
296
|
+
extra_waypoints,
|
|
297
|
+
)
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Mapping, Optional, Union, List, Sequence, Literal
|
|
8
|
+
|
|
9
|
+
import jsonschema # type: ignore
|
|
10
|
+
|
|
11
|
+
from opentrons_shared_data import load_shared_data, get_shared_data_root
|
|
12
|
+
from opentrons.protocols.api_support.util import ModifiedList
|
|
13
|
+
from opentrons.protocols.api_support.constants import (
|
|
14
|
+
OPENTRONS_NAMESPACE,
|
|
15
|
+
CUSTOM_NAMESPACE,
|
|
16
|
+
STANDARD_DEFS_PATH,
|
|
17
|
+
USER_DEFS_PATH,
|
|
18
|
+
)
|
|
19
|
+
from opentrons_shared_data.labware.types import LabwareDefinition
|
|
20
|
+
from opentrons_shared_data.errors.exceptions import InvalidProtocolData
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
MODULE_LOG = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
LabwareProblem = Literal[
|
|
26
|
+
"no-schema-id", "bad-schema-id", "schema-mismatch", "invalid-json"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NotALabwareError(InvalidProtocolData):
|
|
31
|
+
def __init__(
|
|
32
|
+
self, problem: LabwareProblem, wrapping: Sequence[BaseException]
|
|
33
|
+
) -> None:
|
|
34
|
+
messages: dict[LabwareProblem, str] = {
|
|
35
|
+
"no-schema-id": "No schema ID present in file",
|
|
36
|
+
"bad-schema-id": "Bad schema ID in file",
|
|
37
|
+
"invalid-json": "File does not contain valid JSON",
|
|
38
|
+
"schema-mismatch": "File does not match labware schema",
|
|
39
|
+
}
|
|
40
|
+
super().__init__(
|
|
41
|
+
message=messages[problem], detail={"kind": problem}, wrapping=wrapping
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_labware_definition(
|
|
46
|
+
load_name: str,
|
|
47
|
+
namespace: Optional[str] = None,
|
|
48
|
+
version: Optional[int] = None,
|
|
49
|
+
bundled_defs: Optional[Mapping[str, LabwareDefinition]] = None,
|
|
50
|
+
extra_defs: Optional[Mapping[str, LabwareDefinition]] = None,
|
|
51
|
+
) -> LabwareDefinition:
|
|
52
|
+
"""
|
|
53
|
+
Look up and return a definition by load_name + namespace + version and
|
|
54
|
+
return it or raise an exception
|
|
55
|
+
|
|
56
|
+
:param str load_name: corresponds to 'loadName' key in definition
|
|
57
|
+
:param str namespace: The namespace the labware definition belongs to.
|
|
58
|
+
If unspecified, will search 'opentrons' then 'custom_beta'
|
|
59
|
+
:param int version: The version of the labware definition. If unspecified,
|
|
60
|
+
will use version 1.
|
|
61
|
+
:param bundled_defs: A bundle of labware definitions to exclusively use for
|
|
62
|
+
finding labware definitions, if specified
|
|
63
|
+
:param extra_defs: An extra set of definitions (in addition to the system
|
|
64
|
+
definitions) in which to search
|
|
65
|
+
"""
|
|
66
|
+
load_name = load_name.lower()
|
|
67
|
+
|
|
68
|
+
if bundled_defs is not None:
|
|
69
|
+
return _get_labware_definition_from_bundle(
|
|
70
|
+
bundled_defs, load_name, namespace, version
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
checked_extras = extra_defs or {}
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
return _get_labware_definition_from_bundle(
|
|
77
|
+
checked_extras, load_name, namespace, version
|
|
78
|
+
)
|
|
79
|
+
except (FileNotFoundError, RuntimeError):
|
|
80
|
+
pass
|
|
81
|
+
|
|
82
|
+
return _get_standard_labware_definition(load_name, namespace, version)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_all_labware_definitions(schema_version: str = "2") -> List[str]:
|
|
86
|
+
"""
|
|
87
|
+
Return a list of standard and custom labware definitions with load_name +
|
|
88
|
+
name_space + version existing on the robot
|
|
89
|
+
"""
|
|
90
|
+
labware_list = ModifiedList()
|
|
91
|
+
|
|
92
|
+
def _check_for_subdirectories(path: Union[str, Path, os.DirEntry[str]]) -> None:
|
|
93
|
+
with os.scandir(path) as top_path:
|
|
94
|
+
for sub_dir in top_path:
|
|
95
|
+
if sub_dir.is_dir():
|
|
96
|
+
labware_list.append(sub_dir.name)
|
|
97
|
+
|
|
98
|
+
# check for standard labware
|
|
99
|
+
_check_for_subdirectories(
|
|
100
|
+
get_shared_data_root() / STANDARD_DEFS_PATH / schema_version
|
|
101
|
+
)
|
|
102
|
+
# check for custom labware
|
|
103
|
+
for namespace in os.scandir(USER_DEFS_PATH):
|
|
104
|
+
_check_for_subdirectories(namespace)
|
|
105
|
+
return labware_list
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def save_definition(
|
|
109
|
+
labware_def: LabwareDefinition, force: bool = False, location: Optional[Path] = None
|
|
110
|
+
) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Save a labware definition
|
|
113
|
+
|
|
114
|
+
:param labware_def: A deserialized JSON labware definition
|
|
115
|
+
:param bool force: If true, overwrite an existing definition if found.
|
|
116
|
+
Cannot overwrite Opentrons definitions.
|
|
117
|
+
:param location: File path
|
|
118
|
+
"""
|
|
119
|
+
namespace = labware_def["namespace"]
|
|
120
|
+
load_name = labware_def["parameters"]["loadName"]
|
|
121
|
+
version = labware_def["version"]
|
|
122
|
+
|
|
123
|
+
verify_definition(labware_def)
|
|
124
|
+
|
|
125
|
+
if not namespace or not load_name or not version:
|
|
126
|
+
raise RuntimeError(
|
|
127
|
+
"Could not save definition, labware def is missing a field: "
|
|
128
|
+
+ f"{namespace}, {load_name}, {version}"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if namespace == OPENTRONS_NAMESPACE:
|
|
132
|
+
raise RuntimeError(
|
|
133
|
+
f'Saving definitions to the "{OPENTRONS_NAMESPACE}" namespace '
|
|
134
|
+
+ "is not permitted"
|
|
135
|
+
)
|
|
136
|
+
def_path = _get_path_to_labware(load_name, namespace, version, location)
|
|
137
|
+
|
|
138
|
+
if not force and def_path.is_file():
|
|
139
|
+
raise RuntimeError(
|
|
140
|
+
f"The given definition ({namespace}/{load_name} v{version}) "
|
|
141
|
+
+ "already exists. Cannot save definition without force=True"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
Path(def_path).parent.mkdir(parents=True, exist_ok=True)
|
|
145
|
+
with open(def_path, "w") as f:
|
|
146
|
+
json.dump(labware_def, f)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def verify_definition( # noqa: C901
|
|
150
|
+
contents: str | bytes | LabwareDefinition | object,
|
|
151
|
+
) -> LabwareDefinition:
|
|
152
|
+
"""Verify that an input string is a labware definition and return it.
|
|
153
|
+
|
|
154
|
+
:param contents: The untrusted input to parse and validate. If str or bytes, it's
|
|
155
|
+
parsed as JSON. Otherwise, it should be the output of json.load().
|
|
156
|
+
|
|
157
|
+
:raises NotALabwareError:
|
|
158
|
+
|
|
159
|
+
:returns: The parsed and validated definition
|
|
160
|
+
"""
|
|
161
|
+
schemata_by_version = {
|
|
162
|
+
2: json.loads(load_shared_data("labware/schemas/2.json").decode("utf-8")),
|
|
163
|
+
3: json.loads(load_shared_data("labware/schemas/3.json").decode("utf-8")),
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
parsed_json: object = (
|
|
168
|
+
json.loads(contents) if isinstance(contents, (str, bytes)) else contents
|
|
169
|
+
)
|
|
170
|
+
except json.JSONDecodeError as e:
|
|
171
|
+
raise NotALabwareError("invalid-json", [e]) from e
|
|
172
|
+
|
|
173
|
+
if isinstance(parsed_json, dict):
|
|
174
|
+
try:
|
|
175
|
+
schema_version: object = parsed_json["schemaVersion"]
|
|
176
|
+
except KeyError as e:
|
|
177
|
+
raise NotALabwareError("no-schema-id", [e]) from e
|
|
178
|
+
else:
|
|
179
|
+
raise NotALabwareError("no-schema-id", [])
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
# we can type ignore this because we handle the KeyError below
|
|
183
|
+
schema = schemata_by_version[schema_version] # type: ignore[index]
|
|
184
|
+
except KeyError as e:
|
|
185
|
+
raise NotALabwareError("bad-schema-id", [e]) from e
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
jsonschema.validate(parsed_json, schema)
|
|
189
|
+
except jsonschema.ValidationError as e:
|
|
190
|
+
raise NotALabwareError("schema-mismatch", [e]) from e
|
|
191
|
+
|
|
192
|
+
# we can type ignore this because if it passes the jsonschema it has
|
|
193
|
+
# the correct structure
|
|
194
|
+
return parsed_json # type: ignore[return-value]
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _get_labware_definition_from_bundle(
|
|
198
|
+
bundled_labware: Mapping[str, LabwareDefinition],
|
|
199
|
+
load_name: str,
|
|
200
|
+
namespace: Optional[str] = None,
|
|
201
|
+
version: Optional[int] = None,
|
|
202
|
+
) -> LabwareDefinition:
|
|
203
|
+
"""
|
|
204
|
+
Look up and return a bundled definition by ``load_name`` + ``namespace``
|
|
205
|
+
+ ``version`` and return it or raise an exception. The``namespace`` and
|
|
206
|
+
``version`` args are optional, they only have to be specified if there is
|
|
207
|
+
ambiguity (eg when multiple labware in the bundle share the same
|
|
208
|
+
``load_name``)
|
|
209
|
+
|
|
210
|
+
:param str load_name: corresponds to 'loadName' key in definition
|
|
211
|
+
:param str namespace: The namespace the labware definition belongs to
|
|
212
|
+
:param int version: The version of the labware definition
|
|
213
|
+
:param Dict bundled_labware: A dictionary of labware definitions to search
|
|
214
|
+
"""
|
|
215
|
+
load_name = load_name.lower()
|
|
216
|
+
|
|
217
|
+
bundled_candidates = [
|
|
218
|
+
b for b in bundled_labware.values() if b["parameters"]["loadName"] == load_name
|
|
219
|
+
]
|
|
220
|
+
if namespace:
|
|
221
|
+
namespace = namespace.lower()
|
|
222
|
+
bundled_candidates = [
|
|
223
|
+
b for b in bundled_candidates if b["namespace"] == namespace
|
|
224
|
+
]
|
|
225
|
+
if version:
|
|
226
|
+
bundled_candidates = [b for b in bundled_candidates if b["version"] == version]
|
|
227
|
+
|
|
228
|
+
if len(bundled_candidates) == 1:
|
|
229
|
+
return bundled_candidates[0]
|
|
230
|
+
elif len(bundled_candidates) > 1:
|
|
231
|
+
raise RuntimeError(
|
|
232
|
+
f"Ambiguous labware access. Bundle contains multiple "
|
|
233
|
+
f"labware with load name {load_name}, "
|
|
234
|
+
f"namespace {namespace}, and version {version}."
|
|
235
|
+
)
|
|
236
|
+
else:
|
|
237
|
+
raise RuntimeError(
|
|
238
|
+
f"No labware found in bundle with load name {load_name}, "
|
|
239
|
+
f"namespace {namespace}, and version {version}."
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _get_standard_labware_definition(
|
|
244
|
+
load_name: str, namespace: Optional[str] = None, version: Optional[int] = None
|
|
245
|
+
) -> LabwareDefinition:
|
|
246
|
+
if version is None:
|
|
247
|
+
checked_version = 1
|
|
248
|
+
else:
|
|
249
|
+
checked_version = version
|
|
250
|
+
error_msg_string = """Unable to find a labware
|
|
251
|
+
definition for "{0}",
|
|
252
|
+
version {1}, in the {2} namespace.
|
|
253
|
+
Please confirm your protocol includes the correct
|
|
254
|
+
labware spelling and (optionally) the correct version
|
|
255
|
+
number and namespace.
|
|
256
|
+
|
|
257
|
+
If you are referencing a custom labware in your
|
|
258
|
+
protocol, you must add it to your Custom Labware
|
|
259
|
+
Definitions Folder from the Opentrons App before
|
|
260
|
+
uploading your protocol.
|
|
261
|
+
"""
|
|
262
|
+
if namespace is None:
|
|
263
|
+
for fallback_namespace in [OPENTRONS_NAMESPACE, CUSTOM_NAMESPACE]:
|
|
264
|
+
try:
|
|
265
|
+
return _get_standard_labware_definition(
|
|
266
|
+
load_name, fallback_namespace, checked_version
|
|
267
|
+
)
|
|
268
|
+
except FileNotFoundError:
|
|
269
|
+
pass
|
|
270
|
+
|
|
271
|
+
raise FileNotFoundError(
|
|
272
|
+
error_msg_string.format(load_name, checked_version, OPENTRONS_NAMESPACE)
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
namespace = namespace.lower()
|
|
276
|
+
def_path = _get_path_to_labware(load_name, namespace, checked_version)
|
|
277
|
+
|
|
278
|
+
try:
|
|
279
|
+
with open(def_path, "rb") as f:
|
|
280
|
+
labware_def = json.loads(f.read().decode("utf-8"))
|
|
281
|
+
except FileNotFoundError:
|
|
282
|
+
raise FileNotFoundError(
|
|
283
|
+
f'Labware "{load_name}" not found with version {checked_version} '
|
|
284
|
+
f'in namespace "{namespace}".'
|
|
285
|
+
)
|
|
286
|
+
return labware_def # type: ignore[no-any-return]
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def _get_path_to_labware(
|
|
290
|
+
load_name: str, namespace: str, version: int, base_path: Optional[Path] = None
|
|
291
|
+
) -> Path:
|
|
292
|
+
if namespace == OPENTRONS_NAMESPACE:
|
|
293
|
+
# all labware in OPENTRONS_NAMESPACE is stored in shared data
|
|
294
|
+
schema_3_path = (
|
|
295
|
+
get_shared_data_root()
|
|
296
|
+
/ STANDARD_DEFS_PATH
|
|
297
|
+
/ "3"
|
|
298
|
+
/ load_name
|
|
299
|
+
/ f"{version}.json"
|
|
300
|
+
)
|
|
301
|
+
schema_2_path = (
|
|
302
|
+
get_shared_data_root()
|
|
303
|
+
/ STANDARD_DEFS_PATH
|
|
304
|
+
/ "2"
|
|
305
|
+
/ load_name
|
|
306
|
+
/ f"{version}.json"
|
|
307
|
+
)
|
|
308
|
+
return schema_3_path if schema_3_path.exists() else schema_2_path
|
|
309
|
+
if not base_path:
|
|
310
|
+
base_path = USER_DEFS_PATH
|
|
311
|
+
def_path = base_path / namespace / load_name / f"{version}.json"
|
|
312
|
+
return def_path
|
|
File without changes
|