from datetime import datetime from io import StringIO from pathlib import Path from tinydb import TinyDB, Query import secrets import pandas as pd from pydantic import BaseModel, field_serializer from .his_io import dtypes pandas_json_format = 'split' class Session(BaseModel): token: str table_name: str = '' students_df: pd.DataFrame points_df: pd.DataFrame his_header: pd.DataFrame grade_1_0: float = 0.92 grade_4_0: float = 0.4 max_points: int = 100 created: datetime = datetime.now() edited: datetime = datetime.now() def __eq__(self, other: object) -> bool: return isinstance(other, Session) and \ self.token == other.token and \ self.table_name == other.table_name and \ self.students_df.equals(other.students_df) and \ self.points_df.equals(other.points_df) and \ self.his_header.equals(other.his_header) and \ self.grade_1_0 == other.grade_1_0 and \ self.grade_4_0 == other.grade_4_0 and \ self.max_points == other.max_points and \ self.created == other.created and \ self.edited == other.edited @field_serializer('students_df', 'points_df') def serialize_df(self, df: pd.DataFrame): return df.reset_index().to_json(orient=pandas_json_format) @field_serializer('his_header') def serialize_his_header(self, df): return df.to_json(orient=pandas_json_format) @field_serializer('created', 'edited') def serialize_datetime(self, dt): return dt.isoformat() class Config: arbitrary_types_allowed = True class DB: def __init__(self, db_path='db.json'): self.db_path = Path(db_path) self.db = TinyDB(self.db_path, access_mode='r+') def create_session(self): token = secrets.token_urlsafe(16) self.db.insert({'token': token}) return Session(**{ 'token': token, 'students_df': pd.DataFrame(), 'points_df': pd.DataFrame(), 'his_header': pd.DataFrame(), }) def get_session(self, token: str) -> Session: results = self.db.search(Query().token == token) if len(results) == 0: raise ValueError(f'Session with token {token} not found') session = results[0].copy() session['points_df'] = pd.read_json(StringIO(session['points_df']), dtype=dtypes.students_table, orient=pandas_json_format).set_index('Matrikelnummer') session['students_df'] = pd.read_json(StringIO(session['students_df']), dtype=dtypes.students_table, orient=pandas_json_format).set_index('Matrikelnummer') session['his_header'] = pd.read_json(StringIO(session['his_header']), dtype=dtypes.his_header, orient=pandas_json_format) return Session(**session) def save_session(self, session: Session): write_session = session.model_dump() self.db.upsert(write_session, Query().token == write_session['token']) def delete_session(self, session: Session): self.db.remove(Query().token == session.token) def list_tokens(self): return [session['token'] for session in self.db.all()]