diff --git a/src/dials_rest/routers/find_spots.py b/src/dials_rest/routers/find_spots.py index 542273a..3f97b7b 100644 --- a/src/dials_rest/routers/find_spots.py +++ b/src/dials_rest/routers/find_spots.py @@ -121,7 +121,7 @@ async def find_spots( else: experiments = ExperimentListFactory.from_filenames([params.filename]) if params.scan_range and len(experiments) > 1: - # This means we've imported a sequence of still image: select + # This means we've imported a sequence of still images: select # only the experiment, i.e. image, we're interested in start, end = params.scan_range experiments = experiments[start - 1 : end] @@ -129,7 +129,31 @@ async def find_spots( logger.exception(e) raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail=f"File not found: {params.filename}", + detail=str(e), + ) + except ValueError as e: + logger.exception(e) + msg = str(e) + if "does not match any files" in msg: + logger.exception(e) + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=msg, + ) + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=msg, + ) + except Exception as e: + logger.exception(e) + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=str(e), + ) + if not experiments: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=f"Could not find matching image format for {params.filename}", ) phil_params = find_spots_phil_scope.fetch(source=phil.parse("")).extract() diff --git a/src/dials_rest/routers/image.py b/src/dials_rest/routers/image.py index a8e129c..8c91d34 100644 --- a/src/dials_rest/routers/image.py +++ b/src/dials_rest/routers/image.py @@ -135,7 +135,26 @@ async def image_as_bitmap( logger.exception(e) raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail=f"File not found: {params.filename}", + detail=str(e), + ) + except ValueError as e: + logger.exception(e) + msg = str(e) + if "does not match any files" in msg: + logger.exception(e) + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=msg, + ) + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=msg, + ) + except Exception as e: + logger.exception(e) + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail=str(e), ) phil_params = export_bitmaps.phil_scope.extract() diff --git a/tests/routers/test_find_spots.py b/tests/routers/test_find_spots.py index 0c32b76..26a9a98 100644 --- a/tests/routers/test_find_spots.py +++ b/tests/routers/test_find_spots.py @@ -2,12 +2,47 @@ from unittest import mock import pytest +from fastapi import status def test_find_spots_file_not_found_responds_404(client, authentication_headers): data = {"filename": "/made/up/path.cbf"} response = client.post("find_spots", json=data, headers=authentication_headers) - assert response.status_code == 404 + assert response.status_code == status.HTTP_404_NOT_FOUND + + +def test_find_spots_template_no_matching_file_responds_404( + client, authentication_headers +): + data = {"filename": "/made/up/path_#####.cbf"} + response = client.post("find_spots", json=data, headers=authentication_headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + + +def test_find_spots_fails_to_understand_h5_data_file_responds_422( + client, authentication_headers, dials_data +): + data = { + "filename": os.fspath( + # this is the data file rather than NeXus file, so dials should + # fail to understand + dials_data("vmxi_thaumatin", pathlib=True) + / "image_15799_data_000001.h5" + ), + } + response = client.post("find_spots", json=data, headers=authentication_headers) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + +def test_find_spots_fails_to_understand_text_file_responds_422( + client, authentication_headers, tmp_path +): + filename = tmp_path / "image_00001.cbf" + filename.touch() + for filename in {filename, tmp_path / "image_#####.cbf"}: + data = {"filename": os.fspath(filename)} + response = client.post("find_spots", json=data, headers=authentication_headers) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @pytest.mark.parametrize("filename", ["centroid_0001.cbf", "centroid_####.cbf"]) diff --git a/tests/routers/test_image.py b/tests/routers/test_image.py index 781eb20..501f74a 100644 --- a/tests/routers/test_image.py +++ b/tests/routers/test_image.py @@ -2,18 +2,55 @@ from io import BytesIO import pytest +from fastapi import status from PIL import Image def test_export_bitmap_without_jwt_responds_403(client): response = client.post("export_bitmap") - assert response.status_code == 403 + assert response.status_code == status.HTTP_403_FORBIDDEN def test_export_bitmap_file_not_found_responds_404(client, authentication_headers): data = {"filename": "/made/up/path.cbf"} response = client.post("export_bitmap", json=data, headers=authentication_headers) - assert response.status_code == 404 + assert response.status_code == status.HTTP_404_NOT_FOUND + + +def test_export_bitmap_template_no_matching_file_responds_404( + client, authentication_headers +): + data = {"filename": "/made/up/path_#####.cbf"} + response = client.post("export_bitmap", json=data, headers=authentication_headers) + assert response.status_code == status.HTTP_404_NOT_FOUND + + +def test_export_bitmap_fails_to_understand_h5_data_file_responds_422( + client, authentication_headers, dials_data +): + data = { + "filename": os.fspath( + # this is the data file rather than NeXus file, so dials should + # fail to understand + dials_data("vmxi_thaumatin", pathlib=True) + / "image_15799_data_000001.h5" + ), + } + response = client.post("export_bitmap", json=data, headers=authentication_headers) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY + + +def test_export_bitmap_fails_to_understand_text_file_responds_422( + client, authentication_headers, tmp_path +): + filename = tmp_path / "image_00001.cbf" + filename.touch() + for filename in {filename, tmp_path / "image_#####.cbf"}: + data = {"filename": os.fspath(filename)} + response = client.post( + "export_bitmap", json=data, headers=authentication_headers + ) + assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY @pytest.mark.parametrize("filename", ["centroid_0001.cbf", "centroid_####.cbf"])