94 lines
2.7 KiB
Python
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)')
|