generateur_v3/backend/api_old/database/exercices/validators.py

94 lines
2.7 KiB
Python
Raw Normal View History

2022-09-16 21:50:55 +02:00
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)')