Files
letta-server/letta/orm/base.py
Kian Jones b8e9a80d93 merge this (#4759)
* wait I forgot to comit locally

* cp the entire core directory and then rm the .git subdir
2025-09-17 15:47:40 -07:00

86 lines
3.0 KiB
Python

from datetime import datetime, timezone
from typing import Optional
from sqlalchemy import Boolean, DateTime, String, func, text
from sqlalchemy.orm import DeclarativeBase, Mapped, declarative_mixin, declared_attr, mapped_column
class Base(DeclarativeBase):
"""absolute base for sqlalchemy classes"""
@declarative_mixin
class CommonSqlalchemyMetaMixins(Base):
__abstract__ = True
created_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), server_default=func.now(), server_onupdate=func.now())
is_deleted: Mapped[bool] = mapped_column(Boolean, server_default=text("FALSE"))
def set_updated_at(self, timestamp: Optional[datetime] = None) -> None:
"""
Set the updated_at timestamp for the model instance.
Args:
timestamp (Optional[datetime]): The timestamp to set.
If None, uses the current UTC time.
"""
self.updated_at = timestamp or datetime.now(timezone.utc)
def _set_created_and_updated_by_fields(self, actor_id: str) -> None:
"""Populate created_by_id and last_updated_by_id based on actor."""
if not self.created_by_id:
self.created_by_id = actor_id
# Always set the last_updated_by_id when updating
self.last_updated_by_id = actor_id
@declared_attr
def _created_by_id(cls):
return cls._user_by_id()
@declared_attr
def _last_updated_by_id(cls):
return cls._user_by_id()
@classmethod
def _user_by_id(cls):
"""a flexible non-constrained record of a user.
This way users can get added, deleted etc without history freaking out
"""
return mapped_column(String, nullable=True)
@property
def last_updated_by_id(self) -> Optional[str]:
return self._user_id_getter("last_updated")
@last_updated_by_id.setter
def last_updated_by_id(self, value: str) -> None:
self._user_id_setter("last_updated", value)
@property
def created_by_id(self) -> Optional[str]:
return self._user_id_getter("created")
@created_by_id.setter
def created_by_id(self, value: str) -> None:
self._user_id_setter("created", value)
def _user_id_getter(self, prop: str) -> Optional[str]:
"""returns the user id for the specified property"""
full_prop = f"_{prop}_by_id"
prop_value = getattr(self, full_prop, None)
return prop_value
def _user_id_setter(self, prop: str, value: str) -> None:
"""returns the user id for the specified property"""
full_prop = f"_{prop}_by_id"
if not value:
setattr(self, full_prop, None)
return
# Safety check
prefix, id_ = value.split("-", 1)
assert prefix == "user", f"{prefix} is not a valid id prefix for a user id"
# Set the full value
setattr(self, full_prop, value)