1
0
forked from ScoDoc/ScoDoc

Modernisation code: remplace DictDefault

This commit is contained in:
Emmanuel Viennet 2023-03-08 22:23:55 +01:00
parent 40978f30ee
commit fc786db83e
9 changed files with 80 additions and 89 deletions

View File

@ -28,6 +28,7 @@
"""Génération des bulletins de notes
"""
import collections
import email
import time
import numpy as np
@ -143,7 +144,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
if not nt.get_etud_etat(etudid):
raise ScoValueError("Étudiant non inscrit à ce semestre")
I = scu.DictDefault(defaultvalue="")
I = collections.defaultdict(str)
I["etudid"] = etudid
I["formsemestre_id"] = formsemestre_id
I["sem"] = formsemestre.get_infos_dict()
@ -260,7 +261,7 @@ def formsemestre_bulletinetud_dict(formsemestre_id, etudid, version="long"):
# n'affiche pas le rang sur le bulletin s'il y a des
# notes en attente dans ce semestre
rang = scu.RANG_ATTENTE_STR
rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR)
rang_gr = collections.defaultdict(lambda: scu.RANG_ATTENTE_STR)
inscriptions_counts = nt.get_inscriptions_counts()
I["rang"] = rang
I["rang_gr"] = rang_gr
@ -710,50 +711,15 @@ def etud_descr_situation_semestre(
decisions_ue : noms (acronymes) des UE validées, séparées par des virgules.
descr_decisions_ue : ' UE acquises: UE1, UE2', ou vide si pas de dec. ou si pas show_uevalid
descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention
descr_parcours : le nom (libelle) du parcours dans lequel est inscrit l'étudiant en BUT (vide ailleurs)
"""
# Fonction utilisée par tous les bulletins (APC ou classiques)
cnx = ndb.GetDBConnexion()
infos = scu.DictDefault(defaultvalue="")
infos = collections.defaultdict(str)
# --- Situation et décisions jury
# démission/inscription ?
events = sco_etud.scolar_events_list(
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
)
date_inscr = None
date_dem = None
date_def = None
for event in events:
event_type = event["event_type"]
if event_type == "INSCRIPTION":
if date_inscr:
# plusieurs inscriptions ???
# date_inscr += ', ' + event['event_date'] + ' (!)'
# il y a eu une erreur qui a laissé un event 'inscription'
# on l'efface:
log(
f"etud_descr_situation_semestre: removing duplicate INSCRIPTION event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_inscr = event["event_date"]
elif event_type == "DEMISSION":
# assert date_dem == None, 'plusieurs démissions !'
if date_dem: # cela ne peut pas arriver sauf bug (signale a Evry 2013?)
log(
f"etud_descr_situation_semestre: removing duplicate DEMISSION event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_dem = event["event_date"]
elif event_type == "DEFAILLANCE":
if date_def:
log(
f"etud_descr_situation_semestre: removing duplicate DEFAILLANCE event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_def = event["event_date"]
date_inscr, date_dem, date_def = _dates_insc_dem_def(etudid, formsemestre_id)
if show_date_inscr:
if not date_inscr:
infos["date_inscription"] = ""
@ -851,6 +817,49 @@ def etud_descr_situation_semestre(
return infos, dpv
def _dates_insc_dem_def(etudid, formsemestre_id) -> tuple:
"Cherche les dates d'inscription, démission et défaillance de l'étudiant"
cnx = ndb.GetDBConnexion()
events = sco_etud.scolar_events_list(
cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id}
)
date_inscr = None
date_dem = None
date_def = None
for event in events:
event_type = event["event_type"]
if event_type == "INSCRIPTION":
if date_inscr:
# plusieurs inscriptions ???
# date_inscr += ', ' + event['event_date'] + ' (!)'
# il y a eu une erreur qui a laissé un event 'inscription'
# on l'efface:
log(
f"etud_descr_situation_semestre: removing duplicate INSCRIPTION event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_inscr = event["event_date"]
elif event_type == "DEMISSION":
# assert date_dem == None, 'plusieurs démissions !'
if date_dem: # cela ne peut pas arriver sauf bug (signale a Evry 2013?)
log(
f"etud_descr_situation_semestre: removing duplicate DEMISSION event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_dem = event["event_date"]
elif event_type == "DEFAILLANCE":
if date_def:
log(
f"etud_descr_situation_semestre: removing duplicate DEFAILLANCE event for etudid={etudid} !"
)
sco_etud.scolar_events_delete(cnx, event["event_id"])
else:
date_def = event["event_date"]
return date_inscr, date_dem, date_def
def _format_situation_fields(
infos, field_names: list[str], extra_values: list[str]
) -> None:

View File

@ -27,6 +27,7 @@
"""Evaluations
"""
import collections
import datetime
import operator
import time
@ -171,8 +172,8 @@ def do_evaluation_etat(evaluation_id, partition_id=None, select_first_partition=
# On considere une note "manquante" lorsqu'elle n'existe pas
# ou qu'elle est en attente (ATT)
GrNbMissing = scu.DictDefault() # group_id : nb notes manquantes
GrNotes = scu.DictDefault(defaultvalue=[]) # group_id: liste notes valides
GrNbMissing = collections.defaultdict(int) # group_id : nb notes manquantes
GrNotes = collections.defaultdict(list) # group_id: liste notes valides
TotalNbMissing = 0
TotalNbAtt = 0
groups = {} # group_id : group

View File

@ -27,6 +27,7 @@
"""Opérations d'inscriptions aux semestres et modules
"""
import collections
import time
import flask
@ -543,10 +544,8 @@ def formsemestre_inscription_option(etudid, formsemestre_id):
mods = sco_moduleimpl.moduleimpl_withmodule_list(formsemestre_id=formsemestre_id)
inscr = sco_moduleimpl.do_moduleimpl_inscription_list(etudid=etudid)
# Formulaire
modimpls_by_ue_ids = scu.DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ]
modimpls_by_ue_names = scu.DictDefault(
defaultvalue=[]
) # ue_id : [ moduleimpl_name ]
modimpls_by_ue_ids = collections.defaultdict(list) # ue_id : [ moduleimpl_id ]
modimpls_by_ue_names = collections.defaultdict(list) # ue_id : [ moduleimpl_name ]
ues = []
ue_ids = set()
initvalues = {}

View File

@ -33,8 +33,8 @@ Elle n'est pas utilisée pour les parcours, ni pour rien d'autre
(c'est donc un attribut "cosmétique").
"""
import collections
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app import log
@ -54,7 +54,7 @@ def group_sems_by_modalite(sems):
"""Given the list of fromsemestre, group them by modalite,
sorted in each one by semestre id and date
"""
sems_by_mod = scu.DictDefault(defaultvalue=[])
sems_by_mod = collections.defaultdict(list)
modalites = list_formsemestres_modalites(sems)
for modalite in modalites:
for sem in sems:

View File

@ -27,6 +27,7 @@
"""Opérations d'inscriptions aux modules (interface pour gérer options ou parcours)
"""
import collections
from operator import itemgetter
import flask
@ -676,7 +677,7 @@ def get_etuds_with_capitalized_ue(formsemestre_id: int) -> list[dict]:
"""For each UE, computes list of students capitalizing the UE.
returns { ue_id : [ { infos } ] }
"""
ues_cap_info = scu.DictDefault(defaultvalue=[])
ues_cap_info = collections.defaultdict(list)
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)

View File

@ -27,6 +27,7 @@
"""Feuille excel pour préparation des jurys classiques (non BUT)
"""
import collections
import time
from openpyxl.styles.numbers import FORMAT_NUMBER_00
@ -64,10 +65,10 @@ def feuille_preparation_jury(formsemestre_id):
"partition_id"
]
prev_moy_ue = scu.DictDefault(defaultvalue={}) # ue_code_s : { etudid : moy ue }
prev_moy_ue = collections.defaultdict(dict) # ue_code_s : { etudid : moy ue }
prev_ue_acro = {} # ue_code_s : acronyme (à afficher)
prev_moy = {} # moyennes gen sem prec
moy_ue = scu.DictDefault(defaultvalue={}) # ue_acro : moyennes { etudid : moy ue }
moy_ue = collections.defaultdict(dict) # ue_acro : moyennes { etudid : moy ue }
ue_acro = {} # ue_code_s : acronyme (à afficher)
moy = {} # moyennes gen
moy_inter = {} # moyenne gen. sur les 2 derniers semestres

View File

@ -29,7 +29,7 @@
Formulaires paramétrage PV et génération des tables
"""
import collections
import time
from reportlab.platypus import Paragraph
from reportlab.lib import styles
@ -283,7 +283,7 @@ def formsemestre_pvjury(formsemestre_id, format="html", publish=True):
H.append(tab.html())
# Count number of cases for each decision
counts = scu.DictDefault()
counts = collections.defaultdict(int)
for row in rows:
counts[row["decision"]] += 1
# add codes for previous (for explanation, without count)

View File

@ -29,6 +29,7 @@
- statistiques decisions
- suivi cohortes
"""
import collections
import os
import tempfile
import re
@ -178,7 +179,8 @@ def _results_by_category(
if etud[category] in Count:
Count[etud[category]][etud[result]] += 1
else:
Count[etud[category]] = scu.DictDefault(kv_dict={etud[result]: 1})
Count[etud[category]] = collections.defaultdict(int, {etud[result]: 1})
# conversion en liste de dict
C = [Count[cat] for cat in categories]
# Totaux par lignes et colonnes
@ -551,7 +553,7 @@ def table_suivi_cohorte(
indices_sems.sort()
for p in P:
p.nb_etuds = 0 # nombre total d'etudiants dans la periode
p.sems_by_id = scu.DictDefault(defaultvalue=[])
p.sems_by_id = collections.defaultdict(list)
for s in p.sems:
p.sems_by_id[s["semestre_id"]].append(s)
p.nb_etuds += len(s["members"])
@ -1162,7 +1164,7 @@ def table_suivi_cursus(formsemestre_id, only_primo=False, grouped_parcours=True)
civilites,
statuts,
) = tsp_etud_list(formsemestre_id, only_primo=only_primo)
codes_etuds = scu.DictDefault(defaultvalue=[])
codes_etuds = collections.defaultdict(list)
for etud in etuds:
etud["code_cursus"], etud["decisions_jury"] = get_code_cursus_etud(etud)
codes_etuds[etud["code_cursus"]].append(etud)
@ -1350,17 +1352,16 @@ def graph_cursus(
civilites,
statuts,
)
edges = scu.DictDefault(
defaultvalue=set()
) # {("SEM"formsemestre_id_origin, "SEM"formsemestre_id_dest) : etud_set}
edges = collections.defaultdict(set)
# {("SEM"formsemestre_id_origin, "SEM"formsemestre_id_dest) : etud_set}
def sem_node_name(sem, prefix="SEM"):
"pydot node name for this integer id"
return prefix + str(sem["formsemestre_id"])
sems = {}
effectifs = scu.DictDefault(defaultvalue=set()) # formsemestre_id : etud_set
decisions = scu.DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud }
effectifs = collections.defaultdict(set) # formsemestre_id : etud_set
decisions = collections.defaultdict(dict) # formsemestre_id : { code : nb_etud }
isolated_nodes = [] # [ node_name_de_formsemestre_id, ... ]
connected_nodes = set() # { node_name_de_formsemestre_id }
diploma_nodes = []

View File

@ -30,7 +30,7 @@
"""
import base64
import bisect
import copy
import collections
import datetime
from enum import IntEnum
import io
@ -270,32 +270,11 @@ def get_mention(moy):
return ""
class DictDefault(dict): # obsolete, use collections.defaultdict
"""A dictionnary with default value for all keys
Each time a non existent key is requested, it is added to the dict.
(used in python 2.4, can't use new __missing__ method)
"""
defaultvalue = 0
def __init__(self, defaultvalue=0, kv_dict={}):
dict.__init__(self)
self.defaultvalue = defaultvalue
self.update(kv_dict)
def __getitem__(self, k):
if k in self:
return self.get(k)
value = copy.copy(self.defaultvalue)
self[k] = value
return value
def group_by_key(d, key):
gr = DictDefault(defaultvalue=[])
def group_by_key(d: dict, key) -> dict:
grouped = collections.defaultdict(lambda: [])
for e in d:
gr[e[key]].append(e)
return gr
grouped[e[key]].append(e)
return grouped
# ----- Global lock for critical sections (except notes_tables caches)