text: """Contains mixin class for database models.
  
  TimestampMixin – Provides the timestamps for database objects
  EditedMixin – Provides the ability to track changes of database objects
  """
  from typing import TypeVar
  
  from sqlalchemy import Column, DateTime, ForeignKey, Integer, func
  from sqlalchemy.ext.declarative import declared_attr
  from sqlalchemy.orm import relationship
  
  from .auth import User
  
  Relationship = TypeVar("Relationship")
  
  
  class TimestampMixin(object):
      """Timestamp db-mixin class.
  
      Usage: class Sample(Model, Timestamp)
      """
  
      created_on = Column(DateTime, default=func.now())
      updated_on = Column(DateTime, default=func.now(), onupdate=func.now())
  
  
  class EditedMixin(TimestampMixin):
      """Edited db-mixin class.
  
      Provides the ability to track the creation and editing of
      user who created / changed the record via Api
      - **attributes**::
  
          :str created: property
          :int created: setter
          :str edited: property
          :int edited: setter
      """
  
      @declared_attr
      def _created_by(cls) -> Column:
          return Column(Integer, ForeignKey("user.id"))
      # This crutch is required to generate the Pydantic model,
      # since this requires an annotation on the attribute
      # <crutch>
      created: int = property(lambda self: self._created_by_user)
  
      @created.setter
      def created(self, uid) -> None:
          self._created_by = uid
      # </crutch>
  
      @declared_attr
      def _created_by_user(cls) -> Relationship:
          return relationship(
              User,
              primaryjoin=f"cast(User.id, Integer) == "
              f"foreign({cls.__name__.capitalize()}._created_by)",
              backref=f"created_{cls.__name__.lower()}",
              lazy="joined",
          )
  
      @declared_attr
      def _edited_by(cls) -> Column:
          return Column(ForeignKey("user.id"))
      # Same like 'created' attribute
      edited: int = property(lambda self: self._edited_by_user)
  
      @edited.setter
      def edited(self, uid) -> None:
          self._edited_by = uid
  
      @declared_attr
      def _edited_by_user(cls) -> Relationship:
          return relationship(
              User,
              primaryjoin=f"cast(User.id, Integer) == "
              f"foreign({cls.__name__.capitalize()}._edited_by)",
              backref=f"edited_{cls.__name__.lower()}",
          )
  
      def entry_update(self, current_user: object) -> None:
          """Use when changing data.
  
          Usage:
          def __init__(): or def __call__():
              self.entry_update(current_user, **kwargs)
              self.write()
          """
          if self.created:
              self.edited = current_user.id
          else:
              self.created = current_user.id
              self.edited = current_user.id
  