Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove retina endpoints #154

Merged
merged 10 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Removed support for Python 3.6 and 3.7
- Added support for Python 3.11
- Removed the retina endpoints

## 0.11.0 (2022-12-14)

Expand Down
38 changes: 0 additions & 38 deletions gcapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,40 +206,6 @@ class ComponentInterfacesAPI(APIBase[gcapi.models.ComponentInterface]):
model = gcapi.models.ComponentInterface


class RetinaLandmarkAnnotationSetsAPI(
ModifiableMixin, APIBase[gcapi.models.LandmarkAnnotationSet]
):
base_path = "retina/landmark-annotation/"
model = gcapi.models.LandmarkAnnotationSet

def for_image(self, pk):
result = yield self.yield_request(
method="GET", path=self.base_path, params={"image_id": pk}
)
return result


class RetinaPolygonAnnotationSetsAPI(
ModifiableMixin, APIBase[gcapi.models.NestedPolygonAnnotationSet]
):
base_path = "retina/polygon-annotation-set/"
model = gcapi.models.NestedPolygonAnnotationSet


class RetinaSinglePolygonAnnotationsAPI(
ModifiableMixin, APIBase[gcapi.models.SinglePolygonAnnotation]
):
base_path = "retina/single-polygon-annotation/"
model = gcapi.models.SinglePolygonAnnotation


class RetinaETDRSGridAnnotationsAPI(
ModifiableMixin, APIBase[gcapi.models.ETDRSGridAnnotation]
):
base_path = "retina/etdrs-grid-annotation/"
model = gcapi.models.ETDRSGridAnnotation


class UploadsAPI(APIBase[gcapi.models.UserUpload]):
base_path = "uploads/"
model = gcapi.models.UserUpload
Expand Down Expand Up @@ -410,10 +376,6 @@ class ApiDefinitions:
algorithm_jobs: AlgorithmJobsAPI
archives: ArchivesAPI
workstation_configs: WorkstationConfigsAPI
retina_landmark_annotations: RetinaLandmarkAnnotationSetsAPI
retina_polygon_annotation_sets: RetinaPolygonAnnotationSetsAPI
retina_single_polygon_annotations: RetinaSinglePolygonAnnotationsAPI
retina_etdrs_grid_annotations: RetinaETDRSGridAnnotationsAPI
raw_image_upload_sessions: UploadSessionsAPI
archive_items: ArchiveItemsAPI
interfaces: ComponentInterfacesAPI
Expand Down
117 changes: 10 additions & 107 deletions tests/async_integration_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
ARCHIVE_TOKEN,
DEMO_PARTICIPANT_TOKEN,
READERSTUDY_TOKEN,
RETINA_TOKEN,
async_recurse_call,
)

Expand All @@ -38,114 +37,18 @@ async def get_archive_items(client, archive_pk, min_size):
return il


@pytest.mark.parametrize(
"annotation",
[
"retina_landmark_annotations",
"retina_polygon_annotation_sets",
"retina_single_polygon_annotations",
],
)
@pytest.mark.anyio
async def test_list_annotations(local_grand_challenge, annotation):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
) as c:
response = await getattr(c, annotation).list()
assert len(response) == 0


@pytest.mark.anyio
async def test_create_landmark_annotation(local_grand_challenge):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
) as c:
nil_uuid = "00000000-0000-4000-9000-000000000000"
create_data = {
"grader": 0,
"singlelandmarkannotation_set": [
{"image": nil_uuid, "landmarks": [[0, 0], [1, 1], [2, 2]]},
{"image": nil_uuid, "landmarks": [[0, 0], [1, 1], [2, 2]]},
],
}
with pytest.raises(HTTPStatusError) as e:
await c.retina_landmark_annotations.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert (
response["grader"][0] == 'Invalid pk "0" - object does not exist.'
)
for sla_error in response["singlelandmarkannotation_set"]:
assert (
sla_error["image"][0]
== f'Invalid pk "{nil_uuid}" - object does not exist.' # noqa: B907
)


@pytest.mark.anyio
async def test_create_polygon_annotation_set(local_grand_challenge):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
) as c:
nil_uuid = "00000000-0000-4000-9000-000000000000"
create_data = {
"grader": 0,
"image": nil_uuid,
"singlepolygonannotation_set": [
{"z": 0, "value": [[0, 0], [1, 1], [2, 2]]},
{"z": 1, "value": [[0, 0], [1, 1], [2, 2]]},
],
}
with pytest.raises(HTTPStatusError) as e:
await c.retina_polygon_annotation_sets.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert (
response["grader"][0] == 'Invalid pk "0" - object does not exist.'
)
assert (
response["image"][0]
== f'Invalid pk "{nil_uuid}" - object does not exist.' # noqa: B907
)
assert response["name"][0] == "This field is required."


@pytest.mark.anyio
async def test_create_single_polygon_annotations(local_grand_challenge):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
) as c:
create_data = {
"z": 0,
"value": [[0, 0], [1, 1], [2, 2]],
"annotation_set": 0,
}

with pytest.raises(HTTPStatusError) as e:
await c.retina_single_polygon_annotations.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert (
response["annotation_set"][0]
== 'Invalid pk "0" - object does not exist.'
)


@pytest.mark.anyio
async def test_raw_image_and_upload_session(local_grand_challenge):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
base_url=local_grand_challenge, verify=False, token=ARCHIVE_TOKEN
) as c:
assert len(await c.raw_image_upload_sessions.page()) == 0


@pytest.mark.anyio
async def test_local_response(local_grand_challenge):
async with AsyncClient(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
base_url=local_grand_challenge, verify=False, token=ARCHIVE_TOKEN
) as c:
# Empty response, but it didn't error out so the server is responding
assert len(await c.algorithms.page()) == 0
Expand All @@ -170,20 +73,20 @@ async def test_chunked_uploads(local_grand_challenge):
"count"
] == 1 + existing_chunks_admin

# retina
# archive
async with AsyncClient(
token=RETINA_TOKEN, base_url=local_grand_challenge, verify=False
) as c_retina:
existing_chunks_retina = (await c_retina(path="uploads/"))["count"]
token=ARCHIVE_TOKEN, base_url=local_grand_challenge, verify=False
) as c_archive:
existing_chunks_archive = (await c_archive(path="uploads/"))["count"]

with open(file_to_upload, "rb") as f:
await c_retina.uploads.upload_fileobj(
await c_archive.uploads.upload_fileobj(
fileobj=f, filename=file_to_upload.name
)

assert (await c_retina(path="uploads/"))[
assert (await c_archive(path="uploads/"))[
"count"
] == 1 + existing_chunks_retina
] == 1 + existing_chunks_archive

async with AsyncClient(token="whatever") as c:
with pytest.raises(HTTPStatusError):
Expand Down Expand Up @@ -983,7 +886,7 @@ async def test_add_cases_to_reader_study_invalid_path(

assert str(e.value) == (
"Invalid file paths: " # noqa: B907
f"{{'generic-medical-image': ['{file_path}']}}"
f"{{'generic-medical-image': ['{file_path!r}']}}"
)


Expand Down
101 changes: 6 additions & 95 deletions tests/integration_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
ARCHIVE_TOKEN,
DEMO_PARTICIPANT_TOKEN,
READERSTUDY_TOKEN,
RETINA_TOKEN,
recurse_call,
)

Expand Down Expand Up @@ -39,94 +38,6 @@ def get_archive_items(client, archive_pk, min_size):
return items


@pytest.mark.parametrize(
"annotation",
[
"retina_landmark_annotations",
"retina_polygon_annotation_sets",
"retina_single_polygon_annotations",
],
)
def test_list_annotations(local_grand_challenge, annotation):
c = Client(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
)
response = getattr(c, annotation).list()
assert len(response) == 0


def test_create_landmark_annotation(local_grand_challenge):
c = Client(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
)
nil_uuid = "00000000-0000-4000-9000-000000000000"
create_data = {
"grader": 0,
"singlelandmarkannotation_set": [
{"image": nil_uuid, "landmarks": [[0, 0], [1, 1], [2, 2]]},
{"image": nil_uuid, "landmarks": [[0, 0], [1, 1], [2, 2]]},
],
}
with pytest.raises(HTTPStatusError) as e:
c.retina_landmark_annotations.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert response["grader"][0] == 'Invalid pk "0" - object does not exist.'
for sla_error in response["singlelandmarkannotation_set"]:
assert (
sla_error["image"][0]
== f'Invalid pk "{nil_uuid}" - object does not exist.' # noqa: B907
)


def test_create_polygon_annotation_set(local_grand_challenge):
c = Client(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
)
nil_uuid = "00000000-0000-4000-9000-000000000000"
create_data = {
"grader": 0,
"image": nil_uuid,
"singlepolygonannotation_set": [
{"z": 0, "value": [[0, 0], [1, 1], [2, 2]]},
{"z": 1, "value": [[0, 0], [1, 1], [2, 2]]},
],
}
with pytest.raises(HTTPStatusError) as e:
c.retina_polygon_annotation_sets.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert response["grader"][0] == 'Invalid pk "0" - object does not exist.'
assert (
response["image"][0]
== f'Invalid pk "{nil_uuid}" - object does not exist.' # noqa: B907
)
assert response["name"][0] == "This field is required."


def test_create_single_polygon_annotations(local_grand_challenge):
c = Client(
base_url=local_grand_challenge, verify=False, token=RETINA_TOKEN
)
create_data = {
"z": 0,
"value": [[0, 0], [1, 1], [2, 2]],
"annotation_set": 0,
}

with pytest.raises(HTTPStatusError) as e:
c.retina_single_polygon_annotations.create(**create_data)
response = e.value.response
assert response.status_code == 400
response = response.json()
assert (
response["annotation_set"][0]
== 'Invalid pk "0" - object does not exist.'
)


@pytest.mark.parametrize(
"files",
(
Expand Down Expand Up @@ -173,18 +84,18 @@ def test_chunked_uploads(local_grand_challenge):

assert c_admin(path="uploads/")["count"] == 1 + existing_chunks_admin

# retina
c_retina = Client(
token=RETINA_TOKEN, base_url=local_grand_challenge, verify=False
# archive
c_archive = Client(
token=ARCHIVE_TOKEN, base_url=local_grand_challenge, verify=False
)
existing_chunks_retina = c_retina(path="uploads/")["count"]
existing_chunks_archive = c_archive(path="uploads/")["count"]

with open(file_to_upload, "rb") as f:
c_retina.uploads.upload_fileobj(
c_archive.uploads.upload_fileobj(
fileobj=f, filename=file_to_upload.name
)

assert c_retina(path="uploads/")["count"] == 1 + existing_chunks_retina
assert c_archive(path="uploads/")["count"] == 1 + existing_chunks_archive

c = Client(token="whatever")
with pytest.raises(HTTPStatusError):
Expand Down
1 change: 0 additions & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from httpx import AsyncHTTPTransport, HTTPStatusError, HTTPTransport

RETINA_TOKEN = "f1f98a1733c05b12118785ffd995c250fe4d90da"
ADMIN_TOKEN = "1b9436200001f2eaf57cd77db075cbb60a49a00a"
READERSTUDY_TOKEN = "01614a77b1c0b4ecd402be50a8ff96188d5b011d"
DEMO_PARTICIPANT_TOKEN = "00aa710f4dc5621a0cb64b0795fbba02e39d7700"
Expand Down
Loading