From 7e3f1e69c9f9bd7898bfee9d52008f9d38706aa7 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Tue, 6 Sep 2022 12:56:40 -0400 Subject: [PATCH] feat(shared-data): add robot definitions (#11428) Add some quick and small json files that can represent kinds of robot, primarily as a thing for other files to reference. Closes RCORE-126 --- shared-data/js/types.ts | 8 +++++ .../opentrons_shared_data/robot/__init__.py | 25 ++++++++++++++++ .../opentrons_shared_data/robot/dev_types.py | 17 +++++++++++ shared-data/python/setup.py | 2 +- shared-data/python/tests/robot/__init__.py | 0 .../python/tests/robot/test_typechecks.py | 20 +++++++++++++ shared-data/robot/definitions/1/ot2.json | 5 ++++ shared-data/robot/definitions/1/ot3.json | 5 ++++ shared-data/robot/schemas/1.json | 30 +++++++++++++++++++ 9 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 shared-data/python/opentrons_shared_data/robot/__init__.py create mode 100644 shared-data/python/opentrons_shared_data/robot/dev_types.py create mode 100644 shared-data/python/tests/robot/__init__.py create mode 100644 shared-data/python/tests/robot/test_typechecks.py create mode 100644 shared-data/robot/definitions/1/ot2.json create mode 100644 shared-data/robot/definitions/1/ot3.json create mode 100644 shared-data/robot/schemas/1.json diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index 8b4f96a6bf5..c2789c894af 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -22,6 +22,14 @@ import type { INode } from 'svgson' import type { RunTimeCommand } from '../protocol' import type { PipetteName } from './pipettes' +export type RobotName = 'OT-2 Standard' | 'OT-3 Standard' + +export interface RobotDefinition { + displayName: string + robotName: RobotName + models: string[] +} + // TODO Ian 2019-06-04 split this out into eg ../labware/flowTypes/labwareV1.js export interface WellDefinition { diameter?: number diff --git a/shared-data/python/opentrons_shared_data/robot/__init__.py b/shared-data/python/opentrons_shared_data/robot/__init__.py new file mode 100644 index 00000000000..53927f56c3f --- /dev/null +++ b/shared-data/python/opentrons_shared_data/robot/__init__.py @@ -0,0 +1,25 @@ +"""opentrons_shared_data.robot: Submodule for handling robot definition data.""" +from pathlib import Path +from typing import cast +from typing_extensions import Final + +import json + +from .. import get_shared_data_root + +from .dev_types import RobotDefinition, RobotName + +DEFAULT_ROBOT_DEFINITION_VERSION: Final = 1 + + +def load( + robot_name: RobotName, version: int = DEFAULT_ROBOT_DEFINITION_VERSION +) -> RobotDefinition: + """Load the definition for the specified robot id.""" + for fi in Path( + get_shared_data_root() / "robot" / "definitions" / f"{version}" + ).iterdir(): + defn = json.load(fi.open("r")) + if defn["robotName"] == robot_name: + return cast(RobotDefinition, defn) + raise KeyError(robot_name) diff --git a/shared-data/python/opentrons_shared_data/robot/dev_types.py b/shared-data/python/opentrons_shared_data/robot/dev_types.py new file mode 100644 index 00000000000..d207d202c81 --- /dev/null +++ b/shared-data/python/opentrons_shared_data/robot/dev_types.py @@ -0,0 +1,17 @@ +"""opentrons_shared_data.robot.dev_types: types for robot def.""" +from typing import NewType, List, Dict, Any +from typing_extensions import Literal, TypedDict + +RobotSchemaVersion1 = Literal[1] + +RobotSchema = NewType("RobotSchema", Dict[str, Any]) + +RobotName = Literal["OT-2 Standard", "OT-3 Standard"] + + +class RobotDefinition(TypedDict): + """A python version of the robot definition type.""" + + displayName: str + robotName: RobotName + models: List[str] diff --git a/shared-data/python/setup.py b/shared-data/python/setup.py index cecf3f691fb..8cc3912b02d 100644 --- a/shared-data/python/setup.py +++ b/shared-data/python/setup.py @@ -21,7 +21,7 @@ fcntl.fcntl(sys.stdout, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) DATA_ROOT = ".." -DATA_SUBDIRS = ["deck", "labware", "module", "pipette", "protocol", "gripper"] +DATA_SUBDIRS = ["deck", "labware", "module", "pipette", "protocol", "gripper", "robot"] DATA_TYPES = ["definitions", "schemas"] DEST_BASE_PATH = "data" diff --git a/shared-data/python/tests/robot/__init__.py b/shared-data/python/tests/robot/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/shared-data/python/tests/robot/test_typechecks.py b/shared-data/python/tests/robot/test_typechecks.py new file mode 100644 index 00000000000..ea0f7dd7542 --- /dev/null +++ b/shared-data/python/tests/robot/test_typechecks.py @@ -0,0 +1,20 @@ +import sys + +import pytest +import typeguard + + +from opentrons_shared_data.robot import load +from opentrons_shared_data.robot.dev_types import RobotDefinition, RobotName + +pytestmark = pytest.mark.xfail( + condition=sys.version_info >= (3, 10), + reason="https://github.com/agronholm/typeguard/issues/242", +) + + +@pytest.mark.parametrize("defname", ["OT-2 Standard", "OT-3 Standard"]) +def test_v1_defs(defname: RobotName) -> None: + defn = load(robot_name=defname, version=1) + typeguard.check_type("defn", defn, RobotDefinition) + assert defn["robotName"] == defname diff --git a/shared-data/robot/definitions/1/ot2.json b/shared-data/robot/definitions/1/ot2.json new file mode 100644 index 00000000000..094db42ecc4 --- /dev/null +++ b/shared-data/robot/definitions/1/ot2.json @@ -0,0 +1,5 @@ +{ + "displayName": "OT-2", + "robotName": "OT-2 Standard", + "models": ["OT-2 Standard", "OT-2 Refresh"] +} diff --git a/shared-data/robot/definitions/1/ot3.json b/shared-data/robot/definitions/1/ot3.json new file mode 100644 index 00000000000..15346626c68 --- /dev/null +++ b/shared-data/robot/definitions/1/ot3.json @@ -0,0 +1,5 @@ +{ + "displayName": "OT-3", + "robotName": "OT-3 Standard", + "models": ["OT-3 Standard"] +} diff --git a/shared-data/robot/schemas/1.json b/shared-data/robot/schemas/1.json new file mode 100644 index 00000000000..8001f9363b8 --- /dev/null +++ b/shared-data/robot/schemas/1.json @@ -0,0 +1,30 @@ +{ + "$id": "opentronsRobotSchemaV1", + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "robotName": { + "type": "string", + "enum": ["OT-2 Standard", "OT-3 Standard"] + } + }, + "description": "Describes an Opentrons liquid handling robot.", + "type": "object", + "required": ["displayName", "robotName", "models"], + "properties": { + "displayName": { + "description": "A user-facing friendly name for the machine.", + "type": "string" + }, + "robotName": { + "description": "A machine-readable but still printable name for the machine.", + "type": "#/definitions/robotName" + }, + "models": { + "description": "A list of robot models.", + "type": "array", + "items": { + "type": "string" + } + } + } +}