#!/usr/bin/env python3 # -*- mode: python -*- # -*- coding: utf-8 -*- """Exemple connexion sur ScoDoc 9 et utilisation de l'ancienne API ScoDoc 7 à la mode "PHP": les gens passaient directement __ac_name et __ac_password dans chaque requête, en POST ou en GET. Cela n'a jamais été documenté mais était implicitement supporté. C'est "deprecated" et ne sera plus supporté à partir de juillet 2022. Ce script va tester: - Liste semestres - Liste modules - Creation d'une évaluation - Saisie d'une note Utilisation: créer les variables d'environnement: (indiquer les valeurs pour le serveur ScoDoc que vous voulez interroger) export SCODOC_URL="https://scodoc.xxx.net/" export SCODOC_USER="xxx" export SCODOC_PASSWD="xxx" export CHECK_CERTIFICATE=0 # ou 1 si serveur de production avec certif SSL valide (on peut aussi placer ces valeurs dans un fichier .env du répertoire tests/api). """ from dotenv import load_dotenv import json import os import pdb import requests import urllib3 from pprint import pprint as pp # --- Lecture configuration (variables d'env ou .env) BASEDIR = os.path.abspath(os.path.dirname(__file__)) load_dotenv(os.path.join(BASEDIR, ".env")) CHECK_CERTIFICATE = bool(int(os.environ.get("CHECK_CERTIFICATE", False))) SCODOC_URL = os.environ["SCODOC_URL"] SCODOC_DEPT = os.environ["SCODOC_DEPT"] DEPT_URL = SCODOC_URL + "/ScoDoc/" + SCODOC_DEPT + "/Scolarite" SCODOC_USER = os.environ["SCODOC_USER"] SCODOC_PASSWORD = os.environ["SCODOC_PASSWD"] print(f"SCODOC_URL={SCODOC_URL}") # --- if not CHECK_CERTIFICATE: urllib3.disable_warnings() class ScoError(Exception): pass def GET(path: str, params=None, errmsg=None): """Get and returns as JSON""" # ajoute auth params["__ac_name"] = SCODOC_USER params["__ac_password"] = SCODOC_PASSWORD r = requests.get(DEPT_URL + "/" + path, params=params, verify=CHECK_CERTIFICATE) if r.status_code != 200: raise ScoError(errmsg or "erreur !") return r.json() # decode la reponse JSON def POST(path: str, data: dict, errmsg=None): """Post""" data["__ac_name"] = data.get("__ac_name", SCODOC_USER) data["__ac_password"] = data.get("__ac_password", SCODOC_PASSWORD) r = requests.post(DEPT_URL + "/" + path, data=data, verify=CHECK_CERTIFICATE) return r # --- # pas besoin d'ouvrir une session, on y va directement: # --- Recupere la liste de tous les semestres: sems = GET("Notes/formsemestre_list", params={"format": "json"}) # sems est une liste de semestres (dictionnaires) for sem in sems: if sem["etat"]: break if sem["etat"] == "0": raise ScoError("Aucun semestre non verrouillé !") # Affiche le semestre trouvé: pp(sem) # Liste des étudiants dans le 1er semestre non verrouillé: group_list = GET( "groups_view", params={ "formsemestre_id": sem["formsemestre_id"], "with_codes": 1, "format": "json", }, ) if not group_list: # config inadaptée pour les tests... raise ScoError("aucun étudiant inscrit dans le semestre") etud = group_list[0] # le premier étudiant inscrit ici # test un POST r = POST( "Absences/AddBilletAbsence", { "begin": "2021-10-25", "end": "2021-10-26", "description": "test API scodoc7", "etudid": etud["etudid"], }, ) assert r.status_code == 200 assert r.text.startswith('<?xml version="1.0" encoding="utf-8"?>') assert "billet_id" in r.text # Essai avec un compte invalide r_invalid = POST( "Absences/AddBilletAbsence", { "__ac_name": "xxx", "begin": "2021-10-25", "end": "2021-10-26", "description": "test API scodoc7", "etudid": etud["etudid"], }, ) assert r_invalid.status_code == 403 # compte invalide => not authorized # AddBilletAbsence en json r = POST( "Absences/AddBilletAbsence", { "begin": "2021-10-25", "end": "2021-10-26", "description": "test API scodoc7", "etudid": etud["etudid"], "xml_reply": 0, }, ) assert r.status_code == 200 assert isinstance(json.loads(r.text)[0]["billet_id"], int) # Les fonctions ci-dessous ne fonctionnent plus en ScoDoc 9 # Voir https://scodoc.org/git/viennet/ScoDoc/issues/149 # # ---- Liste les modules et prend le premier # mods = GET("/Notes/moduleimpl_list", params={"formsemestre_id": sem["formsemestre_id"]}) # print(f"{len(mods)} modules dans le semestre {sem['titre']}") # mod = mods[0] # # ---- Etudiants inscrits dans ce module # inscrits = GET( # "Notes/do_moduleimpl_inscription_list", # params={"moduleimpl_id": mod["moduleimpl_id"]}, # ) # print(f"{len(inscrits)} inscrits dans ce module") # # prend le premier inscrit, au hasard: # etudid = inscrits[0]["etudid"] # # ---- Création d'une evaluation le dernier jour du semestre # jour = sem["date_fin"] # evaluation_id = POST( # "/Notes/do_evaluation_create", # data={ # "moduleimpl_id": mod["moduleimpl_id"], # "coefficient": 1, # "jour": jour, # "5/9/2019", # "heure_debut": "9h00", # "heure_fin": "10h00", # "note_max": 20, # notes sur 20 # "description": "essai", # }, # errmsg="échec création évaluation", # ) # print( # f"Evaluation créée dans le module {mod['moduleimpl_id']}, evaluation_id={evaluation_id}" # ) # print( # f"Pour vérifier, aller sur: {DEPT_URL}/Notes/moduleimpl_status?moduleimpl_id={mod['moduleimpl_id']}", # ) # # ---- Saisie d'une note # junk = POST( # "/Notes/save_note", # data={ # "etudid": etudid, # "evaluation_id": evaluation_id, # "value": 16.66, # la note ! # "comment": "test API", # }, # )