# -*- mode: python -*- # -*- coding: utf-8 -*- """Creation environnement pour test. A utiliser avec debug.py (côté serveur). La classe ScoFake offre un ensemble de raccourcis permettant d'écrire facilement des tests ou de reproduire des bugs. """ from __future__ import print_function from functools import wraps import sys import string import collections import pprint import random random.seed(12345) # tests reproductibles from debug import REQUEST import sco_utils from notes_log import log from sco_exceptions import ScoValueError import scolars import sco_formsemestre import sco_formsemestre_inscriptions import sco_formsemestre_validation import sco_moduleimpl import sco_synchro_etuds import sco_edit_formation import sco_edit_ue import sco_codes_parcours import sco_saisie_notes DEMODIR = sco_utils.SCO_SRCDIR + "/scotests/demo/" NOMS = [x.strip() for x in open(DEMODIR + "/noms.txt").readlines()] PRENOMS_H = [x.strip() for x in open(DEMODIR + "/prenoms-h.txt").readlines()] PRENOMS_F = [x.strip() for x in open(DEMODIR + "/prenoms-f.txt").readlines()] PRENOMS_X = [x.strip() for x in open(DEMODIR + "/prenoms-x.txt").readlines()] # nb: en python2, les chaines ci-dessus sont en utf8 def id_generator(size=6, chars=string.ascii_uppercase + string.digits): return "".join(random.choice(chars) for _ in range(size)) def logging_meth(func): @wraps(func) def wrapper_logging_meth(self, *args, **kwargs): r = func(self, *args, **kwargs) self.log("%s(%s) -> \n%s" % (func.__name__, kwargs, pprint.pformat(r))) return r return wrapper_logging_meth class ScoFake: def __init__(self, context, verbose=True): self.context = context self.verbose = verbose def log(self, msg): if self.verbose: print("ScoFake: " + str(msg), file=sys.stderr) sys.stderr.flush() log("ScoFake: " + str(msg)) def civilitenomprenom(self): """un nom et un prenom au hasard, toujours en majuscules. """ civilite = random.choice(("M", "M", "M", "F", "F", "F", "X")) if civilite == "F": prenom = random.choice(PRENOMS_F) elif civilite == "M": prenom = random.choice(PRENOMS_H) elif civilite == "X": prenom = random.choice(PRENOMS_X) else: raise ValueError("invalid civilite value") return civilite, random.choice(NOMS).upper(), prenom.upper() @logging_meth def create_etud( self, cnx=None, code_nip="", nom="", prenom="", code_ine="", civilite="", etape="TST1", email="test@localhost", emailperso="perso@localhost", date_naissance="01/01/2001", lieu_naissance="Paris", dept_naissance="75", domicile="1, rue du test", codepostaldomicile="75123", villedomicile="TestCity", paysdomicile="France", telephone="0102030405", typeadresse="domicile", boursier=None, description="etudiant test", ): """Crée un étudiant""" if not cnx: cnx = self.context.GetDBConnexion() if code_nip == "": code_nip = str(random.randint(10000, 99999)) if not civilite or not nom or not prenom: r_civilite, r_nom, r_prenom = self.civilitenomprenom() if not civilite: civilite = r_civilite if not nom: nom = r_nom if not prenom: prenom = r_prenom etud = scolars.create_etud(self.context, cnx, args=locals(), REQUEST=REQUEST) inscription = "2020" # pylint: disable=unused-variable sco_synchro_etuds.do_import_etud_admission( self.context, cnx, etud["etudid"], locals() ) return etud @logging_meth def create_formation( self, acronyme="test", titre="Formation test", titre_officiel="Le titre officiel de la formation test", type_parcours=sco_codes_parcours.ParcoursDUT.TYPE_PARCOURS, formation_code=None, code_specialite=None, ): """Crée une formation""" if not acronyme: acronyme = "TEST" + str(random.randint(100000, 999999)) oid = self.context.do_formation_create(locals(), REQUEST=REQUEST) oids = self.context.formation_list(args={"formation_id": oid}) if not oids: raise ScoValueError("formation not created !") return oids[0] @logging_meth def create_ue( self, formation_id=None, acronyme=None, numero=None, titre="", type=None, ue_code=None, ects=None, is_external=None, code_apogee=None, coefficient=None, ): """Crée une UE""" if numero is None: numero = sco_edit_ue.next_ue_numero(self.context, formation_id, 0) oid = self.context.do_ue_create(locals(), REQUEST) oids = self.context.do_ue_list(args={"ue_id": oid}) if not oids: raise ScoValueError("ue not created !") return oids[0] @logging_meth def create_matiere(self, ue_id=None, titre=None, numero=None): oid = self.context.do_matiere_create(locals(), REQUEST) oids = self.context.do_matiere_list(args={"matiere_id": oid}) if not oids: raise ScoValueError("matiere not created !") return oids[0] @logging_meth def create_module( self, titre=None, code=None, heures_cours=None, heures_td=None, heures_tp=None, coefficient=None, ue_id=None, formation_id=None, matiere_id=None, semestre_id=1, numero=None, abbrev=None, ects=None, code_apogee=None, module_type=None, ): oid = self.context.do_module_create(locals(), REQUEST) oids = self.context.do_module_list(args={"module_id": oid}) if not oids: raise ScoValueError("module not created ! (oid=%s)" % oid) return oids[0] @logging_meth def create_formsemestre( self, formation_id=None, semestre_id=None, titre=None, date_debut=None, date_fin=None, etat=None, gestion_compensation=None, bul_hide_xml=None, gestion_semestrielle=None, bul_bgcolor=None, modalite=None, resp_can_edit=None, resp_can_change_ens=None, ens_can_edit_eval=None, elt_sem_apo=None, elt_annee_apo=None, etapes=None, responsables=["bach"], ): oid = self.context.do_formsemestre_create(locals(), REQUEST) # oids = self.context.do_formsemestre_list(args={"formsemestre_id": oid}) oids = sco_formsemestre.do_formsemestre_list( self.context, args={"formsemestre_id": oid} ) # API inconsistency if not oids: raise ScoValueError("formsemestre not created !") return oids[0] @logging_meth def create_moduleimpl( self, module_id=None, formsemestre_id=None, responsable_id=None, ): oid = sco_moduleimpl.do_moduleimpl_create(self.context, locals()) oids = sco_moduleimpl.do_moduleimpl_list( self.context, moduleimpl_id=oid ) # API inconsistency if not oids: raise ScoValueError("moduleimpl not created !") return oids[0] @logging_meth def inscrit_etudiant(self, sem, etud): sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( self.context, sem["formsemestre_id"], etud["etudid"], etat="I", etape=etud.get("etape", None), REQUEST=REQUEST, method="test_inscrit_etudiant", ) @logging_meth def create_evaluation( self, moduleimpl_id=None, jour=None, heure_debut="8h00", heure_fin="9h00", description=None, note_max=20, coefficient=None, visibulletin=None, publish_incomplete=None, evaluation_type=None, numero=None, REQUEST=REQUEST, ): args = locals() del args["self"] oid = self.context.do_evaluation_create(**args) oids = self.context.do_evaluation_list(args={"evaluation_id": oid}) if not oids: raise ScoValueError("evaluation not created !") return oids[0] @logging_meth def create_note( self, evaluation=None, etud=None, note=None, comment=None, uid="bach", ): return sco_saisie_notes._notes_add( self.context, uid, evaluation["evaluation_id"], [(etud["etudid"], note)], comment=comment, ) def setup_formation( self, nb_semestre=1, nb_ue_per_semestre=2, nb_module_per_ue=2, acronyme=None, titre=None, ): """Création d'une formation, avec UE, modules et évaluations. Formation avec `nb_semestre` comportant chacun `nb_ue_per_semestre` UE et dans chaque UE `nb_module_per_ue` modules (on a une seule matière par UE). Returns: formation (dict), liste d'ue (dicts), liste de modules. """ f = self.create_formation(acronyme=acronyme, titre=titre) ue_list = [] mod_list = [] for semestre_id in range(1, nb_semestre + 1): for n in range(1, nb_ue_per_semestre + 1): ue = self.create_ue( formation_id=f["formation_id"], acronyme="TSU%s%s" % (semestre_id, n), titre="ue test %s%s" % (semestre_id, n), ) ue_list.append(ue) mat = self.create_matiere(ue_id=ue["ue_id"], titre="matière test") for _ in range(nb_module_per_ue): mod = self.create_module( matiere_id=mat["matiere_id"], semestre_id=semestre_id, code="TSM%s" % len(mod_list), coefficient=1.0, titre="module test", ue_id=ue["ue_id"], # faiblesse de l'API formation_id=f["formation_id"], # faiblesse de l'API ) mod_list.append(mod) return f, ue_list, mod_list def setup_formsemestre( self, f, mod_list, semestre_id=1, date_debut="01/01/2020", date_fin="30/06/2020", nb_evaluations_per_module=1, titre=None, responsables=["bach"], modalite=None, ): """Création semestre, avec modules et évaluations.""" sem = self.create_formsemestre( formation_id=f["formation_id"], semestre_id=semestre_id, date_debut=date_debut, date_fin=date_fin, titre=titre, responsables=responsables, modalite=modalite, ) eval_list = [] for mod in mod_list: if mod["semestre_id"] == semestre_id: mi = self.create_moduleimpl( module_id=mod["module_id"], formsemestre_id=sem["formsemestre_id"], responsable_id="bach", ) for e_idx in range(1, nb_evaluations_per_module + 1): e = self.create_evaluation( moduleimpl_id=mi["moduleimpl_id"], jour=date_debut, description="evaluation test %s" % e_idx, coefficient=1.0, ) eval_list.append(e) return sem, eval_list def set_etud_notes_sem( self, sem, eval_list, etuds, notes=None, random_min=0, random_max=20 ): """Met des notes aux étudiants indiqués des evals indiquées. Args: sem: dict eval_list: list of dicts etuds: list of dicts notes: liste des notes (float). Si non spécifié, tire au hasard dans `[random_min, random_max]` """ set_random = notes is None for e in eval_list: if set_random: notes = [float(random.randint(random_min, random_max)) for _ in etuds] for etud, note in zip(etuds, notes): self.create_note(evaluation=e, etud=etud, note=note) def set_code_jury( self, sem, etud, code_etat=sco_codes_parcours.ADM, devenir=sco_codes_parcours.NEXT, assidu=True, ): """Affecte décision de jury""" sco_formsemestre_validation.formsemestre_validation_etud_manu( self.context, formsemestre_id=sem["formsemestre_id"], etudid=etud["etudid"], code_etat=code_etat, devenir=devenir, assidu=assidu, REQUEST=REQUEST, )