root_entity.py 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. # (c) Nelen & Schuurmans
  2. from datetime import datetime
  3. from datetime import timezone
  4. from typing import Optional
  5. from typing import Type
  6. from typing import TypeVar
  7. from .exceptions import BadRequest
  8. from .value_object import ValueObject
  9. __all__ = ["RootEntity", "now"]
  10. def now():
  11. # this function is there so that we can mock it in tests
  12. return datetime.now(timezone.utc)
  13. T = TypeVar("T", bound="RootEntity")
  14. class RootEntity(ValueObject):
  15. id: Optional[int] = None
  16. created_at: datetime
  17. updated_at: datetime
  18. @classmethod
  19. def create(cls: Type[T], **values) -> T:
  20. values.setdefault("created_at", now())
  21. values.setdefault("updated_at", values["created_at"])
  22. return super(RootEntity, cls).create(**values)
  23. def update(self: T, **values) -> T:
  24. if "id" in values and self.id is not None and values["id"] != self.id:
  25. raise BadRequest("Cannot change the id of an entity")
  26. values.setdefault("updated_at", now())
  27. return super().update(**values)
  28. def __hash__(self):
  29. assert self.id is not None
  30. return hash(self.__class__) + hash(self.id)