exceptions.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. # (c) Nelen & Schuurmans
  2. from typing import Any
  3. from typing import Dict
  4. from typing import List
  5. from typing import Optional
  6. from typing import Union
  7. from pydantic import create_model
  8. from pydantic import ValidationError
  9. from .types import Id
  10. __all__ = [
  11. "AlreadyExists",
  12. "Conflict",
  13. "DoesNotExist",
  14. "PermissionDenied",
  15. "PreconditionFailed",
  16. "BadRequest",
  17. "Unauthorized",
  18. "BadRequest",
  19. ]
  20. class DoesNotExist(Exception):
  21. def __init__(self, name: str, id: Optional[Id] = None):
  22. super().__init__()
  23. self.name = name
  24. self.id = id
  25. def __str__(self):
  26. if self.id:
  27. return f"does not exist: {self.name} with id={self.id}"
  28. else:
  29. return f"does not exist: {self.name}"
  30. class Conflict(Exception):
  31. def __init__(self, msg: Optional[str] = None):
  32. super().__init__(msg)
  33. class AlreadyExists(Conflict):
  34. def __init__(self, value: Any = None, key: str = "id"):
  35. super().__init__(f"record with {key}={value} already exists")
  36. class PreconditionFailed(Exception):
  37. def __init__(self, msg: str = "precondition failed", obj: Any = None):
  38. super().__init__(msg)
  39. self.obj = obj
  40. # pydantic.ValidationError needs some model; for us it doesn't matter
  41. # We do it the same way as FastAPI does it.
  42. request_model = create_model("Request")
  43. class BadRequest(Exception):
  44. def __init__(self, err_or_msg: Union[ValidationError, str]):
  45. self._internal_error = err_or_msg
  46. super().__init__(err_or_msg)
  47. def errors(self) -> List[Dict[str, Any]]:
  48. if isinstance(self._internal_error, ValidationError):
  49. return [dict() for x in self._internal_error.errors()]
  50. return [{"error": self}]
  51. def __str__(self) -> str:
  52. error = self._internal_error
  53. if isinstance(error, ValidationError):
  54. details = error.errors()[0]
  55. loc = "'" + ",".join([str(x) for x in details["loc"]]) + "' "
  56. if loc == "'*' ":
  57. loc = ""
  58. return f"validation error: {loc}{details['msg']}"
  59. return f"validation error: {super().__str__()}"
  60. class Unauthorized(Exception):
  61. pass
  62. class PermissionDenied(Exception):
  63. pass