forked from ScoDoc/ScoDoc
Compare commits
7 Commits
5cdf089a1b
...
6955c36ff5
Author | SHA1 | Date | |
---|---|---|---|
|
6955c36ff5 | ||
08dfaeb436 | |||
ee050889f0 | |||
84d0b4fb9d | |||
d35940cc0d | |||
bea7b2ed8a | |||
|
87d04905fe |
@ -21,6 +21,7 @@ from app.api import api_web_bp, get_model_api_object, tools
|
||||
from app.decorators import permission_required, scodoc
|
||||
from app.models import (
|
||||
Assiduite,
|
||||
Evaluation,
|
||||
FormSemestre,
|
||||
Identite,
|
||||
ModuleImpl,
|
||||
@ -282,6 +283,7 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False)
|
||||
404,
|
||||
message="étudiant inconnu",
|
||||
)
|
||||
|
||||
# Récupération des assiduités de l'étudiant
|
||||
assiduites_query: Query = etud.assiduites
|
||||
|
||||
@ -304,6 +306,89 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False)
|
||||
return data_set
|
||||
|
||||
|
||||
@bp.route("/assiduites/<int:etudid>/evaluations")
|
||||
@api_web_bp.route("/assiduites/<int:etudid>/evaluations")
|
||||
# etudid
|
||||
@bp.route("/assiduites/etudid/<int:etudid>/evaluations")
|
||||
@api_web_bp.route("/assiduites/etudid/<int:etudid>/evaluations")
|
||||
# ine
|
||||
@bp.route("/assiduites/ine/<ine>/evaluations")
|
||||
@api_web_bp.route("/assiduites/ine/<ine>/evaluations")
|
||||
# nip
|
||||
@bp.route("/assiduites/nip/<nip>/evaluations")
|
||||
@api_web_bp.route("/assiduites/nip/<nip>/evaluations")
|
||||
@login_required
|
||||
@scodoc
|
||||
@as_json
|
||||
@permission_required(Permission.ScoView)
|
||||
def assiduites_evaluations(etudid: int = None, nip=None, ine=None):
|
||||
"""
|
||||
Retourne la liste de toutes les évaluations de l'étudiant
|
||||
Pour chaque évaluation, retourne la liste des objets assiduités
|
||||
sur la plage de l'évaluation
|
||||
|
||||
Présentation du retour :
|
||||
[
|
||||
{
|
||||
"evaluation_id": 1234,
|
||||
"assiduites": [
|
||||
{
|
||||
"assiduite_id":1234,
|
||||
...
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
"""
|
||||
# Récupération de l'étudiant
|
||||
etud: Identite = tools.get_etud(etudid, nip, ine)
|
||||
if etud is None:
|
||||
return json_error(
|
||||
404,
|
||||
message="étudiant inconnu",
|
||||
)
|
||||
|
||||
# Récupération des évaluations et des assidiutés
|
||||
etud_evaluations_assiduites: list[dict] = scass.get_etud_evaluations_assiduites(
|
||||
etud
|
||||
)
|
||||
|
||||
return etud_evaluations_assiduites
|
||||
|
||||
|
||||
@api_web_bp.route("/evaluation/<int:evaluation_id>/assiduites")
|
||||
@bp.route("/evaluation/<int:evaluation_id>/assiduites")
|
||||
@login_required
|
||||
@scodoc
|
||||
@as_json
|
||||
@permission_required(Permission.ScoView)
|
||||
def evaluation_assiduites(evaluation_id):
|
||||
"""
|
||||
Retourne les objets assiduités de chaque étudiant sur la plage de l'évaluation
|
||||
Présentation du retour :
|
||||
{
|
||||
"<etudid>" : [
|
||||
{
|
||||
"assiduite_id":1234,
|
||||
...
|
||||
},
|
||||
]
|
||||
}
|
||||
"""
|
||||
# Récupération de l'évaluation
|
||||
evaluation: Evaluation = Evaluation.get_evaluation(evaluation_id)
|
||||
|
||||
evaluation_assiduites_par_etudid: dict[int, list[Assiduite]] = {}
|
||||
for assi in scass.get_evaluation_assiduites(evaluation):
|
||||
etudid: str = str(assi.etudid)
|
||||
etud_assiduites = evaluation_assiduites_par_etudid.get(etudid, [])
|
||||
etud_assiduites.append(assi.to_dict(format_api=True))
|
||||
evaluation_assiduites_par_etudid[etudid] = etud_assiduites
|
||||
|
||||
return evaluation_assiduites_par_etudid
|
||||
|
||||
|
||||
@bp.route("/assiduites/group/query", defaults={"with_query": True})
|
||||
@api_web_bp.route("/assiduites/group/query", defaults={"with_query": True})
|
||||
@login_required
|
||||
|
@ -89,12 +89,17 @@ def _get_etud_by_code(
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
@as_json
|
||||
def etudiants_courants(long=False):
|
||||
def etudiants_courants(long: bool = False):
|
||||
"""
|
||||
La liste des étudiants des semestres "courants" (tous départements)
|
||||
(date du jour comprise dans la période couverte par le sem.)
|
||||
dans lesquels l'utilisateur a la permission ScoView
|
||||
(donc tous si le dept du rôle est None).
|
||||
La liste des étudiants des semestres "courants".
|
||||
Considère tous les départements dans lesquels l'utilisateur a la
|
||||
permission `ScoView` (donc tous si le dépt. du rôle est `None`),
|
||||
et les formsemestres contenant la date courante,
|
||||
ou à défaut celle indiquée en argument (au format ISO).
|
||||
|
||||
QUERY
|
||||
-----
|
||||
date_courante:<string:date_courante>
|
||||
|
||||
Exemple de résultat :
|
||||
[
|
||||
@ -183,8 +188,13 @@ def etudiant(etudid: int = None, nip: str = None, ine: str = None):
|
||||
@permission_required(Permission.ScoView)
|
||||
def get_photo_image(etudid: int = None, nip: str = None, ine: str = None):
|
||||
"""
|
||||
Retourne la photo de l'étudiant
|
||||
correspondant ou un placeholder si non existant.
|
||||
Retourne la photo de l'étudiant ou un placeholder si non existant.
|
||||
Le paramètre `size` peut prendre la valeur `small` (taille réduite, hauteur
|
||||
environ 90 pixels) ou `orig` (défaut, image de la taille originale).
|
||||
|
||||
QUERY
|
||||
-----
|
||||
size:<string:size>
|
||||
|
||||
etudid : l'etudid de l'étudiant
|
||||
nip : le code nip de l'étudiant
|
||||
|
@ -108,6 +108,17 @@ def formsemestres_query():
|
||||
dept_id : id du département
|
||||
ine ou nip: code d'un étudiant: ramène alors tous les semestres auxquels il est inscrit.
|
||||
etat: 0 si verrouillé, 1 sinon
|
||||
|
||||
QUERY
|
||||
-----
|
||||
etape_apo:<string:etape_apo>
|
||||
annee_scolaire:<string:annee_scolaire>
|
||||
dept_acronym:<string:dept_acronym>
|
||||
dept_id:<int:dept_id>
|
||||
etat:<int:etat>
|
||||
nip:<string:nip>
|
||||
ine:<string:ine>
|
||||
|
||||
"""
|
||||
etape_apo = request.args.get("etape_apo")
|
||||
annee_scolaire = request.args.get("annee_scolaire")
|
||||
@ -376,7 +387,16 @@ def formsemestre_programme(formsemestre_id: int):
|
||||
def formsemestre_etudiants(
|
||||
formsemestre_id: int, with_query: bool = False, long: bool = False
|
||||
):
|
||||
"""Étudiants d'un formsemestre."""
|
||||
"""Étudiants d'un formsemestre.
|
||||
|
||||
Si l'état est spécifié, ne renvoie que les inscrits (`I`), les
|
||||
démissionnaires (`D`) ou les défaillants (`DEF`)
|
||||
|
||||
QUERY
|
||||
-----
|
||||
etat:<string:etat>
|
||||
|
||||
"""
|
||||
query = FormSemestre.query.filter_by(id=formsemestre_id)
|
||||
if g.scodoc_dept:
|
||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||
@ -531,6 +551,13 @@ def etat_evals(formsemestre_id: int):
|
||||
def formsemestre_resultat(formsemestre_id: int):
|
||||
"""Tableau récapitulatif des résultats
|
||||
Pour chaque étudiant, son état, ses groupes, ses moyennes d'UE et de modules.
|
||||
|
||||
Si `format=raw`, ne converti pas les valeurs.
|
||||
|
||||
QUERY
|
||||
-----
|
||||
format:<string:format>
|
||||
|
||||
"""
|
||||
format_spec = request.args.get("format", None)
|
||||
if format_spec is not None and format_spec != "raw":
|
||||
@ -623,6 +650,12 @@ def formsemestre_edt(formsemestre_id: int):
|
||||
|
||||
group_ids permet de filtrer sur les groupes ScoDoc.
|
||||
show_modules_titles affiche le titre complet du module (défaut), sinon juste le code.
|
||||
|
||||
QUERY
|
||||
-----
|
||||
group_ids:<string:group_ids>
|
||||
show_modules_titles:<bool:show_modules_titles>
|
||||
|
||||
"""
|
||||
query = FormSemestre.query.filter_by(id=formsemestre_id)
|
||||
if g.scodoc_dept:
|
||||
|
@ -151,7 +151,13 @@ def etud_in_group(group_id: int):
|
||||
@permission_required(Permission.ScoView)
|
||||
@as_json
|
||||
def etud_in_group_query(group_id: int):
|
||||
"""Étudiants du groupe, filtrés par état"""
|
||||
"""Étudiants du groupe, filtrés par état (aucun, I, D, DEF)
|
||||
|
||||
QUERY
|
||||
-----
|
||||
etat:<string:etat>
|
||||
|
||||
"""
|
||||
etat = request.args.get("etat")
|
||||
if etat not in {None, scu.INSCRIT, scu.DEMISSION, scu.DEF}:
|
||||
return json_error(API_CLIENT_ERROR, "etat: valeur invalide")
|
||||
|
@ -59,6 +59,13 @@ def users_info_query():
|
||||
Seuls les utilisateurs "accessibles" (selon les permissions) sont retournés.
|
||||
Si accès via API web, le département de l'URL est ignoré, seules
|
||||
les permissions de l'utilisateur sont prises en compte.
|
||||
|
||||
QUERY
|
||||
-----
|
||||
active:<bool:active>
|
||||
departement:<string:departement>
|
||||
starts_with:<string:starts_with>
|
||||
|
||||
"""
|
||||
query = User.query
|
||||
active = request.args.get("active")
|
||||
|
@ -35,9 +35,9 @@ def after_cas_login():
|
||||
if user.cas_allow_login:
|
||||
current_app.logger.info(f"CAS: login {user.user_name}")
|
||||
if login_user(user):
|
||||
flask.session[
|
||||
"scodoc_cas_login_date"
|
||||
] = datetime.datetime.now().isoformat()
|
||||
flask.session["scodoc_cas_login_date"] = (
|
||||
datetime.datetime.now().isoformat()
|
||||
)
|
||||
user.cas_last_login = datetime.datetime.utcnow()
|
||||
if flask.session.get("CAS_EDT_ID"):
|
||||
# essaie de récupérer l'edt_id s'il est présent
|
||||
@ -45,8 +45,10 @@ def after_cas_login():
|
||||
# via l'expression `cas_edt_id_from_xml_regexp`
|
||||
# voir flask_cas.routing
|
||||
edt_id = flask.session.get("CAS_EDT_ID")
|
||||
current_app.logger.info(f"""after_cas_login: storing edt_id for {
|
||||
user.user_name}: '{edt_id}'""")
|
||||
current_app.logger.info(
|
||||
f"""after_cas_login: storing edt_id for {
|
||||
user.user_name}: '{edt_id}'"""
|
||||
)
|
||||
user.edt_id = edt_id
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
@ -55,12 +57,17 @@ def after_cas_login():
|
||||
current_app.logger.info(
|
||||
f"CAS login denied for {user.user_name} (not allowed to use CAS)"
|
||||
)
|
||||
else:
|
||||
else: # pas d'utilisateur ScoDoc ou bien compte inactif
|
||||
current_app.logger.info(
|
||||
f"""CAS login denied for {
|
||||
user.user_name if user else ""
|
||||
} cas_id={cas_id} (unknown or inactive)"""
|
||||
)
|
||||
if ScoDocSiteConfig.is_cas_forced():
|
||||
# Dans ce cas, pas de redirect vers la page de login pour éviter de boucler
|
||||
raise ScoValueError(
|
||||
"compte ScoDoc inexistant ou inactif pour cet utilisateur CAS"
|
||||
)
|
||||
else:
|
||||
current_app.logger.info(
|
||||
f"""CAS attribute '{ScoDocSiteConfig.get("cas_attribute_id")}' not found !
|
||||
|
@ -10,6 +10,7 @@ from flask_sqlalchemy.query import Query
|
||||
|
||||
from app import log, db, set_sco_dept
|
||||
from app.models import (
|
||||
Evaluation,
|
||||
Identite,
|
||||
FormSemestre,
|
||||
FormSemestreInscription,
|
||||
@ -731,6 +732,95 @@ def create_absence_billet(
|
||||
return calculator.to_dict()["demi"]
|
||||
|
||||
|
||||
def get_evaluation_assiduites(evaluation: Evaluation) -> Query:
|
||||
"""
|
||||
Renvoie une query d'assiduité en fonction des étudiants inscrits à l'évaluation
|
||||
et de la date de l'évaluation.
|
||||
|
||||
Attention : Si l'évaluation n'a pas de date, renvoie None
|
||||
"""
|
||||
|
||||
# Evaluation sans date
|
||||
if evaluation.date_debut is None:
|
||||
return None
|
||||
|
||||
# Récupération des étudiants inscrits à l'évaluation
|
||||
etuds: Query = Identite.query.join(
|
||||
ModuleImplInscription, Identite.id == ModuleImplInscription.etudid
|
||||
).filter(ModuleImplInscription.moduleimpl_id == evaluation.moduleimpl_id)
|
||||
|
||||
etudids: list[int] = [etud.id for etud in etuds]
|
||||
|
||||
# Récupération des assiduités des étudiants inscrits à l'évaluation
|
||||
date_debut: datetime = evaluation.date_debut
|
||||
date_fin: datetime
|
||||
|
||||
if evaluation.date_fin is not None:
|
||||
date_fin = evaluation.date_fin
|
||||
else:
|
||||
# On met à la fin de la journée de date_debut
|
||||
date_fin = datetime.combine(date_debut.date(), time.max)
|
||||
|
||||
# Filtrage par rapport à la plage de l'évaluation
|
||||
assiduites: Query = Assiduite.query.filter(
|
||||
Assiduite.date_debut >= date_debut,
|
||||
Assiduite.date_fin <= date_fin,
|
||||
Assiduite.etudid.in_(etudids),
|
||||
)
|
||||
|
||||
return assiduites
|
||||
|
||||
|
||||
def get_etud_evaluations_assiduites(etud: Identite) -> list[dict]:
|
||||
"""
|
||||
Retourne la liste des évaluations d'un étudiant. Pour chaque évaluation,
|
||||
retourne la liste des assiduités concernant la plage de l'évaluation.
|
||||
"""
|
||||
|
||||
etud_evaluations_assiduites: list[dict] = []
|
||||
|
||||
# On récupère les moduleimpls puis les évaluations liés aux moduleimpls
|
||||
modsimpl_ids: list[int] = [
|
||||
modimp_inscr.moduleimpl_id
|
||||
for modimp_inscr in ModuleImplInscription.query.filter_by(etudid=etud.id)
|
||||
]
|
||||
evaluations: Query = Evaluation.query.filter(
|
||||
Evaluation.moduleimpl_id.in_(modsimpl_ids)
|
||||
)
|
||||
# Pour chaque évaluation, on récupère l'assiduité de l'étudiant sur la plage
|
||||
# de l'évaluation
|
||||
|
||||
for evaluation in evaluations:
|
||||
eval_assis: dict = {"evaluation_id": evaluation.id, "assiduites": []}
|
||||
# Pas d'assiduités si pas de date
|
||||
if evaluation.date_debut is None:
|
||||
continue
|
||||
|
||||
date_debut: datetime = evaluation.date_debut
|
||||
date_fin: datetime
|
||||
|
||||
if evaluation.date_fin is not None:
|
||||
date_fin = evaluation.date_fin
|
||||
else:
|
||||
# On met à la fin de la journée de date_debut
|
||||
date_fin = datetime.combine(date_debut.date(), time.max)
|
||||
|
||||
# Filtrage par rapport à la plage de l'évaluation
|
||||
assiduites: Query = etud.assiduites.filter(
|
||||
Assiduite.date_debut >= date_debut,
|
||||
Assiduite.date_fin <= date_fin,
|
||||
)
|
||||
# On récupère les assiduités et on met à jour le dictionnaire
|
||||
eval_assis["assiduites"] = [
|
||||
assi.to_dict(format_api=True) for assi in assiduites
|
||||
]
|
||||
|
||||
# On ajoute le dictionnaire à la liste des évaluations
|
||||
etud_evaluations_assiduites.append(eval_assis)
|
||||
|
||||
return etud_evaluations_assiduites
|
||||
|
||||
|
||||
# Gestion du cache
|
||||
def get_assiduites_count(etudid: int, sem: dict) -> tuple[int, int, int]:
|
||||
"""Les comptes d'absences de cet étudiant dans ce semestre:
|
||||
|
@ -691,9 +691,13 @@ def module_edit(
|
||||
str(parcour.id) for parcour in ref_comp.parcours
|
||||
]
|
||||
+ ["-1"],
|
||||
"explanation": """Parcours dans lesquels est utilisé ce module.<br>
|
||||
Attention: si le module ne doit pas avoir les mêmes coefficients suivant le parcours,
|
||||
il faut en créer plusieurs versions, car dans ScoDoc chaque module a ses coefficients.""",
|
||||
"explanation": """Parcours dans lesquels est utilisé ce module (inutile
|
||||
hors BUT, pour les modules standards et dans les UEs de bonus).
|
||||
<br>
|
||||
Attention: si le module ne doit pas avoir les mêmes coefficients suivant
|
||||
le parcours, il faut en créer plusieurs versions, car dans ScoDoc chaque
|
||||
module a ses coefficients.
|
||||
""",
|
||||
},
|
||||
)
|
||||
]
|
||||
|
@ -931,11 +931,12 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
||||
return "\n".join(H)
|
||||
|
||||
|
||||
def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
||||
def feuille_saisie_notes(evaluation_id, group_ids: list[int] = None):
|
||||
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
||||
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
|
||||
if not evaluation:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
group_ids = group_ids or []
|
||||
modimpl = evaluation.moduleimpl
|
||||
formsemestre = modimpl.formsemestre
|
||||
mod_responsable = sco_users.user_info(modimpl.responsable_id)
|
||||
@ -950,7 +951,8 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
||||
if evaluation.date_debut
|
||||
else "(sans date)"
|
||||
)
|
||||
eval_titre = f"""{evaluation.description if evaluation.description else "évaluation"} {date_str}"""
|
||||
eval_titre = f"""{evaluation.description if evaluation.description else "évaluation"
|
||||
} {date_str}"""
|
||||
|
||||
description = f"""{eval_titre} en {evaluation.moduleimpl.module.abbrev or ""} ({
|
||||
evaluation.moduleimpl.module.code
|
||||
@ -986,7 +988,7 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
||||
rows.append(
|
||||
[
|
||||
str(etudid),
|
||||
e["nom"].upper(),
|
||||
e.get("nom_disp", "") or e.get("nom_usuel", "") or e["nom"],
|
||||
e["prenom"].lower().capitalize(),
|
||||
e["inscr"]["etat"],
|
||||
grc,
|
||||
@ -1206,7 +1208,7 @@ def _get_sorted_etuds(evaluation: Evaluation, etudids: list, formsemestre_id: in
|
||||
def _form_saisie_notes(
|
||||
evaluation: Evaluation, modimpl: ModuleImpl, groups_infos, destination=""
|
||||
):
|
||||
"""Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M
|
||||
"""Formulaire HTML saisie des notes dans l'évaluation du moduleimpl
|
||||
pour les groupes indiqués.
|
||||
|
||||
On charge tous les étudiants, ne seront montrés que ceux
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.6.980"
|
||||
SCOVERSION = "9.6.981"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
@ -66,6 +66,7 @@ def test_permissions(api_headers):
|
||||
"assiduite_id": 1,
|
||||
"justif_id": 1,
|
||||
"etudids": "1",
|
||||
"ue_id": 1,
|
||||
}
|
||||
# Arguments spécifiques pour certaines routes
|
||||
# par défaut, on passe tous les arguments de all_args
|
||||
|
@ -461,6 +461,7 @@ def gen_api_map(app, endpoint_start="api"):
|
||||
|
||||
# Récupération de la fonction associée à la route
|
||||
func = app.view_functions[rule.endpoint]
|
||||
func_name = parse_doc_name(func.__doc__ or "") or func.__name__
|
||||
|
||||
# Pour chaque segment de la route
|
||||
for i, segment in enumerate(segments):
|
||||
@ -494,7 +495,7 @@ def gen_api_map(app, endpoint_start="api"):
|
||||
|
||||
# On ajoute le token comme enfant du token courant
|
||||
# en donnant la méthode et le nom de la fonction associée
|
||||
child.func_name = func.__name__
|
||||
child.func_name = func_name
|
||||
method: str = "POST" if "POST" in rule.methods else "GET"
|
||||
child.method = method
|
||||
current_token.add_child(child)
|
||||
@ -602,6 +603,9 @@ def generate_svg(element, fname):
|
||||
)
|
||||
ET.SubElement(marker, "polygon", {"points": "0 0, 10 3.5, 0 7"})
|
||||
|
||||
# Ajoute un décalage vertical pour avoir un peu de padding en haut
|
||||
element.set("transform", "translate(0, 10)")
|
||||
|
||||
# Ajout de l'élément principal à l'élément racine
|
||||
svg.append(element)
|
||||
|
||||
@ -610,6 +614,50 @@ def generate_svg(element, fname):
|
||||
tree.write(fname, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
|
||||
def _get_doc_lines(keyword, doc) -> list[str]:
|
||||
"""
|
||||
Renvoie les lignes de la doc qui suivent le mot clé keyword
|
||||
|
||||
La doc doit contenir des lignes de la forme:
|
||||
|
||||
KEYWORD
|
||||
-------
|
||||
...
|
||||
|
||||
"""
|
||||
# Récupérer les lignes de la doc
|
||||
lines = [line.strip() for line in doc.split("\n")]
|
||||
# On cherche la ligne "KEYWORD" et on vérifie que la ligne suivante est "-----"
|
||||
# Si ce n'est pas le cas, on renvoie un dictionnaire vide
|
||||
try:
|
||||
kw_index = lines.index(keyword)
|
||||
kw_line = "-" * len(keyword)
|
||||
if lines[kw_index + 1] != kw_line:
|
||||
return []
|
||||
except ValueError:
|
||||
return []
|
||||
# On récupère les lignes de la doc qui correspondent au keyword (enfin on espère)
|
||||
kw_lines = lines[kw_index + 2 :]
|
||||
return kw_lines
|
||||
|
||||
|
||||
def parse_doc_name(doc):
|
||||
"""
|
||||
renvoie le nom de la route à partir de la docstring
|
||||
|
||||
La doc doit contenir des lignes de la forme:
|
||||
|
||||
DOC_ANCHOR
|
||||
----------
|
||||
nom_de_la_route
|
||||
|
||||
Il ne peut y avoir qu'une seule ligne suivant -----
|
||||
|
||||
"""
|
||||
name_lines: list[str] = _get_doc_lines("DOC_ANCHOR", doc)
|
||||
return name_lines[0] if name_lines else None
|
||||
|
||||
|
||||
def parse_query_doc(doc):
|
||||
"""
|
||||
renvoie un dictionnaire {param: <type:nom_param>} (ex: {assiduite_id : <int:assiduite_id>})
|
||||
@ -625,18 +673,7 @@ def parse_query_doc(doc):
|
||||
Dès qu'une ligne ne respecte pas ce format (voir regex dans la fonction), on arrête de parser
|
||||
Attention, la ligne ----- doit être collée contre QUERY et contre le premier paramètre
|
||||
"""
|
||||
# Récupérer les lignes de la doc
|
||||
lines = [line.strip() for line in doc.split("\n")]
|
||||
# On cherche la ligne "QUERY" et on vérifie que la ligne suivante est "-----"
|
||||
# Si ce n'est pas le cas, on renvoie un dictionnaire vide
|
||||
try:
|
||||
query_index = lines.index("QUERY")
|
||||
if lines[query_index + 1] != "-----":
|
||||
return {}
|
||||
except ValueError:
|
||||
return {}
|
||||
# On récupère les lignes de la doc qui correspondent à la query (enfin on espère)
|
||||
query_lines = lines[query_index + 2 :]
|
||||
query_lines: list[str] = _get_doc_lines("QUERY", doc)
|
||||
|
||||
query = {}
|
||||
regex = re.compile(r"^(\w+):(<.+>)$")
|
||||
|
Loading…
Reference in New Issue
Block a user