import uuid from pydantic import validator import io import os from fastapi import UploadFile, Form from pathlib import Path from typing import IO, Any, List, Optional, Type from fastapi import FastAPI from sqlmodel import Field, Session, SQLModel, create_engine, select from services.exoValidation import get_support_from_data from services.io import add_fast_api_root, get_filename, get_or_create_dir, remove_fastapi_root class FileFieldMeta(type): def __getitem__(self, upload_root: str,) -> Type['FileField']: return type('MyFieldValue', (FileField,), {'upload_root': upload_root}) class FileField(str, metaclass=FileFieldMeta): upload_root: str @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, value: str | IO, values): print(cls.upload_root, cls.default_naming_field) upload_root = get_or_create_dir( add_fast_api_root(cls.upload_root)) if not isinstance(value, str): value.seek(0) is_binary = isinstance(value, io.BytesIO) name = get_filename(value, 'exo_source.py') parent = get_or_create_dir(os.path.join( upload_root, values['id_code'])) mode = 'w+' if not is_binary else 'wb+' path = os.path.join(parent, name) with open(path, mode) as f: f.write(value.read()) return remove_fastapi_root(path) else: if not os.path.exists(value): raise ValueError('File does not exist') return value class Hero(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) id_code : str path: FileField['/testing', 'id_code'] class HeroCreate(SQLModel): path: FileField[42] class HeroRead(SQLModel): id: int id_code: str path: str sqlite_file_name = "testing.db" sqlite_url = f"sqlite:///{sqlite_file_name}" connect_args = {"check_same_thread": False} engine = create_engine(sqlite_url, echo=True, connect_args=connect_args) def create_db_and_tables(): SQLModel.metadata.create_all(engine) app = FastAPI() @app.on_event("startup") def on_startup(): create_db_and_tables() @app.get("/heroes/", response_model=List[HeroRead]) def read_heroes(): with Session(engine) as session: heroes = session.exec(select(Hero)).all() return heroes @app.post("/heroes/", ) def create_hero(file: UploadFile, name: str = Form()): with Session(engine) as session: file_obj = file.file._file db_hero = Hero(path=file_obj, id_code=name) session.add(db_hero) session.commit() session.refresh(db_hero) return "db_hero"