from sqlmodel import JSON, Column, select from sqlalchemy.inspection import inspect from enum import Enum import os from pydantic import BaseModel from pydantic import validator, root_validator from generateur.generateur_main import generate_from_path from services.exoValidation import get_support_from_path from services.io import add_fast_api_root, get_filename_from_path from services.schema import as_form from typing import Any, List, Optional from sqlmodel import SQLModel, Field, Relationship, Session from database.auth.models import User, UserRead from typing import TYPE_CHECKING, Optional from .FileField import FileField from database.db import get_session if TYPE_CHECKING: from database.auth.models import User class ExampleEnum(Enum): csv = 'csv' pdf = 'pdf' web = 'web' undisponible = 'undisponible' class GeneratorOutput(BaseModel): calcul: str correction: str | None = None class Example(BaseModel): type: ExampleEnum = ExampleEnum.undisponible data: List[GeneratorOutput] | None = None class ExercicesTagLink(SQLModel, table=True): exercice_id: Optional[int] = Field( default=None, foreign_key='exercice.id', primary_key=True) tag_id: Optional[int] = Field( default=None, foreign_key='tag.id', primary_key=True) class ExerciceBase(SQLModel): name: str = Field(max_length=50, index=True) consigne: Optional[str] = Field(max_length=200, default=None) private: Optional[bool] = Field(default=False) class Supports(SQLModel): csv: bool pdf: bool web: bool class Exercice(ExerciceBase,Supports, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(unique=True, index=True) exo_source: FileField['/uploads'] author_id: int = Field(foreign_key='user.id') author: "User" = Relationship(back_populates='exercices') origin_id: Optional[int] = Field( foreign_key='exercice.id', default=None, nullable=True) original: Optional['Exercice'] = Relationship(back_populates='duplicated', sa_relationship_kwargs=dict( remote_side='Exercice.id' )) duplicated: List['Exercice'] = Relationship(back_populates='original') tags: List['Tag'] = Relationship( back_populates='exercices', link_model=ExercicesTagLink) examples: Optional[Example] = Field( sa_column=Column(JSON), default={}) def dict_relationship(self, *, exclude: List[str], include: List[str]): relationships = inspect(self.__class__).relationships.items() relationsData = {rname: getattr(self, rname) for rname, rp in relationships if rname not in exclude and (rname in include if len(include) != 0 else True)} return {**self.dict(), **relationsData} class Config: validate_assignment = True extra='allow' class ColorEnum(Enum): green='#00ff00' red="#ff0000" blue="#0000ff" string="string" class TagBase(SQLModel): label: str = Field(max_length=20) color: ColorEnum class Tag(TagBase, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code: str = Field(unique=True, index=True) author_id: int = Field(foreign_key='user.id') author: "User" = Relationship(back_populates='tags') exercices: List["Exercice"] = Relationship( back_populates='tags', link_model=ExercicesTagLink) class TagCreate(TagBase): id_code: str = None class TagRead(TagBase): id_code: str @as_form class ExerciceCreate(ExerciceBase): pass class ExerciceEdit(ExerciceCreate): pass class ExerciceOrigin(SQLModel): #id: int id_code: str name: str class Author(SQLModel): username: str def get_source_path_from_name_and_id(name: str, id_code: str): return f'/uploads/{id_code}/{name}' class ExerciceReadBase(ExerciceBase): id_code: str author: Author original: ExerciceOrigin | None tags: List[TagRead] = None exo_source: str examples: Example = None is_author: bool = None @validator('exo_source') def get_exo_source_name(cls, value, values): if value is not None: return get_filename_from_path(value) return value class ExerciceRead(ExerciceBase): id: int author_id:int author: User original: Optional[Exercice] tags: List[Tag] class ExerciceReadFull(ExerciceReadBase): supports: Supports