Skip to content
Draft
Changes from all 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
16 changes: 16 additions & 0 deletions src/labthings_fastapi/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

# `_thing_servers` is used as a global from `ThingServer.__init__`
from labthings_fastapi.outputs import blob
from labthings_fastapi.problem_details import ProblemDetails
from labthings_fastapi.server.config_model import (
ThingsConfig,
ThingServerConfig,
Expand Down Expand Up @@ -245,6 +246,21 @@
def _add_exception_handlers(self) -> None:
"""Add exception handlers to the FastAPI application."""

@self.app.exception_handler(Exception)
async def exceptions_to_problemdetails(
_request: Request, exc: Exception
) -> JSONResponse:
"""Handle all exceptions by returning a ProblemDetails object.

By default, this does not expose stack traces or line numbers.

:param _request: the request that started the code that failed.
:param exc: the error that occurred.
:return: a response containing a ProblemDetails object.
"""
pd = ProblemDetails.from_exception(exc)
return JSONResponse(pd.model_dump(), status_code=pd.status or 500)

Check warning on line 262 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

261-262 lines are not covered with tests

@self.app.exception_handler(GlobalLockBusyError)
async def global_lock_exception_handler(
_request: Request, exc: GlobalLockBusyError
Expand All @@ -258,11 +274,11 @@
async def serialisation_error_handler(
request: Request, exc: PydanticSerializationError
) -> JSONResponse:
LOGGER.error(

Check warning on line 277 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

277 line is not covered with tests
f"Couldn't serialise response to {request.url} because of error: \n"
f"{exc}"
)
return JSONResponse(status_code=500, content={"detail": str(exc)})

Check warning on line 281 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

281 line is not covered with tests

@property
def debug(self) -> bool:
Expand Down Expand Up @@ -318,7 +334,7 @@

:return: all instances of ``cls`` that have been added to this server.
"""
return [t for t in self.things.values() if isinstance(t, cls)]

Check warning on line 337 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

337 line is not covered with tests

def thing_by_class(self, cls: type[ThingInstance]) -> ThingInstance:
"""Return the instance of ``cls`` attached to this server.
Expand All @@ -332,10 +348,10 @@

:raise RuntimeError: if there is not exactly one matching Thing.
"""
instances = self.things_by_class(cls)
if len(instances) == 1:
return instances[0]
raise RuntimeError(

Check warning on line 354 in src/labthings_fastapi/server/__init__.py

View workflow job for this annotation

GitHub Actions / coverage

351-354 lines are not covered with tests
f"There are {len(instances)} Things of class {cls}, expected 1."
)

Expand Down
Loading