95 lines
3.5 KiB
Python
95 lines
3.5 KiB
Python
# Dynamic import
|
||
import importlib
|
||
|
||
# Get function args
|
||
import inspect
|
||
|
||
# check file properties
|
||
import os
|
||
|
||
# The directory where student work will be
|
||
# not a real path, do not use ./ or stuff like this
|
||
BASE_MODULE_PATH = 'python_app/modules'
|
||
if BASE_MODULE_PATH != '':
|
||
BASE_MODULE_PATH += '/'
|
||
|
||
|
||
def application(env, start_response):
|
||
""" Cette fonction est appellée à chaque requête HTTP et doit exécuter le bon code python. """
|
||
|
||
path = env['PATH_INFO'][1:] # removing first slash
|
||
# slash stuff
|
||
if path.endswith('/'):
|
||
path = path[:-1]
|
||
path_elements = tuple(d for d in path.split('/') if d != '')
|
||
path_minus_one = '/'.join(path_elements[:-1])
|
||
|
||
# Find which python module and function will be called
|
||
if os.path.isfile(BASE_MODULE_PATH + path_minus_one):
|
||
path = path_minus_one
|
||
function = path_elements[-1]
|
||
elif os.path.isfile(BASE_MODULE_PATH + path):
|
||
function = 'index'
|
||
elif os.path.isdir(BASE_MODULE_PATH + path):
|
||
path += '/main'
|
||
function = 'index'
|
||
else:
|
||
return htmlresp(404, 'Le dossier <em>{}</em> n’a pas été trouvé.'.format(path), start_response)
|
||
|
||
|
||
|
||
# Module full path
|
||
module_path = BASE_MODULE_PATH + path
|
||
module_path = module_path.replace('/', '.')
|
||
|
||
# Import the function
|
||
try:
|
||
m = importlib.import_module(module_path)
|
||
importlib.reload(m)
|
||
except ModuleNotFoundError:
|
||
#print('Le fichier {} n’a pas été trouvé. {}'.format(module_path, str(path_elements)))
|
||
return htmlresp(404, 'Le fichier <em>{}</em> n’a pas été trouvé.'.format(path), start_response)
|
||
|
||
# Find which parameters the function needs
|
||
try:
|
||
f = getattr(m,function)
|
||
# Call the function with the rigth attributes
|
||
except AttributeError:
|
||
return htmlresp(404, 'La fonction <em>{}</em> n’a pas été trouvée dans {}'.format(function, module_path), start_response)
|
||
|
||
# Pass url parameters to the function
|
||
try:
|
||
#print(inspect.getargspec(f))
|
||
#params = {p:(d if d is not None else '') for p,d in zip(inspect.getargspec(f).args, inspect.getargspec(f).defaults)}
|
||
expected_params = inspect.getargspec(f).args
|
||
params = {}
|
||
# TODO POST params?
|
||
for item in env['QUERY_STRING'].split('&'):
|
||
if item == '':
|
||
continue
|
||
k,v = tuple(item.split('='))
|
||
if k in expected_params:
|
||
params[k] = v
|
||
except Exception:
|
||
return htmlresp(400, 'La fonction <em>{}</em> demande les arguments suivants : {}. On a uniquement {}.'.format(function, params, ), start_response)
|
||
|
||
try:
|
||
response = f(**params)
|
||
if type(response) is tuple:
|
||
return htmlresp(response[0], str(response[1]), start_response, False)
|
||
else:
|
||
return htmlresp(200, str(response), start_response, False)
|
||
except Exception as e:
|
||
return htmlresp(400, 'Erreur à l’exécution de la fonction <em>{}</em>.<pre style="color:#d90303;">{}</pre>'.format(function, e), start_response)
|
||
|
||
|
||
def htmlresp(code, message, start_response, squelette=True):
|
||
""" Cette fonction crée le squelette HTML minimal """
|
||
html = '<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>{}</body></html>'
|
||
return resp(code, [('Content-Type','text/html')], html.format(message) if squelette else message, start_response)
|
||
|
||
def resp(code, headers, message, start_response):
|
||
""" Cette fonction permet de faire une réponse HTTP """
|
||
start_response(str(code), headers)
|
||
return bytes(message, 'utf8')
|