Skip to content

Commit

Permalink
feat(robot_server): add a GET endpoint to get all data files (#15744)
Browse files Browse the repository at this point in the history
re AUTH-569

<!--
Thanks for taking the time to open a pull request! Please make sure
you've read the "Opening Pull Requests" section of our Contributing
Guide:


https://github.com/Opentrons/opentrons/blob/edge/CONTRIBUTING.md#opening-pull-requests

To ensure your code is reviewed quickly and thoroughly, please fill out
the sections below to the best of your ability!
-->

# Overview

<!--
Use this section to describe your pull-request at a high level. If the
PR addresses any open issues, please tag the issues here.
-->

Adding a GET endpoint to access a list of all data file info on the
robot server.

# Test Plan

<!--
Use this section to describe the steps that you took to test your Pull
Request.
If you did not perform any testing provide justification why.

OT-3 Developers: You should default to testing on actual physical
hardware.
Once again, if you did not perform testing against hardware, justify
why.

Note: It can be helpful to write a test plan before doing development

Example Test Plan (HTTP API Change)

- Verified that new optional argument `dance-party` causes the robot to
flash its lights, move the pipettes,
then home.
- Verified that when you omit the `dance-party` option the robot homes
normally
- Added protocol that uses `dance-party` argument to G-Code Testing
Suite
- Ran protocol that did not use `dance-party` argument and everything
was successful
- Added unit tests to validate that changes to pydantic model are
correct

-->

# Changelog

<!--
List out the changes to the code in this PR. Please try your best to
categorize your changes and describe what has changed and why.

Example changelog:
- Fixed app crash when trying to calibrate an illegal pipette
- Added state to API to track pipette usage
- Updated API docs to mention only two pipettes are supported

IMPORTANT: MAKE SURE ANY BREAKING CHANGES ARE PROPERLY COMMUNICATED
-->

-Added a get_all_data_files function in the dataFiles/router.py
-Updated test

# Review requests

<!--
Describe any requests for your reviewers here.
-->

# Risk assessment

<!--
Carefully go over your pull request and look at the other parts of the
codebase it may affect. Look for the possibility, even if you think it's
small, that your change may affect some other part of the system - for
instance, changing return tip behavior in protocol may also change the
behavior of labware calibration.

Identify the other parts of the system your codebase may affect, so that
in addition to your own review and testing, other people who may not
have the system internalized as much as you can focus their attention
and testing there.
-->

---------

Co-authored-by: shiyaochen <[email protected]>
  • Loading branch information
syao1226 and shiyaochen authored Jul 23, 2024
1 parent d3a8001 commit 8fe39ab
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
5 changes: 3 additions & 2 deletions robot-server/robot_server/data_files/data_files_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(

def get_file_info_by_hash(self, file_hash: str) -> Optional[DataFileInfo]:
"""Get the ID of data file having the provided hash."""
for file in self._sql_get_all_from_engine():
for file in self.sql_get_all_from_engine():
if file.file_hash == file_hash:
return file
return None
Expand Down Expand Up @@ -65,7 +65,8 @@ def get(self, data_file_id: str) -> DataFileInfo:

return _convert_row_data_file_info(data_file_row)

def _sql_get_all_from_engine(self) -> List[DataFileInfo]:
def sql_get_all_from_engine(self) -> List[DataFileInfo]:
"""Get all data file entries from the database."""
statement = sqlalchemy.select(data_files_table).order_by(sqlite_rowid)
with self._sql_engine.begin() as transaction:
all_rows = transaction.execute(statement).all()
Expand Down
35 changes: 35 additions & 0 deletions robot-server/robot_server/data_files/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

from robot_server.service.json_api import (
SimpleBody,
SimpleMultiBody,
PydanticResponse,
MultiBodyMeta,
)
from robot_server.errors.error_responses import ErrorDetails, ErrorBody
from .dependencies import get_data_files_directory, get_data_files_store
Expand Down Expand Up @@ -218,3 +220,36 @@ async def get_data_file(
content=buffered_file.contents.decode("utf-8"),
media_type="text/plain",
)


@PydanticResponse.wrap_route(
datafiles_router.get,
path="/dataFiles",
summary="Get a list of all data files stored on the robot server",
responses={status.HTTP_200_OK: {"model": SimpleMultiBody[str]}},
)
async def get_all_data_files(
data_files_store: DataFilesStore = Depends(get_data_files_store),
) -> PydanticResponse[SimpleMultiBody[DataFile]]:
"""Get a list of all data files stored on the robot server.
Args:
data_files_store: In-memory database of data file resources.
"""
data_files = data_files_store.sql_get_all_from_engine()

meta = MultiBodyMeta(cursor=0, totalLength=len(data_files))

return await PydanticResponse.create(
content=SimpleMultiBody.construct(
data=[
DataFile.construct(
id=data_file_info.id,
name=data_file_info.name,
createdAt=data_file_info.created_at,
)
for data_file_info in data_files
],
meta=meta,
),
)
43 changes: 43 additions & 0 deletions robot-server/tests/data_files/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
from fastapi import UploadFile
from opentrons.protocol_reader import FileHasher, FileReaderWriter, BufferedFile

from robot_server.service.json_api import MultiBodyMeta

from robot_server.data_files.data_files_store import DataFilesStore, DataFileInfo
from robot_server.data_files.models import DataFile, FileIdNotFoundError
from robot_server.data_files.router import (
upload_data_file,
get_data_file_info_by_id,
get_data_file,
get_all_data_files,
)
from robot_server.errors.error_responses import ApiError

Expand Down Expand Up @@ -322,3 +325,43 @@ async def test_get_data_file(
assert result.status_code == 200
assert result.body == b"some_content"
assert result.media_type == "text/plain"


async def test_get_all_data_file_info(
decoy: Decoy,
data_files_store: DataFilesStore,
) -> None:
"""Get a list of all data file info from the database."""
decoy.when(data_files_store.sql_get_all_from_engine()).then_return(
[
DataFileInfo(
id="qwerty",
name="abc.xyz",
file_hash="123",
created_at=datetime(year=2024, month=7, day=15),
),
DataFileInfo(
id="hfhcjdeowjfie",
name="mcd.kfc",
file_hash="124",
created_at=datetime(year=2024, month=7, day=22),
),
]
)

result = await get_all_data_files(data_files_store=data_files_store)

assert result.status_code == 200
assert result.content.data == [
DataFile(
id="qwerty",
name="abc.xyz",
createdAt=datetime(year=2024, month=7, day=15),
),
DataFile(
id="hfhcjdeowjfie",
name="mcd.kfc",
createdAt=datetime(year=2024, month=7, day=22),
),
]
assert result.content.meta == MultiBodyMeta(cursor=0, totalLength=2)

0 comments on commit 8fe39ab

Please sign in to comment.