Skip to content

Commit

Permalink
refactor(api): add scaffolding for opentrons.file_runner module (#7757)
Browse files Browse the repository at this point in the history
Closes #7644
  • Loading branch information
mcous authored May 3, 2021
1 parent be85f3e commit 60df556
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 1 deletion.
6 changes: 5 additions & 1 deletion api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ ot_shared_data_sources := $(filter %.json,$(shell $(SHX) find ../shared-data/))
ot_resources := $(filter %,$(shell $(SHX) find src/opentrons/resources))
ot_sources := $(ot_py_sources) $(ot_shared_data_sources) $(ot_resources)

ot_tests_to_typecheck := tests/opentrons/protocol_api_experimental tests/opentrons/protocol_engine tests/opentrons/motion_planning
ot_tests_to_typecheck := \
tests/opentrons/protocol_api_experimental \
tests/opentrons/protocol_engine \
tests/opentrons/motion_planning \
tests/opentrons/file_runner

# Defined separately than the clean target so the wheel file doesn’t have to
# depend on a PHONY target
Expand Down
25 changes: 25 additions & 0 deletions api/src/opentrons/file_runner/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Protocol file runner module.
This module is responsible for logic that interprets different
types of protocol files in order to execute their logic. Primary
responsibilities of this module are:
- Extract metadata from protocol files
- Translate protocol file commands into ProtocolEngine commands
- Dispatch ProtocolEngine commands to an engine instance
"""

from .abstract_file_runner import AbstractFileRunner
from .json_file_runner import JsonFileRunner
from .python_file_runner import PythonFileRunner
from .protocol_file import ProtocolFile, ProtocolFileType

__all__ = [
# runner interfaces
"AbstractFileRunner",
"JsonFileRunner",
"PythonFileRunner",
# value objects
"ProtocolFile",
"ProtocolFileType",
]
21 changes: 21 additions & 0 deletions api/src/opentrons/file_runner/abstract_file_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Abstract interfaces for protocol file running."""
from abc import ABC, abstractmethod


class AbstractFileRunner(ABC):
"""Abstract interface for an object that can run protocol files."""

@abstractmethod
def play(self) -> None:
"""Start (or un-pause) running the protocol file."""
...

@abstractmethod
def pause(self) -> None:
"""Pause the running protocol file's execution."""
...

@abstractmethod
def stop(self) -> None:
"""Cancel the running protocol file."""
...
18 changes: 18 additions & 0 deletions api/src/opentrons/file_runner/json_file_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""File runner interfaces for JSON protocols."""
from .abstract_file_runner import AbstractFileRunner


class JsonFileRunner(AbstractFileRunner):
"""JSON protocol file runner."""

def play(self) -> None:
"""Start (or un-pause) running the JSON protocol file."""
raise NotImplementedError()

def pause(self) -> None:
"""Pause the running JSON protocol file's execution."""
raise NotImplementedError()

def stop(self) -> None:
"""Cancel the running JSON protocol file."""
raise NotImplementedError()
30 changes: 30 additions & 0 deletions api/src/opentrons/file_runner/protocol_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Value objects and models representing protocol files."""
# TODO(mc, 2021-04-30): as these objects are fleshed out, pull in
# existing logic and models from:
# - api/src/opentrons/protocols/types.py
# - robot-server/robot_server/service/protocol/models.py
from dataclasses import dataclass
from enum import Enum


class ProtocolFileType(str, Enum):
"""Type of a protocol file.
Attributes:
PYTHON: a Python protocol file or module
JSON: a JSON protocol
"""

PYTHON = "python"
JSON = "json"


@dataclass(frozen=True)
class ProtocolFile:
"""A value object representing a protocol file on disk.
Attributes:
file_type: Whether the file is a JSON protocol or Python protocol
"""

file_type: ProtocolFileType
18 changes: 18 additions & 0 deletions api/src/opentrons/file_runner/python_file_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""File runner interfaces for Python protocols."""
from .abstract_file_runner import AbstractFileRunner


class PythonFileRunner(AbstractFileRunner):
"""Python protocol file runner."""

def play(self) -> None:
"""Start (or un-pause) running the Python protocol file."""
raise NotImplementedError()

def pause(self) -> None:
"""Pause the running Python protocol file's execution."""
raise NotImplementedError()

def stop(self) -> None:
"""Cancel the running Python protocol file."""
raise NotImplementedError()
1 change: 1 addition & 0 deletions api/tests/opentrons/file_runner/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Tests for the opentrons.file_runner module."""
28 changes: 28 additions & 0 deletions api/tests/opentrons/file_runner/test_json_file_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Tests for a JsonFileRunner interface."""
import pytest

from opentrons.file_runner import JsonFileRunner


@pytest.fixture
def subject() -> JsonFileRunner:
"""Get a JsonFileRunner test subject."""
return JsonFileRunner()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_play(subject: JsonFileRunner) -> None:
"""It should be able to start the run."""
subject.play()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_pause(subject: JsonFileRunner) -> None:
"""It should be able to pause the run."""
subject.pause()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_stop(subject: JsonFileRunner) -> None:
"""It should be able to stop the run."""
subject.stop()
28 changes: 28 additions & 0 deletions api/tests/opentrons/file_runner/test_python_file_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Tests for a PythonFileRunner interface."""
import pytest

from opentrons.file_runner import PythonFileRunner


@pytest.fixture
def subject() -> PythonFileRunner:
"""Get a PythonFileRunner test subject."""
return PythonFileRunner()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_play(subject: PythonFileRunner) -> None:
"""It should be able to start the run."""
subject.play()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_pause(subject: PythonFileRunner) -> None:
"""It should be able to pause the run."""
subject.pause()


@pytest.mark.xfail(raises=NotImplementedError)
def test_python_runner_stop(subject: PythonFileRunner) -> None:
"""It should be able to stop the run."""
subject.stop()

0 comments on commit 60df556

Please sign in to comment.