Skip to content

Commit

Permalink
Add experimental exception handling in client/server
Browse files Browse the repository at this point in the history
Demonstrate that MissingDatasetTypeError can be caught in
the server and raised again in the client.
  • Loading branch information
timj committed Nov 2, 2023
1 parent 2324ae8 commit 9afece7
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
6 changes: 5 additions & 1 deletion python/lsst/daf/butler/remote_butler/_remote_butler.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
from .._timespan import Timespan
from ..datastore import DatasetRefURIs
from ..dimensions import DataCoordinate, DataId, DimensionConfig, DimensionUniverse, SerializedDataCoordinate
from ..registry import NoDefaultCollectionError, Registry, RegistryDefaults
from ..registry import MissingDatasetTypeError, NoDefaultCollectionError, Registry, RegistryDefaults
from ..registry.wildcards import CollectionWildcard
from ..transfers import RepoExportContext
from ._config import RemoteButlerConfigModel
Expand Down Expand Up @@ -216,6 +216,10 @@ def get_dataset_type(self, name: str) -> DatasetType:
# and only go to the server if the dataset type is not known.
path = f"dataset_type/{name}"
response = self._client.get(self._get_url(path))
if response.status_code != httpx.codes.OK:
content = response.json()
if content["exception"] == "MissingDatasetTypeError":
raise MissingDatasetTypeError(content["detail"])
response.raise_for_status()
return DatasetType.from_simple(SerializedDatasetType(**response.json()), universe=self.dimensions)

Expand Down
15 changes: 14 additions & 1 deletion python/lsst/daf/butler/remote_butler/server/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@
from functools import cache
from typing import Any

from fastapi import Depends, FastAPI
from fastapi import Depends, FastAPI, Request
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.responses import JSONResponse
from lsst.daf.butler import (
Butler,
DataCoordinate,
MissingDatasetTypeError,
SerializedDataCoordinate,
SerializedDatasetRef,
SerializedDatasetType,
Expand All @@ -55,6 +57,17 @@
app.add_middleware(GZipMiddleware, minimum_size=1000)


@app.exception_handler(MissingDatasetTypeError)
def missing_dataset_type_exception_handler(request: Request, exc: MissingDatasetTypeError) -> JSONResponse:
# Remove the double quotes around the string form. These confuse
# the JSON serialization when single quotes are in the message.
message = str(exc).strip('"')
return JSONResponse(
status_code=404,
content={"detail": message, "exception": "MissingDatasetTypeError"},
)


@cache
def _make_global_butler() -> Butler:
return Butler.from_config(BUTLER_ROOT)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
TestClient = None
app = None

from lsst.daf.butler import Butler, DataCoordinate, DatasetRef, StorageClassFactory
from lsst.daf.butler import Butler, DataCoordinate, DatasetRef, MissingDatasetTypeError, StorageClassFactory
from lsst.daf.butler.tests import DatastoreMock
from lsst.daf.butler.tests.utils import MetricTestRepo, makeTestTempDir, removeTestTempDir

Expand Down Expand Up @@ -107,6 +107,9 @@ def test_get_dataset_type(self):
bias_type = self.butler.get_dataset_type("bias")
self.assertEqual(bias_type.name, "bias")

with self.assertRaises(MissingDatasetTypeError):
self.butler.get_dataset_type("not_bias")

def test_find_dataset(self):
storage_class = self.storageClassFactory.getStorageClass("Exposure")

Expand Down

0 comments on commit 9afece7

Please sign in to comment.