context.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. # (c) Nelen & Schuurmans
  2. import os
  3. from contextvars import ContextVar
  4. from typing import FrozenSet
  5. from typing import Optional
  6. from pydantic import AnyUrl
  7. from pydantic import FileUrl
  8. from .value_object import ValueObject
  9. __all__ = ["ctx", "User", "Tenant", "Scope"]
  10. class User(ValueObject):
  11. id: str
  12. name: str
  13. Scope = FrozenSet[str]
  14. class Tenant(ValueObject):
  15. id: int
  16. name: str
  17. class Context:
  18. """Provide global access to some contextual properties.
  19. The implementation makes use of python's contextvars, which automatically integrates
  20. with asyncio tasks (so that each task runs in its own context). This makes sure that
  21. every request-response cycle is isolated.
  22. """
  23. def __init__(self):
  24. self._path_value: ContextVar[AnyUrl] = ContextVar(
  25. "path_value",
  26. default=FileUrl.build(scheme="file", host="/", path=os.getcwd()),
  27. )
  28. self._user_value: ContextVar[User] = ContextVar(
  29. "user_value", default=User(id="ANONYMOUS", name="anonymous")
  30. )
  31. self._tenant_value: ContextVar[Optional[Tenant]] = ContextVar(
  32. "tenant_value", default=None
  33. )
  34. def reset(self):
  35. self._path_value.reset()
  36. self._user_value.reset()
  37. self._tenant_value.reset()
  38. @property
  39. def path(self) -> AnyUrl:
  40. return self._path_value.get()
  41. @path.setter
  42. def path(self, value: AnyUrl) -> None:
  43. self._path_value.set(value)
  44. @property
  45. def user(self) -> User:
  46. return self._user_value.get()
  47. @user.setter
  48. def user(self, value: User) -> None:
  49. self._user_value.set(value)
  50. @property
  51. def tenant(self) -> Optional[Tenant]:
  52. return self._tenant_value.get()
  53. @tenant.setter
  54. def tenant(self, value: Optional[Tenant]) -> None:
  55. self._tenant_value.set(value)
  56. ctx = Context()