1
0
forked from ScoDoc/ScoDoc

Merge pull request 'APIDoc : Samples + fix query + légères modifs' (#970) from iziram/ScoDoc:master into master

Reviewed-on: ScoDoc/ScoDoc#970
This commit is contained in:
Emmanuel Viennet 2024-07-25 15:12:58 +02:00
commit 0a7bb35604
6 changed files with 237 additions and 106 deletions

View File

@ -64,6 +64,11 @@ def assiduite(assiduite_id: int = None):
"est_just": False or True, "est_just": False or True,
} }
``` ```
SAMPLES
-------
/assiduite/1;
""" """
return get_model_api_object(Assiduite, assiduite_id, Identite) return get_model_api_object(Assiduite, assiduite_id, Identite)
@ -93,6 +98,11 @@ def assiduite_justificatifs(assiduite_id: int = None, long: bool = False):
... ...
] ]
``` ```
SAMPLES
-------
/assiduite/1/justificatifs;
/assiduite/1/justificatifs/long;
""" """
return get_assiduites_justif(assiduite_id, long) return get_assiduites_justif(assiduite_id, long)
@ -156,6 +166,13 @@ def assiduites_count(
metric: la/les métriques de comptage (journee, demi, heure, compte) metric: la/les métriques de comptage (journee, demi, heure, compte)
split: divise le comptage par état split: divise le comptage par état
SAMPLES
-------
/assiduites/1/count;
/assiduites/1/count/query?etat=retard;
/assiduites/1/count/query?split;
/assiduites/1/count/query?etat=present,retard&metric=compte,heure;
""" """
# Récupération de l'étudiant # Récupération de l'étudiant
@ -221,6 +238,7 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False)
date_fin:<string:date_fin_iso> date_fin:<string:date_fin_iso>
etat:<array[string]:etat> etat:<array[string]:etat>
formsemestre_id:<int:formsemestre_id> formsemestre_id:<int:formsemestre_id>
with_justifs:<bool:with_justifs>
PARAMS PARAMS
----- -----
@ -231,6 +249,14 @@ def assiduites(etudid: int = None, nip=None, ine=None, with_query: bool = False)
date_fin:date de fin de l'assiduité (inférieur ou égal) date_fin:date de fin de l'assiduité (inférieur ou égal)
etat:etat de l'étudiant &rightarrow; absent, present ou retard etat:etat de l'étudiant &rightarrow; absent, present ou retard
formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité
with_justif:ajoute les justificatifs liés à l'assiduité
SAMPLES
-------
/assiduites/1;
/assiduites/1/query?etat=retard;
/assiduites/1/query?moduleimpl_id=1;
/assiduites/1/query?with_justifs=;
""" """
@ -300,6 +326,11 @@ def assiduites_evaluations(etudid: int = None, nip=None, ine=None):
] ]
} }
] ]
SAMPLES
-------
/assiduites/1/evaluations;
``` ```
""" """
@ -344,7 +375,7 @@ def evaluation_assiduites(evaluation_id):
CATEGORY CATEGORY
-------- --------
evaluations Évaluations
""" """
# Récupération de l'évaluation # Récupération de l'évaluation
try: try:
@ -384,6 +415,7 @@ def assiduites_group(with_query: bool = False):
etat:<array[string]:etat> etat:<array[string]:etat>
etudids:<array[int]:etudids> etudids:<array[int]:etudids>
formsemestre_id:<int:formsemestre_id> formsemestre_id:<int:formsemestre_id>
with_justif:<bool:with_justif>
PARAMS PARAMS
----- -----
@ -395,6 +427,11 @@ def assiduites_group(with_query: bool = False):
etat:etat de l'étudiant &rightarrow; absent, present ou retard etat:etat de l'étudiant &rightarrow; absent, present ou retard
etudids:liste des ids des étudiants concernés par la recherche etudids:liste des ids des étudiants concernés par la recherche
formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité
with_justifs:ajoute les justificatifs liés à l'assiduité
SAMPLES
-------
/assiduites/group/query?etudids=1,2,3;
""" """
@ -474,6 +511,13 @@ def assiduites_formsemestre(formsemestre_id: int, with_query: bool = False):
date_fin:date de fin de l'assiduité (inférieur ou égal) date_fin:date de fin de l'assiduité (inférieur ou égal)
etat:etat de l'étudiant &rightarrow; absent, present ou retard etat:etat de l'étudiant &rightarrow; absent, present ou retard
formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité
SAMPLES
-------
/assiduites/formsemestre/1;
/assiduites/formsemestre/1/query?etat=retard;
/assiduites/formsemestre/1/query?moduleimpl_id=1;
""" """
# Récupération du formsemestre à partir du formsemestre_id # Récupération du formsemestre à partir du formsemestre_id
@ -549,6 +593,13 @@ def assiduites_formsemestre_count(
formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité formsemestre_id:l'identifiant du formsemestre concerné par l'assiduité
metric: la/les métriques de comptage (journee, demi, heure, compte) metric: la/les métriques de comptage (journee, demi, heure, compte)
split: divise le comptage par état split: divise le comptage par état
SAMPLES
-------
/assiduites/formsemestre/1/count;
/assiduites/formsemestre/1/count/query?etat=retard;
/assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure;
""" """
# Récupération du formsemestre à partir du formsemestre_id # Récupération du formsemestre à partir du formsemestre_id
@ -621,6 +672,11 @@ def assiduite_create(etudid: int = None, nip=None, ine=None):
] ]
``` ```
SAMPLES
-------
/assiduite/1/create;[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]
/assiduite/1/create;[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]
""" """
# Récupération de l'étudiant # Récupération de l'étudiant
etud: Identite = tools.get_etud(etudid, nip, ine) etud: Identite = tools.get_etud(etudid, nip, ine)
@ -696,6 +752,11 @@ def assiduites_create():
] ]
``` ```
SAMPLES
-------
/assiduites/create;[{""etudid"":1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]
/assiduites/create;[{""etudid"":-1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]
""" """
create_list: list[object] = request.get_json(force=True) create_list: list[object] = request.get_json(force=True)
@ -874,6 +935,10 @@ def assiduite_delete():
] ]
``` ```
SAMPLES
-------
/assiduite/delete;[2,2,3]
""" """
# Récupération des ids envoyés dans la liste # Récupération des ids envoyés dans la liste
assiduites_list: list[int] = request.get_json(force=True) assiduites_list: list[int] = request.get_json(force=True)
@ -958,6 +1023,13 @@ def assiduite_edit(assiduite_id: int):
"est_just"?: bool "est_just"?: bool
} }
``` ```
SAMPLES
-------
/assiduite/1/edit;{""etat"":""absent""}
/assiduite/1/edit;{""moduleimpl_id"":2}
/assiduite/1/edit;{""etat"": ""retard"",""moduleimpl_id"":3}
""" """
# Récupération de l'assiduité à modifier # Récupération de l'assiduité à modifier
@ -1013,6 +1085,12 @@ def assiduites_edit():
} }
] ]
``` ```
SAMPLES
-------
/assiduites/edit;[{""etat"":""absent"",""assiduite_id"":1}]
/assiduites/edit;[{""moduleimpl_id"":2,""assiduite_id"":1}]
/assiduites/edit;[{""etat"": ""retard"",""moduleimpl_id"":3,""assiduite_id"":1}]
""" """
edit_list: list[object] = request.get_json(force=True) edit_list: list[object] = request.get_json(force=True)

View File

@ -55,6 +55,11 @@ def justificatif(justif_id: int = None):
"user_id": 1 or null, "user_id": 1 or null,
} }
``` ```
SAMPLES
-------
/justificatif/1;
""" """
return get_model_api_object( return get_model_api_object(
@ -114,6 +119,12 @@ def justificatifs(etudid: int = None, nip=None, ine=None, with_query: bool = Fal
order:retourne les justificatifs dans l'ordre décroissant (non vide = True) order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
courant:retourne les justificatifs de l'année courante (bool : v/t ou f) courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
group_id:<int:group_id> group_id:<int:group_id>
SAMPLES
-------
/justificatifs/1;
/justificatifs/1/query?etat=attente;
""" """
# Récupération de l'étudiant # Récupération de l'étudiant
etud: Identite = tools.get_etud(etudid, nip, ine) etud: Identite = tools.get_etud(etudid, nip, ine)
@ -176,6 +187,11 @@ def justificatifs_dept(dept_id: int = None, with_query: bool = False):
order:retourne les justificatifs dans l'ordre décroissant (non vide = True) order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
courant:retourne les justificatifs de l'année courante (bool : v/t ou f) courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
group_id:<int:group_id> group_id:<int:group_id>
SAMPLES
-------
/justificatifs/dept/1;
""" """
# Récupération du département et des étudiants du département # Récupération du département et des étudiants du département
@ -269,6 +285,11 @@ def justificatifs_formsemestre(formsemestre_id: int, with_query: bool = False):
order:retourne les justificatifs dans l'ordre décroissant (non vide = True) order:retourne les justificatifs dans l'ordre décroissant (non vide = True)
courant:retourne les justificatifs de l'année courante (bool : v/t ou f) courant:retourne les justificatifs de l'année courante (bool : v/t ou f)
group_id:<int:group_id> group_id:<int:group_id>
SAMPLES
-------
/justificatifs/formsemestre/1;
""" """
# Récupération du formsemestre # Récupération du formsemestre
@ -336,6 +357,9 @@ def justif_create(etudid: int = None, nip=None, ine=None):
... ...
] ]
``` ```
SAMPLES
-------
/justificatif/1/create;[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""attente""}]
""" """
@ -477,6 +501,12 @@ def justif_edit(justif_id: int):
"date_fin"?: str "date_fin"?: str
} }
``` ```
SAMPLES
-------
/justificatif/1/edit;{""etat"":""valide""}
/justificatif/1/edit;{""raison"":""MEDIC""}
""" """
# Récupération du justificatif à modifier # Récupération du justificatif à modifier
@ -591,6 +621,11 @@ def justif_delete():
... ...
] ]
``` ```
SAMPLES
-------
/justificatif/delete;[2, 2, 3]
""" """
# Récupération des justif_ids # Récupération des justif_ids
@ -836,6 +871,11 @@ def justif_remove(justif_id: int = None):
def justif_list(justif_id: int = None): def justif_list(justif_id: int = None):
""" """
Liste les fichiers du justificatif Liste les fichiers du justificatif
SAMPLES
-------
/justificatif/1/list;
""" """
# Récupération du justificatif concerné # Récupération du justificatif concerné
@ -878,6 +918,11 @@ def justif_list(justif_id: int = None):
def justif_justifies(justif_id: int = None): def justif_justifies(justif_id: int = None):
""" """
Liste assiduite_id justifiées par le justificatif Liste assiduite_id justifiées par le justificatif
SAMPLES
-------
/justificatif/1/justifies;
""" """
# On récupère le justificatif concerné # On récupère le justificatif concerné

View File

@ -244,13 +244,13 @@ permet de rechercher une entrée à partir du résultat attendu.
</div> </div>
</div> </div>
(carte générée avec `flask gen-api-map -e "api."`) (carte générée avec `flask gen-api-doc`)
### Tableau récapitulatif des entrées de l'API ### Tableau récapitulatif des entrées de l'API
{{table_api|safe}} {{table_api|safe}}
(table générée avec `flask gen-api-map -e "api."`) (table générée avec `flask gen-api-doc`)
#### Note sur les exemples d'utilisation #### Note sur les exemples d'utilisation

View File

@ -740,19 +740,6 @@ def generate_ens_calendars(): # generate-ens-calendars
edt_ens.generate_ens_calendars() edt_ens.generate_ens_calendars()
@app.cli.command()
@click.option(
"-e",
"--endpoint",
default="api",
help="Endpoint à partir duquel générer la carte des routes",
)
@with_appcontext
def gen_api_map(endpoint): # gen-api-map
"""Génère la carte des routes de l'API."""
tools.gen_api_map(app, endpoint_start=endpoint)
@app.cli.command() @app.cli.command()
@click.option( @click.option(
"-e", "-e",

View File

@ -1,36 +1,38 @@
"entry_name";"url";"permission";"method";"content" "entry_name";"url";"permission";"method";"content"
"assiduite";"/assiduite/1";"ScoView";"GET"; "assiduite";"/assiduite/1";"ScoView";"GET";
"assiduites";"/assiduites/1";"ScoView";"GET"; "assiduite_justificatifs";"/assiduite/1/justificatifs";"ScoView";"GET";
"assiduites";"/assiduites/1/query?etat=retard";"ScoView";"GET"; "assiduite_justificatifs";"/assiduite/1/justificatifs/long";"ScoView";"GET";
"assiduites";"/assiduites/1/query?moduleimpl_id=1";"ScoView";"GET";
"assiduites";"/assiduites/1/query?with_justifs=";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count";"ScoView";"GET"; "assiduites_count";"/assiduites/1/count";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count/query?etat=retard";"ScoView";"GET"; "assiduites_count";"/assiduites/1/count/query?etat=retard";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count/query?split";"ScoView";"GET"; "assiduites_count";"/assiduites/1/count/query?split";"ScoView";"GET";
"assiduites_count";"/assiduites/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET"; "assiduites_count";"/assiduites/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET";
"assiduites";"/assiduites/1";"ScoView";"GET";
"assiduites";"/assiduites/1/query?etat=retard";"ScoView";"GET";
"assiduites";"/assiduites/1/query?moduleimpl_id=1";"ScoView";"GET";
"assiduites";"/assiduites/1/query?with_justifs=";"ScoView";"GET";
"assiduites_evaluations";"/assiduites/1/evaluations";"ScoView";"GET";
"assiduites_group";"/assiduites/group/query?etudids=1,2,3";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1";"ScoView";"GET"; "assiduites_formsemestre";"/assiduites/formsemestre/1";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1/query?etat=retard";"ScoView";"GET"; "assiduites_formsemestre";"/assiduites/formsemestre/1/query?etat=retard";"ScoView";"GET";
"assiduites_formsemestre";"/assiduites/formsemestre/1/query?moduleimpl_id=1";"ScoView";"GET"; "assiduites_formsemestre";"/assiduites/formsemestre/1/query?moduleimpl_id=1";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count";"ScoView";"GET"; "assiduites_formsemestre_count";"/assiduites/formsemestre/1/count";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=retard";"ScoView";"GET"; "assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=retard";"ScoView";"GET";
"assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET"; "assiduites_formsemestre_count";"/assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure";"ScoView";"GET";
"assiduites_group";"/assiduites/group/query?etudids=1,2,3";"ScoView";"GET";
"assiduites_justificatifs";"/assiduite/1/justificatifs";"ScoView";"GET";
"assiduites_justificatifs";"/assiduite/1/justificatifs/long";"ScoView";"GET";
"assiduite_create";"/assiduite/1/create";"UsersAdmin";"POST";"[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]" "assiduite_create";"/assiduite/1/create";"UsersAdmin";"POST";"[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]"
"assiduite_create";"/assiduite/1/create";"UsersAdmin";"POST";"[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]" "assiduite_create";"/assiduite/1/create";"UsersAdmin";"POST";"[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""absent""}]"
"assiduites_create";"/assiduites/create";"UsersAdmin";"POST";"[{""etudid"":1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]" "assiduites_create";"/assiduites/create";"UsersAdmin";"POST";"[{""etudid"":1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]"
"assiduites_create";"/assiduites/create";"UsersAdmin";"POST";"[{""etudid"":-1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]" "assiduites_create";"/assiduites/create";"UsersAdmin";"POST";"[{""etudid"":-1,""date_debut"": ""2023-10-26T08:00"",""date_fin"": ""2023-10-26T10:00"",""etat"": ""absent""}]"
"assiduite_delete";"/assiduite/delete";"UsersAdmin";"POST";"[2,2,3]"
"assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""etat"":""absent""}" "assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""etat"":""absent""}"
"assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""moduleimpl_id"":2}" "assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""moduleimpl_id"":2}"
"assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""etat"": ""retard"",""moduleimpl_id"":3}" "assiduite_edit";"/assiduite/1/edit";"UsersAdmin";"POST";"{""etat"": ""retard"",""moduleimpl_id"":3}"
"assiduite_delete";"/assiduite/delete";"UsersAdmin";"POST";"[2,2,3]"
"justificatif";"/justificatif/1";"ScoView";"GET"; "justificatif";"/justificatif/1";"ScoView";"GET";
"justificatifs";"/justificatifs/1";"ScoView";"GET"; "justificatifs";"/justificatifs/1";"ScoView";"GET";
"justificatifs";"/justificatifs/1/query?etat=attente";"ScoView";"GET"; "justificatifs";"/justificatifs/1/query?etat=attente";"ScoView";"GET";
"justificatifs_dept";"/justificatifs/dept/1";"ScoView";"GET"; "justificatifs_dept";"/justificatifs/dept/1";"ScoView";"GET";
"justificatifs_formsemestre";"/justificatifs/formsemestre/1";"ScoView";"GET"; "justificatifs_formsemestre";"/justificatifs/formsemestre/1";"ScoView";"GET";
"justificatif_create";"/justificatif/1/create";"UsersAdmin";"POST";"[{""date_debut"": ""2023-10-27T08:00"",""date_fin"": ""2023-10-27T10:00"",""etat"": ""attente""}]" "justif_edit";"/justificatif/1/edit";"UsersAdmin";"POST";"{""etat"":""valide""}"
"justificatif_edit";"/justificatif/1/edit";"UsersAdmin";"POST";"{""etat"":""valide""}" "justif_edit";"/justificatif/1/edit";"UsersAdmin";"POST";"{""raison"":""MEDIC""}"
"justificatif_edit";"/justificatif/1/edit";"UsersAdmin";"POST";"{""raison"":""MEDIC""}" "justif_delete";"/justificatif/delete";"UsersAdmin";"POST";"[2, 2, 3]"
"justificatif_delete";"/justificatif/delete";"UsersAdmin";"POST";"[2,2,3]" "justif_list";"/justificatif/1/list";"ScoView";"GET";
"justif_justifies";"/justificatif/1/justifies";"UsersAdmin";"GET";
1 entry_name url permission method content
2 assiduite /assiduite/1 ScoView GET
3 assiduites assiduite_justificatifs /assiduites/1 /assiduite/1/justificatifs ScoView GET
4 assiduites assiduite_justificatifs /assiduites/1/query?etat=retard /assiduite/1/justificatifs/long ScoView GET
assiduites /assiduites/1/query?moduleimpl_id=1 ScoView GET
assiduites /assiduites/1/query?with_justifs= ScoView GET
5 assiduites_count /assiduites/1/count ScoView GET
6 assiduites_count /assiduites/1/count/query?etat=retard ScoView GET
7 assiduites_count /assiduites/1/count/query?split ScoView GET
8 assiduites_count /assiduites/1/count/query?etat=present,retard&metric=compte,heure ScoView GET
9 assiduites /assiduites/1 ScoView GET
10 assiduites /assiduites/1/query?etat=retard ScoView GET
11 assiduites /assiduites/1/query?moduleimpl_id=1 ScoView GET
12 assiduites /assiduites/1/query?with_justifs= ScoView GET
13 assiduites_evaluations /assiduites/1/evaluations ScoView GET
14 assiduites_group /assiduites/group/query?etudids=1,2,3 ScoView GET
15 assiduites_formsemestre /assiduites/formsemestre/1 ScoView GET
16 assiduites_formsemestre /assiduites/formsemestre/1/query?etat=retard ScoView GET
17 assiduites_formsemestre /assiduites/formsemestre/1/query?moduleimpl_id=1 ScoView GET
18 assiduites_formsemestre_count /assiduites/formsemestre/1/count ScoView GET
19 assiduites_formsemestre_count /assiduites/formsemestre/1/count/query?etat=retard ScoView GET
20 assiduites_formsemestre_count /assiduites/formsemestre/1/count/query?etat=present,retard&metric=compte,heure ScoView GET
assiduites_group /assiduites/group/query?etudids=1,2,3 ScoView GET
assiduites_justificatifs /assiduite/1/justificatifs ScoView GET
assiduites_justificatifs /assiduite/1/justificatifs/long ScoView GET
21 assiduite_create /assiduite/1/create UsersAdmin POST [{"date_debut": "2023-10-27T08:00","date_fin": "2023-10-27T10:00","etat": "absent"}]
22 assiduite_create /assiduite/1/create UsersAdmin POST [{"date_debut": "2023-10-27T08:00","date_fin": "2023-10-27T10:00","etat": "absent"}]
23 assiduites_create /assiduites/create UsersAdmin POST [{"etudid":1,"date_debut": "2023-10-26T08:00","date_fin": "2023-10-26T10:00","etat": "absent"}]
24 assiduites_create /assiduites/create UsersAdmin POST [{"etudid":-1,"date_debut": "2023-10-26T08:00","date_fin": "2023-10-26T10:00","etat": "absent"}]
25 assiduite_delete /assiduite/delete UsersAdmin POST [2,2,3]
26 assiduite_edit /assiduite/1/edit UsersAdmin POST {"etat":"absent"}
27 assiduite_edit /assiduite/1/edit UsersAdmin POST {"moduleimpl_id":2}
28 assiduite_edit /assiduite/1/edit UsersAdmin POST {"etat": "retard","moduleimpl_id":3}
assiduite_delete /assiduite/delete UsersAdmin POST [2,2,3]
29 justificatif /justificatif/1 ScoView GET
30 justificatifs /justificatifs/1 ScoView GET
31 justificatifs /justificatifs/1/query?etat=attente ScoView GET
32 justificatifs_dept /justificatifs/dept/1 ScoView GET
33 justificatifs_formsemestre /justificatifs/formsemestre/1 ScoView GET
34 justificatif_create justif_edit /justificatif/1/create /justificatif/1/edit UsersAdmin POST [{"date_debut": "2023-10-27T08:00","date_fin": "2023-10-27T10:00","etat": "attente"}] {"etat":"valide"}
35 justificatif_edit justif_edit /justificatif/1/edit UsersAdmin POST {"etat":"valide"} {"raison":"MEDIC"}
36 justificatif_edit justif_delete /justificatif/1/edit /justificatif/delete UsersAdmin POST {"raison":"MEDIC"} [2, 2, 3]
37 justificatif_delete justif_list /justificatif/delete /justificatif/1/list UsersAdmin ScoView POST GET [2,2,3]
38 justif_justifies /justificatif/1/justifies UsersAdmin GET

View File

@ -4,12 +4,14 @@ Script permettant de générer une carte SVG de l'API de ScoDoc
Écrit par Matthias HARTMANN Écrit par Matthias HARTMANN
""" """
import sys
import xml.etree.ElementTree as ET
import re import re
import sys
import unicodedata
import xml.etree.ElementTree as ET
from flask import render_template
from app.auth.models import Permission from app.auth.models import Permission
from flask import render_template
class COLORS: class COLORS:
@ -270,6 +272,13 @@ class Token:
return group return group
def strip_accents(s):
"""Retourne la chaîne s séparant les accents et les caractères de base."""
return "".join(
c for c in unicodedata.normalize("NFD", s) if unicodedata.category(c) != "Mn"
)
def _create_svg_element(text, color="rgb(230,156,190)"): def _create_svg_element(text, color="rgb(230,156,190)"):
""" """
Fonction générale pour créer un élément SVG simple Fonction générale pour créer un élément SVG simple
@ -503,8 +512,6 @@ def analyze_api_routes(app, endpoint_start: str) -> tuple:
child.method = method child.method = method
current_token.add_child(child) current_token.add_child(child)
# Gestion de doctable
doctable = parse_doctable_doc(func.__doc__ or "")
href = func_name href = func_name
if child.query and not href.endswith("-query"): if child.query and not href.endswith("-query"):
href += "-query" href += "-query"
@ -527,14 +534,15 @@ def analyze_api_routes(app, endpoint_start: str) -> tuple:
if func_name not in doctable_lines: if func_name not in doctable_lines:
doctable_lines[func_name] = { doctable_lines[func_name] = {
"doctable": doctable,
"method": method, "method": method,
"nom": func_name, "nom": func_name,
"href": href, "href": href,
"query": doc_dict.get("QUERY", "") != "",
"permission": permissions, "permission": permissions,
"description": doc_dict.get("", ""), "description": doc_dict.get("", ""),
"params": doc_dict.get("PARAMS", ""), "params": doc_dict.get("PARAMS", ""),
"category": doc_dict.get("CATEGORY", [False])[0] or category, "category": doc_dict.get("CATEGORY", [False])[0] or category,
"samples": doc_dict.get("SAMPLES"),
} }
# On met à jour le token courant pour le prochain segment # On met à jour le token courant pour le prochain segment
@ -547,15 +555,13 @@ def analyze_api_routes(app, endpoint_start: str) -> tuple:
# point d'entrée de la commande `flask gen-api-map` # point d'entrée de la commande `flask gen-api-map`
def gen_api_map(app, endpoint_start="api.") -> str: def gen_api_map(api_map: Token, doctable_lines: dict[str, dict]) -> str:
""" """
Fonction permettant de générer une carte SVG de l'API de ScoDoc Fonction permettant de générer une carte SVG de l'API de ScoDoc
Elle récupère les routes de l'API et les transforme en un arbre de Token Elle récupère les routes de l'API et les transforme en un arbre de Token
puis génère un fichier SVG à partir de cet arbre puis génère un fichier SVG à partir de cet arbre
""" """
api_map, doctable_lines = analyze_api_routes(app, endpoint_start)
# On génère le SVG à partir de l'arbre de Token # On génère le SVG à partir de l'arbre de Token
generate_svg(api_map.to_svg_group(), "/tmp/api_map.svg") generate_svg(api_map.to_svg_group(), "/tmp/api_map.svg")
print( print(
@ -745,23 +751,6 @@ def _get_doc_lines(keyword, doc_string: str) -> list[str]:
return kw_lines return kw_lines
def parse_doc_name(doc_string: str) -> str:
"""
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_string)
return name_lines[0] if name_lines else None
def parse_query_doc(doc_string: str) -> dict[str, str]: def parse_query_doc(doc_string: str) -> dict[str, str]:
""" """
renvoie un dictionnaire {param: <type:nom_param>} (ex: {assiduite_id : <int:assiduite_id>}) renvoie un dictionnaire {param: <type:nom_param>} (ex: {assiduite_id : <int:assiduite_id>})
@ -795,45 +784,28 @@ def parse_query_doc(doc_string: str) -> dict[str, str]:
return query return query
def parse_doctable_doc(doc_string: str) -> dict[str, str]: def _gen_table_line(doctable: dict = None):
"""
Retourne un dictionnaire représentant les informations du tableau d'api
à partir de la doc (DOC-TABLE)
éléments optionnels:
- `permissions` permissions nécessaires pour accéder à la route (ScoView, AbsChange, ...)
- `href` nom (sans #) de l'ancre dans la page ScoDoc9API
DOC-TABLE
---------
permissions: ScoView
href: une-fonction
"""
doc_lines: list[str] = _get_doc_lines("DOC-TABLE", doc_string)
table = {}
# on parcourt les lignes de la doc
for line in doc_lines:
# On sépare le paramètre et sa valeur
param, value = line.split(":")
# On met à jour le dictionnaire
table[param.strip()] = value.strip()
return table
def _gen_table_line(
nom="", href="", method="", permission="", doctable: dict = None, **kwargs
):
""" """
Génère une ligne de tableau markdown Génère une ligne de tableau markdown
| nom de la route| methode HTTP| Permission | | nom de la route| methode HTTP| Permission |
""" """
lien: str = href
if "href" in doctable: nom, method, permission = (
lien: str = doctable.get("href") doctable.get("nom", ""),
doctable.get("method", ""),
doctable.get("permission", ""),
)
if doctable is None:
doctable = {}
lien: str = doctable.get("href", nom)
doctable["query"]: bool
if doctable.get("query") and not lien.endswith("-query"):
lien += "-query"
nav: str = f"[{nom}]({'#'+lien})" nav: str = f"[{nom}]({'#'+lien})"
table: str = "|" table: str = "|"
@ -858,19 +830,58 @@ def _gen_table(lines: list[dict]) -> str:
""" """
Génère un tableau markdown à partir d'une liste de lignes Génère un tableau markdown à partir d'une liste de lignes
lines : liste de dictionnaire au format : lines : liste de dictionnaire au format doc_lines.
- doctable : dict généré par parse_doctable_doc
- nom : nom de la fonction associée à la route
- method : GET ou POST
- permission : Permissions de la route (auto récupérée)
""" """
table = _gen_table_head() table = _gen_table_head()
table += "\n".join([_gen_table_line(**line) for line in lines]) table += "\n".join([_gen_table_line(line) for line in lines])
return table return table
def _gen_csv_line(doc_line: dict) -> str:
"""
Génère les lignes de tableau csv en fonction d'une route (doc_line)
format :
"entry_name";"url";"permission";"method";"content"
"""
entry_name: str = doc_line.get("nom", "")
method: str = doc_line.get("method", "GET")
permission: str = (
"UsersAdmin" if doc_line.get("permission") != "ScoView" else "ScoView"
)
samples: list[str] = doc_line.get("samples", [])
csv_lines: list[str] = []
for sample in samples:
url, content = sample.split(";", maxsplit=1)
csv_line = f'"{entry_name}";"{url}";"{permission}";"{method}";'
if content:
csv_line += f'"{content}"'
csv_lines.append(csv_line)
return "\n".join(csv_lines)
def _gen_csv(lines: list[dict], filename: str = "/tmp/samples.csv") -> str:
"""
Génère un fichier csv à partir d'une liste de lignes
lines : liste de dictionnaire au format doc_lines.
"""
csv = '"entry_name";"url";"permission";"method";"content"\n'
csv += "\n".join(
[_gen_csv_line(line) for line in lines if line.get("samples") is not None]
)
with open(filename, "w", encoding="UTF-8") as f:
f.write(csv)
print(
f"Les samples ont été générés avec succès. Vous pouvez le consulter à l'adresse suivante : {filename}"
)
def _write_gen_table(table: str, filename: str = "/tmp/api_table.md"): def _write_gen_table(table: str, filename: str = "/tmp/api_table.md"):
"""Ecriture du fichier md avec la table""" """Ecriture du fichier md avec la table"""
with open(filename, "w", encoding="UTF-8") as f: with open(filename, "w", encoding="UTF-8") as f:
@ -886,6 +897,16 @@ def doc_route(doctable: dict) -> str:
jinja_obj.update(doctable) jinja_obj.update(doctable)
jinja_obj["nom"] = doctable["nom"].strip() # on retire les caractères blancs jinja_obj["nom"] = doctable["nom"].strip() # on retire les caractères blancs
if doctable.get("samples") is not None:
jinja_obj["sample"] = {
"nom": f"{jinja_obj['nom']}.json",
"href": f"{jinja_obj['nom']}.json.md",
}
jinja_obj["query"]: bool
if jinja_obj["query"]:
jinja_obj["nom"] += "(-query)"
if doctable.get("params"): if doctable.get("params"):
jinja_obj["params"] = [] jinja_obj["params"] = []
for param in doctable["params"]: for param in doctable["params"]:
@ -901,43 +922,41 @@ def doc_route(doctable: dict) -> str:
descr = "\n".join(s for s in doctable["description"]) descr = "\n".join(s for s in doctable["description"])
jinja_obj["description"] = descr.strip() jinja_obj["description"] = descr.strip()
jinja_obj["sample"] = {
"nom": f"{jinja_obj['nom']}.json",
"href": f"{jinja_obj['nom'].replace('_', '-')}.json.md",
}
return render_template("doc/apidoc.j2", doc=jinja_obj) return render_template("doc/apidoc.j2", doc=jinja_obj)
def gen_api_doc(app, endpoint_start="api."): def gen_api_doc(app, endpoint_start="api."):
"commande gen-api-doc" "commande gen-api-doc"
_, doctable_lines = analyze_api_routes(app, endpoint_start) api_map, doctable_lines = analyze_api_routes(app, endpoint_start)
mddoc: str = "" mddoc: str = ""
categories: dict = {} categories: dict = {}
for value in doctable_lines.values(): for value in doctable_lines.values():
category = value["category"] category = value["category"].capitalize()
if category not in categories: if category not in categories:
categories[category] = [] categories[category] = []
categories[category].append(value) categories[category].append(value)
# sort categories by name # sort categories by name
categories: dict = dict(sorted(categories.items(), key=lambda x: x[0].capitalize())) categories: dict = dict(
sorted(categories.items(), key=lambda x: strip_accents(x[0]))
)
category: str category: str
routes: list[dict] routes: list[dict]
for category, routes in categories.items(): for category, routes in categories.items():
# sort routes by name # sort routes by name
routes.sort(key=lambda x: x["nom"]) routes.sort(key=lambda x: strip_accents(x["nom"]))
mddoc += f"### API {category.capitalize()}\n\n" mddoc += f"### API {category.capitalize()}\n\n"
for route in routes: for route in routes:
mddoc += doc_route(route) mddoc += doc_route(route)
mddoc += "\n\n" mddoc += "\n\n"
table_api = gen_api_map(app, endpoint_start=endpoint_start) table_api = gen_api_map(api_map, doctable_lines)
mdpage = render_template("doc/ScoDoc9API.j2", doc_api=mddoc, table_api=table_api) mdpage = render_template("doc/ScoDoc9API.j2", doc_api=mddoc, table_api=table_api)
_gen_csv(list(doctable_lines.values()))
fname = "/tmp/ScoDoc9API.md" fname = "/tmp/ScoDoc9API.md"
with open(fname, "w", encoding="utf-8") as f: with open(fname, "w", encoding="utf-8") as f: