api_gateway.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. from datetime import datetime
  2. from http import HTTPStatus
  3. from typing import Optional
  4. import inject
  5. from clean_python import DoesNotExist
  6. from clean_python import Id
  7. from clean_python import Json
  8. from clean_python import Mapper
  9. from .. import SyncGateway
  10. from .api_provider import SyncApiProvider
  11. from .exceptions import ApiException
  12. __all__ = ["SyncApiGateway"]
  13. class SyncApiGateway(SyncGateway):
  14. path: str
  15. mapper = Mapper()
  16. def __init__(self, provider_override: Optional[SyncApiProvider] = None):
  17. self.provider_override = provider_override
  18. def __init_subclass__(cls, path: str) -> None:
  19. assert not path.startswith("/")
  20. assert "{id}" in path
  21. cls.path = path
  22. super().__init_subclass__()
  23. @property
  24. def provider(self) -> SyncApiProvider:
  25. return self.provider_override or inject.instance(SyncApiProvider)
  26. def get(self, id: Id) -> Optional[Json]:
  27. try:
  28. result = self.provider.request("GET", self.path.format(id=id))
  29. assert result is not None
  30. return self.mapper.to_internal(result)
  31. except ApiException as e:
  32. if e.status is HTTPStatus.NOT_FOUND:
  33. return None
  34. raise e
  35. def add(self, item: Json) -> Json:
  36. item = self.mapper.to_external(item)
  37. result = self.provider.request("POST", self.path.format(id=""), json=item)
  38. assert result is not None
  39. return self.mapper.to_internal(result)
  40. def remove(self, id: Id) -> bool:
  41. try:
  42. self.provider.request("DELETE", self.path.format(id=id)) is not None
  43. except ApiException as e:
  44. if e.status is HTTPStatus.NOT_FOUND:
  45. return False
  46. raise e
  47. else:
  48. return True
  49. def update(
  50. self, item: Json, if_unmodified_since: Optional[datetime] = None
  51. ) -> Json:
  52. if if_unmodified_since is not None:
  53. raise NotImplementedError("if_unmodified_since not implemented")
  54. item = self.mapper.to_external(item)
  55. id_ = item.pop("id", None)
  56. if id_ is None:
  57. raise DoesNotExist("resource", id_)
  58. try:
  59. result = self.provider.request("PATCH", self.path.format(id=id_), json=item)
  60. assert result is not None
  61. return self.mapper.to_internal(result)
  62. except ApiException as e:
  63. if e.status is HTTPStatus.NOT_FOUND:
  64. raise DoesNotExist("resource", id_)
  65. raise e