Skip to content

Commit

Permalink
feat(shared-data, app, protocol-designer, api-client, api, robot-serv…
Browse files Browse the repository at this point in the history
…er): schemaV7 migration (#13007)

closes RAUT-515 and RAUT-272 and RQA-1128
---------

Co-authored-by: TamarZanzouri <[email protected]>
  • Loading branch information
jerader and TamarZanzouri authored Jul 26, 2023
1 parent a87555f commit 9f29c9d
Show file tree
Hide file tree
Showing 136 changed files with 20,928 additions and 1,960 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { POST, request } from '../request'

import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV6'
import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV7'
import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { CommandData, CreateCommandParams } from '../runs/types'
Expand Down
4 changes: 2 additions & 2 deletions api-client/src/protocols/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import type {
LoadedLabware,
LoadedModule,
} from '@opentrons/shared-data'
import type { RunTimeCommand } from '@opentrons/shared-data/protocol/types/schemaV6'
import type { RunTimeCommand } from '@opentrons/shared-data/protocol/types/schemaV7'
import type {
LoadLabwareRunTimeCommand,
LoadModuleRunTimeCommand,
LoadPipetteRunTimeCommand,
LoadLiquidRunTimeCommand,
} from '@opentrons/shared-data/protocol/types/schemaV6/command/setup'
} from '@opentrons/shared-data/protocol/types/schemaV7/command/setup'

interface PipetteNamesByMount {
left: PipetteName | null
Expand Down
2 changes: 1 addition & 1 deletion api-client/src/runs/commands/createCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { ResponsePromise } from '../../request'
import type { HostConfig } from '../../types'
import type { CommandData } from '../types'
import type { CreateCommandParams } from './types'
import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV6'
import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV7'

export function createCommand(
config: HostConfig,
Expand Down
2 changes: 1 addition & 1 deletion api-client/src/runs/commands/createLiveCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { ResponsePromise } from '../../request'
import type { HostConfig } from '../../types'
import type { CommandData } from '../types'
import type { CreateCommandParams } from './types'
import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV6'
import type { CreateCommand } from '@opentrons/shared-data/protocol/types/schemaV7'

export function createLiveCommand(
config: HostConfig,
Expand Down
9 changes: 7 additions & 2 deletions api/src/opentrons/protocol_reader/file_format_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from pydantic import ValidationError as PydanticValidationError

from opentrons_shared_data.labware.labware_definition import LabwareDefinition
from opentrons_shared_data.protocol.models import ProtocolSchemaV6 as JsonProtocolV6
from opentrons_shared_data.protocol.models import (
ProtocolSchemaV6 as JsonProtocolV6,
ProtocolSchemaV7 as JsonProtocolV7,
)

from opentrons.protocols.models import JsonProtocol as JsonProtocolUpToV5

Expand Down Expand Up @@ -57,7 +60,9 @@ def validate_sync() -> None:
async def _validate_json_protocol(info: IdentifiedJsonMain) -> None:
def validate_sync() -> None:
try:
if info.schema_version == 6:
if info.schema_version == 7:
JsonProtocolV7.parse_obj(info.unvalidated_json)
elif info.schema_version == 6:
JsonProtocolV6.parse_obj(info.unvalidated_json)
else:
JsonProtocolUpToV5.parse_obj(info.unvalidated_json)
Expand Down
16 changes: 13 additions & 3 deletions api/src/opentrons/protocol_runner/json_file_reader.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
"""JSON file reading."""
from typing import Union

from opentrons_shared_data.protocol.models.protocol_schema_v6 import ProtocolSchemaV6
from opentrons.protocol_reader import ProtocolSource
from opentrons_shared_data.protocol.models.protocol_schema_v7 import ProtocolSchemaV7
from opentrons.protocol_reader import ProtocolSource, JsonProtocolConfig


class JsonFileReader:
"""Reads and parses JSON protocol files."""

@staticmethod
def read(protocol_source: ProtocolSource) -> ProtocolSchemaV6:
def read(
protocol_source: ProtocolSource,
) -> Union[ProtocolSchemaV6, ProtocolSchemaV7]:
"""Read and parse file into a JsonProtocol model."""
return ProtocolSchemaV6.parse_file(protocol_source.main_file)
if (
isinstance(protocol_source.config, JsonProtocolConfig)
and protocol_source.config.schema_version == 6
):
return ProtocolSchemaV6.parse_file(protocol_source.main_file)
else:
return ProtocolSchemaV7.parse_file(protocol_source.main_file)
112 changes: 105 additions & 7 deletions api/src/opentrons/protocol_runner/json_translator.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
"""Translation of JSON protocol commands into ProtocolEngine commands."""
from typing import cast, List
from typing import cast, List, Union
from pydantic import parse_obj_as

from opentrons_shared_data.pipette.dev_types import PipetteNameType
from opentrons_shared_data.protocol.models import ProtocolSchemaV6, protocol_schema_v6
from opentrons_shared_data.protocol.models import (
ProtocolSchemaV6,
protocol_schema_v6,
ProtocolSchemaV7,
protocol_schema_v7,
)

from opentrons.types import MountType
from opentrons.protocol_engine import (
Expand All @@ -23,7 +28,8 @@ class CommandTranslatorError(Exception):


def _translate_labware_command(
protocol: ProtocolSchemaV6, command: protocol_schema_v6.Command
protocol: ProtocolSchemaV6,
command: protocol_schema_v6.Command,
) -> pe_commands.LoadLabwareCreate:
labware_id = command.params.labwareId
# v6 data model supports all commands and therefor most props are optional.
Expand All @@ -49,8 +55,38 @@ def _translate_labware_command(
return labware_command


def _translate_v7_labware_command(
command: protocol_schema_v7.Command,
) -> pe_commands.LoadLabwareCreate:
labware_id = command.params.labwareId
# v7 data model supports all commands and therefor most props are optional.
# load labware command must contain labware_id and definition_id.
assert labware_id is not None
assert command.params.version is not None
assert command.params.namespace is not None
assert command.params.loadName is not None

labware_command = pe_commands.LoadLabwareCreate(
params=pe_commands.LoadLabwareParams(
labwareId=command.params.labwareId,
displayName=command.params.displayName,
version=command.params.version,
namespace=command.params.namespace,
loadName=command.params.loadName,
location=parse_obj_as(
# https://github.com/samuelcolvin/pydantic/issues/1847
LabwareLocation, # type: ignore[arg-type]
command.params.location,
),
),
key=command.key,
)
return labware_command


def _translate_module_command(
protocol: ProtocolSchemaV6, command: protocol_schema_v6.Command
protocol: ProtocolSchemaV6,
command: protocol_schema_v6.Command,
) -> pe_commands.CommandCreate:
module_id = command.params.moduleId
modules = protocol.modules
Expand All @@ -69,8 +105,28 @@ def _translate_module_command(
return translated_obj


def _translate_v7_module_command(
command: protocol_schema_v7.Command,
) -> pe_commands.CommandCreate:
module_id = command.params.moduleId
# v7 data model supports all commands and therefor most props are optional.
# load module command must contain module_id. modules cannot be None.
assert module_id is not None
assert command.params.model is not None
translated_obj = pe_commands.LoadModuleCreate(
params=pe_commands.LoadModuleParams(
model=ModuleModel(command.params.model),
location=DeckSlotLocation.parse_obj(command.params.location),
moduleId=command.params.moduleId,
),
key=command.key,
)
return translated_obj


def _translate_pipette_command(
protocol: ProtocolSchemaV6, command: protocol_schema_v6.Command
protocol: ProtocolSchemaV6,
command: protocol_schema_v6.Command,
) -> pe_commands.CommandCreate:
pipette_id = command.params.pipetteId
# v6 data model supports all commands and therefor most props are optional.
Expand All @@ -87,8 +143,27 @@ def _translate_pipette_command(
return translated_obj


def _translate_v7_pipette_command(
command: protocol_schema_v7.Command,
) -> pe_commands.CommandCreate:
pipette_id = command.params.pipetteId
# v7 data model supports all commands and therefor most props are optional.
# load pipette command must contain pipette_id.
assert pipette_id is not None
assert command.params.pipetteName is not None
translated_obj = pe_commands.LoadPipetteCreate(
params=pe_commands.LoadPipetteParams(
pipetteName=PipetteNameType(command.params.pipetteName),
mount=MountType(command.params.mount),
pipetteId=command.params.pipetteId,
),
key=command.key,
)
return translated_obj


def _translate_simple_command(
command: protocol_schema_v6.Command,
command: Union[protocol_schema_v6.Command, protocol_schema_v7.Command]
) -> pe_commands.CommandCreate:
dict_command = command.dict(exclude_none=True)

Expand All @@ -113,7 +188,9 @@ def _translate_simple_command(
class JsonTranslator:
"""Class that translates commands/liquids from PD/JSON to ProtocolEngine."""

def translate_liquids(self, protocol: ProtocolSchemaV6) -> List[Liquid]:
def translate_liquids(
self, protocol: Union[ProtocolSchemaV6, ProtocolSchemaV7]
) -> List[Liquid]:
"""Takes json protocol v6 and translates liquids->protocol engine liquids."""
protocol_liquids = protocol.liquids or {}

Expand All @@ -130,6 +207,16 @@ def translate_liquids(self, protocol: ProtocolSchemaV6) -> List[Liquid]:
]

def translate_commands(
self,
protocol: Union[ProtocolSchemaV7, ProtocolSchemaV6],
) -> List[pe_commands.CommandCreate]:
"""Takes json protocol and translates commands->protocol engine commands."""
if isinstance(protocol, ProtocolSchemaV6):
return self._translate_v6_commands(protocol)
else:
return self._translate_v7_commands(protocol)

def _translate_v6_commands(
self,
protocol: ProtocolSchemaV6,
) -> List[pe_commands.CommandCreate]:
Expand All @@ -146,3 +233,14 @@ def translate_commands(
translated_obj = _translate_simple_command(command)
commands_list.append(translated_obj)
return commands_list

def _translate_v7_commands(
self,
protocol: Union[ProtocolSchemaV7],
) -> List[pe_commands.CommandCreate]:
"""Takes json protocol v7 and translates commands->protocol engine commands."""
commands_list: List[pe_commands.CommandCreate] = []
for command in protocol.commands:
translated_obj = _translate_simple_command(command)
commands_list.append(translated_obj)
return commands_list
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
(4, "protocol/fixtures/4/simpleV4.json"),
(5, "protocol/fixtures/5/simpleV5.json"),
(6, "protocol/fixtures/6/simpleV6.json"),
# todo(mm, 2022-12-22): Add simpleV7 when we support that in production.
(7, "protocol/fixtures/7/simpleV7.json"),
],
)
async def test_valid_json_main_file(
Expand Down Expand Up @@ -73,9 +73,8 @@ async def test_valid_python_main_file() -> None:


@pytest.mark.parametrize(
# todo(mm, 2022-12-22): Add v7+ when we support that in production.
"identified_schema_version",
range(3, 7),
range(3, 8),
)
async def test_invalid_json_main(identified_schema_version: int) -> None:
"""It should raise when non-conforming JSON is provided as a main file."""
Expand Down
14 changes: 13 additions & 1 deletion api/tests/opentrons/protocol_reader/test_file_identifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,19 @@ class _ValidJsonProtocolSpec:
"spec",
[
# Basic JSON protocols of various versions:
# todo(mm, 2022-12-22): Add a v7 protocol when we support that in production.
_ValidJsonProtocolSpec(
file_name="foo.json",
contents=load_shared_data("protocol/fixtures/7/simpleV7.json"),
expected_schema_version=7,
expected_robot_type="OT-2 Standard",
expected_metadata={
"protocolName": "Simple test protocol",
"author": "engineering <[email protected]>",
"description": "A short test protocol",
"created": 1223131231,
"tags": ["unitTest"],
},
),
_ValidJsonProtocolSpec(
file_name="foo.json",
contents=load_shared_data("protocol/fixtures/6/simpleV6.json"),
Expand Down
Loading

0 comments on commit 9f29c9d

Please sign in to comment.