diff --git a/api/mypy.ini b/api/mypy.ini index 2b5647d15b2..818190965e2 100644 --- a/api/mypy.ini +++ b/api/mypy.ini @@ -23,17 +23,11 @@ disallow_incomplete_defs = False no_implicit_optional = False warn_return_any = False -# ~30 errors -[mypy-tests.opentrons.drivers.*] +[mypy-tests.opentrons.protocol_api_old.*] # disallow_untyped_defs = False # disallow_untyped_calls = False # disallow_incomplete_defs = False -[mypy-tests.opentrons.protocol_api_old.*] -disallow_untyped_defs = False -disallow_untyped_calls = False -disallow_incomplete_defs = False - # ~10 errors [mypy-tests.opentrons.system.*] disallow_untyped_defs = False diff --git a/api/tests/opentrons/protocol_api_old/core/protocol_api/test_well_implementation.py b/api/tests/opentrons/protocol_api_old/core/protocol_api/test_well_implementation.py index 69d14301a62..de1b0628bb1 100644 --- a/api/tests/opentrons/protocol_api_old/core/protocol_api/test_well_implementation.py +++ b/api/tests/opentrons/protocol_api_old/core/protocol_api/test_well_implementation.py @@ -13,7 +13,7 @@ ["B0100", "B", "0100"], ], ) -def test_row_column(name, row, col): +def test_row_column(name: str, row: str, col: str) -> None: w = LegacyWellCore( well_geometry=None, # type: ignore[arg-type] display_name=None, # type: ignore[arg-type] @@ -33,7 +33,7 @@ def test_row_column(name, row, col): ["A 1"], ], ) -def test_row_column_fail(name): +def test_row_column_fail(name: str) -> None: with pytest.raises(AssertionError, match=f"could not match '{name}'"): LegacyWellCore( well_geometry=None, # type: ignore[arg-type] diff --git a/api/tests/opentrons/protocol_api_old/test_accessor_fn.py b/api/tests/opentrons/protocol_api_old/test_accessor_fn.py index dbbf23af4bb..23381d1d1e1 100644 --- a/api/tests/opentrons/protocol_api_old/test_accessor_fn.py +++ b/api/tests/opentrons/protocol_api_old/test_accessor_fn.py @@ -1,7 +1,14 @@ from opentrons.types import Point +from opentrons.protocol_api import Labware +from opentrons.protocol_api.core.legacy.legacy_labware_core import LegacyLabwareCore +from opentrons_shared_data.labware.types import LabwareDefinition -def test_wells_accessor(min_lw, min_lw_impl, minimal_labware_def): +def test_wells_accessor( + min_lw: Labware, + min_lw_impl: LegacyLabwareCore, + minimal_labware_def: LabwareDefinition, +) -> None: depth1 = minimal_labware_def["wells"]["A1"]["depth"] depth2 = minimal_labware_def["wells"]["A2"]["depth"] x = minimal_labware_def["wells"]["A2"]["x"] @@ -13,7 +20,11 @@ def test_wells_accessor(min_lw, min_lw_impl, minimal_labware_def): assert min_lw.wells()[1].geometry._position == a2 -def test_wells_name_accessor(min_lw, min_lw_impl, minimal_labware_def): +def test_wells_name_accessor( + min_lw: Labware, + min_lw_impl: LegacyLabwareCore, + minimal_labware_def: LabwareDefinition, +) -> None: depth1 = minimal_labware_def["wells"]["A1"]["depth"] depth2 = minimal_labware_def["wells"]["A2"]["depth"] x = minimal_labware_def["wells"]["A2"]["x"] @@ -25,13 +36,17 @@ def test_wells_name_accessor(min_lw, min_lw_impl, minimal_labware_def): assert min_lw.wells_by_name()["A2"].geometry._position == a2 -def test_deprecated_index_accessors(min_lw): +def test_deprecated_index_accessors(min_lw: Labware) -> None: assert min_lw.wells_by_name() == min_lw.wells_by_index() assert min_lw.rows_by_name() == min_lw.rows_by_index() assert min_lw.columns_by_name() == min_lw.columns_by_index() -def test_dict_accessor(min_lw, min_lw_impl, minimal_labware_def): +def test_dict_accessor( + min_lw: Labware, + min_lw_impl: LegacyLabwareCore, + minimal_labware_def: LabwareDefinition, +) -> None: depth1 = minimal_labware_def["wells"]["A1"]["depth"] depth2 = minimal_labware_def["wells"]["A2"]["depth"] x = minimal_labware_def["wells"]["A2"]["x"] @@ -43,7 +58,11 @@ def test_dict_accessor(min_lw, min_lw_impl, minimal_labware_def): assert min_lw["A2"].geometry._position == a2 -def test_rows_accessor(min_lw2_impl, min_lw2, minimal_labware_def2): +def test_rows_accessor( + min_lw2_impl: LegacyLabwareCore, + min_lw2: Labware, + minimal_labware_def2: LabwareDefinition, +) -> None: depth1 = minimal_labware_def2["wells"]["A1"]["depth"] x1 = minimal_labware_def2["wells"]["A1"]["x"] y1 = minimal_labware_def2["wells"]["A1"]["y"] @@ -57,7 +76,11 @@ def test_rows_accessor(min_lw2_impl, min_lw2, minimal_labware_def2): assert min_lw2.rows()[1][1].geometry._position == b2 -def test_row_name_accessor(min_lw2_impl, min_lw2, minimal_labware_def2): +def test_row_name_accessor( + min_lw2_impl: LegacyLabwareCore, + min_lw2: Labware, + minimal_labware_def2: LabwareDefinition, +) -> None: depth1 = minimal_labware_def2["wells"]["A1"]["depth"] x1 = minimal_labware_def2["wells"]["A1"]["x"] y1 = minimal_labware_def2["wells"]["A1"]["y"] @@ -71,7 +94,11 @@ def test_row_name_accessor(min_lw2_impl, min_lw2, minimal_labware_def2): assert min_lw2.rows_by_name()["B"][1].geometry._position == b2 -def test_cols_accessor(min_lw_impl, min_lw, minimal_labware_def): +def test_cols_accessor( + min_lw_impl: LegacyLabwareCore, + min_lw: Labware, + minimal_labware_def: LabwareDefinition, +) -> None: depth1 = minimal_labware_def["wells"]["A1"]["depth"] depth2 = minimal_labware_def["wells"]["A2"]["depth"] x = minimal_labware_def["wells"]["A2"]["x"] @@ -83,7 +110,11 @@ def test_cols_accessor(min_lw_impl, min_lw, minimal_labware_def): assert min_lw.columns()[1][0].geometry._position == a2 -def test_col_name_accessor(min_lw, min_lw_impl, minimal_labware_def): +def test_col_name_accessor( + min_lw: Labware, + min_lw_impl: LegacyLabwareCore, + minimal_labware_def: LabwareDefinition, +) -> None: depth1 = minimal_labware_def["wells"]["A1"]["depth"] depth2 = minimal_labware_def["wells"]["A2"]["depth"] x = minimal_labware_def["wells"]["A2"]["x"] diff --git a/api/tests/opentrons/protocol_api_old/test_context.py b/api/tests/opentrons/protocol_api_old/test_context.py index e8ec2859d51..43398be4917 100644 --- a/api/tests/opentrons/protocol_api_old/test_context.py +++ b/api/tests/opentrons/protocol_api_old/test_context.py @@ -1,15 +1,25 @@ """ Test the functions and classes in the protocol context """ - -import json +# TODO: The below imports are only used in test_tip_length_for_caldata, which needs to be fixed. +# import json +# from opentrons_shared_data.pipette.types import LabwareUri +# from decoy import Decoy +# from opentrons.protocols.api_support import instrument as instrument_support +# from opentrons.calibration_storage import types as cs_types +# from opentrons.util.helpers import utc_now + +from typing import Any, Callable, Dict, List, Optional, Tuple +import pytest import mock -from typing import Any, Dict +from pytest import MonkeyPatch -from opentrons_shared_data import load_shared_data -from opentrons_shared_data.pipette.types import LabwareUri +from opentrons_shared_data.labware.types import LabwareDefinition from opentrons_shared_data.errors.exceptions import UnexpectedTipRemovalError +from opentrons.hardware_control.adapters import SynchronousAdapter +from opentrons.protocol_api import Labware import opentrons.protocol_api as papi import opentrons.protocols.api_support as papi_support +from opentrons.protocols.api_support.labware_like import LabwareLike import opentrons.protocols.geometry as papi_geometry from opentrons.protocols.api_support.deck_type import STANDARD_OT2_DECK @@ -20,15 +30,12 @@ from opentrons.types import Mount, Point, Location, TransferTipPolicy from opentrons.hardware_control import API, ThreadManagedHardware from opentrons.hardware_control.instruments.ot2.pipette import Pipette -from opentrons.hardware_control.types import Axis +from opentrons.hardware_control.types import Axis, CriticalPoint +from opentrons.protocol_api.core.legacy.deck import Deck from opentrons.hardware_control.modules import SimulatingModule from opentrons.protocols.advanced_control import transfers as tf -from opentrons.protocols.api_support import instrument as instrument_support from opentrons.protocols.api_support.types import APIVersion -from opentrons.calibration_storage import types as cs_types -from opentrons.util.helpers import utc_now -import pytest # TODO (lc 12-8-2022) Not sure if we plan to keep these tests, but if we do # we should re-write them to be agnostic to the underlying hardware. Otherwise @@ -36,7 +43,7 @@ pytestmark = pytest.mark.ot2_only -def set_version_added(attr, mp, version): +def set_version_added(attr: str, mp: MonkeyPatch, version: str) -> str: """helper to mock versionadded for an attr attr is the attr @@ -44,7 +51,7 @@ def set_version_added(attr, mp, version): version is an APIVersion """ - def get_wrapped(attr): + def get_wrapped(attr: str) -> str: if hasattr(attr, "__wrapped__"): return get_wrapped(attr.__wrapped__) return attr @@ -58,26 +65,9 @@ def get_wrapped(attr): return attr -@pytest.fixture -def get_labware_def(monkeypatch): - def dummy_load( - labware_name, - namespace=None, - version=None, - bundled_defs=None, - extra_defs=None, - api_level=None, - ): - # TODO: Ian 2019-05-30 use fixtures not real defs - labware_def = json.loads( - load_shared_data(f"labware/definitions/2/{labware_name}/1.json") - ) - return labware_def - - monkeypatch.setattr(papi.labware, "get_labware_definition", dummy_load) - - -async def test_motion(ctx, hardware): +async def test_motion( + ctx: papi.ProtocolContext, hardware: ThreadManagedHardware +) -> None: ctx.home() instr = ctx.load_instrument("p10_single", Mount.RIGHT) old_pos = await hardware.current_position(instr._core.get_mount()) @@ -92,7 +82,9 @@ async def test_motion(ctx, hardware): ) -def test_max_speeds(ctx, monkeypatch, hardware): +def test_max_speeds( + ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware +) -> None: ctx.home() with mock.patch.object(ctx._core.get_hardware(), "move_to") as mock_move: instr = ctx.load_instrument("p10_single", Mount.RIGHT) @@ -117,7 +109,9 @@ def test_max_speeds(ctx, monkeypatch, hardware): ) -async def test_location_cache(ctx, monkeypatch, get_labware_def, hardware): +async def test_location_cache( + ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware +) -> None: right = ctx.load_instrument("p10_single", Mount.RIGHT) lw = ctx.load_labware("corning_96_wellplate_360ul_flat", 1) ctx.home() @@ -125,14 +119,14 @@ async def test_location_cache(ctx, monkeypatch, get_labware_def, hardware): test_args = None def fake_plan_move( - from_loc, - to_loc, - deck, - well_z_margin=None, - lw_z_margin=None, - force_direct=False, - minimum_z_height=None, - ): + from_loc: Location, + to_loc: Location, + deck: Deck, + well_z_margin: Optional[float] = None, + lw_z_margin: Optional[float] = None, + force_direct: Optional[bool] = False, + minimum_z_height: Optional[float] = None, + ) -> List[Tuple[Point, Optional[CriticalPoint]]]: nonlocal test_args test_args = (from_loc, to_loc, deck, well_z_margin, lw_z_margin) return [ @@ -157,7 +151,9 @@ def fake_plan_move( assert test_args[0].labware.as_well() == lw.wells()[0] # type: ignore[index] -def test_location_cache_two_pipettes(ctx, get_labware_def, hardware): +def test_location_cache_two_pipettes( + ctx: papi.ProtocolContext, hardware: ThreadManagedHardware +) -> None: """It should be invalidated when next movement is a different pipette than the cached location.""" ctx.home() @@ -179,12 +175,16 @@ def test_location_cache_two_pipettes(ctx, get_labware_def, hardware): assert m.call_args[0][1] == right_loc -def test_location_cache_two_pipettes_fails_pre_2_10(ctx, get_labware_def, hardware): +def test_location_cache_two_pipettes_fails_pre_2_10( + ctx: papi.ProtocolContext, hardware: ThreadManagedHardware +) -> None: """It should reuse location cache even if cached location was set by move of a different pipette.""" ctx.home() left = ctx.load_instrument("p10_single", Mount.LEFT) right = ctx.load_instrument("p10_single", Mount.RIGHT) + assert hasattr(left._core, "_api_version") + assert hasattr(right._core, "_api_version") left._core._api_version = APIVersion(2, 9) right._core._api_version = APIVersion(2, 9) @@ -201,7 +201,9 @@ def test_location_cache_two_pipettes_fails_pre_2_10(ctx, get_labware_def, hardwa assert m.call_args[0][1] == right_loc -def test_move_uses_arc(ctx, monkeypatch, get_labware_def, hardware): +def test_move_uses_arc( + ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware +) -> None: ctx.home() right = ctx.load_instrument("p10_single", Mount.RIGHT) lw = ctx.load_labware("corning_96_wellplate_360ul_flat", 1) @@ -218,7 +220,7 @@ def test_move_uses_arc(ctx, monkeypatch, get_labware_def, hardware): ) -def test_pipette_info(ctx): +def test_pipette_info(ctx: papi.ProtocolContext) -> None: right = ctx.load_instrument("p300_multi", Mount.RIGHT) left = ctx.load_instrument("p1000_single", Mount.LEFT) assert right.type == "multi" @@ -234,7 +236,7 @@ def test_pipette_info(ctx): assert left.model == model -def test_pick_up_and_drop_tip(ctx, get_labware_def): +def test_pick_up_and_drop_tip(ctx: papi.ProtocolContext) -> None: ctx.home() tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 1) tip_length = tiprack.tip_length @@ -260,7 +262,7 @@ def test_pick_up_and_drop_tip(ctx, get_labware_def): assert pipette.critical_point() == nozzle_offset -def test_pick_up_without_prep_after(ctx, get_labware_def): +def test_pick_up_without_prep_after(ctx: papi.ProtocolContext) -> None: ctx.home() tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 1) lw = ctx.load_labware("corning_96_wellplate_360ul_flat", 2) @@ -278,7 +280,9 @@ def test_pick_up_without_prep_after(ctx, get_labware_def): instr.drop_tip(tiprack["A2"].top()) -def test_pick_up_tip_old_version(hardware, deck_definition_name, get_labware_def): +def test_pick_up_tip_old_version( + hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: # API version 2.12, a pick-up tip would not prepare-for-aspirate api_version = APIVersion(2, 12) ctx = papi.create_protocol_context( @@ -310,7 +314,9 @@ def test_pick_up_tip_old_version(hardware, deck_definition_name, get_labware_def instr.pick_up_tip(tiprack["A2"].top(), prep_after=True) -def test_return_tip_old_version(hardware, deck_definition_name, get_labware_def): +def test_return_tip_old_version( + hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: # API version 2.2, a returned tip would be picked up by the # next pick up tip call api_version = APIVersion(2, 1) @@ -342,7 +348,7 @@ def test_return_tip_old_version(hardware, deck_definition_name, get_labware_def) assert not tiprack.wells()[0].has_tip -def test_return_tip(ctx, get_labware_def): +def test_return_tip(ctx: papi.ProtocolContext) -> None: ctx.home() tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 1) mount = Mount.LEFT @@ -368,7 +374,7 @@ def test_return_tip(ctx, get_labware_def): assert not tiprack.wells()[1].has_tip -def test_use_filter_tips(ctx, get_labware_def): +def test_use_filter_tips(ctx: papi.ProtocolContext) -> None: ctx.home() tiprack = ctx.load_labware_by_name("opentrons_96_filtertiprack_200ul", 2) @@ -388,7 +394,9 @@ def test_use_filter_tips(ctx, get_labware_def): @pytest.mark.parametrize( "tiprack_kind", ["opentrons_96_tiprack_10ul", "eppendorf_96_tiprack_10ul_eptips"] ) -def test_pick_up_tip_no_location(ctx, get_labware_def, pipette_model, tiprack_kind): +def test_pick_up_tip_no_location( + ctx: papi.ProtocolContext, pipette_model: str, tiprack_kind: str +) -> None: ctx.home() tiprack1 = ctx.load_labware(tiprack_kind, 1) @@ -430,12 +438,14 @@ def test_pick_up_tip_no_location(ctx, get_labware_def, pipette_model, tiprack_ki assert not tiprack2.wells()[0].has_tip -def test_instrument_trash(ctx, get_labware_def): +def test_instrument_trash(ctx: papi.ProtocolContext) -> None: ctx.home() mount = Mount.LEFT instr = ctx.load_instrument("p300_single", mount) + assert isinstance(instr.trash_container, Labware) + assert instr.trash_container.name == "opentrons_1_trash_1100ml_fixed" new_trash = ctx.load_labware("usascientific_12_reservoir_22ml", 2) @@ -445,16 +455,18 @@ def test_instrument_trash(ctx, get_labware_def): @pytest.mark.ot3_only -def test_instrument_trash_ot3(ctx, get_labware_def): +def test_instrument_trash_ot3(ctx: papi.ProtocolContext) -> None: ctx.home() mount = Mount.LEFT instr = ctx.load_instrument("flex_1channel_1000", mount) + assert isinstance(instr, papi.ProtocolContext) + assert instr.trash_container.name == "opentrons_1_trash_3200ml_fixed" -def test_aspirate(ctx, get_labware_def): +def test_aspirate(ctx: papi.ProtocolContext) -> None: ctx.home() lw = ctx.load_labware("corning_96_wellplate_360ul_flat", 1) tiprack = ctx.load_labware("opentrons_96_tiprack_10ul", 2) @@ -486,6 +498,7 @@ def test_aspirate(ctx, get_labware_def): instr.well_bottom_clearance.aspirate = 1.0 instr.aspirate(2.0, lw.wells()[0]) dest_point, dest_lw = lw.wells()[0].bottom() + assert isinstance(dest_point, Point) dest_point = dest_point._replace(z=dest_point.z + 1.0) assert len(fake_move.call_args_list) == 1 assert fake_move.call_args_list[0] == mock.call( @@ -498,7 +511,10 @@ def test_aspirate(ctx, get_labware_def): ctx._core.get_hardware()._obj_to_adapt, "aspirate" ) as fake_hw_aspirate: hardware = ctx._core.get_hardware() - hardware._obj_to_adapt.hardware_instruments[Mount.RIGHT]._current_volume = 1 + assert isinstance(hardware, SynchronousAdapter) + mount = hardware._obj_to_adapt.hardware_instruments[Mount.RIGHT] + assert mount is not None + mount._current_volume = 1 instr.aspirate(2.0) fake_move.assert_not_called() @@ -512,6 +528,7 @@ def test_aspirate(ctx, get_labware_def): ) as fake_hw_aspirate: instr.aspirate(2.0) assert len(fake_move.call_args_list) == 2 + assert isinstance(dest_lw, LabwareLike) # reset plunger at the top of the well after blowout assert fake_move.call_args_list[0] == mock.call( Mount.RIGHT, @@ -525,7 +542,7 @@ def test_aspirate(ctx, get_labware_def): ) -def test_dispense(ctx, get_labware_def, monkeypatch): +def test_dispense(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: ctx.home() lw = ctx.load_labware("corning_96_wellplate_360ul_flat", 1) instr = ctx.load_instrument("p10_single", Mount.RIGHT) @@ -554,6 +571,7 @@ def test_dispense(ctx, get_labware_def, monkeypatch): instr.well_bottom_clearance.dispense = 2.0 instr.dispense(2.0, lw.wells()[0]) dest_point, dest_lw = lw.wells()[0].bottom() + assert isinstance(dest_point, Point) dest_point = dest_point._replace(z=dest_point.z + 2.0) fake_move.assert_called_with( Mount.RIGHT, dest_point, critical_point=None, speed=400, max_speeds={} @@ -567,6 +585,7 @@ def test_dispense(ctx, get_labware_def, monkeypatch): instr.well_bottom_clearance.dispense = 2.0 instr.dispense(2.0, lw.wells()[0]) dest_point, dest_lw = lw.wells()[0].bottom() + assert isinstance(dest_point, Point) dest_point = dest_point._replace(z=dest_point.z + 2.0) fake_move.assert_called_with( Mount.RIGHT, dest_point, critical_point=None, speed=400, max_speeds={} @@ -576,7 +595,7 @@ def test_dispense(ctx, get_labware_def, monkeypatch): fake_move.assert_not_called() -def test_prevent_liquid_handling_without_tip(ctx): +def test_prevent_liquid_handling_without_tip(ctx: papi.ProtocolContext) -> None: ctx.home() tr = ctx.load_labware("opentrons_96_tiprack_300ul", "1") @@ -595,7 +614,9 @@ def test_prevent_liquid_handling_without_tip(ctx): pipR.dispense(100, plate.wells()[1]) -def test_starting_tip_and_reset_tipracks(ctx, get_labware_def, monkeypatch): +def test_starting_tip_and_reset_tipracks( + ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch +) -> None: ctx.home() tr = ctx.load_labware("opentrons_96_tiprack_300ul", 1) @@ -623,7 +644,7 @@ def test_starting_tip_and_reset_tipracks(ctx, get_labware_def, monkeypatch): assert tr.wells()[3].has_tip -def test_mix(ctx, monkeypatch): +def test_mix(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: ctx.home() lw = ctx.load_labware("opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", 1) tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 3) @@ -634,13 +655,21 @@ def test_mix(ctx, monkeypatch): aspirate_called_with = None dispense_called_with = None - def fake_aspirate(vol=None, loc=None, rate=None): + def fake_aspirate( + vol: Optional[float] = None, + loc: Optional[Location] = None, + rate: Optional[int] = None, + ) -> None: nonlocal aspirate_called_with nonlocal mix_steps aspirate_called_with = ("aspirate", vol, loc, rate) mix_steps.append(aspirate_called_with) - def fake_dispense(vol=None, loc=None, rate=None): + def fake_dispense( + vol: Optional[float] = None, + loc: Optional[Location] = None, + rate: Optional[int] = None, + ) -> None: nonlocal dispense_called_with nonlocal mix_steps dispense_called_with = ("dispense", vol, loc, rate) @@ -664,7 +693,9 @@ def fake_dispense(vol=None, loc=None, rate=None): assert mix_steps == expected_mix_steps -def test_touch_tip_default_args(monkeypatch, hardware, deck_definition_name): +def test_touch_tip_default_args( + monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: api_version = APIVersion(2, 3) ctx = papi.create_protocol_context( api_version=api_version, hardware_api=hardware, deck_type=deck_definition_name @@ -704,7 +735,9 @@ def test_touch_tip_default_args(monkeypatch, hardware, deck_definition_name): assert fake_move.call_args_list[0][0][1].z != old_z -def test_touch_tip_new_default_args(ctx, monkeypatch): +def test_touch_tip_new_default_args( + ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch +) -> None: ctx.home() lw = ctx.load_labware("opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", 1) tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 3) @@ -743,7 +776,11 @@ def test_touch_tip_new_default_args(ctx, monkeypatch): assert fake_move.call_args_list[0][0][1].z != old_z -def test_touch_tip_disabled(ctx, monkeypatch, get_labware_fixture): +def test_touch_tip_disabled( + ctx: papi.ProtocolContext, + monkeypatch: MonkeyPatch, + get_labware_fixture: Callable[[str], LabwareDefinition], +) -> None: ctx.home() trough1 = get_labware_fixture("fixture_12_trough") trough_lw = ctx.load_labware_from_definition(trough1, "1") @@ -756,7 +793,7 @@ def test_touch_tip_disabled(ctx, monkeypatch, get_labware_fixture): move_mock.assert_not_called() -def test_blow_out(ctx, monkeypatch): +def test_blow_out(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: ctx.home() lw = ctx.load_labware("opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", 1) tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 3) @@ -766,7 +803,7 @@ def test_blow_out(ctx, monkeypatch): instr.pick_up_tip() instr.aspirate(10, lw.wells()[0]) - def fake_move(location): + def fake_move(location: Point) -> None: nonlocal move_location move_location = location @@ -787,7 +824,7 @@ def fake_move(location): assert move_location == lw.wells()[0].bottom() -def test_transfer_options(ctx, monkeypatch): +def test_transfer_options(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: lw1 = ctx.load_labware("biorad_96_wellplate_200ul_pcr", 1) lw2 = ctx.load_labware("corning_96_wellplate_360ul_flat", 2) tiprack = ctx.load_labware("opentrons_96_tiprack_300ul", 3) @@ -796,7 +833,7 @@ def test_transfer_options(ctx, monkeypatch): ctx.home() transfer_options = None - def fake_execute_transfer(xfer_plan): + def fake_execute_transfer(xfer_plan: tf.TransferPlan) -> None: nonlocal transfer_options transfer_options = xfer_plan._options @@ -876,11 +913,15 @@ def fake_execute_transfer(xfer_plan): instr.transfer(300, lw1["A1"], lw2["A1"], air_gap=10000) -def test_flow_rate(ctx, monkeypatch): +def test_flow_rate(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: instr = ctx.load_instrument("p300_single", Mount.RIGHT) old_sfm = instr._core.set_flow_rate - def pass_on(aspirate=None, dispense=None, blow_out=None): + def pass_on( + aspirate: Optional[int] = None, + dispense: Optional[int] = None, + blow_out: Optional[int] = None, + ) -> None: old_sfm(aspirate=aspirate, dispense=dispense, blow_out=blow_out) set_flow_rate = mock.Mock(side_effect=pass_on) @@ -900,11 +941,16 @@ def pass_on(aspirate=None, dispense=None, blow_out=None): assert instr.flow_rate.blow_out == 2 -def test_pipette_speed(ctx, monkeypatch): +def test_pipette_speed(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: instr = ctx.load_instrument("p300_single", Mount.RIGHT) + assert hasattr(instr._core, "set_pipette_speed") old_sfm = instr._core.set_pipette_speed - def pass_on(aspirate=None, dispense=None, blow_out=None): + def pass_on( + aspirate: Optional[int] = None, + dispense: Optional[int] = None, + blow_out: Optional[int] = None, + ) -> None: old_sfm(aspirate=aspirate, dispense=dispense, blow_out=blow_out) set_speed = mock.Mock(side_effect=pass_on) @@ -923,7 +969,7 @@ def pass_on(aspirate=None, dispense=None, blow_out=None): assert instr.speed.blow_out == 2 -def test_loaded_labwares(ctx): +def test_loaded_labwares(ctx: papi.ProtocolContext) -> None: assert ctx.loaded_labwares == {12: ctx.fixed_trash} lw1 = ctx.load_labware("opentrons_96_tiprack_300ul", 3) lw2 = ctx.load_labware("opentrons_96_tiprack_300ul", 8) @@ -936,7 +982,12 @@ def test_loaded_labwares(ctx): assert sorted(ctx.loaded_labwares.keys()) == sorted([3, 5, 8, 12]) -def test_loaded_modules(ctx, monkeypatch): +def _safe_cast_to_int(value: Any) -> int: + result = int(value) + return result + + +def test_loaded_modules(ctx: papi.ProtocolContext, monkeypatch: MonkeyPatch) -> None: assert ctx.loaded_modules == {} from collections import OrderedDict @@ -946,7 +997,10 @@ def test_loaded_modules(ctx, monkeypatch): temp2 = ctx.load_module("temperature module", 4) expected_load_order = OrderedDict( - {int(mod.geometry.parent): mod for mod in [mag1, mag2, temp1, temp2]} + { + _safe_cast_to_int(mod.geometry.parent): mod + for mod in [mag1, mag2, temp1, temp2] + } ) assert ctx.loaded_modules == expected_load_order @@ -956,7 +1010,7 @@ def test_loaded_modules(ctx, monkeypatch): assert ctx.loaded_modules[4] == temp2 -def test_order_of_module_load(): +def test_order_of_module_load() -> None: import opentrons.hardware_control as hardware_control import opentrons.protocol_api as protocol_api @@ -1012,54 +1066,57 @@ def test_order_of_module_load(): assert id(async_temp2) == id(hw_temp2) -def test_tip_length_for_caldata(ctx, decoy, monkeypatch): - # TODO (lc 10-27-2022) We need to investigate why the pipette id is - # being reported as none for this test (and probably all the others) - from opentrons.hardware_control.instruments.ot2 import ( - instrument_calibration as instr_cal, - ) - from opentrons.calibration_storage import types as CSTypes - - instr = ctx.load_instrument("p20_single_gen2", "left") - tip_rack = ctx.load_labware("geb_96_tiprack_10ul", "1") - - mock_load_tip_length = decoy.mock(func=instr_cal.load_tip_length_for_pipette) - monkeypatch.setattr(instr_cal, "load_tip_length_for_pipette", mock_load_tip_length) - - decoy.when(mock_load_tip_length(None, tip_rack._core.get_definition())).then_return( - instr_cal.TipLengthCalibration( - tip_length=2, - last_modified=utc_now(), - source=cs_types.SourceType.user, - status=CSTypes.CalibrationStatus(markedBad=False), - uri=LabwareUri("opentrons/geb_96_tiprack_10ul/1"), - tiprack="somehash", - pipette=None, # type: ignore[arg-type] - ) - ) - - assert ( - instrument_support.tip_length_for( - pipette=instr.hw_pipette, - tip_rack_definition=tip_rack._core.get_definition(), - ) - == 2 - ) - - decoy.when(mock_load_tip_length(None, tip_rack._core.get_definition())).then_raise( - cs_types.TipLengthCalNotFound("oh no") - ) - - assert instrument_support.tip_length_for( - pipette=instr.hw_pipette, - tip_rack_definition=tip_rack._core.get_definition(), - ) == ( - tip_rack._core.get_definition()["parameters"]["tipLength"] - - instr.hw_pipette["tip_overlap"]["opentrons/geb_96_tiprack_10ul/1"] - ) - - -def test_bundled_labware(get_labware_fixture, hardware): +# def test_tip_length_for_caldata(ctx: papi.ProtocolContext, decoy: Decoy, monkeypatch: MonkeyPatch) -> None: +# # TODO (lc 10-27-2022) We need to investigate why the pipette id is +# # being reported as none for this test (and probably all the others) +# from opentrons.hardware_control.instruments.ot2 import ( +# instrument_calibration as instr_cal, +# ) +# from opentrons.calibration_storage import types as CSTypes + +# instr = ctx.load_instrument("p20_single_gen2", "left") +# tip_rack = ctx.load_labware("geb_96_tiprack_10ul", "1") + +# mock_load_tip_length = decoy.mock(func=instr_cal.load_tip_length_for_pipette) +# monkeypatch.setattr(instr_cal, "load_tip_length_for_pipette", mock_load_tip_length) + +# decoy.when(mock_load_tip_length(None, tip_rack._core.get_definition())).then_return( +# instr_cal.TipLengthCalibration( +# tip_length=2, +# last_modified=utc_now(), +# source=cs_types.SourceType.user, +# status=CSTypes.CalibrationStatus(markedBad=False), +# uri=LabwareUri("opentrons/geb_96_tiprack_10ul/1"), +# tiprack="somehash", +# pipette=None, # type: ignore[arg-type] +# ) +# ) + +# assert ( +# instrument_support.tip_length_for( +# pipette=instr.hw_pipette, +# tip_rack_definition=tip_rack._core.get_definition(), +# ) +# == 2 +# ) + +# decoy.when(mock_load_tip_length(None, tip_rack._core.get_definition())).then_raise( +# cs_types.TipLengthCalNotFound("oh no") +# ) + +# assert instrument_support.tip_length_for( +# pipette=instr.hw_pipette, +# tip_rack_definition=tip_rack._core.get_definition(), +# ) == ( +# tip_rack._core.get_definition()["parameters"]["tipLength"] +# - instr.hw_pipette["tip_overlap"]["opentrons/geb_96_tiprack_10ul/1"] +# ) + + +def test_bundled_labware( + get_labware_fixture: Callable[[str], LabwareDefinition], + hardware: ThreadManagedHardware, +) -> None: fixture_96_plate = get_labware_fixture("fixture_96_plate") bundled_labware = {"fixture/fixture_96_plate/1": fixture_96_plate} @@ -1075,7 +1132,10 @@ def test_bundled_labware(get_labware_fixture, hardware): assert ctx.loaded_labwares[3]._core.get_definition() == fixture_96_plate -def test_bundled_labware_missing(get_labware_fixture, hardware): +def test_bundled_labware_missing( + get_labware_fixture: Callable[[str], LabwareDefinition], + hardware: ThreadManagedHardware, +) -> None: bundled_labware: Dict[str, Any] = {} with pytest.raises( RuntimeError, match="No labware found in bundle with load name fixture_96_plate" @@ -1103,7 +1163,9 @@ def test_bundled_labware_missing(get_labware_fixture, hardware): ctx.load_labware("fixture_96_plate", 3, namespace="fixture") -def test_bundled_data(hardware, deck_definition_name): +def test_bundled_data( + hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: bundled_data = {"foo": b"1,2,3"} ctx = papi.create_protocol_context( api_version=APIVersion(2, 13), @@ -1115,7 +1177,11 @@ def test_bundled_data(hardware, deck_definition_name): assert ctx.bundled_data == bundled_data -def test_extra_labware(get_labware_fixture, hardware, deck_definition_name): +def test_extra_labware( + get_labware_fixture: Callable[[str], LabwareDefinition], + hardware: ThreadManagedHardware, + deck_definition_name: str, +) -> None: fixture_96_plate = get_labware_fixture("fixture_96_plate") bundled_labware = {"fixture/fixture_96_plate/1": fixture_96_plate} ctx = papi.create_protocol_context( @@ -1130,7 +1196,9 @@ def test_extra_labware(get_labware_fixture, hardware, deck_definition_name): assert ctx.loaded_labwares[3]._core.get_definition() == fixture_96_plate -def test_api_version_checking(hardware, deck_definition_name): +def test_api_version_checking( + hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: minor_over = APIVersion( papi.MAX_SUPPORTED_VERSION.major, papi.MAX_SUPPORTED_VERSION.minor + 1, @@ -1154,7 +1222,9 @@ def test_api_version_checking(hardware, deck_definition_name): ) -def test_api_per_call_checking(monkeypatch, hardware, deck_definition_name): +def test_api_per_call_checking( + monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: ctx = papi.create_protocol_context( api_version=APIVersion(1, 9), hardware_api=hardware, @@ -1175,7 +1245,9 @@ def test_api_per_call_checking(monkeypatch, hardware, deck_definition_name): ctx.set_rail_lights(on=True) -def test_home_plunger(monkeypatch, hardware, deck_definition_name): +def test_home_plunger( + monkeypatch: MonkeyPatch, hardware: ThreadManagedHardware, deck_definition_name: str +) -> None: ctx = papi.create_protocol_context( api_version=APIVersion(2, 0), hardware_api=hardware, @@ -1191,7 +1263,7 @@ def test_move_to_with_thermocycler( ) -> None: """Test move_to raises for unsafe moves with thermocycler.""" - def raiser(*args, **kwargs): + def raiser(*args: Any, **kwargs: Any) -> None: raise RuntimeError("Cannot") mod = ctx.load_module("thermocycler") @@ -1212,7 +1284,7 @@ def test_move_to_with_heater_shaker( ) -> None: """Test move_to raises for unsafe moves with heater-shaker.""" - def raiser(*args, **kwargs): + def raiser(*args: Any, **kwargs: Any) -> None: raise RuntimeError("Cannot") mod = ctx.load_module("heaterShakerModuleV1", 1) diff --git a/api/tests/opentrons/protocol_api_old/test_instrument.py b/api/tests/opentrons/protocol_api_old/test_instrument.py index c4070d8825f..5f274f513b4 100644 --- a/api/tests/opentrons/protocol_api_old/test_instrument.py +++ b/api/tests/opentrons/protocol_api_old/test_instrument.py @@ -1,10 +1,12 @@ """ Test the InstrumentContext class and its functions """ import pytest from unittest import mock +from typing import Any, Callable, Dict from opentrons.types import Mount from opentrons.protocols.advanced_control import transfers from opentrons.protocols.api_support.types import APIVersion +from opentrons.hardware_control import ThreadManagedHardware import opentrons.protocol_api as papi @@ -12,8 +14,10 @@ @pytest.fixture -def make_context_and_labware(hardware, deck_definition_name): - def _make_context_and_labware(api_version): +def make_context_and_labware( + hardware: ThreadManagedHardware, deck_definition_name: str +) -> Callable[[APIVersion], Dict[str, Any]]: + def _make_context_and_labware(api_version: APIVersion) -> Dict[str, Any]: ctx = papi.create_protocol_context( api_version=api_version, hardware_api=hardware, @@ -31,8 +35,9 @@ def _make_context_and_labware(api_version): "liquid_handling_command", ["transfer", "consolidate", "distribute"] ) def test_blowout_location_unsupported_version( - make_context_and_labware, liquid_handling_command -): + make_context_and_labware: Callable[[APIVersion], Dict[str, Any]], + liquid_handling_command: str, +) -> None: # not supported in versions below 2.8 context_and_labware = make_context_and_labware(APIVersion(2, 7)) context_and_labware["ctx"].home() @@ -65,11 +70,11 @@ def test_blowout_location_unsupported_version( ], ) def test_blowout_location_invalid( - make_context_and_labware, - liquid_handling_command, - blowout_location, - expected_error_match, -): + make_context_and_labware: Callable[[APIVersion], Dict[str, Any]], + liquid_handling_command: str, + blowout_location: str, + expected_error_match: str, +) -> None: context_and_labware = make_context_and_labware(APIVersion(2, 8)) context_and_labware["ctx"].home() lw1 = context_and_labware["lw1"] @@ -94,8 +99,11 @@ def test_blowout_location_invalid( ], ) def test_valid_blowout_location( - make_context_and_labware, liquid_handling_command, blowout_location, expected_strat -): + make_context_and_labware: Callable[[APIVersion], Dict[str, Any]], + liquid_handling_command: str, + blowout_location: str, + expected_strat: str, +) -> None: context_and_labware = make_context_and_labware(APIVersion(2, 8)) context_and_labware["ctx"].home() lw1 = context_and_labware["lw1"] diff --git a/api/tests/opentrons/protocol_api_old/test_labware.py b/api/tests/opentrons/protocol_api_old/test_labware.py index b98d603b28f..1dd0128d432 100644 --- a/api/tests/opentrons/protocol_api_old/test_labware.py +++ b/api/tests/opentrons/protocol_api_old/test_labware.py @@ -4,12 +4,15 @@ from decoy import Decoy from opentrons_shared_data.labware.types import WellDefinition +from opentrons_shared_data.labware.types import LabwareDefinition +from opentrons.protocol_api import Labware from opentrons.hardware_control.modules.types import ( MagneticModuleModel, TemperatureModuleModel, ThermocyclerModuleModel, HeaterShakerModuleModel, + ModuleModel, ) from opentrons.protocols.api_support.types import APIVersion @@ -139,7 +142,7 @@ def test_bottom() -> None: assert well.bottom() == Location(Point(expected_x, expected_y, expected_z), well) -def test_from_center_cartesian(): +def test_from_center_cartesian() -> None: slot1 = Location(Point(10, 11, 12), 1) # type: ignore[arg-type] well_name = "circular_well_json" has_tip = False @@ -209,13 +212,15 @@ def test_from_center_cartesian(): @pytest.fixture -def corning_96_wellplate_360ul_flat_def(): +def corning_96_wellplate_360ul_flat_def() -> LabwareDefinition: labware_name = "corning_96_wellplate_360ul_flat" return labware.get_labware_definition(labware_name) @pytest.fixture -def corning_96_wellplate_360ul_flat(corning_96_wellplate_360ul_flat_def): +def corning_96_wellplate_360ul_flat( + corning_96_wellplate_360ul_flat_def: LabwareDefinition, +) -> Labware: return labware.Labware( core=LegacyLabwareCore( definition=corning_96_wellplate_360ul_flat_def, @@ -228,13 +233,15 @@ def corning_96_wellplate_360ul_flat(corning_96_wellplate_360ul_flat_def): @pytest.fixture -def opentrons_96_tiprack_300ul_def(): +def opentrons_96_tiprack_300ul_def() -> LabwareDefinition: labware_name = "opentrons_96_tiprack_300ul" return labware.get_labware_definition(labware_name) @pytest.fixture -def opentrons_96_tiprack_300ul(opentrons_96_tiprack_300ul_def): +def opentrons_96_tiprack_300ul( + opentrons_96_tiprack_300ul_def: LabwareDefinition, +) -> Labware: return labware.Labware( core=LegacyLabwareCore( definition=opentrons_96_tiprack_300ul_def, @@ -246,7 +253,7 @@ def opentrons_96_tiprack_300ul(opentrons_96_tiprack_300ul_def): ) -def test_back_compat(corning_96_wellplate_360ul_flat) -> None: +def test_back_compat(corning_96_wellplate_360ul_flat: Labware) -> None: lw = corning_96_wellplate_360ul_flat # Note that this test uses the display name of wells to test for equality, @@ -292,7 +299,7 @@ def test_back_compat(corning_96_wellplate_360ul_flat) -> None: assert repr(w11[1][2]) == well_c3_name -def test_well_parent(corning_96_wellplate_360ul_flat) -> None: +def test_well_parent(corning_96_wellplate_360ul_flat: Labware) -> None: lw = corning_96_wellplate_360ul_flat parent = Location(Point(7, 8, 9), lw) well_name = "circular_well_json" @@ -321,7 +328,7 @@ def test_well_parent(corning_96_wellplate_360ul_flat) -> None: def test_tip_tracking_init( - corning_96_wellplate_360ul_flat, opentrons_96_tiprack_300ul + corning_96_wellplate_360ul_flat: Labware, opentrons_96_tiprack_300ul: Labware ) -> None: tiprack = opentrons_96_tiprack_300ul assert tiprack.is_tiprack @@ -334,7 +341,7 @@ def test_tip_tracking_init( assert not well.has_tip -def test_use_tips(opentrons_96_tiprack_300ul) -> None: +def test_use_tips(opentrons_96_tiprack_300ul: Labware) -> None: tiprack = opentrons_96_tiprack_300ul well_list = tiprack.wells() @@ -371,7 +378,8 @@ def test_use_tips(opentrons_96_tiprack_300ul) -> None: def test_select_next_tip( - opentrons_96_tiprack_300ul, opentrons_96_tiprack_300ul_def + opentrons_96_tiprack_300ul: Labware, + opentrons_96_tiprack_300ul_def: LabwareDefinition, ) -> None: tiprack = opentrons_96_tiprack_300ul well_list = tiprack.wells() @@ -422,7 +430,7 @@ def test_select_next_tip( tiprack.use_tips(well_list[0]) -def test_previous_tip(opentrons_96_tiprack_300ul) -> None: +def test_previous_tip(opentrons_96_tiprack_300ul: Labware) -> None: tiprack = opentrons_96_tiprack_300ul # If all wells are used, we can't get a previous tip assert tiprack.previous_tip() is None @@ -439,7 +447,7 @@ def test_previous_tip(opentrons_96_tiprack_300ul) -> None: assert tiprack.previous_tip(3) == tiprack.wells()[5] -def test_return_tips(opentrons_96_tiprack_300ul) -> None: +def test_return_tips(opentrons_96_tiprack_300ul: Labware) -> None: tiprack = opentrons_96_tiprack_300ul # If all wells are used, we get an error if we try to return @@ -471,7 +479,7 @@ def test_return_tips(opentrons_96_tiprack_300ul) -> None: + list(HeaterShakerModuleModel) ), ) -def test_module_geometry_load(module_model) -> None: +def test_module_geometry_load(module_model: ModuleModel) -> None: definition = module_geometry.load_definition(module_model) geometry = module_geometry.create_geometry( definition=definition, @@ -502,7 +510,7 @@ def test_module_geometry_load(module_model) -> None: "thermocyclerModuleV2", ], ) -def test_module_load_labware(module_name) -> None: +def test_module_load_labware(module_name: str) -> None: labware_name = "corning_96_wellplate_360ul_flat" labware_def = labware.get_labware_definition(labware_name) mod_model = validation.ensure_module_model(module_name) @@ -528,7 +536,7 @@ def test_module_load_labware(module_name) -> None: assert mod.highest_z == old_z -def test_tiprack_list(): +def test_tiprack_list() -> None: labware_name = "opentrons_96_tiprack_300ul" labware_def = labware.get_labware_definition(labware_name) tiprack = labware.Labware( @@ -570,7 +578,7 @@ def test_tiprack_list(): labware.select_tiprack_from_list([tiprack], 1, tiprack.wells()[95]) -def test_uris(): +def test_uris() -> None: details = ("opentrons", "opentrons_96_tiprack_300ul", "1") uri = "opentrons/opentrons_96_tiprack_300ul/1" assert helpers.uri_from_details(*details) == uri @@ -587,7 +595,9 @@ def test_uris(): assert lw.uri == uri -def test_labware_hash_func_same_implementation(minimal_labware_def) -> None: +def test_labware_hash_func_same_implementation( + minimal_labware_def: LabwareDefinition, +) -> None: """Test that multiple Labware objects with same implementation and version have the same __hash__""" impl = LegacyLabwareCore(minimal_labware_def, Location(Point(0, 0, 0), "Test Slot")) @@ -604,7 +614,7 @@ def test_labware_hash_func_same_implementation(minimal_labware_def) -> None: def test_labware_hash_func_same_implementation_different_version( - minimal_labware_def, + minimal_labware_def: LabwareDefinition, ) -> None: """Test that multiple Labware objects with same implementation yet different version have different __hash__""" @@ -627,7 +637,7 @@ def test_labware_hash_func_same_implementation_different_version( def test_labware_hash_func_diff_implementation_same_version( - minimal_labware_def, + minimal_labware_def: LabwareDefinition, ) -> None: """Test that multiple Labware objects with different implementation yet sane version have different __hash__""" diff --git a/api/tests/opentrons/protocol_api_old/test_module_context.py b/api/tests/opentrons/protocol_api_old/test_module_context.py index 30ec8804721..5f92dd7ba57 100644 --- a/api/tests/opentrons/protocol_api_old/test_module_context.py +++ b/api/tests/opentrons/protocol_api_old/test_module_context.py @@ -1,6 +1,6 @@ -from typing import cast - +from typing import cast, Any, Type import mock +from opentrons.protocol_api.protocol_context import ProtocolContext import pytest import opentrons.protocol_api as papi @@ -113,37 +113,37 @@ def ctx_with_heater_shaker( # ______ load_module tests _______ -def test_load_module(ctx_with_tempdeck): +def test_load_module(ctx_with_tempdeck: papi.ProtocolContext) -> None: ctx_with_tempdeck.home() mod = ctx_with_tempdeck.load_module("tempdeck", 1) assert isinstance(mod, papi.TemperatureModuleContext) -def test_load_module_default_slot(ctx_with_thermocycler): +def test_load_module_default_slot(ctx_with_thermocycler: papi.ProtocolContext) -> None: ctx_with_thermocycler.home() mod = ctx_with_thermocycler.load_module("thermocycler") assert isinstance(mod, papi.ThermocyclerContext) -def test_no_slot_module_error(ctx_with_magdeck): +def test_no_slot_module_error(ctx_with_magdeck: papi.ProtocolContext) -> None: ctx_with_magdeck.home() with pytest.raises(ValueError): assert ctx_with_magdeck.load_module("magdeck") -def test_invalid_slot_module_error(ctx_with_thermocycler): +def test_invalid_slot_module_error(ctx_with_thermocycler: papi.ProtocolContext) -> None: ctx_with_thermocycler.home() with pytest.raises(ValueError): assert ctx_with_thermocycler.load_module("thermocycler", 1) -def test_bad_slot_module_error(ctx_with_tempdeck): +def test_bad_slot_module_error(ctx_with_tempdeck: papi.ProtocolContext) -> None: ctx_with_tempdeck.home() with pytest.raises(ValueError): assert ctx_with_tempdeck.load_module("thermocycler", 42) -def test_incorrect_module_error(ctx_with_tempdeck): +def test_incorrect_module_error(ctx_with_tempdeck: papi.ProtocolContext) -> None: ctx_with_tempdeck.home() with pytest.raises(ValueError): assert ctx_with_tempdeck.load_module("the cool module", 1) @@ -172,7 +172,9 @@ def test_incorrect_module_error(ctx_with_tempdeck): ("heaterShakerModuleV1", papi.HeaterShakerContext, "heaterShakerModuleV1"), ], ) -def test_load_simulating_module(ctx, loadname, klass, model): +def test_load_simulating_module( + ctx: ProtocolContext, loadname: str, klass: Type[papi.ProtocolContext], model: str +) -> None: """Check that a known module will not throw an error if in simulation mode. Note: This is basically an integration test that checks that a module can be @@ -191,7 +193,7 @@ def test_load_simulating_module(ctx, loadname, klass, model): # _________ Magnetic Module tests __________ -def test_magdeck(ctx_with_magdeck, mock_module_controller): +def test_magdeck(ctx_with_magdeck: papi.ProtocolContext) -> None: mod = ctx_with_magdeck.load_module("Magnetic Module", 1) assert ctx_with_magdeck.deck[1] == mod.geometry @@ -199,22 +201,26 @@ def test_magdeck(ctx_with_magdeck, mock_module_controller): # _________ Thermocycler tests __________ -def test_thermocycler(ctx_with_thermocycler, mock_module_controller): +def test_thermocycler(ctx_with_thermocycler: papi.ProtocolContext) -> None: mod = ctx_with_thermocycler.load_module("thermocycler") assert ctx_with_thermocycler.deck[7] == mod.geometry -def test_thermocycler_lid_status(ctx_with_thermocycler, mock_module_controller): +def test_thermocycler_lid_status( + ctx_with_thermocycler: papi.ProtocolContext, mock_module_controller: mock.MagicMock +) -> None: mod = ctx_with_thermocycler.load_module("thermocycler") m = mock.PropertyMock(return_value=ThermocyclerLidStatus.OPEN) + assert isinstance(mod, papi.ThermocyclerContext) type(mock_module_controller).lid_status = m assert mod.lid_position == "open" def test_thermocycler_profile_invalid_repetitions( - ctx_with_thermocycler, mock_module_controller -): + ctx_with_thermocycler: papi.ProtocolContext, mock_module_controller: mock.MagicMock +) -> None: mod = ctx_with_thermocycler.load_module("thermocycler") + assert isinstance(mod, papi.ThermocyclerContext) with pytest.raises(ValueError, match="positive integer"): mod.execute_profile( @@ -227,21 +233,25 @@ def test_thermocycler_profile_invalid_repetitions( def test_thermocycler_profile_no_temperature( - ctx_with_thermocycler, mock_module_controller -): + ctx_with_thermocycler: papi.ProtocolContext, mock_module_controller: mock.MagicMock +) -> None: mod = ctx_with_thermocycler.load_module("thermocycler") + assert isinstance(mod, papi.ThermocyclerContext) with pytest.raises(ValueError, match="temperature must be defined"): mod.execute_profile( steps=[ {"temperature": 10, "hold_time_seconds": 30}, - {"hold_time_seconds": 90}, + {"hold_time_seconds": 90}, # type: ignore ], repetitions=5, ) -def test_thermocycler_profile_no_hold(ctx_with_thermocycler, mock_module_controller): +def test_thermocycler_profile_no_hold( + ctx_with_thermocycler: papi.ProtocolContext, mock_module_controller: mock.MagicMock +) -> None: mod = ctx_with_thermocycler.load_module("thermocycler") + assert isinstance(mod, papi.ThermocyclerContext) with pytest.raises( ValueError, match="either hold_time_minutes or hold_time_seconds" ): @@ -252,7 +262,7 @@ def test_thermocycler_profile_no_hold(ctx_with_thermocycler, mock_module_control @pytest.mark.apiv2_non_pe_only # Semi plate configuration removed in PAPIv2.14. -def test_thermocycler_semi_plate_configuration(ctx): +def test_thermocycler_semi_plate_configuration(ctx: papi.ProtocolContext) -> None: labware_name = "nest_96_wellplate_100ul_pcr_full_skirt" mod = ctx.load_module("thermocycler", configuration="semi") assert mod.geometry.labware_offset == Point(-23.28, 82.56, 97.8) @@ -267,7 +277,9 @@ def test_thermocycler_semi_plate_configuration(ctx): assert tc_well_name == other_well_name -def test_thermocycler_flag_unsafe_move(ctx_with_thermocycler, mock_module_controller): +def test_thermocycler_flag_unsafe_move( + ctx_with_thermocycler: papi.ProtocolContext, mock_module_controller: mock.MagicMock +) -> None: """Flag unsafe should raise if the lid is open and source or target is the labware on thermocycler.""" mod = ctx_with_thermocycler.load_module("thermocycler", configuration="semi") @@ -280,6 +292,8 @@ def test_thermocycler_flag_unsafe_move(ctx_with_thermocycler, mock_module_contro m = mock.PropertyMock(return_value=ThermocyclerLidStatus.CLOSED) type(mock_module_controller).lid_status = m + assert isinstance(mod, papi.ProtocolContext) + with pytest.raises(RuntimeError, match="Cannot move to labware"): mod._core.flag_unsafe_move(with_tc_labware, without_tc_labware) with pytest.raises(RuntimeError, match="Cannot move to labware"): @@ -330,7 +344,7 @@ def test_hs_flag_unsafe_move_raises( ) -> None: """Test unsafe move raises underlying error.""" - def raiser(*args, **kwargs): + def raiser(*args: Any, **kwargs: Any) -> None: raise PipetteMovementRestrictedByHeaterShakerError("uh oh") mod = ctx_with_heater_shaker.load_module("heaterShakerModuleV1", 3) @@ -370,7 +384,7 @@ def test_heater_shaker_loading( # __________ Testing loading Labware on modules ___________ -def test_module_load_labware(ctx_with_tempdeck): +def test_module_load_labware(ctx_with_tempdeck: papi.ProtocolContext) -> None: labware_name = "corning_96_wellplate_360ul_flat" # TODO Ian 2019-05-29 load fixtures, not real defs labware_def = load_labware_definition(labware_name, 1) @@ -382,18 +396,21 @@ def test_module_load_labware(ctx_with_tempdeck): labware_def["cornerOffsetFromSlot"]["y"], labware_def["cornerOffsetFromSlot"]["z"], ) + assert isinstance(mod, papi.ProtocolContext) assert lw._core.get_geometry().offset == lw_offset + mod.geometry.location.point assert lw.name == labware_name -def test_module_load_labware_with_label(ctx_with_tempdeck): +def test_module_load_labware_with_label( + ctx_with_tempdeck: papi.ProtocolContext, +) -> None: labware_name = "corning_96_wellplate_360ul_flat" mod = ctx_with_tempdeck.load_module("Temperature Module", 1) lw = mod.load_labware(labware_name, label="my cool labware") assert lw.name == "my cool labware" -def test_module_load_invalid_labware(ctx_with_tempdeck): +def test_module_load_invalid_labware(ctx_with_tempdeck: papi.ProtocolContext) -> None: labware_name = "corning_96_wellplate_360ul_flat" mod = ctx_with_tempdeck.load_module("Temperature Module", 1) # wrong version number @@ -406,9 +423,12 @@ def test_module_load_invalid_labware(ctx_with_tempdeck): assert mod.load_labware(labware_name, namespace="opentrons", version=1) -def test_deprecated_module_load_labware_by_name(ctx_with_tempdeck): +def test_deprecated_module_load_labware_by_name( + ctx_with_tempdeck: papi.ProtocolContext, +) -> None: """It should call load labware""" mod = ctx_with_tempdeck.load_module("Temperature Module", 1) + assert isinstance(mod, papi.ProtocolContext) mod.load_labware = mock.MagicMock() mod.load_labware_by_name( name="a module", namespace="ns", label="a label", version=2 @@ -419,12 +439,13 @@ def test_deprecated_module_load_labware_by_name(ctx_with_tempdeck): @pytest.mark.apiv2_non_pe_only # engage(height=...) param was removed in PAPIv2.14. -async def test_magdeck_gen1_labware_props(ctx): +async def test_magdeck_gen1_labware_props(ctx: papi.ProtocolContext) -> None: # TODO Ian 2019-05-29 load fixtures, not real defs labware_name = "biorad_96_wellplate_200ul_pcr" labware_def = load_labware_definition(labware_name, 1) mod = ctx.load_module("magdeck", 1) assert mod.labware is None + assert isinstance(mod, papi.ProtocolContext) mod.engage(height=45) assert mod._core._sync_module_hardware.current_height == 45 with pytest.raises(ValueError): @@ -461,8 +482,9 @@ async def test_magdeck_gen1_labware_props(ctx): @pytest.mark.apiv2_non_pe_only # engage(height=...) param was removed in PAPIv2.14. -def test_magdeck_gen2_labware_props(ctx): +def test_magdeck_gen2_labware_props(ctx: papi.ProtocolContext) -> None: mod = ctx.load_module("magnetic module gen2", 1) + assert isinstance(mod, papi.ProtocolContext) mod.engage(height=25) assert mod._core._sync_module_hardware.current_height == 25 with pytest.raises(ValueError): @@ -471,7 +493,7 @@ def test_magdeck_gen2_labware_props(ctx): assert mod._core._sync_module_hardware.current_height == 0 -def test_module_compatibility(): +def test_module_compatibility() -> None: assert ( models_compatible( requested_model=ThermocyclerModuleModel.THERMOCYCLER_V1,