Skip to content

Commit

Permalink
Modifed get_robot_type to be parameterized on some singleton class …
Browse files Browse the repository at this point in the history
…types for robot models
  • Loading branch information
fsinapi committed Dec 6, 2023
1 parent 34cc782 commit 629ac67
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 33 deletions.
5 changes: 1 addition & 4 deletions api/src/opentrons/hardware_control/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
pipette_load_name_conversions as pipette_load_name,
)
from opentrons_shared_data.pipette.dev_types import PipetteName
from opentrons_shared_data.robot.dev_types import RobotType, RobotTypeEnum
from opentrons_shared_data.robot.dev_types import RobotType
from opentrons import types as top_types
from opentrons.config import robot_configs
from opentrons.config.types import RobotConfig, OT3Config
Expand Down Expand Up @@ -302,9 +302,6 @@ async def build_hardware_simulator(
def __repr__(self) -> str:
return "<{} using backend {}>".format(type(self), type(self._backend))

def get_robot_type(self) -> RobotTypeEnum:
return RobotTypeEnum.OT2

async def get_serial_number(self) -> Optional[str]:
return await self._backend.get_serial_number()

Expand Down
5 changes: 1 addition & 4 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from opentrons_shared_data.pipette import (
pipette_load_name_conversions as pipette_load_name,
)
from opentrons_shared_data.robot.dev_types import RobotType, RobotTypeEnum
from opentrons_shared_data.robot.dev_types import RobotType
from opentrons_shared_data.errors.exceptions import (
StallOrCollisionDetectedError,
)
Expand Down Expand Up @@ -291,9 +291,6 @@ async def set_gantry_load(self, gantry_load: GantryLoad) -> None:
)
await self._backend.update_to_default_current_settings(gantry_load)

def get_robot_type(self) -> RobotTypeEnum:
return RobotTypeEnum.FLEX

async def get_serial_number(self) -> Optional[str]:
return await self._backend.get_serial_number()

Expand Down
28 changes: 22 additions & 6 deletions api/src/opentrons/hardware_control/protocols/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Typing protocols describing a hardware controller."""
from typing_extensions import Protocol
from typing_extensions import Protocol, Type

from .module_provider import ModuleProvider
from .hardware_manager import HardwareManager
Expand All @@ -19,7 +19,13 @@
from .flex_calibratable import FlexCalibratable
from .flex_instrument_configurer import FlexInstrumentConfigurer

from .types import CalibrationType, MountArgType, ConfigType
from .types import (
CalibrationType,
MountArgType,
ConfigType,
OT2RobotType,
FlexRobotType,
)


class HardwareControlInterface(
Expand All @@ -31,7 +37,7 @@ class HardwareControlInterface(
AsyncioConfigurable,
Stoppable,
Simulatable,
Identifiable,
Identifiable[Type[OT2RobotType]],
Protocol[CalibrationType, MountArgType, ConfigType],
):
"""A mypy protocol for a hardware controller.
Expand All @@ -48,14 +54,23 @@ class HardwareControlInterface(
however, they can satisfy protocols.
"""

...
def get_robot_type(self) -> Type[OT2RobotType]:
return OT2RobotType


class FlexHardwareControlInterface(
HardwareControlInterface[CalibrationType, MountArgType, ConfigType],
ModuleProvider,
ExecutionControllable,
LiquidHandler[CalibrationType, MountArgType, ConfigType],
ChassisAccessoryManager,
HardwareManager,
AsyncioConfigurable,
Stoppable,
Simulatable,
GripperController,
FlexCalibratable,
FlexInstrumentConfigurer[MountArgType],
Identifiable[Type[FlexRobotType]],
Protocol[CalibrationType, MountArgType, ConfigType],
):
"""A mypy protocol for a hardware controller with Flex-specific extensions.
Expand All @@ -64,7 +79,8 @@ class FlexHardwareControlInterface(
with some additional functionality and parameterization not supported on the OT-2.
"""

...
def get_robot_type(self) -> Type[FlexRobotType]:
return FlexRobotType


__all__ = [
Expand Down
7 changes: 4 additions & 3 deletions api/src/opentrons/hardware_control/protocols/identifiable.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing_extensions import Protocol
from opentrons_shared_data.robot.dev_types import RobotTypeEnum

from .types import ProtocolRobotType

class Identifiable(Protocol):

class Identifiable(Protocol[ProtocolRobotType]):
"""Protocol specifying support for hardware identification."""

def get_robot_type(self) -> RobotTypeEnum:
def get_robot_type(self) -> ProtocolRobotType:
"""Return the enumerated robot type that this API controls.
When a caller needs to determine whether an API function is expected
Expand Down
14 changes: 13 additions & 1 deletion api/src/opentrons/hardware_control/protocols/types.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
"""Types that are common across protocols."""

from typing import TypeVar, Union
from typing import TypeVar, Union, Type
from opentrons.hardware_control.types import OT3Mount
from opentrons.types import Mount
from opentrons.config.types import RobotConfig, OT3Config


class OT2RobotType:
pass


class FlexRobotType:
pass


CalibrationType = TypeVar("CalibrationType")

MountArgType = TypeVar(
"MountArgType", Mount, Union[OT3Mount, Mount], contravariant=True
)

ConfigType = TypeVar("ConfigType", RobotConfig, OT3Config)

ProtocolRobotType = TypeVar(
"ProtocolRobotType", Type[FlexRobotType], Type[OT2RobotType], covariant=True
)
12 changes: 6 additions & 6 deletions api/src/opentrons/protocol_engine/resources/ot3_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional, TYPE_CHECKING

from opentrons.protocol_engine.errors import HardwareNotSupportedError
from opentrons_shared_data.robot.dev_types import RobotTypeEnum
from opentrons.hardware_control.protocols.types import FlexRobotType

if TYPE_CHECKING:
from opentrons.hardware_control import HardwareControlAPI, OT3HardwareControlAPI
Expand All @@ -14,9 +14,9 @@ def ensure_ot3_hardware(
error_msg: Optional[str] = None,
) -> OT3HardwareControlAPI:
"""Validate that the HardwareControlAPI is of OT-3 instance."""
if hardware_api.get_robot_type() != RobotTypeEnum.FLEX:
raise HardwareNotSupportedError(
error_msg or "This command is supported by OT-3 only."
)
if hardware_api.get_robot_type() == FlexRobotType:
return hardware_api # type: ignore

return hardware_api # type: ignore
raise HardwareNotSupportedError(
error_msg or "This command is supported by OT-3 only."
)
8 changes: 5 additions & 3 deletions api/tests/opentrons/protocol_engine/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from opentrons.hardware_control import HardwareControlAPI, OT2HardwareControlAPI
from opentrons.hardware_control.api import API
from opentrons_shared_data.robot.dev_types import RobotTypeEnum
from opentrons.hardware_control.protocols.types import FlexRobotType, OT2RobotType

if TYPE_CHECKING:
from opentrons.hardware_control.ot3api import OT3API
Expand All @@ -35,7 +35,9 @@ def hardware_api(decoy: Decoy) -> HardwareControlAPI:
@pytest.fixture
def ot2_hardware_api(decoy: Decoy) -> API:
"""Get a mocked out OT-2 hardware API."""
return decoy.mock(cls=API)
mock = decoy.mock(cls=API)
decoy.when(mock.get_robot_type()).then_return(OT2RobotType)
return mock


@pytest.mark.ot3_only
Expand All @@ -46,7 +48,7 @@ def ot3_hardware_api(decoy: Decoy) -> OT3API:
from opentrons.hardware_control.ot3api import OT3API

mock = decoy.mock(cls=OT3API)
decoy.when(mock.get_robot_type()).then_return(RobotTypeEnum.FLEX)
decoy.when(mock.get_robot_type()).then_return(FlexRobotType)
return mock
except ImportError:
# TODO (tz, 9-23-22) Figure out a better way to use this fixture with OT-3 api only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from opentrons.protocol_engine.errors.exceptions import HardwareNotSupportedError

from opentrons.hardware_control.api import API
from opentrons_shared_data.robot.dev_types import RobotTypeEnum
from opentrons.hardware_control.protocols.types import FlexRobotType, OT2RobotType


@pytest.mark.ot3_only
Expand All @@ -17,7 +17,7 @@ def test_ensure_ot3_hardware(decoy: Decoy) -> None:
from opentrons.hardware_control.ot3api import OT3API

ot_3_hardware_api = decoy.mock(cls=OT3API)
decoy.when(ot_3_hardware_api.get_robot_type()).then_return(RobotTypeEnum.FLEX)
decoy.when(ot_3_hardware_api.get_robot_type()).then_return(FlexRobotType)
result = ensure_ot3_hardware(
ot_3_hardware_api,
)
Expand All @@ -30,7 +30,7 @@ def test_ensure_ot3_hardware(decoy: Decoy) -> None:
def test_ensure_ot3_hardware_raises_error(decoy: Decoy) -> None:
"""Should raise a HardwareNotSupportedError exception."""
ot_2_hardware_api = decoy.mock(cls=API)
decoy.when(ot_2_hardware_api.get_robot_type()).then_return(RobotTypeEnum.OT2)
decoy.when(ot_2_hardware_api.get_robot_type()).then_return(OT2RobotType)
with pytest.raises(HardwareNotSupportedError):
ensure_ot3_hardware(
ot_2_hardware_api,
Expand Down
6 changes: 3 additions & 3 deletions robot-server/tests/instruments/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
GripperModel,
)
from opentrons_shared_data.pipette.dev_types import PipetteName, PipetteModel
from opentrons_shared_data.robot.dev_types import RobotTypeEnum
from opentrons.hardware_control.protocols.types import FlexRobotType, OT2RobotType

from robot_server.instruments.instrument_models import (
Gripper,
Expand All @@ -52,7 +52,7 @@
def ot2_hardware_api(decoy: Decoy) -> HardwareControlAPI:
"""Get a mock hardware control API."""
mock = decoy.mock(cls=API)
decoy.when(mock.get_robot_type()).then_return(RobotTypeEnum.OT2)
decoy.when(mock.get_robot_type()).then_return(OT2RobotType)
return mock


Expand Down Expand Up @@ -81,7 +81,7 @@ def ot3_hardware_api(decoy: Decoy) -> HardwareControlAPI:
from opentrons.hardware_control.ot3api import OT3API

mock = decoy.mock(cls=OT3API)
decoy.when(mock.get_robot_type()).then_return(RobotTypeEnum.FLEX)
decoy.when(mock.get_robot_type()).then_return(FlexRobotType)
return mock
except ImportError:
return None # type: ignore[return-value]
Expand Down

0 comments on commit 629ac67

Please sign in to comment.