185 lines
5.2 KiB
Python
185 lines
5.2 KiB
Python
from sqlmodel import 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 Generateur
|
|
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 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 Exercice(ExerciceBase, 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)
|
|
|
|
|
|
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 ExoSupport(BaseModel):
|
|
pdf: bool
|
|
csv: bool
|
|
web: bool
|
|
|
|
|
|
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
|
|
examples: List[GeneratorOutput] | None = None
|
|
|
|
|
|
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 ExerciceRead(ExerciceBase):
|
|
id_code: str
|
|
author: Author
|
|
original: ExerciceOrigin | None
|
|
tags: List[TagRead] = None
|
|
exo_source: str
|
|
|
|
supports: ExoSupport = None
|
|
|
|
examples: Example = None
|
|
|
|
is_author: bool = None
|
|
|
|
@validator('supports', always=True, pre=True)
|
|
def get_supports(cls, value, values):
|
|
exo_source = get_source_path_from_name_and_id(values['exo_source'], values['id_code'])
|
|
exo_source = add_fast_api_root(exo_source)
|
|
if os.path.exists(exo_source):
|
|
support_compatibility = get_support_from_path(
|
|
exo_source)
|
|
return support_compatibility
|
|
return None
|
|
|
|
@validator('examples', always=True)
|
|
def get_examples(cls, value, values):
|
|
if values.get('supports') == None:
|
|
return {}
|
|
supports = values.get('supports').dict()
|
|
exo_source = get_source_path_from_name_and_id(
|
|
values['exo_source'], values['id_code'])
|
|
return {
|
|
"type": ExampleEnum.csv if supports['csv'] == True else ExampleEnum.web if supports['web'] == True else None,
|
|
"data": Generateur(add_fast_api_root(exo_source), 3, "csv" if supports['csv'] == True else "web" if supports['web'] == True else None, True) if supports['csv'] == True == True or supports['web'] == True == True else 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
|
|
|
|
|