102 lines
3.0 KiB
Python
102 lines
3.0 KiB
Python
|
|
from fastapi.exceptions import HTTPException
|
|
from fastapi import UploadFile, status
|
|
from tortoise.validators import Validator
|
|
from tortoise.exceptions import ValidationError
|
|
import types
|
|
from services.timeout import timeout
|
|
from services.io import is_binary_file
|
|
import os
|
|
|
|
def checkExoSupportCompatibility(obj):
|
|
isPdf = False if (obj['pdf'] == None or (
|
|
obj['calcul'] == False and obj['pdf'] == False)) else True
|
|
|
|
isCsv = False if (obj['csv'] == None or (
|
|
obj['calcul'] == False and obj['csv'] == False)) else True
|
|
|
|
isWeb = False if (obj['web'] == None or (
|
|
obj['calcul'] == False and obj['web'] == False)) else True
|
|
|
|
return {
|
|
'pdf': isPdf, 'csv': isCsv, 'web': isWeb}
|
|
|
|
|
|
def get_module_from_string(value: str, *args, **kwargs):
|
|
locs = {}
|
|
try:
|
|
exec(value, dict(), locs)
|
|
except Exception as err:
|
|
raise ValueError(err)
|
|
return locs
|
|
|
|
|
|
def execute_main_if_avalaible(spec, *args, **kwargs):
|
|
try:
|
|
return spec["main"]()
|
|
except KeyError as atrerror:
|
|
raise ValueError(f"Fonction 'main' introuvable")
|
|
except Exception as e:
|
|
raise ValueError(f'[Error] : {e}')
|
|
|
|
|
|
def get_spec_with_timeout(data, time):
|
|
return get_module_from_string(data)
|
|
with timeout(time, ValidationError('[Error] : Script took too long')):
|
|
return get_module_from_string(data)
|
|
|
|
|
|
def fill_empty_values(object):
|
|
default_object = {"calcul": False, 'pdf': False, 'csv': False,
|
|
'web': False, 'correction': False}
|
|
return {**default_object, **object}
|
|
|
|
|
|
def get_support_from_data(data: str):
|
|
|
|
locs = get_spec_with_timeout(data, 5)
|
|
result = execute_main_if_avalaible(locs)
|
|
result = fill_empty_values(result)
|
|
|
|
exo_supports_compatibility = checkExoSupportCompatibility(result)
|
|
return exo_supports_compatibility
|
|
|
|
|
|
def get_support_from_path(path: str):
|
|
if not os.path.exists(path):
|
|
raise ValidationError('[Error] : No such file or directory')
|
|
is_binary = is_binary_file(path)
|
|
|
|
if is_binary:
|
|
mode = 'rb'
|
|
else:
|
|
mode = 'r'
|
|
|
|
with open(path, mode) as f:
|
|
data = f.read() if mode == "r" else f.read().decode('utf8')
|
|
return get_support_from_data(data)
|
|
|
|
|
|
async def validate_file(file: UploadFile):
|
|
data = await file.read()
|
|
try:
|
|
exo_supports_compatibility = get_support_from_data(
|
|
data)
|
|
if not exo_supports_compatibility['pdf'] and not exo_supports_compatibility['csv'] and not exo_supports_compatibility['web']:
|
|
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail={"exo_source_error":
|
|
'Exercice non valide (compatible avec aucun support)'})
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail={
|
|
"exo_source_error": e.args[0]})
|
|
except HTTPException as e:
|
|
raise e
|
|
await file.seek(0)
|
|
return file
|
|
|
|
async def validate_file_optionnal(file: UploadFile = None):
|
|
if not file:
|
|
return None
|
|
return await validate_file(file)
|
|
|
|
|