generateur_v3/backend/api_old/database/exercices/validators.py
2022-09-16 21:50:55 +02:00

94 lines
2.7 KiB
Python

from contextlib import contextmanager
import os
import typing
from tortoise.validators import Validator
from tortoise.exceptions import ValidationError
import importlib.util
import types
from services.timeout import timeout
from .customField import is_binary_file
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 {
'isPdf': isPdf, 'isCsv': isCsv, 'isWeb': isWeb}
def get_module_from_string(value: str) -> types.ModuleType:
spec = types.ModuleType('exo')
try:
exec(value, spec.__dict__)
except Exception as err:
raise ValidationError(f'[Error] : {err}')
return spec
def execute_main_if_present(spec):
try:
return spec.main()
except AttributeError as atrerror:
raise ValidationError(f"[Error] : function 'main' is missing")
except Exception as e:
raise ValidationError(f'[Error] : {e}')
def get_spec_with_timeout(data, time):
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_compatibility_for_exo_source_from_data(data: str):
spec = get_spec_with_timeout(data, 5)
result = execute_main_if_present(spec)
result = fill_empty_values(result)
exo_supports_compatibility = checkExoSupportCompatibility(result)
return exo_supports_compatibility
def get_support_compatibility_for_exo_source_from_path(path):
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_compatibility_for_exo_source_from_data(data)
class ExoSourceValidator(Validator):
"""
A validator to validate ...
"""
def __call__(self, value: typing.IO):
exo_supports_compatibility = get_support_compatibility_for_exo_source_from_data(
value.read())
if not exo_supports_compatibility['isPdf'] and not exo_supports_compatibility['isCsv'] and not exo_supports_compatibility['isWeb']:
raise ValidationError('[Error] : Exercice non valide (compatible avec aucun support)')