[Scodoc-devel] [SVN] Scolar : [1537] Optimisations reduisant temps chargement semestres.

eviennet at lipn.univ-paris13.fr eviennet at lipn.univ-paris13.fr
Mar 26 Juil 07:37:41 CEST 2016


Une pièce jointe HTML a été nettoyée...
URL: <https://www-rt.iutv.univ-paris13.fr/pipermail/scodoc-devel/attachments/20160726/ec02c4a4/attachment-0001.html>
-------------- section suivante --------------
Modified: branches/ScoDoc7/ZAbsences.py
===================================================================
--- branches/ScoDoc7/ZAbsences.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/ZAbsences.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -1910,11 +1910,12 @@
 # --------------------------------------------------------------------
 class CAbsSemEtud:
     """Comptes d'absences d'un etudiant dans un semestre"""
-    def __init__(self, context, formsemestre_id, etudid):
+    def __init__(self, context, sem, etudid):
         self.context = context
-        self.formsemestre_id = formsemestre_id
+        self.sem = sem
         self.etudid = etudid
         self._loaded = False
+        formsemestre_id = sem['formsemestre_id']
         context.Notes._getNotesCache().add_listener(self.invalidate, formsemestre_id, (etudid, formsemestre_id))
         
     def CountAbs(self):
@@ -1929,9 +1930,8 @@
     def load(self):
         "Load state from DB"
         #log('loading CAbsEtudSem(%s,%s)' % (self.etudid, self.formsemestre_id))
-        sem = sco_formsemestre.get_formsemestre(self.context, self.formsemestre_id)
-        debut_sem = DateDMYtoISO(sem['date_debut'])
-        fin_sem = DateDMYtoISO(sem['date_fin'])
+        debut_sem = DateDMYtoISO(self.sem['date_debut'])
+        fin_sem = DateDMYtoISO(self.sem['date_fin'])
         
         self._CountAbs = self.context.Absences.CountAbs(etudid=self.etudid, debut=debut_sem, fin=fin_sem)
         self._CountAbsJust = self.context.Absences.CountAbsJust(etudid=self.etudid, debut=debut_sem,fin=fin_sem)        
@@ -1946,20 +1946,20 @@
 # Accès au cache des absences
 ABS_CACHE_INST = {} # { DeptId : { formsemestre_id : { etudid :  CAbsEtudSem } } }
 
-def getAbsSemEtud(context, formsemestre_id, etudid):
-    AbsSemEtuds = getAbsSemEtuds(context, formsemestre_id)
+def getAbsSemEtud(context, sem, etudid):
+    AbsSemEtuds = getAbsSemEtuds(context, sem)
     if not etudid in AbsSemEtuds:
-       AbsSemEtuds[etudid] = CAbsSemEtud(context, formsemestre_id, etudid)
+       AbsSemEtuds[etudid] = CAbsSemEtud(context, sem, etudid)
     return AbsSemEtuds[etudid]
 
-def getAbsSemEtuds(context, formsemestre_id):
+def getAbsSemEtuds(context, sem):
     u = context.GetDBConnexionString() # identifie le dept de facon fiable
     if not u in ABS_CACHE_INST:
         ABS_CACHE_INST[u] = {}
     C = ABS_CACHE_INST[u]
-    if formsemestre_id not in C:
-        C[formsemestre_id] = {}
-    return C[formsemestre_id]
+    if sem['formsemestre_id'] not in C:
+        C[sem['formsemestre_id']] = {}
+    return C[sem['formsemestre_id']]
 
 def invalidateAbsEtudDate(context, etudid, date):
     """Doit etre appelé à chaque modification des absences pour cet étudiant et cette date.
@@ -1981,7 +1981,7 @@
         context.Notes._inval_cache(pdfonly=pdfonly, formsemestre_id=sem['formsemestre_id'])
         
         # Inval cache compteurs absences:
-        AbsSemEtuds = getAbsSemEtuds(context, sem['formsemestre_id'])
+        AbsSemEtuds = getAbsSemEtuds(context, sem)
         if etudid in AbsSemEtuds:
             AbsSemEtuds[etudid].invalidate()
 

Modified: branches/ScoDoc7/html_sidebar.py
===================================================================
--- branches/ScoDoc7/html_sidebar.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/html_sidebar.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -93,7 +93,7 @@
     </h2>
     <b>Absences</b>""" % params)
         if etud['cursem']:
-            AbsEtudSem = getAbsSemEtud(context, etud['cursem']['formsemestre_id'], etudid)
+            AbsEtudSem = getAbsSemEtud(context, etud['cursem'], etudid)
             params['nbabs']= AbsEtudSem.CountAbs()
             params['nbabsjust'] = AbsEtudSem.CountAbsJust()
             params['nbabsnj'] =  params['nbabs'] - params['nbabsjust']

Modified: branches/ScoDoc7/notes_table.py
===================================================================
--- branches/ScoDoc7/notes_table.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/notes_table.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -42,6 +42,7 @@
 import sco_parcours_dut 
 import sco_formsemestre
 from sco_formsemestre_edit import formsemestre_uecoef_list, formsemestre_uecoef_create
+import sco_evaluations
 import sco_compute_moy
 from sco_formulas import NoteVector
 
@@ -152,6 +153,7 @@
         self.sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
         self.moduleimpl_stats = {} # { moduleimpl_id : {stats} }
         self._uecoef = {} # { ue_id : coef } cache coef manuels ue cap
+        self._evaluations_etats = None #liste des evaluations avec état
         # Infos sur les etudiants
         self.inscrlist = context.do_formsemestre_inscription_list(
             args = { 'formsemestre_id' : formsemestre_id })
@@ -176,7 +178,7 @@
         self.bonus = DictDefault(defaultvalue=0)
         # Notes dans les modules  { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
         self._modmoys, self._modimpls, self._valid_evals_per_mod, valid_evals, mods_att, self.expr_diagnostics =\
-            sco_compute_moy.do_formsemestre_moyennes(context, formsemestre_id)
+            sco_compute_moy.do_formsemestre_moyennes(context, self, formsemestre_id)
         self._mods_att = mods_att # liste des modules avec des notes en attente
         self._matmoys = {} # moyennes par matieres
         self._valid_evals = {} # { evaluation_id : eval }
@@ -414,6 +416,7 @@
     def get_evals_in_mod(self, moduleimpl_id):
         "liste des evaluations valides dans un module"
         return [ e for e in self._valid_evals.values() if e['moduleimpl_id'] == moduleimpl_id ]
+    
     def get_mod_stats(self, moduleimpl_id):
         """moyenne generale, min, max pour un module
         Ne prend en compte que les evaluations où toutes les notes sont entrées
@@ -584,7 +587,7 @@
         formula = sco_compute_moy.get_ue_expression(self.formsemestre_id, ue_id, cnx)
         if formula:            
             moy = sco_compute_moy.compute_user_formula(
-                self.context, self.formsemestre_id, etudid, 
+                self.context, self.sem, etudid, 
                 moy, moy_valid,
                 notes, coefs, coefs_mask, formula,
                 diag_info=expr_diag)
@@ -1006,6 +1009,26 @@
                        {'formsemestre_id' : self.formsemestre_id, 'etudid' : etudid, 'code_attente' : NOTES_ATTENTE} )
         return len(cursor.fetchall()) > 0
 
+    def get_evaluations_etats(self): # evaluation_list_in_sem
+        """[ {...evaluation et son etat...} ]
+        """
+        if self._evaluations_etats is None:
+            self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem(
+                self.context, self.formsemestre_id)    
+
+        return self._evaluations_etats
+
+    def get_sem_evaluation_etat_list(self):
+        """Liste des evaluations de ce semestre, avec leur etat
+        """
+        return self.get_evaluations_etats()
+    
+    def get_mod_evaluation_etat_list(self, moduleimpl_id):
+        """Liste des évaluations de ce module
+        """
+        return [ e for e in self.get_evaluations_etats()
+                 if e['moduleimpl_id'] == moduleimpl_id ]
+        
 import thread
 class CacheNotesTable:
     """gestion rudimentaire de cache pour les NotesTables"""

Modified: branches/ScoDoc7/notesdb.py
===================================================================
--- branches/ScoDoc7/notesdb.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/notesdb.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -470,6 +470,8 @@
 
 def TimetoISO8601(t, null_is_empty=False):
     "convert time string to ISO 8601 (allow 16:03, 16h03, 16)"
+    if isinstance( t, datetime.time ):
+        return t.isoformat()
     if not t and null_is_empty:
         return ''
     t = t.strip().upper().replace('H', ':')

Modified: branches/ScoDoc7/sco_bulletins.py
===================================================================
--- branches/ScoDoc7/sco_bulletins.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_bulletins.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -97,17 +97,18 @@
     if not version in ('short','long','selectedevals'):
         raise ValueError('invalid version code !')
     
+    prefs = context.get_preferences(formsemestre_id)
+    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> toutes notes
+    
     I = DictDefault(defaultvalue='')
     I['etudid'] = etudid
     I['formsemestre_id'] = formsemestre_id
-    I['sem'] = sco_formsemestre.get_formsemestre(context, formsemestre_id)
+    I['sem'] = nt.sem
     if REQUEST:
         I['server_name'] = REQUEST.BASE0
     else:
         I['server_name'] = ''
-
-    prefs = context.get_preferences(formsemestre_id)
-    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> toutes notes
+    
     # Formation et parcours
     I['formation'] = context.formation_list( args={ 'formation_id' : I['sem']['formation_id'] } )[0]
     I['parcours'] = sco_codes_parcours.get_parcours_from_code(I['formation']['type_parcours'])
@@ -125,7 +126,7 @@
         pid=partition['partition_id']
         partitions_etud_groups[pid] = sco_groups.get_etud_groups_in_partition(context, pid)
     # --- Absences
-    AbsSemEtud = ZAbsences.getAbsSemEtud(context, formsemestre_id, etudid)
+    AbsSemEtud = ZAbsences.getAbsSemEtud(context, nt.sem, etudid)
     I['nbabs'] =  AbsSemEtud.CountAbs()
     I['nbabsjust'] = AbsSemEtud.CountAbsJust()
     

Modified: branches/ScoDoc7/sco_bulletins_json.py
===================================================================
--- branches/ScoDoc7/sco_bulletins_json.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_bulletins_json.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -259,7 +259,7 @@
     if  context.get_preference('bul_show_abs', formsemestre_id):
         debut_sem = DateDMYtoISO(sem['date_debut'])
         fin_sem = DateDMYtoISO(sem['date_fin'])
-        AbsEtudSem = ZAbsences.getAbsSemEtud(context, formsemestre_id, etudid)
+        AbsEtudSem = ZAbsences.getAbsSemEtud(context, sem, etudid)
         nbabs = AbsEtudSem.CountAbs()
         nbabsjust = AbsEtudSem.CountAbsJust()
         

Modified: branches/ScoDoc7/sco_bulletins_xml.py
===================================================================
--- branches/ScoDoc7/sco_bulletins_xml.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_bulletins_xml.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -260,7 +260,7 @@
     if  context.get_preference('bul_show_abs', formsemestre_id):
         debut_sem = DateDMYtoISO(sem['date_debut'])
         fin_sem = DateDMYtoISO(sem['date_fin'])
-        AbsEtudSem = ZAbsences.getAbsSemEtud(context, formsemestre_id, etudid)
+        AbsEtudSem = ZAbsences.getAbsSemEtud(context, sem, etudid)
         nbabs = AbsEtudSem.CountAbs()
         nbabsjust = AbsEtudSem.CountAbsJust()
         doc._push()

Modified: branches/ScoDoc7/sco_compute_moy.py
===================================================================
--- branches/ScoDoc7/sco_compute_moy.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_compute_moy.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -96,17 +96,21 @@
         else:
             return None
 
-def compute_user_formula(context, formsemestre_id, etudid, 
+def compute_user_formula(context, sem, etudid, 
                          moy, moy_valid, notes, coefs, coefs_mask, 
                          formula,
-                         diag_info={} # infos supplementaires a placer ds messages d'erreur
+                         diag_info={}, # infos supplementaires a placer ds messages d'erreur
+                         use_abs=True
                          ):
     """Calcul moyenne a partir des notes et coefs, en utilisant la formule utilisateur (une chaine).
     Retourne moy, et en cas d'erreur met à jour diag_info (msg)
     """
-    AbsSemEtud = ZAbsences.getAbsSemEtud(context, formsemestre_id, etudid)
-    nbabs = AbsSemEtud.CountAbs()
-    nbabs_just = AbsSemEtud.CountAbsJust()
+    if use_abs:
+        AbsSemEtud = ZAbsences.getAbsSemEtud(context, sem, etudid)
+        nbabs = AbsSemEtud.CountAbs()
+        nbabs_just = AbsSemEtud.CountAbsJust()
+    else:
+        nbabs, nbabs_just = 0, 0
     try:
         moy_val = float(moy)
     except:
@@ -145,7 +149,7 @@
     
     return user_moy
 
-def do_moduleimpl_moyennes(context, mod):
+def do_moduleimpl_moyennes(context, nt, mod):
     """Retourne dict { etudid : note_moyenne } pour tous les etuds inscrits
     au moduleimpl mod, la liste des evaluations "valides" (toutes notes entrées
     ou en attente), et att (vrai s'il y a des notes en attente dans ce module).
@@ -159,21 +163,22 @@
     """
     diag_info = {} # message d'erreur formule
     moduleimpl_id = mod['moduleimpl_id']
+    sem = sco_formsemestre.get_formsemestre(context, mod['formsemestre_id'])
     etudids = context.do_moduleimpl_listeetuds(moduleimpl_id) # tous, y compris demissions
     # Inscrits au semestre (pour traiter les demissions):
     inssem_set = Set( [x['etudid'] for x in
                        context.do_formsemestre_inscription_listinscrits(mod['formsemestre_id'])])
     insmod_set = inssem_set.intersection(etudids) # inscrits au semestre et au module
-    evals = context.do_evaluation_list(args={ 'moduleimpl_id' : moduleimpl_id })
-    evals.reverse() # la plus ancienne en tête
+    
+    evals = nt.get_mod_evaluation_etat_list(moduleimpl_id)
+    evals.sort(key=lambda x: (x['numero'], x['jour'], x['heure_debut']), reverse=True) # la plus ancienne en tête
+    
     user_expr = moduleimpl_has_expression(context, mod)
     attente = False
     # recupere les notes de toutes les evaluations
     eval_rattr = None
     for e in evals:
-        e['nb_inscrits'] = len(
-            sco_groups.do_evaluation_listeetuds_groups(context, e['evaluation_id'],
-                                                       getallstudents=True))
+        e['nb_inscrits'] = e['etat']['nb_inscrits']
         NotesDB = context._notes_getall(e['evaluation_id']) # toutes, y compris demissions
         # restreint aux étudiants encore inscrits à ce module        
         notes = [ NotesDB[etudid]['value'] for etudid in NotesDB 
@@ -183,7 +188,7 @@
         e['nb_neutre'] = len( [ x for x in notes if x == NOTES_NEUTRALISE ] )
         e['nb_att'] = len( [ x for x in notes if x == NOTES_ATTENTE ] )
         e['notes'] = NotesDB
-        e['etat'] = sco_evaluations.do_evaluation_etat(context, e['evaluation_id'])
+        
         if e['etat']['evalattente']:
             attente = True
         if e['evaluation_type'] == EVALUATION_RATTRAPAGE:
@@ -198,6 +203,9 @@
                     if ((e['etat']['evalcomplete'] or e['etat']['evalattente']) and (e['note_max'] > 0)) ]
     # 
     R = {}
+    formula = unescape_html(mod['computation_expr'])
+    formula_use_abs = 'abs' in formula
+    
     for etudid in insmod_set: # inscrits au semestre et au module
         sum_notes = 0.
         sum_coefs = 0.
@@ -228,7 +236,7 @@
             moy_valid = False
         
         if user_expr:
-            # (experimental) recalcule la moyenne en utilisant la formule utilisateur
+            # recalcule la moyenne en utilisant la formule utilisateur
             notes = []
             coefs = []
             coefs_mask = [] # 0/1, 0 si coef a ete annulé
@@ -252,11 +260,12 @@
                     coefs.append(0.)
                     coefs_mask.append(0)
             if nb_notes > 0:
-                formula = unescape_html(mod['computation_expr'])
-                user_moy = compute_user_formula(context, mod['formsemestre_id'], etudid, 
-                                                R[etudid], moy_valid,
-                                                notes, coefs, coefs_mask, formula,
-                                                diag_info=diag_info)
+                user_moy = compute_user_formula(
+                    context, sem, etudid, 
+                    R[etudid], moy_valid,
+                    notes, coefs, coefs_mask, formula,
+                    diag_info=diag_info,
+                    use_abs= formula_use_abs)
                 if diag_info:
                     diag_info['moduleimpl_id'] = moduleimpl_id
                 R[etudid] = user_moy
@@ -276,7 +285,7 @@
     return R, valid_evals, attente, diag_info
 
 
-def do_formsemestre_moyennes(context, formsemestre_id):
+def do_formsemestre_moyennes(context, nt, formsemestre_id):
     """retourne dict { moduleimpl_id : { etudid, note_moyenne_dans_ce_module } },
     la liste des moduleimpls, la liste des evaluations valides,
     liste des moduleimpls  avec notes en attente.
@@ -295,7 +304,7 @@
     for mod in mods:
         moduleimpl_id = mod['moduleimpl_id']
         assert not D.has_key(moduleimpl_id)
-        D[moduleimpl_id], valid_evals_mod, attente, expr_diag = do_moduleimpl_moyennes(context, mod)
+        D[moduleimpl_id], valid_evals_mod, attente, expr_diag = do_moduleimpl_moyennes(context, nt, mod)
         valid_evals_per_mod[moduleimpl_id] = valid_evals_mod
         valid_evals += valid_evals_mod
         if attente:

Modified: branches/ScoDoc7/sco_evaluations.py
===================================================================
--- branches/ScoDoc7/sco_evaluations.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_evaluations.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -29,7 +29,7 @@
 """
 from sets import Set
 
-from notes_log import log
+from notes_log import log, logCallStack
 from sco_utils import *
 from notesdb import *
 import sco_news
@@ -93,9 +93,9 @@
                  text='Suppression d\'une évaluation dans <a href="%(url)s">%(titre)s</a>' % mod,
                  url=mod['url'])
 
+_DEE_TOT = 0
 
-def do_evaluation_etat(context, evaluation_id, partition_id=None, select_first_partition=False,
-                       keep_numeric=False):
+def do_evaluation_etat(context, evaluation_id, partition_id=None, select_first_partition=False):
     """donne infos sur l'etat du evaluation
     { nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att, moyenne, mediane,
     date_last_modif, gr_complets, gr_incomplets, evalcomplete }
@@ -103,19 +103,24 @@
     à ce module ont des notes)
     evalattente est vrai s'il ne manque que des notes en attente
     """
-    #log('do_evaluation_etat: evaluation_id=%s  partition_id=%s' % (evaluation_id, partition_id))
+    #global _DEE_TOT
+    #t0=time.time()
+    # if evaluation_id == 'GEAEVAL82883':
+    #     log('do_evaluation_etat: evaluation_id=%s  partition_id=%s sfp=%s' % (evaluation_id, partition_id, select_first_partition))
+
     nb_inscrits = len(sco_groups.do_evaluation_listeetuds_groups(context, evaluation_id,getallstudents=True))
     NotesDB = context._notes_getall(evaluation_id) # { etudid : value }
     notes = [ x['value'] for x in NotesDB.values() ]
     nb_abs = len( [ x for x in notes if x is None ] )
     nb_neutre = len( [ x for x in notes if x == NOTES_NEUTRALISE ] )
     nb_att = len( [ x for x in notes if x == NOTES_ATTENTE ] )
-    moy, median = notes_moyenne_median(notes)
-    if moy is None:
+    moy_num, median_num = notes_moyenne_median(notes)
+    if moy_num is None:
         median, moy = '',''
+        median_num, moy_num = None, None
     else:
-        median = fmt_note(median, keep_numeric=keep_numeric) # '%.3g' % median
-        moy = fmt_note(moy, keep_numeric=keep_numeric) # '%.3g' % moy
+        median = fmt_note(median_num) 
+        moy = fmt_note(moy_num) 
     # cherche date derniere modif note
     if len(NotesDB):
         t = [ x['date'] for x in NotesDB.values() ]
@@ -199,13 +204,20 @@
         gr_moyennes.append(
             {'group_id':group_id, 
              'group_name' : groups[group_id]['group_name'],
-             'gr_moy' : fmt_note(gr_moy, keep_numeric=keep_numeric),
-             'gr_median':fmt_note(gr_median, keep_numeric=keep_numeric),
+             'gr_moy_num' : gr_moy,
+             'gr_moy' : fmt_note(gr_moy),
+             'gr_median_num' : gr_median,
+             'gr_median':fmt_note(gr_median),
              'gr_nb_notes': len(notes),
              'gr_nb_att' : len([ x for x in notes if x == NOTES_ATTENTE ])
              } )
     gr_moyennes.sort(key=operator.itemgetter('group_name'))
     #log('gr_moyennes=%s' % gr_moyennes) 
+    #_DEE_TOT += (time.time() - t0)
+    #log('%s\t_DEE_TOT=%f' % (evaluation_id, _DEE_TOT))
+    #if evaluation_id == 'GEAEVAL82883':
+    #    logCallStack()
+    
     # retourne mapping
     return {
         'evaluation_id' : evaluation_id,
@@ -213,9 +225,12 @@
         'nb_notes':nb_notes, # nb notes etudiants inscrits
         'nb_notes_total' : nb_notes_total, # nb de notes (incluant desinscrits)
         'nb_abs':nb_abs, 'nb_neutre':nb_neutre, 'nb_att' : nb_att,
-        'moy':moy, 'median':median,
-        'last_modif':last_modif,
-        'gr_incomplets':gr_incomplets,
+        'moy' : moy, 
+        'moy_num' : moy_num,
+        'median' : median,
+        'median_num' : median_num,
+        'last_modif' : last_modif,
+        'gr_incomplets' : gr_incomplets,
         'gr_moyennes' : gr_moyennes,
         'groups' : groups,
         'evalcomplete' : complete,
@@ -223,30 +238,72 @@
 
 
 def do_evaluation_list_in_sem(context, formsemestre_id):
-    """Liste des evaluations pour un semestre (dans tous les modules de ce semestre).
+    """Liste les evaluations de tous les modules de ce semestre.
     Donne pour chaque eval son état (voir do_evaluation_etat)
     { evaluation_id,nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif ... }
+
+    Exemple:
+    [ {
+    'coefficient': 1.0,
+ 'description': 'QCM et cas pratiques',
+ 'etat': {'evalattente': False,
+          'evalcomplete': True,
+          'evaluation_id': 'GEAEVAL82883',
+          'gr_incomplets': [],
+          'gr_moyennes': [{'gr_median': '12.00',
+                           'gr_median_num' : 12.,
+                           'gr_moy': '11.88',
+                           'gr_moy_num' : 11.88,
+                           'gr_nb_att': 0,
+                           'gr_nb_notes': 166,
+                           'group_id': 'GEAG266762',
+                           'group_name': None}],
+          'groups': {'GEAG266762': {'etudid': 'GEAEID80603',
+                                    'group_id': 'GEAG266762',
+                                    'group_name': None,
+                                    'partition_id': 'GEAP266761'}},
+          'last_modif': datetime.datetime(2015, 12, 3, 15, 15, 16),
+          'median': '12.00',
+          'moy': '11.84',
+          'nb_abs': 2,
+          'nb_att': 0,
+          'nb_inscrits': 166,
+          'nb_neutre': 0,
+          'nb_notes': 168,
+          'nb_notes_total': 169},
+ 'evaluation_id': 'GEAEVAL82883',
+ 'evaluation_type': 0,
+ 'heure_debut': datetime.time(8, 0),
+ 'heure_fin': datetime.time(9, 30),
+ 'jour': datetime.date(2015, 11, 3),
+ 'moduleimpl_id': 'GEAMIP80490',
+ 'note_max': 20.0,
+ 'numero': 0,
+ 'publish_incomplete': 0,
+ 'visibulletin': 1} ]
+
     """
-    req = "select evaluation_id from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
-    cnx = context.GetDBConnexion()
-    cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
-    cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
-    res = cursor.fetchall()
-    evaluation_ids = [ x[0] for x in res ]
-    #
-    R = []
-    for evaluation_id in evaluation_ids:
-        R.append( do_evaluation_etat(context, evaluation_id) )
-    return R 
-
-def formsemestre_evaluations_list(context, formsemestre_id):
-    """Liste (non triée) des evals pour ce semestre"""
     req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
     cnx = context.GetDBConnexion()
     cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
     cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
-    return cursor.dictfetchall()
+    res = cursor.dictfetchall()
+    # etat de chaque evaluation:
+    for r in res:
+        r['etat'] = do_evaluation_etat(context, r['evaluation_id'])
+    
+    return res
 
+# remplacé par nt.get_sem_evaluation_etat_list()
+#
+# def formsemestre_evaluations_list(context, formsemestre_id):
+#     """Liste (non triée) des evals pour ce semestre"""
+#     req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
+#     cnx = context.GetDBConnexion()
+#     cursor = cnx.cursor(cursor_factory=ScoDocCursor)    
+#     cursor.execute( req, { 'formsemestre_id' : formsemestre_id } )
+#     return cursor.dictfetchall()
+
 def _eval_etat(evals):
     """evals: list of mappings (etats)
     -> nb_eval_completes, nb_evals_en_cours,
@@ -258,13 +315,13 @@
     nb_evals_completes, nb_evals_en_cours, nb_evals_vides = 0,0,0
     dates = []
     for e in evals:
-        if e['evalcomplete']:
+        if e['etat']['evalcomplete']:
             nb_evals_completes += 1
-        elif e['nb_notes'] == 0: # nb_notes == 0
+        elif e['etat']['nb_notes'] == 0: 
             nb_evals_vides += 1
         else:
             nb_evals_en_cours += 1
-        dates.append(e['last_modif'])
+        dates.append(e['etat']['last_modif'])
 
     dates = sort_dates(dates)
     
@@ -281,25 +338,16 @@
 def do_evaluation_etat_in_sem(context, formsemestre_id, REQUEST=None):
     """-> nb_eval_completes, nb_evals_en_cours, nb_evals_vides,
     date derniere modif, attente"""
-    evals = do_evaluation_list_in_sem(context, formsemestre_id)
+    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> liste evaluations et moduleimpl en attente
+    evals = nt.get_sem_evaluation_etat_list()
     etat = _eval_etat(evals)
     # Ajoute information sur notes en attente
-    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> liste moduleimpl en attente
     etat['attente'] = len(nt.get_moduleimpls_attente()) > 0
     return etat
 
-def do_evaluation_etat_in_mod(context, moduleimpl_id, REQUEST=None):
-    evals = context.do_evaluation_list( { 'moduleimpl_id' : moduleimpl_id } )
-    evaluation_ids = [ x['evaluation_id'] for x in evals ]
-    R = []
-    for evaluation_id in evaluation_ids:
-        R.append( do_evaluation_etat(context, evaluation_id) )
-    etat = _eval_etat(R)
-    # Ajoute information sur notes en attente
-    M = context.do_moduleimpl_list( args={ 'moduleimpl_id' : moduleimpl_id})[0]
-    formsemestre_id = M['formsemestre_id']
-    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
-
+def do_evaluation_etat_in_mod(context, nt, moduleimpl_id):
+    evals = nt.get_mod_evaluation_etat_list(moduleimpl_id)
+    etat = _eval_etat(evals)
     etat['attente'] = moduleimpl_id in [
         m['moduleimpl_id'] for m in nt.get_moduleimpls_attente() ] #> liste moduleimpl en attente
     return etat
@@ -309,7 +357,9 @@
 def formsemestre_evaluations_cal(context, formsemestre_id, REQUEST=None):
     """Page avec calendrier de toutes les evaluations de ce semestre"""
     sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
-    evals = formsemestre_evaluations_list(context, formsemestre_id)
+    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> liste evaluations
+    
+    evals = nt.get_sem_evaluation_etat_list()
     nb_evals = len(evals)
 
     color_incomplete = '#FF6060'
@@ -323,7 +373,7 @@
         year -= 1 # calendrier septembre a septembre
     events = {} # (day, halfday) : event
     for e in evals:
-        etat = do_evaluation_etat(context, e['evaluation_id'])
+        etat = e['etat']
         if not e['jour']:
             continue
         day = e['jour'].strftime('%Y-%m-%d')

Modified: branches/ScoDoc7/sco_formsemestre.py
===================================================================
--- branches/ScoDoc7/sco_formsemestre.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_formsemestre.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -65,10 +65,12 @@
                          },        
     )
 
+
 def get_formsemestre(context, formsemestre_id):
     "list ONE formsemestre"
     try:
-        return do_formsemestre_list(context, args={ 'formsemestre_id' : formsemestre_id } )[0]
+        sem = do_formsemestre_list(context, args={ 'formsemestre_id' : formsemestre_id } )[0]
+        return sem
     except:
         log('get_formsemestre: invalid formsemestre_id (%s)' % formsemestre_id)
         raise

Modified: branches/ScoDoc7/sco_formsemestre_status.py
===================================================================
--- branches/ScoDoc7/sco_formsemestre_status.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_formsemestre_status.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -480,6 +480,7 @@
     Liste des modules et de leurs coefficients
     """
     sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
+    nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) #> liste evaluations
     F = context.formation_list( args={ 'formation_id' : sem['formation_id'] } )[0]
     parcours = sco_codes_parcours.get_parcours_from_code(F['type_parcours'])
     inscrits = context.do_formsemestre_inscription_list( args={ 'formsemestre_id' : formsemestre_id } )
@@ -526,13 +527,12 @@
         
         if with_evals:
             # Ajoute lignes pour evaluations
-            evals = context.do_evaluation_list( { 'moduleimpl_id' : M['moduleimpl_id'] } )
+            evals = nt.get_mod_evaluation_etat_list(M['moduleimpl_id'])
             evals.reverse() # ordre chronologique
             # Ajoute etat:
             for e in evals:
-                e.update( sco_evaluations.do_evaluation_etat(context, e['evaluation_id']) )
                 # Cosmetic: conversions pour affichage
-                if e['evalcomplete']:
+                if e['etat']['evalcomplete']:
                     e['evalcomplete_str'] = 'Oui'
                     e['_evalcomplete_str_td_attrs'] = 'style="color: green;"'
                 else:
@@ -558,9 +558,9 @@
     if with_evals:
         columns_ids += [ 'jour', 'description', 'coefficient', 'evalcomplete_str', 
                          'publish_incomplete_str' ]
-    titles = {}
-    # on veut { id : id }, peu elegant en python 2.3:
-    map( lambda x,titles=titles: titles.__setitem__(x[0],x[1]), zip(columns_ids,columns_ids) )
+
+    titles = { title : title for title in columns_ids }
+        
     titles['ects'] = 'ECTS'
     titles['jour'] = 'Evaluation'
     titles['description'] = ''
@@ -733,7 +733,8 @@
             fontorange = ' fontorange' # style css additionnel
         else:
             fontorange = ''
-        etat = sco_evaluations.do_evaluation_etat_in_mod(context, M['moduleimpl_id'])
+        
+        etat = sco_evaluations.do_evaluation_etat_in_mod(context, nt, M['moduleimpl_id'])
         if etat['nb_evals_completes'] > 0 and etat['nb_evals_en_cours'] == 0 and etat['nb_evals_vides'] == 0:
             H.append('<tr class="formsemestre_status_green%s">' % fontorange)
         else:

Modified: branches/ScoDoc7/sco_formsemestre_validation.py
===================================================================
--- branches/ScoDoc7/sco_formsemestre_validation.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_formsemestre_validation.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -477,7 +477,7 @@
         # Moy Gen (sous le code decision)
         H.append('<td class="rcp_moy">%s</td>' % notes_table.fmt_note( nt.get_etud_moy_gen(etudid)) )
         # Absences (nb d'abs non just. dans ce semestre)
-        AbsEtudSem = getAbsSemEtud(context, sem['formsemestre_id'], etudid)
+        AbsEtudSem = getAbsSemEtud(context, sem, etudid)
         nbabs = AbsEtudSem.CountAbs()
         nbabsjust = AbsEtudSem.CountAbsJust()
         H.append('<td class="rcp_abs">%d</td>' % (nbabs-nbabsjust) )

Modified: branches/ScoDoc7/sco_moduleimpl_status.py
===================================================================
--- branches/ScoDoc7/sco_moduleimpl_status.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_moduleimpl_status.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -158,13 +158,13 @@
     # Ligne: règle de calcul
     has_expression = sco_compute_moy.moduleimpl_has_expression(context, M)
     if has_expression:
-        H.append('<tr><td class="fichetitre2" colspan="2">Règle de calcul: <span class="formula" title="mode de calcul de la moyenne du module">moyenne=<tt>%s</tt></span>' % M['computation_expr'])
+        H.append('<tr><td class="fichetitre2" colspan="4">Règle de calcul: <span class="formula" title="mode de calcul de la moyenne du module">moyenne=<tt>%s</tt></span>' % M['computation_expr'])
         if context.can_change_ens(REQUEST, moduleimpl_id, raise_exc=False):
             H.append('<span class="fl"><a class="stdlink"  href="edit_moduleimpl_expr?moduleimpl_id=%s">changer</a></span>'  % moduleimpl_id)
         H.append('</td></tr>')
     else:
         t0, t1 = '<em>règle de calcul standard</em>', ''
-        H.append('<tr><td colspan="2"><em title="mode de calcul de la moyenne du module">règle de calcul standard</em>')
+        H.append('<tr><td colspan="4"><em title="mode de calcul de la moyenne du module">règle de calcul standard</em>')
         if context.can_change_ens(REQUEST, moduleimpl_id, raise_exc=False):
             H.append(' (<a class="stdlink" href="edit_moduleimpl_expr?moduleimpl_id=%s">changer</a>)' % moduleimpl_id)
         H.append('</td></tr>')

Modified: branches/ScoDoc7/sco_prepajury.py
===================================================================
--- branches/ScoDoc7/sco_prepajury.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_prepajury.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -116,7 +116,7 @@
             if s['formsemestre_id'] == formsemestre_id:       
                 groupestd[etudid] = etud_groups.get(etudid, {}).get(main_partition_id, '')        
         # absences:
-        AbsEtudSem = getAbsSemEtud(context, formsemestre_id, etudid)
+        AbsEtudSem = getAbsSemEtud(context, sem, etudid)
         nbabs[etudid] = AbsEtudSem.CountAbs()
         nbabsjust[etudid] = AbsEtudSem.CountAbsJust()
     

Modified: branches/ScoDoc7/sco_recapcomplet.py
===================================================================
--- branches/ScoDoc7/sco_recapcomplet.py	2016-07-24 08:26:30 UTC (rev 1536)
+++ branches/ScoDoc7/sco_recapcomplet.py	2016-07-26 05:37:41 UTC (rev 1537)
@@ -242,9 +242,7 @@
                     h.append( code )
                     cod2mod[code] = modimpl # pour fabriquer le lien
                     if format == 'xlsall':
-                        evals = context.do_evaluation_list( {'moduleimpl_id' : modimpl['moduleimpl_id']})
-                        for e in evals:
-                            e['eval_state'] = sco_evaluations.do_evaluation_etat(context, e['evaluation_id'])
+                        evals = nt.get_mod_evaluation_etat_list(modimpl['moduleimpl_id'])
                         mod_evals[modimpl['moduleimpl_id']] = evals
                         h += _list_notes_evals_titles(context, code, evals)
     h += ['code_nip', 'etudid']
@@ -583,7 +581,7 @@
     """Liste des notes des evaluations completes de ce module"""
     L = []
     for e in evals:
-        if e['eval_state']['evalcomplete']:
+        if e['etat']['evalcomplete']:
             NotesDB = context._notes_getall(e['evaluation_id'])
             if NotesDB.has_key(etudid):
                 val = NotesDB[etudid]['value']
@@ -597,18 +595,17 @@
     """Liste des titres des evals completes"""
     L = []
     for e in evals:
-        e['eval_state'] = sco_evaluations.do_evaluation_etat(context, e['evaluation_id'], keep_numeric=True)
-        if e['eval_state']['evalcomplete']:
-            L.append(codemodule+'-'+e['jour'])
+        if e['etat']['evalcomplete']:
+            L.append(codemodule+'-'+DateISOtoDMY(e['jour']))
     return L
 
 def _list_notes_evals_stats(context, evals, key):
     """Liste des stats (moy, ou rien!) des evals completes"""
     L = []
     for e in evals:
-        if e['eval_state']['evalcomplete']:
+        if e['etat']['evalcomplete']:
             if key == 'moy':
-                val = e['eval_state']['moy']
+                val = e['etat']['moy_num']
                 L.append( fmt_note(val, keep_numeric=True) )
             elif key == 'max':
                 L.append( e['note_max'] )


Plus d'informations sur la liste de diffusion Scodoc-devel