Source code for twon_lss.schemas.feed
from twon_lss.schemas.user import User
from twon_lss.schemas.post import Post
import json
from pydantic import model_validator, PrivateAttr, Field, RootModel
from typing import List, Dict
from bisect import bisect_right
import typing
[docs]
class Feed(RootModel):
root: typing.List[Post] = Field(default_factory=list)
_user_index: Dict[User, List[Post]] = PrivateAttr(default_factory=dict)
@model_validator(mode='after')
def _build_indexes(self):
self.root = sorted(self.root, key=lambda p: p.timestamp)
self._user_index = {}
for post in self.root:
self._user_index.setdefault(post.user, []).append(post)
return self
def __iter__(self):
return iter(self.root)
def __len__(self):
return len(self.root)
def __getitem__(self, index):
return self.root[index]
def append(self, post: Post) -> None:
self.root.append(post)
self._user_index.setdefault(post.user, []).append(post)
def extend(self, posts: typing.List[Post]) -> None:
for post in posts:
self.append(post)
def get_items_by_user(self, user: User) -> "Feed":
return Feed(root=self._user_index.get(user, []))
def get_unread_items_by_user(self, user: User) -> "Feed":
return Feed(root=[p for p in self.root if user not in p.reads])
def filter_by_timestamp(self, timestamp: int, persistence: int) -> "Feed":
cutoff = timestamp - persistence
idx = bisect_right([p.timestamp for p in self.root], cutoff)
return Feed(root=self.root[idx:])
def to_json(self, path: str) -> None:
"""Save the Feed to a JSON file without the private attributes."""
with open(path, "w") as f:
json.dump([post.model_dump() for post in self.root], f, indent=4)
class Config:
arbitrary_types_allowed = True