diff --git a/app/__init__.py b/app/__init__.py index 6ff9c0df..714ffbd7 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -4,11 +4,6 @@ import os import sys -# Un hack en attendant la migration vers Python3 #sco8 -if sys.version_info.major < 3: - reload(sys) - sys.setdefaultencoding("UTF8") - import logging from logging.handlers import SMTPHandler, RotatingFileHandler @@ -22,10 +17,12 @@ from flask_login import LoginManager from flask_mail import Mail from flask_bootstrap import Bootstrap from flask_moment import Moment +from flask_caching import Cache from config import Config from app.scodoc import notesdb as ndb +from app.scodoc import sco_cache app = Flask(__name__) app.config.from_object(Config) @@ -39,6 +36,8 @@ mail = Mail() bootstrap = Bootstrap(app) moment = Moment() +cache = Cache(config={"CACHE_TYPE": "MemcachedCache"}) # XXX TODO: configuration file + @app.before_request def open_dept_db_connection(): @@ -64,6 +63,8 @@ def create_app(config_class=Config): mail.init_app(app) bootstrap.init_app(app) moment.init_app(app) + cache.init_app(app) + sco_cache.CACHE = cache from app.auth import bp as auth_bp diff --git a/app/scodoc/debug.py b/app/scodoc/debug.py index cd14b33c..85f8a363 100644 --- a/app/scodoc/debug.py +++ b/app/scodoc/debug.py @@ -27,7 +27,7 @@ for sem in sems: print sem['formsemestre_id'], sem['titre_num'] # Recupere la table de notes: -nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) +nt = sco_cache.NotesTableCache.get( formsemestre_id) """ @@ -46,9 +46,9 @@ from app.scodoc import html_sco_header from app.scodoc import sco_archives from app.scodoc import sco_bulletins from app.scodoc import sco_bulletins_xml +from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours from app.scodoc import sco_compute_moy -from app.scodoc import sco_core from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_module from app.scodoc import sco_edit_ue diff --git a/app/scodoc/gen_tables.py b/app/scodoc/gen_tables.py index 470142ef..67512247 100644 --- a/app/scodoc/gen_tables.py +++ b/app/scodoc/gen_tables.py @@ -46,7 +46,6 @@ from collections import OrderedDict from xml.etree import ElementTree import json -from xml.etree import ElementTree from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak from reportlab.platypus import Table, TableStyle, Image, KeepInFrame from reportlab.lib.colors import Color diff --git a/app/scodoc/html_sidebar.py b/app/scodoc/html_sidebar.py index 266e8bab..8fe5e5d9 100644 --- a/app/scodoc/html_sidebar.py +++ b/app/scodoc/html_sidebar.py @@ -78,7 +78,7 @@ def sidebar_common(context, REQUEST=None): def sidebar(context, REQUEST=None): "Main HTML page sidebar" # rewritten from legacy DTML code - from app.scodoc.sco_abs import getAbsSemEtud + from app.scodoc import sco_abs from app.scodoc import sco_etud params = { @@ -114,9 +114,9 @@ def sidebar(context, REQUEST=None): % params ) if etud["cursem"]: - AbsEtudSem = getAbsSemEtud(context, etud["cursem"], etudid) - params["nbabs"] = AbsEtudSem.CountAbs() - params["nbabsjust"] = AbsEtudSem.CountAbsJust() + params["nbabs"], params["nbabsjust"] = sco_abs.get_abs_count( + etudid, etud["cursem"] + ) params["nbabsnj"] = params["nbabs"] - params["nbabsjust"] params["date_debut"] = etud["cursem"]["date_debut"] params["date_fin"] = etud["cursem"]["date_fin"] diff --git a/app/scodoc/notes_cache.py b/app/scodoc/notes_cache.py deleted file mode 100644 index 17a92fd0..00000000 --- a/app/scodoc/notes_cache.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- mode: python -*- -# -*- coding: utf-8 -*- - -############################################################################## -# -# Gestion scolarite IUT -# -# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Emmanuel Viennet emmanuel.viennet@viennet.net -# -############################################################################## - -"""Gestion rudimentaire de cache pour Notes - - - NOTA: inutilisable dans une instance Zope (can't pickle functions) -""" - -from app.scodoc.notes_log import log - - -class CacheFunc(object): - """gestion rudimentaire de cache pour une fonction - func doit etre sans effet de bord, et sans arguments nommés - """ - - def __init__(self, func): - log("new CacheFunc for %s" % str(func)) - self.func = func - self.cache = {} # { arguments : function result } - - def __call__(self, *args): - if args in self.cache: - # log('cache hit %s' % str(args)) - return self.cache[args] - else: - val = self.func(*args) - self.cache[args] = val - log("caching %s(%s)" % (str(self.func), str(args))) - return val - - def inval_cache_entry(self, *args): # > - "expire cache for these args" - log("inval_cache_entry %s(%s)" % (str(self.func), str(args))) # > - del self.cache[args] - - def inval_cache(self): # > - "clear whole cache" - log("inval_cache %s" % (str(self.func))) # > - self.cache = {} diff --git a/app/scodoc/notes_table.py b/app/scodoc/notes_table.py index c3cf369b..2f75395f 100644 --- a/app/scodoc/notes_table.py +++ b/app/scodoc/notes_table.py @@ -36,7 +36,7 @@ from flask import g, url_for import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb -from app.scodoc.notes_log import log, logCallStack +from app.scodoc.notes_log import log from app.scodoc.sco_formulas import NoteVector from app.scodoc.sco_exceptions import ( AccessDenied, @@ -57,7 +57,7 @@ from app.scodoc.sco_codes_parcours import ( from app.scodoc.sco_parcours_dut import formsemestre_get_etud_capitalisation from app.scodoc import sco_codes_parcours from app.scodoc import sco_compute_moy -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_module from app.scodoc import sco_edit_ue @@ -178,12 +178,12 @@ class NotesTable(object): """ - def __init__(self, context, formsemestre_id): + def __init__( + self, context, formsemestre_id + ): # context is not used in ScoDoc8 ! XXX log("NotesTable( formsemestre_id=%s )" % formsemestre_id) - # open('/tmp/cache.log','a').write('NotesTables(%s)\n' % formsemestre_id) # XXX DEBUG if not formsemestre_id: - logCallStack() - raise ScoValueError("invalid formsemestre_id (%s)" % formsemestre_id) + raise ValueError("invalid formsemestre_id (%s)" % formsemestre_id) self.context = context self.formsemestre_id = formsemestre_id cnx = ndb.GetDBConnexion() @@ -1170,8 +1170,8 @@ class NotesTable(object): "comp_ue_capitalisees: recomputing UE moy (etudid=%s, ue_id=%s formsemestre_id=%s)" % (etudid, ue_cap["ue_id"], ue_cap["formsemestre_id"]) ) - nt_cap = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, ue_cap["formsemestre_id"] + nt_cap = sco_cache.NotesTableCache.get( + ue_cap["formsemestre_id"] ) # > UE capitalisees par un etud moy_ue_cap = nt_cap.get_etud_ue_status(etudid, ue_cap["ue_id"])[ "moy" diff --git a/app/scodoc/notesdb.py b/app/scodoc/notesdb.py index 4bb27815..a3156a5a 100644 --- a/app/scodoc/notesdb.py +++ b/app/scodoc/notesdb.py @@ -35,13 +35,13 @@ def unquote(s): def open_dept_connection(): """Open a connection to the current dept db""" - # log("open_dept_connection to " + scu.get_db_cnx_string()) # XXX + # log("open_dept_connection to " + scu.get_db_cnx_string()) return psycopg2.connect(scu.get_db_cnx_string()) def close_dept_connection(): """Commit and close dept db.""" - # log("close_dept_connection to " + scu.get_db_cnx_string()) # XXX + # log("close_dept_connection to " + scu.get_db_cnx_string()) g.db_conn.commit() g.db_conn.close() diff --git a/app/scodoc/pe_jurype.py b/app/scodoc/pe_jurype.py index 35c2992c..5c078718 100644 --- a/app/scodoc/pe_jurype.py +++ b/app/scodoc/pe_jurype.py @@ -54,8 +54,8 @@ import pprint from app.scodoc.gen_tables import GenTable, SeqGenTable import app.scodoc.sco_utils as scu +from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours # sco_codes_parcours.NEXT -> sem suivant -from app.scodoc import sco_core from app.scodoc import sco_etud from app.scodoc import sco_formsemestre from app.scodoc import pe_tagtable @@ -331,7 +331,7 @@ class JuryPE(object): nt = self.get_cache_notes_d_un_semestre( self.context, sem["formsemestre_id"] ) - # sco_core.get_notes_cache(context).get_NotesTable(context, sem['formsemestre_id']) + # sco_cache.NotesTableCache.get( sem['formsemestre_id']) etudiantsDuSemestre = ( nt.get_etudids() ) # nt.identdict.keys() # identification des etudiants du semestre @@ -1139,9 +1139,7 @@ class JuryPE(object): self, context, formsemestre_id ): # inutile en realité ! """Charge la table des notes d'un formsemestre""" - return sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) + return sco_cache.NotesTableCache.get(formsemestre_id) # ------------------------------------------------------------------------------------------------------------------ diff --git a/app/scodoc/pe_semestretag.py b/app/scodoc/pe_semestretag.py index 18e5ba7c..c0a30125 100644 --- a/app/scodoc/pe_semestretag.py +++ b/app/scodoc/pe_semestretag.py @@ -38,7 +38,7 @@ Created on Fri Sep 9 09:15:05 2016 from app.scodoc.notes_log import log from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_tag_module from app.scodoc import pe_tagtable @@ -270,8 +270,8 @@ class SemestreTag(pe_tagtable.TableTag): # => le formsemestre_id du semestre dont vient la capitalisation fid_prec = fids_prec[0] # Lecture des notes de ce semestre - nt_prec = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, fid_prec + nt_prec = sco_cache.NotesTableCache.get( + fid_prec ) # le tableau de note du semestre considéré # Y-a-t-il un module équivalent c'est à dire correspondant au même code (le module_id n'étant pas significatif en cas de changement de PPN) diff --git a/app/scodoc/sco_abs.py b/app/scodoc/sco_abs.py index d33aac07..24c61d4a 100644 --- a/app/scodoc/sco_abs.py +++ b/app/scodoc/sco_abs.py @@ -39,12 +39,14 @@ import cgi from scodoc_manager import sco_mgr from app.scodoc import notesdb as ndb +from app.scodoc.notes_log import log from app.scodoc.scolog import logdb from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidDateError from app.scodoc import sco_abs_notification -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_formsemestre +from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_preferences # --- Misc tools.... ------------------ @@ -300,9 +302,7 @@ def YearTable( return "\n".join(T) -def list_abs_in_range( - context, etudid, debut, fin, matin=None, moduleimpl_id=None, cursor=None -): +def list_abs_in_range(etudid, debut, fin, matin=None, moduleimpl_id=None, cursor=None): """Liste des absences entre deux dates. Args: @@ -347,7 +347,7 @@ WHERE A.ETUDID = %(etudid)s return res -def CountAbs(context, etudid, debut, fin, matin=None, moduleimpl_id=None): +def count_abs(etudid, debut, fin, matin=None, moduleimpl_id=None): """CountAbs matin= 1 ou 0. @@ -355,13 +355,11 @@ def CountAbs(context, etudid, debut, fin, matin=None, moduleimpl_id=None): An integer. """ return len( - list_abs_in_range( - context, etudid, debut, fin, matin=matin, moduleimpl_id=moduleimpl_id - ) + list_abs_in_range(etudid, debut, fin, matin=matin, moduleimpl_id=moduleimpl_id) ) -def CountAbsJust(context, etudid, debut, fin, matin=None, moduleimpl_id=None): +def count_abs_just(etudid, debut, fin, matin=None, moduleimpl_id=None): "Count just. abs" if matin != None: matin = _toboolean(matin) @@ -379,7 +377,7 @@ def CountAbsJust(context, etudid, debut, fin, matin=None, moduleimpl_id=None): SELECT DISTINCT A.JOUR, A.MATIN FROM ABSENCES A, ABSENCES B WHERE A.ETUDID = %(etudid)s - AND A.ETUDID = B.ETUDID + AND A.ETUDID = B.ETUDID AND A.JOUR = B.JOUR AND A.MATIN = B.MATIN AND A.JOUR BETWEEN %(debut)s AND %(fin)s AND A.ESTABS AND (A.ESTJUST OR B.ESTJUST)""" @@ -394,7 +392,7 @@ WHERE A.ETUDID = %(etudid)s return res -def ListeAbsDate(context, etudid, beg_date, end_date): +def list_abs_date(etudid, beg_date, end_date): """Liste des absences et justifs entre deux dates (inclues).""" cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) @@ -436,7 +434,7 @@ def ListeAbsDate(context, etudid, beg_date, end_date): return R -def GetAbsDescription(context, a, cursor=None): +def _get_abs_description(a, cursor=None): "Description associee a l'absence" from app.scodoc import sco_moduleimpl @@ -462,7 +460,7 @@ def GetAbsDescription(context, a, cursor=None): if a["moduleimpl_id"] and a["moduleimpl_id"] != "NULL": # Trouver le nom du module Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( - context, moduleimpl_id=a["moduleimpl_id"] + None, moduleimpl_id=a["moduleimpl_id"] ) if Mlist: M = Mlist[0] @@ -475,7 +473,7 @@ def GetAbsDescription(context, a, cursor=None): return "" -def ListeAbsJour(context, date, am=True, pm=True, is_abs=True, is_just=None): +def list_abs_jour(date, am=True, pm=True, is_abs=True, is_just=None): """Liste des absences et/ou justificatifs ce jour. is_abs: None (peu importe), True, False is_just: idem @@ -497,11 +495,11 @@ WHERE A.jour = %(date)s cursor.execute(req, {"date": date, "is_just": is_just, "is_abs": is_abs}) A = cursor.dictfetchall() for a in A: - a["description"] = GetAbsDescription(context, a, cursor=cursor) + a["description"] = _get_abs_description(a, cursor=cursor) return A -def ListeAbsNonJustJour(context, date, am=True, pm=True): +def list_abs_non_just_jour(date, am=True, pm=True): "Liste des absences non justifiees ce jour" cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) @@ -524,11 +522,11 @@ WHERE B.estjust AND B.jour = %(date)s""" cursor.execute(req, {"date": date}) A = cursor.dictfetchall() for a in A: - a["description"] = GetAbsDescription(context, a, cursor=cursor) + a["description"] = _get_abs_description(a, cursor=cursor) return A -def ListeAbsNonJust(context, etudid, datedebut): +def list_abs_non_just(etudid, datedebut): "Liste des absences NON justifiees (par ordre chronologique)" cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) @@ -546,11 +544,11 @@ ORDER BY JOUR ) A = cursor.dictfetchall() for a in A: - a["description"] = GetAbsDescription(context, a, cursor=cursor) + a["description"] = _get_abs_description(a, cursor=cursor) return A -def ListeAbsJust(context, etudid, datedebut): +def list_abs_just(etudid, datedebut): "Liste des absences justifiees (par ordre chronologique)" cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) @@ -566,11 +564,11 @@ ORDER BY A.JOUR ) A = cursor.dictfetchall() for a in A: - a["description"] = GetAbsDescription(context, a, cursor=cursor) + a["description"] = _get_abs_description(a, cursor=cursor) return A -def ListeJustifs(context, etudid, datedebut, datefin=None, only_no_abs=False): +def list_abs_justifs(etudid, datedebut, datefin=None, only_no_abs=False): """Liste des justificatifs (sans absence relevée) à partir d'une date, ou, si datefin spécifié, entre deux dates. Si only_no_abs: seulement les justificatifs correspondant aux jours sans absences relevées. @@ -592,7 +590,7 @@ AND B.ETUDID = %(etudid)s cursor.execute(req, vars()) A = cursor.dictfetchall() for a in A: - a["description"] = GetAbsDescription(context, a, cursor=cursor) + a["description"] = _get_abs_description(a, cursor=cursor) return A @@ -627,7 +625,7 @@ def add_absence( % vars(), ) cnx.commit() - invalidateAbsEtudDate(context, etudid, jour) + invalidate_abs_etud_date(etudid, jour) sco_abs_notification.abs_notify(context, etudid, jour) @@ -651,7 +649,7 @@ def add_justif(context, etudid, jour, matin, REQUEST, description=None): msg="JOUR=%(jour)s,MATIN=%(matin)s" % vars(), ) cnx.commit() - invalidateAbsEtudDate(context, etudid, jour) + invalidate_abs_etud_date(etudid, jour) def _add_abslist(context, abslist, REQUEST, moduleimpl_id=None): @@ -664,7 +662,7 @@ def _add_abslist(context, abslist, REQUEST, moduleimpl_id=None): else: raise ValueError("invalid ampm !") # ajoute abs si pas deja absent - if CountAbs(context, etudid, jour, jour, matin, moduleimpl_id) == 0: + if count_abs(etudid, jour, jour, matin, moduleimpl_id) == 0: add_absence(context, etudid, jour, matin, 0, REQUEST, "", moduleimpl_id) @@ -688,7 +686,7 @@ def annule_absence(context, etudid, jour, matin, moduleimpl_id=None, REQUEST=Non msg="JOUR=%(jour)s,MATIN=%(matin)s,moduleimpl_id=%(moduleimpl_id)s" % vars(), ) cnx.commit() - invalidateAbsEtudDate(context, etudid, jour) + invalidate_abs_etud_date(etudid, jour) def annule_justif(context, etudid, jour, matin, REQUEST=None): @@ -713,7 +711,7 @@ def annule_justif(context, etudid, jour, matin, REQUEST=None): msg="JOUR=%(jour)s,MATIN=%(matin)s" % vars(), ) cnx.commit() - invalidateAbsEtudDate(context, etudid, jour) + invalidate_abs_etud_date(etudid, jour) # ---- BILLETS @@ -976,88 +974,66 @@ def MonthTableBody( # # Cache absences # -# On cache simplement (à la demande) le nombre d'absences de chaque etudiant -# dans un semestre donné. -# Toute modification du semestre (invalidation) invalide le cache -# (simple mécanisme de "listener" sur le cache de semestres) -# Toute modification des absences d'un étudiant invalide les caches des semestres -# concernés à cette date (en général un seul semestre) +# On cache (via memcached ou autre, voir sco_cache.py) les _nombres_ d'absences +# (justifiées et non justifiées) de chaque etudiant dans un semestre donné. +# Le cache peut être invalidé soit par étudiant/semestre, soit pour tous +# les étudiant d'un semestre. # # On ne cache pas la liste des absences car elle est rarement utilisée (calendrier, # absences à une date donnée). # # -------------------------------------------------------------------- -class CAbsSemEtud(object): - """Comptes d'absences d'un etudiant dans un semestre""" - def __init__(self, context, sem, etudid): - self.context = context - self.sem = sem - self.etudid = etudid - self._loaded = False - formsemestre_id = sem["formsemestre_id"] - sco_core.get_notes_cache(context).add_listener( - self.invalidate, formsemestre_id, (etudid, formsemestre_id) + +def get_abs_count(etudid, sem): + """Les comptes d'absences de cet étudiant dans ce semestre: + tuple (nb abs non justifiées, nb abs justifiées) + Utilise un cache. + """ + date_debut = sem["date_debut_iso"] + date_fin = sem["date_fin_iso"] + key = etudid + "_" + date_debut + "_" + date_fin + r = sco_cache.AbsSemEtudCache.get(key) + if not r: + nb_abs = count_abs( # was CountAbs XXX + etudid=etudid, + debut=date_debut, + fin=date_fin, ) - - def CountAbs(self): - if not self._loaded: - self.load() - return self._CountAbs - - def CountAbsJust(self): - if not self._loaded: - self.load() - return self._CountAbsJust - - def load(self): - "Load state from DB" - # log('loading CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id'])) - # Reload sem, it may have changed - self.sem = sco_formsemestre.get_formsemestre( - self.context, self.sem["formsemestre_id"] + nb_abs_just = count_abs_just( # XXX was CountAbsJust + etudid=etudid, + debut=date_debut, + fin=date_fin, ) - debut_sem = ndb.DateDMYtoISO(self.sem["date_debut"]) - fin_sem = ndb.DateDMYtoISO(self.sem["date_fin"]) + r = (nb_abs, nb_abs_just) + ans = sco_cache.AbsSemEtudCache.set(key, r) + if not ans: + log("warning: get_abs_count failed to cache") + return r - self._CountAbs = CountAbs( - self.context, etudid=self.etudid, debut=debut_sem, fin=fin_sem + +def invalidate_abs_count(etudid, sem): + """Invalidate (clear) cached counts""" + date_debut = sem["date_debut_iso"] + date_fin = sem["date_fin_iso"] + key = etudid + "_" + date_debut + "_" + date_fin + sco_cache.AbsSemEtudCache.delete(key) + + +def invalidate_abs_count_sem(sem): + """Invalidate (clear) cached abs counts for all the students of this semestre""" + inscriptions = ( + sco_formsemestre_inscriptions.do_formsemestre_inscription_listinscrits( + None, sem["formsemestre_id"] ) - self._CountAbsJust = CountAbsJust( - self.context, etudid=self.etudid, debut=debut_sem, fin=fin_sem - ) - self._loaded = True - - def invalidate(self, args=None): - "Notify me that DB has been modified" - # log('invalidate CAbsEtudSem(%s,%s)' % (self.etudid, self.sem['formsemestre_id'])) - self._loaded = False + ) + for ins in inscriptions: + invalidate_abs_count(ins["etudid"], sem) -# Accès au cache des absences -ABS_CACHE_INST = {} # { DeptId : { formsemestre_id : { etudid : CAbsEtudSem } } } - - -def getAbsSemEtud(context, sem, etudid): - AbsSemEtuds = getAbsSemEtuds(context, sem) - if not etudid in AbsSemEtuds: - AbsSemEtuds[etudid] = CAbsSemEtud(context, sem, etudid) - return AbsSemEtuds[etudid] - - -def getAbsSemEtuds(context, sem): - u = sco_mgr.get_db_uri() # identifie le dept de facon fiable - if not u in ABS_CACHE_INST: - ABS_CACHE_INST[u] = {} - C = ABS_CACHE_INST[u] - if sem["formsemestre_id"] not in C: - C[sem["formsemestre_id"]] = {} - return C[sem["formsemestre_id"]] - - -def invalidateAbsEtudDate(context, etudid, date): +def invalidate_abs_etud_date(etudid, date): # was invalidateAbsEtudDate """Doit etre appelé à chaque modification des absences pour cet étudiant et cette date. - Invalide cache absence et PDF bulletins si nécessaire. + Invalide cache absence et caches semestre date: date au format ISO """ from app.scodoc import sco_compute_moy @@ -1070,23 +1046,21 @@ def invalidateAbsEtudDate(context, etudid, date): if sem["date_debut_iso"] <= date and sem["date_fin_iso"] >= date ] - # Invalide les PDF et les abscences: + # Invalide les PDF et les absences: for sem in sems: # Inval cache bulletin et/ou note_table if sco_compute_moy.formsemestre_expressions_use_abscounts( - context, sem["formsemestre_id"] + None, sem["formsemestre_id"] ): - pdfonly = False # seules certaines formules utilisent les absences + # certaines formules utilisent les absences + pdfonly = False else: - pdfonly = ( - True # efface toujours le PDF car il affiche en général les absences - ) + # efface toujours le PDF car il affiche en général les absences + pdfonly = True - sco_core.inval_cache( - context, pdfonly=pdfonly, formsemestre_id=sem["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=sem["formsemestre_id"], pdfonly=pdfonly ) # Inval cache compteurs absences: - AbsSemEtuds = getAbsSemEtuds(context, sem) - if etudid in AbsSemEtuds: - AbsSemEtuds[etudid].invalidate() + invalidate_abs_count_sem(sem) diff --git a/app/scodoc/sco_abs_notification.py b/app/scodoc/sco_abs_notification.py index b70a7980..bbb7bd70 100644 --- a/app/scodoc/sco_abs_notification.py +++ b/app/scodoc/sco_abs_notification.py @@ -62,11 +62,7 @@ def abs_notify(context, etudid, date): if not sem: return # non inscrit a la date, pas de notification - debut_sem = ndb.DateDMYtoISO(sem["date_debut"]) - fin_sem = ndb.DateDMYtoISO(sem["date_fin"]) - nbabs = sco_abs.CountAbs(context, etudid, debut=debut_sem, fin=fin_sem) - nbabsjust = sco_abs.CountAbsJust(context, etudid, debut=debut_sem, fin=fin_sem) - + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) do_abs_notify(context, sem, etudid, date, nbabs, nbabsjust) diff --git a/app/scodoc/sco_abs_views.py b/app/scodoc/sco_abs_views.py index 749886ad..09ea59ea 100644 --- a/app/scodoc/sco_abs_views.py +++ b/app/scodoc/sco_abs_views.py @@ -38,7 +38,7 @@ from app.scodoc.scolog import logdb from app.scodoc.gen_tables import GenTable from app.scodoc import html_sco_header from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_find_etud from app.scodoc import sco_formsemestre @@ -123,7 +123,7 @@ def doSignaleAbsence( if moduleimpl_id and moduleimpl_id != "NULL": mod = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] formsemestre_id = mod["formsemestre_id"] - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) ues = nt.get_ues(etudid=etudid) for ue in ues: modimpls = nt.get_modimpls(ue_id=ue["ue_id"]) @@ -182,7 +182,7 @@ def SignaleAbsenceEtud(context, REQUEST=None): # etudid implied require_module = sco_preferences.get_preference( context, "abs_require_module", formsemestre_id ) - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) ues = nt.get_ues(etudid=etudid) if require_module: menu_module = """ @@ -650,7 +650,7 @@ def AnnuleAbsencesDatesNoJust(context, etudid, dates, moduleimpl_id=None, REQUES "delete from absences where etudid=%(etudid)s and (not estjust) and jour=%(date)s and moduleimpl_id=%(moduleimpl_id)s", vars(), ) - sco_abs.invalidateAbsEtudDate(context, etudid, date) + sco_abs.invalidate_abs_etud_date(etudid, date) # s'assure que les justificatifs ne sont pas "absents" for date in dates: cursor.execute( @@ -737,21 +737,19 @@ def CalAbs(context, REQUEST=None): # etud implied anneescolaire = int(scu.AnneeScolaire(REQUEST)) datedebut = str(anneescolaire) + "-08-31" datefin = str(anneescolaire + 1) + "-07-31" - nbabs = sco_abs.CountAbs(context, etudid=etudid, debut=datedebut, fin=datefin) - nbabsjust = sco_abs.CountAbsJust( - context, etudid=etudid, debut=datedebut, fin=datefin - ) + nbabs = sco_abs.count_abs(etudid=etudid, debut=datedebut, fin=datefin) + nbabsjust = sco_abs.count_abs_just(etudid=etudid, debut=datedebut, fin=datefin) events = [] - for a in sco_abs.ListeAbsJust(context, etudid=etudid, datedebut=datedebut): + for a in sco_abs.list_abs_just(etudid=etudid, datedebut=datedebut): events.append( (str(a["jour"]), "a", "#F8B7B0", "", a["matin"], a["description"]) ) - for a in sco_abs.ListeAbsNonJust(context, etudid=etudid, datedebut=datedebut): + for a in sco_abs.list_abs_non_just(etudid=etudid, datedebut=datedebut): events.append( (str(a["jour"]), "A", "#EE0000", "", a["matin"], a["description"]) ) - justifs_noabs = sco_abs.ListeJustifs( - context, etudid=etudid, datedebut=datedebut, only_no_abs=True + justifs_noabs = sco_abs.list_abs_justifs( + etudid=etudid, datedebut=datedebut, only_no_abs=True ) for a in justifs_noabs: events.append( @@ -926,8 +924,8 @@ def _TablesAbsEtud( REQUEST=None, ): """Tables des absences justifiees et non justifiees d'un étudiant sur l'année en cours""" - absjust = sco_abs.ListeAbsJust(context, etudid=etudid, datedebut=datedebut) - absnonjust = sco_abs.ListeAbsNonJust(context, etudid=etudid, datedebut=datedebut) + absjust = sco_abs.list_abs_just(etudid=etudid, datedebut=datedebut) + absnonjust = sco_abs.list_abs_non_just(etudid=etudid, datedebut=datedebut) # examens ces jours là ? if with_evals: cnx = ndb.GetDBConnexion() diff --git a/app/scodoc/sco_apogee_csv.py b/app/scodoc/sco_apogee_csv.py index b521a6b4..7c1277e8 100644 --- a/app/scodoc/sco_apogee_csv.py +++ b/app/scodoc/sco_apogee_csv.py @@ -95,10 +95,7 @@ import pprint from functools import reduce # Pour la détection auto de l'encodage des fichiers Apogée: -try: - from chardet import detect as chardet_detect -except: - chardet_detect = None +from chardet import detect as chardet_detect import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb @@ -120,8 +117,8 @@ from app.scodoc.sco_codes_parcours import ( NAR, RAT, ) +from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_status from app.scodoc import sco_parcours_dut @@ -168,11 +165,8 @@ def _apo_fmt_note(note): def guess_data_encoding(text, threshold=0.6): """Guess string encoding, using chardet heuristics. - Returns encoding, or None if detection failed (confidence below threshold, - or chardet not installed) + Returns encoding, or None if detection failed (confidence below threshold) """ - if not chardet_detect: - return None # package not installed r = chardet_detect(text) if r["confidence"] < threshold: return None @@ -405,9 +399,7 @@ class ApoEtud(dict): dict: with N, B, J, R keys, ou None si elt non trouvé """ etudid = self.etud["etudid"] - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) if etudid not in nt.identdict: return None # etudiant non inscrit dans ce semestre @@ -515,9 +507,7 @@ class ApoEtud(dict): # l'étudiant n'a pas de semestre courant ?! log("comp_elt_annuel: %s no cur_sem" % etudid) return VOID_APO_RES - cur_nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, cur_sem["formsemestre_id"]) + cur_nt = sco_cache.NotesTableCache.get(cur_sem["formsemestre_id"]) cur_decision = cur_nt.get_etud_decision_sem(etudid) if not cur_decision: # pas de decision => pas de résultat annuel @@ -534,9 +524,7 @@ class ApoEtud(dict): decision_apo = code_scodoc_to_apo(cur_decision["code"]) - autre_nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, autre_sem["formsemestre_id"]) + autre_nt = sco_cache.NotesTableCache.get(autre_sem["formsemestre_id"]) autre_decision = autre_nt.get_etud_decision_sem(etudid) if not autre_decision: # pas de decision dans l'autre => pas de résultat annuel @@ -599,9 +587,7 @@ class ApoEtud(dict): # prend le plus recent avec decision cur_sem = None for sem in cur_sems: - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) decision = nt.get_etud_decision_sem(self.etud["etudid"]) if decision: cur_sem = sem @@ -661,9 +647,7 @@ class ApoEtud(dict): else: autre_sem = None for sem in autres_sems: - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) decision = nt.get_etud_decision_sem(self.etud["etudid"]) if decision: autre_sem = sem @@ -998,9 +982,7 @@ class ApoData(object): s.add(code) continue # associé à une UE: - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] - ) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) for ue in nt.get_ues(): if code in ue["code_apogee"].split(","): s.add(code) diff --git a/app/scodoc/sco_archives.py b/app/scodoc/sco_archives.py index 54afc829..0fad17f9 100644 --- a/app/scodoc/sco_archives.py +++ b/app/scodoc/sco_archives.py @@ -436,7 +436,7 @@ enregistrés et non modifiables, on peut les retrouver ultérieurement. "Version intermédiaire", "Version complète", ], - "allowed_values": ["short", "selectedevals", "long"], + "allowed_values": scu.BULLETINS_VERSIONS, "default": "long", }, ), diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index d8c42320..26bb2f97 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -54,7 +54,7 @@ from app.scodoc import sco_bulletins_generator from app.scodoc import sco_bulletins_json from app.scodoc import sco_bulletins_xml from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_evaluations from app.scodoc import sco_formations @@ -130,13 +130,11 @@ def formsemestre_bulletinetud_dict( """ from app.scodoc import sco_abs - if not version in ("short", "long", "selectedevals"): + if not version in scu.BULLETINS_VERSIONS: raise ValueError("invalid version code !") prefs = sco_preferences.SemPreferences(context, formsemestre_id) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > toutes notes + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes I = scu.DictDefault(defaultvalue="") I["etudid"] = etudid @@ -177,9 +175,7 @@ def formsemestre_bulletinetud_dict( context, pid ) # --- Absences - AbsSemEtud = sco_abs.getAbsSemEtud(context, nt.sem, etudid) - I["nbabs"] = AbsSemEtud.CountAbs() - I["nbabsjust"] = AbsSemEtud.CountAbsJust() + I["nbabs"], I["nbabsjust"] = sco_abs.get_abs_count(etudid, nt.sem) # --- Decision Jury infos, dpv = etud_descr_situation_semestre( @@ -354,8 +350,8 @@ def formsemestre_bulletinetud_dict( # log('cap details %s' % ue_status['moy']) if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]: # detail des modules de l'UE capitalisee - nt_cap = sco_core.get_notes_cache(context).get_NotesTable( - context, ue_status["formsemestre_id"] + nt_cap = sco_cache.NotesTableCache.get( + ue_status["formsemestre_id"] ) # > toutes notes u["modules_capitalized"], _ = _ue_mod_bulletin( @@ -442,22 +438,8 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers ) # peut etre 'NI' is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS if bul_show_abs_modules: - mod_abs = [ - sco_abs.CountAbs( - context, - etudid=etudid, - debut=debut_sem, - fin=fin_sem, - moduleimpl_id=modimpl["moduleimpl_id"], - ), - sco_abs.CountAbsJust( - context, - etudid=etudid, - debut=debut_sem, - fin=fin_sem, - moduleimpl_id=modimpl["moduleimpl_id"], - ), - ] + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) + mod_abs = [nbabs, nbabsjust] mod["mod_abs_txt"] = scu.fmt_abs(mod_abs) else: mod["mod_abs_txt"] = "" diff --git a/app/scodoc/sco_bulletins_generator.py b/app/scodoc/sco_bulletins_generator.py index 3dafa3e4..561a5e37 100644 --- a/app/scodoc/sco_bulletins_generator.py +++ b/app/scodoc/sco_bulletins_generator.py @@ -52,7 +52,7 @@ import reportlab from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak from reportlab.platypus import Table, TableStyle, Image, KeepInFrame -from app.scodoc import sco_utils +from app.scodoc import sco_utils as scu from app.scodoc import VERSION from app.scodoc.sco_exceptions import NoteProcessError from app.scodoc.notes_log import log @@ -117,7 +117,7 @@ class BulletinGenerator(object): ): from app.scodoc import sco_preferences - if not version in ("short", "long", "selectedevals"): + if not version in scu.BULLETINS_VERSIONS: raise ValueError("invalid version code !") self.context = context self.infos = infos @@ -161,7 +161,7 @@ class BulletinGenerator(object): dt, self.infos["etud"]["nom"], ) - filename = sco_utils.unescape_html(filename).replace(" ", "_").replace("&", "") + filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "") return filename def generate(self, format="", stand_alone=True): @@ -281,7 +281,7 @@ def make_formsemestre_bulletinetud( """ from app.scodoc import sco_preferences - if not version in ("short", "long", "selectedevals"): + if not version in scu.BULLETINS_VERSIONS: raise ValueError("invalid version code !") formsemestre_id = infos["formsemestre_id"] diff --git a/app/scodoc/sco_bulletins_json.py b/app/scodoc/sco_bulletins_json.py index cdfed9c7..2c103f09 100644 --- a/app/scodoc/sco_bulletins_json.py +++ b/app/scodoc/sco_bulletins_json.py @@ -34,7 +34,7 @@ import json import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_evaluations from app.scodoc import sco_formsemestre @@ -151,9 +151,7 @@ def formsemestre_bulletinetud_published_dict( context, pid ) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > toutes notes + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes ues = nt.get_ues() modimpls = nt.get_modimpls() nbetuds = len(nt.rangs) @@ -341,10 +339,7 @@ def formsemestre_bulletinetud_published_dict( # --- Absences if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id): - AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) - nbabs = AbsEtudSem.CountAbs() - nbabsjust = AbsEtudSem.CountAbsJust() - + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) d["absences"] = dict(nbabs=nbabs, nbabsjust=nbabsjust) # --- Decision Jury diff --git a/app/scodoc/sco_bulletins_pdf.py b/app/scodoc/sco_bulletins_pdf.py index f848f90b..5e23a842 100644 --- a/app/scodoc/sco_bulletins_pdf.py +++ b/app/scodoc/sco_bulletins_pdf.py @@ -64,7 +64,7 @@ from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate from app.scodoc import VERSION import app.scodoc.sco_utils as scu from app.scodoc.notes_log import log -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formsemestre from app.scodoc import sco_pdf from app.scodoc import sco_preferences @@ -170,17 +170,13 @@ def get_formsemestre_bulletins_pdf( "document pdf et filename" from app.scodoc import sco_bulletins - cached = sco_core.get_notes_cache( - context, - ).get_bulletins_pdf(formsemestre_id, version) + cached = sco_cache.SemBulletinsPDFCache.get(formsemestre_id + "_" + version) if cached: return cached[1], cached[0] fragments = [] sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # Make each bulletin - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etudids, get_sexnom + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etudids, get_sexnom bookmarks = {} filigrannes = {} i = 1 @@ -224,9 +220,9 @@ def get_formsemestre_bulletins_pdf( filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt) filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "") # fill cache - sco_core.get_notes_cache( - context, - ).store_bulletins_pdf(formsemestre_id, version, filename, pdfdoc) + sco_cache.SemBulletinsPDFCache.set( + formsemestre_id + "_" + version, (filename, pdfdoc) + ) return pdfdoc, filename diff --git a/app/scodoc/sco_bulletins_xml.py b/app/scodoc/sco_bulletins_xml.py index 42b87111..6bcd55e8 100644 --- a/app/scodoc/sco_bulletins_xml.py +++ b/app/scodoc/sco_bulletins_xml.py @@ -49,7 +49,7 @@ import app.scodoc.notesdb as ndb from app.scodoc.notes_log import log from app.scodoc import sco_abs from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_evaluations from app.scodoc import sco_formsemestre @@ -144,9 +144,7 @@ def make_xml_formsemestre_bulletinetud( context, pid ) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > toutes notes + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > toutes notes ues = nt.get_ues() modimpls = nt.get_modimpls() nbetuds = len(nt.rangs) @@ -352,9 +350,7 @@ def make_xml_formsemestre_bulletinetud( # --- Absences if sco_preferences.get_preference(context, "bul_show_abs", formsemestre_id): - abs_sem_etud = sco_abs.getAbsSemEtud(context, sem, etudid) - nbabs = abs_sem_etud.CountAbs() - nbabsjust = abs_sem_etud.CountAbsJust() + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) doc.append(Element("absences", nbabs=nbabs, nbabsjust=nbabsjust)) # --- Decision Jury if ( diff --git a/app/scodoc/sco_cache.py b/app/scodoc/sco_cache.py index 44ed3c40..1137e68d 100644 --- a/app/scodoc/sco_cache.py +++ b/app/scodoc/sco_cache.py @@ -34,11 +34,11 @@ # API ScoDoc8 pour les caches: -# sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) +# sco_cache.NotesTableCache.get( formsemestre_id) # => sco_cache.NotesTableCache.get(formsemestre_id) # # sco_core.inval_cache(context, formsemestre_id=None, pdfonly=False, formsemestre_id_list=None) -# => deprecated, sco_cache.inval_cache(formsemestre_id=None, pdfonly=False, formsemestre_id_list=None) +# => deprecated, NotesTableCache.invalidate_formsemestre(formsemestre_id=None, pdfonly=False) # # # Nouvelles fonctions: @@ -54,14 +54,15 @@ # sco_cache.EvaluationCache.get(evaluation_id), set(evaluation_id, value), delete(evaluation_id), # -from collections import defaultdict +import time from flask import g -from flask_caching import Cache +from app.scodoc import notesdb as ndb +from app.scodoc import sco_utils as scu from app.scodoc.notes_log import log -CACHE = Cache(config={"CACHE_TYPE": "MemcachedCache"}) # XXX TODO: configuration file +CACHE = None # set in app.__init__.py class ScoDocCache: @@ -69,6 +70,7 @@ class ScoDocCache: keys are prefixed by the current departement. """ + timeout = None # ttl, infinite by default prefix = "" @classmethod @@ -83,7 +85,7 @@ class ScoDocCache: @classmethod def set(cls, oid, value): """Store evaluation""" - return CACHE.set(cls._get_key(oid), value) + return CACHE.set(cls._get_key(oid), value, timeout=cls.timeout) @classmethod def delete(cls, oid): @@ -93,86 +95,143 @@ class ScoDocCache: @classmethod def delete_many(cls, oids): """Remove multiple keys at once""" - CACHE.delete_many(oids) + CACHE.delete_many([cls._get_key(oid) for oid in oids]) class EvaluationCache(ScoDocCache): "Cache for evaluations" prefix = "EVAL" - -class NotesTableCache(ScoDocCache): - prefix = "NT" - listeners = defaultdict(list) # oid : list of callback functions - @classmethod - def add_listener(cls, func, oid): - """Add a function which will be called each time and object is modified: - the function will be called as func(oid) + def invalidate_sem(cls, formsemestre_id): + "delete evaluations in this formsemestre from cache" + req = """SELECT e.evaluation_id + FROM notes_formsemestre s, notes_evaluation e, notes_moduleimpl m + WHERE s.formsemestre_id = %(formsemestre_id)s and s.formsemestre_id=m.formsemestre_id and e.moduleimpl_id=m.moduleimpl_id; """ - cls.listeners[oid].append(func) + evaluation_ids = [ + x[0] + for x in ndb.SimpleQuery(None, req, {"formsemestre_id": formsemestre_id}) + ] + cls.delete_many(evaluation_ids) @classmethod - def delete(cls, oid): - for listener in cls.listeners[oid]: - listener(oid) - super().delete(oid) - - @classmethod - def delete_many(cls, oids): - for oid in oids: - for listener in cls.listeners[oid]: - listener(oid) - super().delete_many(oids) + def invalidate_all_sems(cls): + "delete all evaluations from cache" + evaluation_ids = [ + x[0] + for x in ndb.SimpleQuery( + None, "SELECT evaluation_id FROM notes_evaluation", "" + ) + ] + cls.delete_many(evaluation_ids) -# XXX OBSOLETE A ENLEVER XXX -class simpleCache: - """A simple cache wich cache data for a most "duration" seconds.""" - - def __init__(self): - self.cache = {} - self.inval_cache() # > - - def inval_cache(self, key=None): # > - if key: - if key in self.cache: - del self.cache[key] - else: - # clear all entries - self.cache = {} # key : data - - def set(self, key, data): - self.cache[key] = data - - def get(self, key): - """returns None if not in cache""" - return self.cache.get(key, None) - - -class expiringCache(simpleCache): - """A simple cache wich cache data for a most "duration" seconds. - - This is used for users (which may be updated from external - information systems) +class AbsSemEtudCache(ScoDocCache): + """Cache pour les comptes d'absences d'un étudiant dans un semestre. + Ce cache étant indépendant des semestre, le compte peut être faux lorsqu'on + change les dates début/fin d'un semestre. + C'est pourquoi il expire après timeout secondes. + Le timeout evite aussi d'éliminer explicitement ces éléments cachés lors + des suppressions d'étudiants ou de semestres. """ - def __init__(self, max_validity=60): - simpleCache.__init__(self) - self.max_validity = max_validity + timeout = 60 * 60 # ttl 60 minutes - def set(self, key, data): - simpleCache.set(self, key, (data, time.time())) - def get(self, key): - info = simpleCache.get(self, key) - if info: - data, t = info - if time.time() - t < self.max_validity: - return data - else: - # expired - self.inval_cache(key) # > - return None +class SemBulletinsPDFCache(ScoDocCache): + """Cache pour les classeurs de bulletins PDF d'un semestre. + Document pdf assez volumineux. La clé inclut le type de bulletin (version). + Clé: formsemestre_id_version + Valeur: (filename, pdfdoc) + """ + + prefix = "SBPDF" + timeout = 12 * 60 * 60 # ttl 12h + + @classmethod + def invalidate_sems(cls, formsemestre_ids): + """Clear cached pdf for all given formsemestres""" + for version in scu.BULLETINS_VERSIONS: + oids = [ + formsemestre_id + "_" + version for formsemestre_id in formsemestre_ids + ] + cls.delete_many(oids) + + +class SemInscriptionsCache(ScoDocCache): + """Cache les inscriptions à un semestre. + Clé: formsemestre_id + Valeur: liste d'inscriptions + [ {'formsemestre_inscription_id': 'SI78677', 'etudid': '1234', 'formsemestre_id': 'SEM012', 'etat': 'I', 'etape': ''}, ... ] + """ + + prefix = "SI" + duration = 12 * 60 * 60 # ttl 12h + + +class NotesTableCache(ScoDocCache): + """Cache pour les NotesTable + Clé: formsemestre_id + Valeur: NotesTable instance + """ + + prefix = "NT" + + @classmethod + def get(cls, formsemestre_id): + """Returns NotesTable for this formsemestre + If not in cache, build it and cache it. + """ + key = cls._get_key(formsemestre_id) + nt = CACHE.get(key) + if nt: + return nt + from app.scodoc import notes_table + + t0 = time.time() + nt = notes_table.NotesTable(None, formsemestre_id) + dt = time.time() - t0 + log("caching formsemestre_id=%s (%gs)" % (formsemestre_id, dt)) + s = cls.set(formsemestre_id, nt) + if not s: + log("Warning: cache.set failed") + return nt + + +def invalidate_formsemestre( # was inval_cache( context, formsemestre_id=None, pdfonly=False) + formsemestre_id=None, pdfonly=False +): + """expire cache pour un semestre (ou tous si formsemestre_id non spécifié). + Si pdfonly, n'expire que les bulletins pdf cachés. + """ + from app.scodoc import sco_parcours_dut + + log("inval_cache, formsemestre_id=%s pdfonly=%s" % (formsemestre_id, pdfonly)) + if formsemestre_id is None: + # clear all caches + log("----- invalidate_formsemestre: clearing all caches -----") + formsemestre_ids = [ + x[0] + for x in ndb.SimpleQuery( + None, "SELECT formsemestre_id FROM notes_formsemestre", "" + ) + ] + else: + formsemestre_ids = [ + formsemestre_id + ] + sco_parcours_dut.list_formsemestre_utilisateurs_uecap(None, formsemestre_id) + log(f"----- invalidate_formsemestre: clearing {formsemestre_ids} -----") + + if not pdfonly: + # Delete cached notes and evaluations + NotesTableCache.delete_many(formsemestre_ids) + if formsemestre_id: + for formsemestre_id in formsemestre_ids: + EvaluationCache.invalidate_sem(formsemestre_id) else: - return None # not in cache + # optimization when we invalidate all evaluations: + EvaluationCache.invalidate_all_sems() + SemInscriptionsCache.delete_many(formsemestre_ids) + + SemBulletinsPDFCache.invalidate_sems(formsemestre_ids) diff --git a/app/scodoc/sco_compute_moy.py b/app/scodoc/sco_compute_moy.py index 2b11c963..c1e5fb09 100644 --- a/app/scodoc/sco_compute_moy.py +++ b/app/scodoc/sco_compute_moy.py @@ -138,9 +138,7 @@ def compute_user_formula( Retourne moy, et en cas d'erreur met à jour diag_info (msg) """ if use_abs: - AbsSemEtud = sco_abs.getAbsSemEtud(context, sem, etudid) - nbabs = AbsSemEtud.CountAbs() - nbabs_just = AbsSemEtud.CountAbsJust() + nbabs, nbabs_just = sco_abs.get_abs_count(etudid, sem) else: nbabs, nbabs_just = 0, 0 try: diff --git a/app/scodoc/sco_config.py b/app/scodoc/sco_config.py index c5a76f4e..c16865da 100644 --- a/app/scodoc/sco_config.py +++ b/app/scodoc/sco_config.py @@ -67,7 +67,7 @@ CONFIG.compute_bonus = bonus_sport.bonus_iutv # - règle "LMD": capitalisation uniquement des UE avec moy. > 10 # Si vrai, capitalise toutes les UE des semestres validés (règle "DUT"). -# CONFIG.CAPITALIZE_ALL_UES = True +CONFIG.CAPITALIZE_ALL_UES = True # ----------------------------------------------------- # -------------- Personnalisation des pages diff --git a/app/scodoc/sco_core.py b/app/scodoc/sco_core.py index 13a6c3da..119415d5 100644 --- a/app/scodoc/sco_core.py +++ b/app/scodoc/sco_core.py @@ -27,19 +27,6 @@ from app.scodoc import sco_cache NOTES_CACHE_INST = {} # { db_cnx_string : CacheNotesTable instance } # XXX OBSOLETE... XXX -CACHE_formsemestre_inscription = {} -CACHE_evaluations = {} - -# cache notes evaluations -def get_evaluations_cache(context): - """returns cache for evaluations""" - u = sco_mgr.get_db_uri() - if u in CACHE_evaluations: - return CACHE_evaluations[u] - else: - log("get_evaluations_cache: new simpleCache") - CACHE_evaluations[u] = sco_cache.simpleCache() - return CACHE_evaluations[u] class CacheNotesTable(object): @@ -112,67 +99,11 @@ class CacheNotesTable(object): finally: self.release() - def get_cached_formsemestre_ids(self): # UNUSED - "List of currently cached formsemestre_id" - return list(self.cache.keys()) - def inval_cache(self, context, formsemestre_id=None, pdfonly=False): # > "expire cache pour un semestre (ou tous si pas d'argument)" from app.scodoc import sco_parcours_dut - log( - "inval_cache, formsemestre_id=%s pdfonly=%s (id=%s)" - % (formsemestre_id, pdfonly, id(self)) # > - ) - try: - self.acquire() - if formsemestre_id is None: - # clear all caches - log("----- inval_cache: clearing all caches -----") - # log('cache was containing ' + str(self.cache.keys())) - # logCallStack() # >>> DEBUG <<< - if not pdfonly: - self.cache = {} - self.pdfcache = {} - self._call_all_listeners() - get_evaluations_cache( - context, - ).inval_cache() - else: - # formsemestre_id modifié: - # on doit virer formsemestre_id et tous les semestres - # susceptibles d'utiliser des UE capitalisées de ce semestre. - to_trash = [ - formsemestre_id - ] + sco_parcours_dut.list_formsemestre_utilisateurs_uecap( - context, formsemestre_id - ) - if not pdfonly: - for formsemestre_id in to_trash: - if formsemestre_id in self.cache: - log( - "delete %s from cache (id=%s)" - % (formsemestre_id, id(self)) - ) - del self.cache[formsemestre_id] - self._call_listeners(formsemestre_id) - get_evaluations_cache( - context, - ).inval_cache() - - for formsemestre_id in to_trash: - for ( - cached_formsemestre_id, - cached_version, - ) in self.pdfcache.keys(): - if cached_formsemestre_id == formsemestre_id: - log( - "delete pdfcache[(%s,%s)]" - % (formsemestre_id, cached_version) - ) - del self.pdfcache[(formsemestre_id, cached_version)] - finally: - self.release() + XXX def store_bulletins_pdf(self, formsemestre_id, version, filename, pdfdoc): "cache pdf data" diff --git a/app/scodoc/sco_debouche.py b/app/scodoc/sco_debouche.py index ba91e824..7a1b99a9 100644 --- a/app/scodoc/sco_debouche.py +++ b/app/scodoc/sco_debouche.py @@ -40,7 +40,7 @@ from app.scodoc.scolog import logdb from app.scodoc.gen_tables import GenTable from app.scodoc import safehtml from app.scodoc import html_sco_header -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_permissions_check from app.scodoc import sco_preferences from app.scodoc import sco_tag_module @@ -114,9 +114,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True): es = [(s["date_fin_iso"], i) for i, s in enumerate(sems)] imax = max(es)[1] last_sem = sems[imax] - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, last_sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(last_sem["formsemestre_id"]) row = { "etudid": etudid, "civilite": etud["civilite"], diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py index 078ef425..4dd6c742 100644 --- a/app/scodoc/sco_edit_formation.py +++ b/app/scodoc/sco_edit_formation.py @@ -33,9 +33,10 @@ import app.scodoc.sco_utils as scu from app.scodoc.notes_log import log from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError + from app.scodoc import html_sco_header +from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core from app.scodoc import sco_edit_module from app.scodoc import sco_edit_ue from app.scodoc import sco_formations @@ -302,13 +303,16 @@ def do_formation_edit(context, args): cnx = ndb.GetDBConnexion() sco_formations._formationEditor.edit(cnx, args) + invalidate_sems_in_formation(args["formation_id"]) - # Invalide les semestres utilisant cette formation: + +def invalidate_sems_in_formation(formation_id): + "Invalide les semestres utilisant cette formation" for sem in sco_formsemestre.do_formsemestre_list( - context, args={"formation_id": args["formation_id"]} + None, args={"formation_id": formation_id} ): - sco_core.inval_cache( - context, formsemestre_id=sem["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=sem["formsemestre_id"] ) # > formation modif. diff --git a/app/scodoc/sco_edit_matiere.py b/app/scodoc/sco_edit_matiere.py index d4e2b056..e909dafa 100644 --- a/app/scodoc/sco_edit_matiere.py +++ b/app/scodoc/sco_edit_matiere.py @@ -34,7 +34,6 @@ from app.scodoc.notes_log import log from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError from app.scodoc import html_sco_header -from app.scodoc import sco_core _matiereEditor = ndb.EditableTable( "notes_matieres", @@ -53,6 +52,9 @@ def do_matiere_list(context, *args, **kw): def do_matiere_edit(context, *args, **kw): "edit a matiere" + from app.scodoc import sco_edit_ue + from app.scodoc import sco_edit_formation + cnx = ndb.GetDBConnexion() # check mat = do_matiere_list(context, {"matiere_id": args[0]["matiere_id"]})[0] @@ -60,7 +62,10 @@ def do_matiere_edit(context, *args, **kw): raise ScoLockedFormError() # edit _matiereEditor.edit(cnx, *args, **kw) - sco_core.inval_cache(context) # > modif matiere + formation_id = sco_edit_ue.do_ue_list(None, {"ue_id": mat["ue_id"]})[0][ + "formation_id" + ] + sco_edit_formation.invalidate_sems_in_formation(formation_id) def do_matiere_create(context, args, REQUEST): diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py index fdec4467..5510567c 100644 --- a/app/scodoc/sco_edit_module.py +++ b/app/scodoc/sco_edit_module.py @@ -36,9 +36,7 @@ from app.scodoc.sco_permissions import Permission from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError, ScoGenError from app.scodoc import html_sco_header from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core from app.scodoc import sco_edit_matiere -from app.scodoc import sco_formsemestre from app.scodoc import sco_moduleimpl from app.scodoc import sco_news @@ -319,6 +317,8 @@ def module_delete(context, module_id=None, REQUEST=None): def do_module_edit(context, val): "edit a module" + from app.scodoc import sco_edit_formation + # check mod = do_module_list(context, {"module_id": val["module_id"]})[0] if module_is_locked(context, mod["module_id"]): @@ -330,14 +330,7 @@ def do_module_edit(context, val): # edit cnx = ndb.GetDBConnexion() _moduleEditor.edit(cnx, val) - - sems = sco_formsemestre.do_formsemestre_list( - context, args={"formation_id": mod["formation_id"]} - ) - if sems: - sco_core.inval_cache( - context, formsemestre_id_list=[s["formsemestre_id"] for s in sems] - ) # > modif module + sco_edit_formation.invalidate_sems_in_formation(mod["formation_id"]) def check_module_code_unicity(code, field, formation_id, context, module_id=None): diff --git a/app/scodoc/sco_edit_ue.py b/app/scodoc/sco_edit_ue.py index 8cd5d32b..cd3a2e7f 100644 --- a/app/scodoc/sco_edit_ue.py +++ b/app/scodoc/sco_edit_ue.py @@ -37,10 +37,12 @@ from app.scodoc.sco_permissions import Permission from app.scodoc.sco_exceptions import ScoValueError, ScoLockedFormError from app.scodoc import html_sco_header +from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_edit_formation from app.scodoc import sco_edit_matiere from app.scodoc import sco_edit_module +from app.scodoc import sco_etud from app.scodoc import sco_formsemestre from app.scodoc import sco_groups from app.scodoc import sco_moduleimpl @@ -48,7 +50,6 @@ from app.scodoc import sco_news from app.scodoc import sco_permissions from app.scodoc import sco_preferences from app.scodoc import sco_tag_module -from app.scodoc import sco_etud _ueEditor = ndb.EditableTable( "notes_ue", @@ -164,7 +165,7 @@ def do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=F cnx = ndb.GetDBConnexion() _ueEditor.delete(cnx, ue_id) # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?): - sco_core.inval_cache(context) + sco_cache.invalidate_formsemestre() # news F = sco_formations.formation_list( context, args={"formation_id": ue["formation_id"]} @@ -918,12 +919,7 @@ def do_ue_edit(context, args, bypass_lock=False, dont_invalidate_cache=False): if not dont_invalidate_cache: # Invalide les semestres utilisant cette formation: - for sem in sco_formsemestre.do_formsemestre_list( - context, args={"formation_id": ue["formation_id"]} - ): - sco_core.inval_cache( - context, formsemestre_id=sem["formsemestre_id"] - ) # > formation (ue) modif. + sco_edit_formation.invalidate_sems_in_formation(ue["formation_id"]) # essai edition en ligne: diff --git a/app/scodoc/sco_etape_apogee.py b/app/scodoc/sco_etape_apogee.py index 5ffc5495..9e666aaf 100644 --- a/app/scodoc/sco_etape_apogee.py +++ b/app/scodoc/sco_etape_apogee.py @@ -389,7 +389,7 @@ apo_csv_store(context, csv_data, annee_scolaire, sem_id) groups_infos = sco_groups_view.DisplayedGroupsInfos(context, [sco_groups.get_default_group(context, formsemestre_id)], formsemestre_id=formsemestre_id, REQUEST=REQUEST) -nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) +nt = sco_cache.NotesTableCache.get( formsemestre_id) # s = SemSet(context, 'NSS29902') diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index e97d67d2..4a30f8f1 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -42,7 +42,7 @@ from app.scodoc.gen_tables import GenTable from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc import html_sco_header from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_edit_ue from app.scodoc import sco_formsemestre @@ -345,9 +345,7 @@ def do_evaluation_edit(context, REQUEST, args): _evaluationEditor.edit(cnx, args) # inval cache pour ce semestre M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] - sco_core.inval_cache( - context, formsemestre_id=M["formsemestre_id"] - ) # > evaluation_edit (coef, ...) + sco_cache.invalidate_formsemestre(formsemestre_id=M["formsemestre_id"]) def do_evaluation_delete(context, REQUEST, evaluation_id): @@ -375,7 +373,7 @@ def do_evaluation_delete(context, REQUEST, evaluation_id): _evaluationEditor.delete(cnx, evaluation_id) # inval cache pour ce semestre M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] - sco_core.inval_cache(context, formsemestre_id=M["formsemestre_id"]) # > eval delete + sco_cache.invalidate_formsemestre(formsemestre_id=M["formsemestre_id"]) # news mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] mod["moduleimpl_id"] = M["moduleimpl_id"] @@ -643,8 +641,7 @@ def do_evaluation_get_all_notes( filter_suppressed and table == "notes_notes" and (by_uid is None) ) # pas de cache pour (rares) appels via undo_notes ou specifiant un enseignant if do_cache: - cache = sco_core.get_evaluations_cache(context) - r = cache.get(evaluation_id) + r = sco_cache.EvaluationCache.get(evaluation_id) if r != None: return r cnx = ndb.GetDBConnexion() @@ -667,7 +664,7 @@ def do_evaluation_get_all_notes( for x in res: d[x["etudid"]] = x if do_cache: - cache.set(evaluation_id, d) + sco_cache.EvaluationCache.set(evaluation_id, d) return d @@ -708,8 +705,8 @@ def _eval_etat(evals): 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""" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > liste evaluations et moduleimpl en attente evals = nt.get_sem_evaluation_etat_list() etat = _eval_etat(evals) @@ -731,9 +728,7 @@ def do_evaluation_etat_in_mod(context, nt, moduleimpl_id): 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) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > liste evaluations + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations evals = nt.get_sem_evaluation_etat_list() nb_evals = len(evals) @@ -873,9 +868,7 @@ def formsemestre_evaluations_delai_correction( N'indique pas les évaluations de ratrapage ni celles des modules de bonus/malus. """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > liste evaluations + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations evals = nt.get_sem_evaluation_etat_list() T = [] diff --git a/app/scodoc/sco_export_results.py b/app/scodoc/sco_export_results.py index 9a682055..dac44bf4 100644 --- a/app/scodoc/sco_export_results.py +++ b/app/scodoc/sco_export_results.py @@ -35,7 +35,7 @@ from app.scodoc.notes_log import log from app.scodoc import html_sco_header from app.scodoc import sco_bac from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formations from app.scodoc import sco_preferences from app.scodoc import sco_pvjury @@ -77,9 +77,7 @@ def _build_results_table(context, start_date=None, end_date=None, types_parcours {} ) # etudid : { formsemestre_id d'inscription le plus recent dans les dates considérées, etud } for formsemestre_id in formsemestre_ids_parcours: - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etudids + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etudids etudids = nt.get_etudids() for etudid in etudids: if etudid not in etuds_infos: # pas encore traité ? diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py index 087d82aa..de86cf77 100644 --- a/app/scodoc/sco_formsemestre.py +++ b/app/scodoc/sco_formsemestre.py @@ -32,7 +32,7 @@ from operator import itemgetter from scodoc_manager import sco_mgr from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formations from app.scodoc import sco_preferences from app.scodoc import sco_users @@ -131,7 +131,6 @@ def formsemestre_enrich(context, sem): # imports ici pour eviter refs circulaires from app.scodoc import sco_formsemestre_edit from app.scodoc import sco_etud - from app.views import notes F = sco_formations.formation_list( context, args={"formation_id": sem["formation_id"]} @@ -268,8 +267,8 @@ def do_formsemestre_edit(context, sem, cnx=None, **kw): write_formsemestre_etapes(context, sem) write_formsemestre_responsables(context, sem) - sco_core.inval_cache( - context, formsemestre_id=sem["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=sem["formsemestre_id"] ) # > modif formsemestre diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index d4e2b65f..8e190da2 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -32,7 +32,7 @@ from app.auth.models import User import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_groups from app.scodoc.notes_log import log from app.scodoc.TrivialFormulator import TrivialFormulator, TF @@ -1375,6 +1375,8 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): cnx = ndb.GetDBConnexion() sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) + sco_cache.EvaluationCache.invalidate_sem(formsemestre_id) + # --- Destruction des modules de ce semestre mods = sco_moduleimpl.do_moduleimpl_list(context, formsemestre_id=formsemestre_id) for mod in mods: @@ -1398,9 +1400,6 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): "DELETE FROM notes_evaluation WHERE evaluation_id=%(evaluation_id)s", e, ) - sco_core.get_evaluations_cache( - context, - ).inval_cache(key=e["evaluation_id"]) sco_moduleimpl.do_moduleimpl_delete( context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id @@ -1706,8 +1705,8 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= z.append("") else: z = ["""

Aucune modification

"""] - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > modif coef UE cap (modifs notes de _certains_ etudiants) header = html_sco_header.html_sem_header( diff --git a/app/scodoc/sco_formsemestre_exterieurs.py b/app/scodoc/sco_formsemestre_exterieurs.py index 1ac881e2..452c9a0c 100644 --- a/app/scodoc/sco_formsemestre_exterieurs.py +++ b/app/scodoc/sco_formsemestre_exterieurs.py @@ -40,7 +40,7 @@ import app.scodoc.notesdb as ndb from app.scodoc.sco_utils import log from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc import html_sco_header -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_formations from app.scodoc import sco_formsemestre @@ -267,9 +267,7 @@ def formsemestre_ext_edit_ue_validations( def _make_page(context, etud, sem, tf, message="", REQUEST=None): - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) moy_gen = nt.get_etud_moy_gen(etud["etudid"]) H = [ html_sco_header.sco_header( diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py index f5734163..9935eafb 100644 --- a/app/scodoc/sco_formsemestre_inscriptions.py +++ b/app/scodoc/sco_formsemestre_inscriptions.py @@ -44,7 +44,7 @@ from app.scodoc import sco_formsemestre from app.scodoc import sco_moduleimpl from app.scodoc import sco_groups from app.scodoc import sco_etud -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import html_sco_header @@ -65,14 +65,13 @@ def do_formsemestre_inscription_list(context, *args, **kw): def do_formsemestre_inscription_listinscrits(context, formsemestre_id): """Liste les inscrits (état I) à ce semestre et cache le résultat""" - cache = sco_core.get_formsemestre_inscription_cache(context) - r = cache.get(formsemestre_id) + r = sco_cache.SemInscriptionsCache.get(formsemestre_id) if r is None: # retreive list r = do_formsemestre_inscription_list( context, args={"formsemestre_id": formsemestre_id, "etat": "I"} ) - cache.set(formsemestre_id, r) + sco_cache.SemInscriptionsCache.set(formsemestre_id, r) return r @@ -111,8 +110,8 @@ def do_formsemestre_inscription_create(context, args, REQUEST, method=None): commit=False, ) # - sco_core.inval_cache( - context, formsemestre_id=args["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=args["formsemestre_id"] ) # > inscription au semestre return r @@ -122,8 +121,8 @@ def do_formsemestre_inscription_delete(context, oid, formsemestre_id=None): cnx = ndb.GetDBConnexion() _formsemestre_inscriptionEditor.delete(cnx, oid) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > desinscription du semestre @@ -131,8 +130,8 @@ def do_formsemestre_inscription_edit(context, args=None, formsemestre_id=None): "edit a formsemestre_inscription" cnx = ndb.GetDBConnexion() _formsemestre_inscriptionEditor.edit(cnx, args) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > modif inscription semestre (demission ?) @@ -148,7 +147,7 @@ def do_formsemestre_desinscription(context, etudid, formsemestre_id, REQUEST=Non raise ScoValueError("desinscription impossible: semestre verrouille") # -- Si decisions de jury, desinscription interdite - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) if nt.etud_has_decision(etudid): raise ScoValueError( "desinscription impossible: l'étudiant a une décision de jury (la supprimer avant si nécessaire)" @@ -452,9 +451,7 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No raise ScoValueError("Modification impossible: semestre verrouille") etud = sco_etud.get_etud_info(etudid=etudid, filled=1)[0] - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etud_ue_status + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etud_ue_status F = html_sco_header.sco_footer(context, REQUEST) H = [ @@ -763,9 +760,7 @@ def list_inscrits_ailleurs(context, formsemestre_id): Pour chacun, donne la liste des semestres. { etudid : [ liste de sems ] } """ - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etudids + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etudids etudids = nt.get_etudids() d = {} for etudid in etudids: diff --git a/app/scodoc/sco_formsemestre_status.py b/app/scodoc/sco_formsemestre_status.py index a0e554f8..1b0c2f43 100644 --- a/app/scodoc/sco_formsemestre_status.py +++ b/app/scodoc/sco_formsemestre_status.py @@ -48,7 +48,7 @@ from app.scodoc import sco_archives from app.scodoc import sco_bulletins from app.scodoc import sco_codes_parcours from app.scodoc import sco_compute_moy -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_evaluations from app.scodoc import sco_formations @@ -617,9 +617,7 @@ def formsemestre_description_table( Liste des modules et de leurs coefficients """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > liste evaluations + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > liste evaluations use_ue_coefs = sco_preferences.get_preference( context, "use_ue_coefs", formsemestre_id ) @@ -778,7 +776,8 @@ def _make_listes_sem(context, sem, REQUEST=None, with_absences=True): r = scu.ScoURL() # root url # construit l'URL "destination" # (a laquelle on revient apres saisie absences) - query_args = cgi.parse_qs(REQUEST.QUERY_STRING) + query_args = cgi.parse_qs(REQUEST.QUERY_STRING) # XXX TODO a revoir #py3 + # soit via flask soit via https://docs.python.org/3/library/urllib.parse.html#module-urllib.parse if "head_message" in query_args: del query_args["head_message"] destination = "%s?%s" % ( @@ -1026,9 +1025,7 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None): ), """

Tableau de bord: cliquez sur un module pour saisir des notes

""", ] - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) if nt.expr_diagnostics: H.append(html_expr_diagnostic(context, nt.expr_diagnostics)) H.append( diff --git a/app/scodoc/sco_formsemestre_validation.py b/app/scodoc/sco_formsemestre_validation.py index f128b56f..cf1d87c2 100644 --- a/app/scodoc/sco_formsemestre_validation.py +++ b/app/scodoc/sco_formsemestre_validation.py @@ -37,12 +37,12 @@ from app.scodoc.notes_log import log from app.scodoc.scolog import logdb from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message from app.scodoc.sco_exceptions import ScoValueError -from app.scodoc.sco_abs import getAbsSemEtud from app.scodoc.sco_codes_parcours import * from app.scodoc import html_sco_header +from app.scodoc import sco_abs from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_etud from app.scodoc import sco_formsemestre @@ -66,8 +66,8 @@ def formsemestre_validation_etud_form( readonly=True, REQUEST=None, ): - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_table_moyennes_triees, get_etud_decision_sem T = nt.get_table_moyennes_triees() if not etudid and not etud_index: @@ -532,8 +532,8 @@ def formsemestre_recap_parcours_table( else: ass = "" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, sem["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + sem["formsemestre_id"] ) # > get_ues, get_etud_moy_gen, get_etud_ue_status if is_cur: type_sem = "*" # now unused @@ -614,9 +614,7 @@ def formsemestre_recap_parcours_table( '%s' % scu.fmt_note(nt.get_etud_moy_gen(etudid)) ) # Absences (nb d'abs non just. dans ce semestre) - AbsEtudSem = getAbsSemEtud(context, sem, etudid) - nbabs = AbsEtudSem.CountAbs() - nbabsjust = AbsEtudSem.CountAbsJust() + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) H.append('%d' % (nbabs - nbabsjust)) # UEs @@ -864,8 +862,8 @@ def do_formsemestre_validation_auto(context, formsemestre_id, REQUEST): "Saisie automatisee des decisions d'un semestre" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) next_semestre_id = sem["semestre_id"] + 1 - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etudids, get_etud_decision_sem, etudids = nt.get_etudids() nb_valid = 0 @@ -1137,9 +1135,7 @@ def do_formsemestre_validate_previous_ue( """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) cnx = ndb.GetDBConnexion(autocommit=False) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etud_ue_status + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etud_ue_status if ue_coefficient != None: sco_formsemestre.do_formsemestre_uecoef_edit_or_create( context, cnx, formsemestre_id, ue_id, ue_coefficient @@ -1186,8 +1182,8 @@ def _invalidate_etud_formation_caches(context, etudid, formation_id): {"etudid": etudid, "formation_id": formation_id}, ) for fsid in [s["formsemestre_id"] for s in r]: - sco_core.inval_cache( - context, formsemestre_id=fsid + sco_cache.invalidate_formsemestre( + formsemestre_id=fsid ) # > modif decision UE (inval tous semestres avec cet etudiant, ok mais conservatif) diff --git a/app/scodoc/sco_groups.py b/app/scodoc/sco_groups.py index 9dcb7d9d..9675307f 100644 --- a/app/scodoc/sco_groups.py +++ b/app/scodoc/sco_groups.py @@ -48,7 +48,7 @@ from app.scodoc.notes_log import log from app.scodoc.scolog import logdb from app.scodoc import html_sco_header from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_permissions_check from app.scodoc import sco_xml @@ -446,9 +446,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG formsemestre_id = partition["formsemestre_id"] sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) groups = get_partition_groups(context, partition) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > inscrdict + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > inscrdict etuds_set = set(nt.inscrdict) # XML response: REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) @@ -598,8 +596,8 @@ def change_etud_group_in_partition( ) cnx.commit() # 4- invalidate cache - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > change etud group @@ -955,8 +953,8 @@ def partition_set_attr(context, partition_id, attr, value, REQUEST=None): partition[attr] = value partitionEditor.edit(cnx, partition) # invalid bulletin cache - sco_core.inval_cache( - context, pdfonly=True, formsemestre_id=partition["formsemestre_id"] + sco_cache.invalidate_formsemestre( + pdfonly=True, formsemestre_id=partition["formsemestre_id"] ) return "enregistré" @@ -1268,9 +1266,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None): createGroup(context, partition_id, group_name, REQUEST=REQUEST) ) # - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > identdict + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > identdict identdict = nt.identdict # build: { civilite : liste etudids trie par niveau croissant } civilites = set([x["civilite"] for x in identdict.values()]) @@ -1313,8 +1309,8 @@ def get_prev_moy(context, etudid, formsemestre_id): etud = info[0] Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id) if Se.prev: - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, Se.prev["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + Se.prev["formsemestre_id"] ) # > get_etud_moy_gen return nt.get_etud_moy_gen(etudid) else: diff --git a/app/scodoc/sco_groups_view.py b/app/scodoc/sco_groups_view.py index 08c4c527..96136495 100644 --- a/app/scodoc/sco_groups_view.py +++ b/app/scodoc/sco_groups_view.py @@ -514,7 +514,7 @@ def groups_table( if with_paiement or with_codes: sco_portal_apogee.check_paiement_etuds(context, groups_infos.members) if with_archives: - import sco_archives_etud + from app.scodoc import sco_archives_etud sco_archives_etud.add_archives_info_to_etud_list(context, groups_infos.members) columns_ids += ["etudarchive"] diff --git a/app/scodoc/sco_import_etuds.py b/app/scodoc/sco_import_etuds.py index a37aacbf..191166ce 100644 --- a/app/scodoc/sco_import_etuds.py +++ b/app/scodoc/sco_import_etuds.py @@ -28,12 +28,9 @@ """ Importation des etudiants à partir de fichiers CSV """ -import os -import sys + import time -import pdb import collections -import types import re import app.scodoc.sco_utils as scu @@ -53,7 +50,7 @@ from app.scodoc.sco_exceptions import ( ScoGenError, ) from app.scodoc import html_sco_header -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_formsemestre from app.scodoc import sco_groups @@ -490,7 +487,8 @@ def scolars_import_excel_file( cnx.commit() # Invalide les caches des semestres dans lesquels on a inscrit des etudiants: - sco_core.inval_cache(context, formsemestre_id_list=formsemestre_to_invalidate) + for formsemestre_id in formsemestre_to_invalidate: + sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id) return diag @@ -731,7 +729,7 @@ def scolars_import_admission( nline += 1 diag.append("%d lignes importées" % n_import) if n_import > 0: - sco_core.inval_cache(context, formsemestre_id=formsemestre_id) + sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id) return diag diff --git a/app/scodoc/sco_import_users.py b/app/scodoc/sco_import_users.py index d4cc07ac..f99d7c14 100644 --- a/app/scodoc/sco_import_users.py +++ b/app/scodoc/sco_import_users.py @@ -27,6 +27,8 @@ """Import d'utilisateurs via fichier Excel """ +import random, time + from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.header import Header @@ -149,7 +151,6 @@ def import_users(U, auth_dept="", context=None): # Adapté de http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440564 # Alphabet tres simple pour des mots de passe simples... -import getpass, random, sha, string, md5, time, base64 ALPHABET = r"""ABCDEFGHIJKLMNPQRSTUVWXYZ123456789123456789AEIOU""" PASSLEN = 6 diff --git a/app/scodoc/sco_liste_notes.py b/app/scodoc/sco_liste_notes.py index 7346b838..f32bb6bb 100644 --- a/app/scodoc/sco_liste_notes.py +++ b/app/scodoc/sco_liste_notes.py @@ -39,7 +39,7 @@ from app.scodoc.TrivialFormulator import TrivialFormulator from app.scodoc import htmlutils from app.scodoc import html_sco_header from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_evaluations from app.scodoc import sco_excel @@ -658,9 +658,7 @@ def _add_moymod_column( ): """Ajoute la colonne moymod à rows""" col_id = "moymod" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etud_mod_moy + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etud_mod_moy nb_notes = 0 sum_notes = 0 notes = [] # liste des notes numeriques, pour calcul histogramme uniquement @@ -730,12 +728,12 @@ def evaluation_check_absences(context, evaluation_id): am, pm, demijournee = _eval_demijournee(E) # Liste les absences à ce moment: - A = sco_abs.ListeAbsJour(context, ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) + A = sco_abs.list_abs_jour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) As = set([x["etudid"] for x in A]) # ensemble des etudiants absents - NJ = sco_abs.ListeAbsNonJustJour(context, ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) + NJ = sco_abs.list_abs_non_just_jour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) NJs = set([x["etudid"] for x in NJ]) # ensemble des etudiants absents non justifies - Just = sco_abs.ListeAbsJour( - context, ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True + Just = sco_abs.list_abs_jour( + ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True ) Justs = set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif diff --git a/app/scodoc/sco_moduleimpl.py b/app/scodoc/sco_moduleimpl.py index 31eed42b..e6a033c0 100644 --- a/app/scodoc/sco_moduleimpl.py +++ b/app/scodoc/sco_moduleimpl.py @@ -36,7 +36,7 @@ from app.scodoc.sco_exceptions import ScoValueError, AccessDenied from app.scodoc.notes_log import log from app.scodoc import scolog from app.scodoc import sco_formsemestre -from app.scodoc import sco_core +from app.scodoc import sco_cache # --- Gestion des "Implémentations de Modules" # Un "moduleimpl" correspond a la mise en oeuvre d'un module @@ -64,8 +64,8 @@ def do_moduleimpl_create(context, args): "create a moduleimpl" cnx = ndb.GetDBConnexion() r = _moduleimplEditor.create(cnx, args) - sco_core.inval_cache( - context, formsemestre_id=args["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=args["formsemestre_id"] ) # > creation moduleimpl return r @@ -91,8 +91,8 @@ def do_moduleimpl_delete(context, oid, formsemestre_id=None): ) # --- destruction du moduleimpl _moduleimplEditor.delete(cnx, oid) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > moduleimpl_delete @@ -115,7 +115,9 @@ def do_moduleimpl_edit(context, args, formsemestre_id=None, cnx=None): cnx = ndb.GetDBConnexion() _moduleimplEditor.edit(cnx, args) - sco_core.inval_cache(context, formsemestre_id=formsemestre_id) # > modif moduleimpl + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id + ) # > modif moduleimpl def do_moduleimpl_withmodule_list( @@ -215,8 +217,8 @@ def do_moduleimpl_inscription_create(context, args, REQUEST=None, formsemestre_i cnx = ndb.GetDBConnexion() log("do_moduleimpl_inscription_create: " + str(args)) r = _moduleimpl_inscriptionEditor.create(cnx, args) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > moduleimpl_inscription if REQUEST: scolog.logdb( @@ -234,8 +236,8 @@ def do_moduleimpl_inscription_delete(context, oid, formsemestre_id=None): "delete moduleimpl_inscription" cnx = ndb.GetDBConnexion() _moduleimpl_inscriptionEditor.delete(cnx, oid) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > moduleimpl_inscription @@ -283,8 +285,8 @@ def do_moduleimpl_inscrit_etuds( formsemestre_id=formsemestre_id, ) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > moduleimpl_inscrit_etuds @@ -311,8 +313,7 @@ def do_ens_create(context, args): def do_ens_delete(context, oid): "delete ens" cnx = ndb.GetDBConnexion() - r = _modules_enseignantsEditor.delete(cnx, oid) - return r + _modules_enseignantsEditor.delete(cnx, oid) def can_change_module_resp(context, REQUEST, moduleimpl_id): diff --git a/app/scodoc/sco_moduleimpl_inscriptions.py b/app/scodoc/sco_moduleimpl_inscriptions.py index a93aa347..805b9d2c 100644 --- a/app/scodoc/sco_moduleimpl_inscriptions.py +++ b/app/scodoc/sco_moduleimpl_inscriptions.py @@ -37,7 +37,7 @@ from app.scodoc.notes_log import log from app.scodoc.scolog import logdb from app.scodoc import html_sco_header from app.scodoc import htmlutils -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_edit_ue from app.scodoc import sco_formsemestre @@ -495,9 +495,7 @@ def get_etuds_with_capitalized_ue(context, formsemestre_id): returns { ue_id : [ { infos } ] } """ UECaps = scu.DictDefault(defaultvalue=[]) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_ues, get_etud_ue_status + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_ues, get_etud_ue_status inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list( context, args={"formsemestre_id": formsemestre_id} ) @@ -569,8 +567,8 @@ def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None) msg="desinscription UE %s" % ue_id, commit=False, ) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > desinscription etudiant des modules diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 47882044..c51cb1bc 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -37,7 +37,7 @@ from app.scodoc import html_sco_header from app.scodoc import htmlutils from app.scodoc import sco_abs from app.scodoc import sco_compute_moy -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_evaluations from app.scodoc import sco_formations @@ -46,7 +46,6 @@ from app.scodoc import sco_formsemestre_status from app.scodoc import sco_groups from app.scodoc import sco_moduleimpl from app.scodoc import sco_permissions_check -from app.scodoc import sco_saisie_notes from app.scodoc import sco_users # ported from old DTML code in oct 2009 @@ -168,9 +167,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No context, moduleimpl_id=M["moduleimpl_id"] ) - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) ModEvals = sco_evaluations.do_evaluation_list( context, {"moduleimpl_id": moduleimpl_id} ) diff --git a/app/scodoc/sco_parcours_dut.py b/app/scodoc/sco_parcours_dut.py index 83d5f3f2..78be68d9 100644 --- a/app/scodoc/sco_parcours_dut.py +++ b/app/scodoc/sco_parcours_dut.py @@ -32,7 +32,7 @@ import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc.notes_log import log from app.scodoc.scolog import logdb -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formsemestre from app.scodoc import sco_formations from app.scodoc.sco_codes_parcours import ( @@ -104,8 +104,8 @@ class DecisionSem(object): def SituationEtudParcours(context, etud, formsemestre_id): """renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)""" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etud_decision_sem, get_etud_moy_gen, get_ues, get_etud_ue_status, etud_check_conditions_ues parcours = nt.parcours # @@ -295,8 +295,8 @@ class SituationEtudParcoursGeneric(object): sem["semestre_id"] == n1 and sem["formation_code"] == self.formation["formation_code"] ): - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + sem["formsemestre_id"] ) # > get_etud_decision_sem decision = nt.get_etud_decision_sem(self.etudid) if decision and ( @@ -311,8 +311,8 @@ class SituationEtudParcoursGeneric(object): sont validés. En sortie, sem_idx_set contient ceux qui n'ont pas été validés.""" for sem in self.get_semestres(): if sem["formation_code"] == self.formation["formation_code"]: - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + sem["formsemestre_id"] ) # > get_etud_decision_sem decision = nt.get_etud_decision_sem(self.etudid) if decision and code_semestre_validant(decision["code"]): @@ -329,9 +329,7 @@ class SituationEtudParcoursGeneric(object): ue_acros = {} # acronyme ue : 1 nb_max_ue = 0 for sem in sems: - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] - ) # > get_ues + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) # > get_ues ues = nt.get_ues(filter_sport=True) for ue in ues: ue_acros[ue["acronyme"]] = 1 @@ -399,8 +397,8 @@ class SituationEtudParcoursGeneric(object): if not sem: code = "" # non inscrit à ce semestre else: - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + sem["formsemestre_id"] ) # > get_etud_decision_sem decision = nt.get_etud_decision_sem(self.etudid) if decision: @@ -471,9 +469,8 @@ class SituationEtudParcoursGeneric(object): # Verifications basiques: # ? # Code etat du semestre precedent: - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, prev["formsemestre_id"] - ) # > get_etud_decision_sem, get_etud_moy_gen, etud_check_conditions_ues + nt = sco_cache.NotesTableCache.get(prev["formsemestre_id"]) + # > get_etud_decision_sem, get_etud_moy_gen, etud_check_conditions_ues self.prev_decision = nt.get_etud_decision_sem(self.etudid) self.prev_moy_gen = nt.get_etud_moy_gen(self.etudid) self.prev_barres_ue_ok = nt.etud_check_conditions_ues(self.etudid)[0] @@ -530,9 +527,8 @@ class SituationEtudParcoursGeneric(object): sem["formation_code"] == self.formation["formation_code"] and sem["semestre_id"] == s ): - nt = sco_core.get_notes_cache(self.context).get_NotesTable( - self.context, sem["formsemestre_id"] - ) # > get_etud_decision_sem + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) + # > get_etud_decision_sem decision = nt.get_etud_decision_sem(self.etudid) if decision and code_semestre_validant(decision["code"]): validated = True @@ -629,8 +625,8 @@ class SituationEtudParcoursGeneric(object): REQUEST=REQUEST, ) - sco_core.inval_cache( - self.context, formsemestre_id=self.prev["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=self.prev["formsemestre_id"] ) # > modif decisions jury (sem, UE) # -- supprime autorisations venant de ce formsemestre @@ -659,18 +655,17 @@ class SituationEtudParcoursGeneric(object): except: cnx.rollback() raise - sco_core.inval_cache( - self.context, formsemestre_id=self.formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=self.formsemestre_id ) # > modif decisions jury et autorisations inscription if decision.formsemestre_id_utilise_pour_compenser: # inval aussi le semestre utilisé pour compenser: - sco_core.inval_cache( - self.context, + sco_cache.invalidate_formsemestre( formsemestre_id=decision.formsemestre_id_utilise_pour_compenser, ) # > modif decision jury for formsemestre_id in to_invalidate: - sco_core.inval_cache( - self.context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > modif decision jury @@ -909,9 +904,7 @@ def formsemestre_validate_ues( """ valid_semestre = CODES_SEM_VALIDES.get(code_etat_sem, False) cnx = ndb.GetDBConnexion(autocommit=False) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_ues, get_etud_ue_status + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_ues, get_etud_ue_status ue_ids = [x["ue_id"] for x in nt.get_ues(etudid=etudid, filter_sport=True)] for ue_id in ue_ids: ue_status = nt.get_etud_ue_status(etudid, ue_id) diff --git a/app/scodoc/sco_poursuite_dut.py b/app/scodoc/sco_poursuite_dut.py index dd74e598..c8e3f6bf 100644 --- a/app/scodoc/sco_poursuite_dut.py +++ b/app/scodoc/sco_poursuite_dut.py @@ -35,7 +35,7 @@ from flask import url_for, g import app.scodoc.sco_utils as scu from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formsemestre from app.scodoc import sco_groups from app.scodoc import sco_preferences @@ -58,9 +58,7 @@ def etud_get_poursuite_info(context, sem, etud): for s in etud["sems"]: if s["semestre_id"] == sem_id: etudid = etud["etudid"] - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, s["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(s["formsemestre_id"]) dec = nt.get_etud_decision_sem(etudid) # Moyennes et rangs des UE ues = nt.get_ues(filter_sport=True) @@ -95,9 +93,7 @@ def etud_get_poursuite_info(context, sem, etud): rangs.append(["rang_" + codeModule, rangModule]) # Absences - AbsSemEtud = sco_abs.getAbsSemEtud(context, nt.sem, etudid) - NbAbs = AbsSemEtud.CountAbs() - NbAbsJust = AbsSemEtud.CountAbsJust() + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, nt.sem) if ( dec and not sem_descr # not sem_descr pour ne prendre que le semestre validé le plus récent @@ -115,8 +111,8 @@ def etud_get_poursuite_info(context, sem, etud): ("date_debut", s["date_debut"]), ("date_fin", s["date_fin"]), ("periode", "%s - %s" % (s["mois_debut"], s["mois_fin"])), - ("AbsNonJust", NbAbs - NbAbsJust), - ("AbsJust", NbAbsJust), + ("AbsNonJust", nbabs - nbabsjust), + ("AbsJust", nbabsjust), ] d += ( moy_ues + rg_ues + modules + rangs diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py index 4d60b8db..76f3c709 100644 --- a/app/scodoc/sco_preferences.py +++ b/app/scodoc/sco_preferences.py @@ -112,7 +112,7 @@ get_base_preferences(context, formsemestre_id) """ from flask import g -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc.notes_log import log from app.scodoc.sco_exceptions import ScoValueError, ScoException from app.scodoc.TrivialFormulator import TrivialFormulator @@ -1797,7 +1797,10 @@ class BasePreferences(object): self.prefs[p["formsemestre_id"]] = {} # Convert types: - if p["name"] in self.prefs_dict and "type" in self.prefs_dict[p["name"]]: + if ( + p["name"] in self.prefs_dict + and "type" in self.prefs_dict[p["name"]] + ): typ = self.prefs_dict[p["name"]]["type"] if typ == "float": # special case for float values (where NULL means 0) @@ -1918,7 +1921,7 @@ class BasePreferences(object): # les preferences peuvent affecter les PDF cachés et les notes calculées: if modif: - sco_core.inval_cache(self.context, pdfonly=False) # > modif preferences + sco_cache.invalidate_formsemestre() finally: scu.GSL.release() @@ -1946,7 +1949,7 @@ class BasePreferences(object): if pdb: log("deleting pref sem=%s %s" % (formsemestre_id, name)) self._editor.delete(cnx, pdb[0]["pref_id"]) - sco_core.inval_cache(self.context, pdfonly=False) # > modif preferences + sco_cache.invalidate_formsemestre() # > modif preferences finally: scu.GSL.release() diff --git a/app/scodoc/sco_prepajury.py b/app/scodoc/sco_prepajury.py index c6928e05..f18b2c49 100644 --- a/app/scodoc/sco_prepajury.py +++ b/app/scodoc/sco_prepajury.py @@ -30,13 +30,13 @@ import time import app.scodoc.sco_utils as scu +from app.scodoc import sco_abs from app.scodoc import sco_groups -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_excel from app.scodoc import sco_formsemestre from app.scodoc import sco_parcours_dut from app.scodoc import sco_codes_parcours -from app.scodoc.sco_abs import getAbsSemEtud from app.scodoc import VERSION from app.scodoc import sco_etud from app.scodoc import sco_preferences @@ -44,8 +44,8 @@ from app.scodoc import sco_preferences def feuille_preparation_jury(context, formsemestre_id, REQUEST): "Feuille excel pour preparation des jurys" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etudids, get_etud_moy_gen, get_ues, get_etud_ue_status, get_etud_decision_sem, identdict, etudids = nt.get_etudids(sorted=True) # tri par moy gen sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) @@ -77,8 +77,8 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): etud = info[0] Se = sco_parcours_dut.SituationEtudParcours(context, etud, formsemestre_id) if Se.prev: - ntp = sco_core.get_notes_cache(context).get_NotesTable( - context, Se.prev["formsemestre_id"] + ntp = sco_cache.NotesTableCache.get( + Se.prev["formsemestre_id"] ) # > get_ues, get_etud_ue_status, get_etud_moy_gen, get_etud_decision_sem for ue in ntp.get_ues(filter_sport=True): ue_status = ntp.get_etud_ue_status(etudid, ue["ue_id"]) @@ -129,10 +129,9 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): main_partition_id, "" ) # absences: - AbsEtudSem = getAbsSemEtud(context, sem, etudid) - nbabs[etudid] = AbsEtudSem.CountAbs() - # nbabsjust[etudid] = AbsEtudSem.CountAbsJust() - nbabsjust[etudid] = AbsEtudSem.CountAbs() - AbsEtudSem.CountAbsJust() + nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) + nbabs[etudid] = nbabs + nbabsjust[etudid] = nbabs - nbabsjust # Codes des UE "semestre précédent": ue_prev_codes = list(prev_moy_ue.keys()) diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index 55ef135c..28d6632e 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -58,7 +58,7 @@ import app.scodoc.notesdb as ndb from app.scodoc.notes_log import log from app.scodoc import html_sco_header from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_ue from app.scodoc import sco_formations from app.scodoc import sco_formsemestre @@ -86,6 +86,7 @@ def _descr_decisions_ues(context, nt, etudid, decisions_ue, decision_sem): if decisions_ue[ue_id] and ( decisions_ue[ue_id]["code"] == sco_codes_parcours.ADM or ( + # XXX ceci devrait dépendre du parcours et non pas être une option ! #sco8 scu.CONFIG.CAPITALIZE_ALL_UES and sco_codes_parcours.code_semestre_validant(decision_sem["code"]) ) @@ -216,8 +217,8 @@ def dict_pvjury( 'decisions_dict' : { etudid : decision (comme ci-dessus) }, } """ - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etudids, get_etud_etat, get_etud_decision_sem, get_etud_decision_ues if etudids is None: etudids = nt.get_etudids() diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py index f999bf6c..da20d77b 100644 --- a/app/scodoc/sco_recapcomplet.py +++ b/app/scodoc/sco_recapcomplet.py @@ -39,7 +39,7 @@ from app.scodoc import sco_bulletins_json from app.scodoc import sco_bulletins_xml from app.scodoc import sco_bulletins, sco_excel from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_evaluations from app.scodoc import sco_formations from app.scodoc import sco_formsemestre @@ -282,8 +282,8 @@ def make_formsemestre_recapcomplet( sem = sco_formsemestre.do_formsemestre_list( context, args={"formsemestre_id": formsemestre_id} )[0] - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_modimpls, get_ues, get_table_moyennes_triees, get_etud_decision_sem, get_etud_etat, get_etud_rang, get_nom_short, get_mod_stats, nt.moy_moy, get_etud_decision_sem, modimpls = nt.get_modimpls() ues = nt.get_ues() # incluant le(s) UE de sport @@ -868,9 +868,7 @@ def _formsemestre_recapcomplet_xml( ): "XML export: liste tous les bulletins XML." - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_table_moyennes_triees + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_table_moyennes_triees T = nt.get_table_moyennes_triees() if not T: return "", "", "xml" @@ -939,9 +937,7 @@ def _formsemestre_recapcomplet_json( "bulletins": [], } bulletins = J["bulletins"] - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_table_moyennes_triees + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_table_moyennes_triees T = nt.get_table_moyennes_triees() for t in T: etudid = t[-1] diff --git a/app/scodoc/sco_report.py b/app/scodoc/sco_report.py index b6c2f517..f538f66e 100644 --- a/app/scodoc/sco_report.py +++ b/app/scodoc/sco_report.py @@ -43,7 +43,7 @@ import app.scodoc.sco_utils as scu from app.scodoc import notesdb as ndb from app.scodoc import html_sco_header from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etud from app.scodoc import sco_excel from app.scodoc import sco_formsemestre @@ -64,8 +64,8 @@ MAX_ETUD_IN_DESCR = 20 def formsemestre_etuds_stats(context, sem, only_primo=False): """Récupère liste d'etudiants avec etat et decision.""" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, sem["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + sem["formsemestre_id"] ) # > get_table_moyennes_triees, identdict, get_etud_decision_sem, get_etud_etat, T = nt.get_table_moyennes_triees() # Construit liste d'étudiants du semestre avec leur decision @@ -413,8 +413,8 @@ def table_suivi_cohorte( logt("table_suivi_cohorte: start") # 1-- Liste des semestres posterieurs dans lesquels ont été les etudiants de sem - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etudids, get_etud_decision_sem etudids = nt.get_etudids() @@ -469,8 +469,8 @@ def table_suivi_cohorte( s["members"] = orig_set.intersection(inset) nb_dipl = 0 # combien de diplomes dans ce semestre ? if s["semestre_id"] == nt.parcours.NB_SEM: - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, s["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + s["formsemestre_id"] ) # > get_etud_decision_sem for etudid in s["members"]: dec = nt.get_etud_decision_sem(etudid) @@ -919,8 +919,8 @@ def _descr_etud_set(context, etudids): def _count_dem_reo(context, formsemestre_id, etudids): "count nb of demissions and reorientation in this etud set" - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etud_etat, get_etud_decision_sem dems = set() reos = set() @@ -985,8 +985,8 @@ def get_codeparcoursetud(context, etud, prefix="", separator=""): i = len(sems) - 1 while i >= 0: s = sems[i] # 'sems' est a l'envers, du plus recent au plus ancien - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, s["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + s["formsemestre_id"] ) # > get_etud_etat, get_etud_decision_sem p.append(_codesem(s, prefix=prefix)) # code decisions jury de chaque semestre: @@ -1032,9 +1032,7 @@ def tsp_etud_list( """ # log('tsp_etud_list(%s, bac="%s")' % (formsemestre_id,bac)) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etudids, + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etudids, etudids = nt.get_etudids() etuds = [] bacs = set() @@ -1287,8 +1285,8 @@ def graph_parcours( nxt = {} etudid = etud["etudid"] for s in etud["sems"]: # du plus recent au plus ancien - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, s["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + s["formsemestre_id"] ) # > get_etud_decision_sem, get_etud_etat dec = nt.get_etud_decision_sem(etudid) if nxt: diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index 80ee1a56..903e13cd 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -47,7 +47,7 @@ from app.scodoc.TrivialFormulator import TrivialFormulator, TF from app.scodoc import html_sco_header from app.scodoc import htmlutils from app.scodoc import sco_abs -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_evaluations from app.scodoc import sco_excel @@ -560,19 +560,17 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True): log("*** exception in _notes_add") if do_it: # inval cache - sco_core.inval_cache( - context, formsemestre_id=M["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=M["formsemestre_id"] ) # > modif notes (exception) cnx.rollback() # abort raise # re-raise exception if do_it: cnx.commit() - sco_core.inval_cache( - context, formsemestre_id=M["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=M["formsemestre_id"] ) # > modif notes - sco_core.get_evaluations_cache( - context, - ).inval_cache(key=evaluation_id) + sco_cache.EvaluationCache.delete(evaluation_id) return nb_changed, nb_suppress, existing_decisions @@ -837,8 +835,8 @@ def has_existing_decision(context, M, E, etudid): Si oui, return True """ formsemestre_id = M["formsemestre_id"] - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id + nt = sco_cache.NotesTableCache.get( + formsemestre_id ) # > get_etud_decision_sem, get_etud_decision_ues if nt.get_etud_decision_sem(etudid): return True @@ -1001,20 +999,16 @@ def _get_sorted_etuds(context, E, etudids, formsemestre_id): jour_iso = ndb.DateDMYtoISO(E["jour"]) warn_abs_lst = [] if E["matin"]: - nbabs = sco_abs.CountAbs(context, etudid, jour_iso, jour_iso, matin=1) - nbabsjust = sco_abs.CountAbsJust( - context, etudid, jour_iso, jour_iso, matin=1 - ) + nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=1) + nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=1) if nbabs: if nbabsjust: warn_abs_lst.append("absent justifié le matin !") else: warn_abs_lst.append("absent le matin !") if E["apresmidi"]: - nbabs = sco_abs.CountAbs(context, etudid, jour_iso, jour_iso, matin=0) - nbabsjust = sco_abs.CountAbsJust( - context, etudid, jour_iso, jour_iso, matin=0 - ) + nbabs = sco_abs.count_abs(etudid, jour_iso, jour_iso, matin=0) + nbabsjust = sco_abs.count_abs_just(etudid, jour_iso, jour_iso, matin=0) if nbabs: if nbabsjust: warn_abs_lst.append("absent justifié l'après-midi !") diff --git a/app/scodoc/sco_semset.py b/app/scodoc/sco_semset.py index 608d96cf..00080d6a 100644 --- a/app/scodoc/sco_semset.py +++ b/app/scodoc/sco_semset.py @@ -40,7 +40,7 @@ sem_set_list(context) """ from app.scodoc import html_sco_header -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_etape_apogee from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_status @@ -232,9 +232,7 @@ class SemSet(dict): self["etuds_without_nip"] = set() # etudids self["jury_ok"] = True for sem in self.sems: - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) sem["etuds"] = list(nt.identdict.values()) sem["nips"] = {e["code_nip"] for e in sem["etuds"] if e["code_nip"]} sem["etuds_without_nip"] = { diff --git a/app/scodoc/sco_synchro_etuds.py b/app/scodoc/sco_synchro_etuds.py index e088b5f9..1a394f78 100644 --- a/app/scodoc/sco_synchro_etuds.py +++ b/app/scodoc/sco_synchro_etuds.py @@ -35,7 +35,7 @@ from operator import itemgetter import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc import html_sco_header -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_formsemestre from app.scodoc import sco_formsemestre_inscriptions from app.scodoc import sco_groups @@ -672,7 +672,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES cnx.commit() log("do_import_etuds_from_portal: re-raising exception") # > import: modif identite, adresses, inscriptions - sco_core.inval_cache(context) + sco_cache.invalidate_formsemestre() raise sco_news.add( @@ -855,7 +855,7 @@ def formsemestre_import_etud_admission( changed_mails.append((info, etud["mail"])) else: unknowns.append(code_nip) - sco_core.inval_cache(context, formsemestre_id=sem["formsemestre_id"]) + sco_cache.invalidate_formsemestre(formsemestre_id=sem["formsemestre_id"]) return no_nip, unknowns, changed_mails diff --git a/app/scodoc/sco_tag_module.py b/app/scodoc/sco_tag_module.py index 077fd7d8..55c18bdc 100644 --- a/app/scodoc/sco_tag_module.py +++ b/app/scodoc/sco_tag_module.py @@ -39,7 +39,7 @@ import types import app.scodoc.sco_utils as scu import app.scodoc.notesdb as ndb from app.scodoc.notes_log import log -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_edit_module from app.scodoc import sco_etud from app.scodoc.sco_exceptions import ScoValueError, AccessDenied @@ -276,9 +276,7 @@ def get_etud_tagged_modules(context, etudid, tagname): etud = sco_etud.get_etud_info(etudid=etudid, filled=True)[0] R = [] for sem in etud["sems"]: - nt = sco_core.get_notes_cache( - context, - ).get_NotesTable(context, sem["formsemestre_id"]) + nt = sco_cache.NotesTableCache.get(sem["formsemestre_id"]) modimpls = nt.get_modimpls() for modimpl in modimpls: tags = module_tag_list(context, module_id=modimpl["module_id"]) @@ -346,5 +344,5 @@ sem = etud['sems'][0] [ tm['moy'] for tm in get_etud_tagged_modules(context, etudid, 'allo') ] # si besoin après modif par le Web: -# sco_core.inval_cache(context) +# sco_cache.invalidate_formsemestre() """ diff --git a/app/scodoc/sco_undo_notes.py b/app/scodoc/sco_undo_notes.py index c9e81524..a41047ea 100644 --- a/app/scodoc/sco_undo_notes.py +++ b/app/scodoc/sco_undo_notes.py @@ -97,17 +97,21 @@ class NotesOperation(dict): # # il y a-t-il une modif plus recente ? # if self['current_notes_by_etud']['date'] <= self['date'] + OPERATION_DATE_TOLERANCE: # - # + invalider cache sco_core.get_evaluations_cache(context, ).inval_cache(key=evaluation_id) + # + invalider cache sco_cache.EvaluationCache.delete(evaluation_id) def list_operations(context, evaluation_id): """returns list of NotesOperation for this evaluation""" - notes = list(sco_evaluations.do_evaluation_get_all_notes( - context, evaluation_id, filter_suppressed=False - ).values()) - notes_log = list(sco_evaluations.do_evaluation_get_all_notes( - context, evaluation_id, filter_suppressed=False, table="notes_notes_log" - ).values()) + notes = list( + sco_evaluations.do_evaluation_get_all_notes( + context, evaluation_id, filter_suppressed=False + ).values() + ) + notes_log = list( + sco_evaluations.do_evaluation_get_all_notes( + context, evaluation_id, filter_suppressed=False, table="notes_notes_log" + ).values() + ) dt = OPERATION_DATE_TOLERANCE NotesDates = {} # { uid : intervalmap } diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 76ef86e9..8c1c7cc0 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -45,7 +45,7 @@ import types import unicodedata import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse -from xml.etree.ElementTree import Element +from xml.etree import ElementTree STRING_TYPES = six.string_types @@ -272,11 +272,6 @@ else: CUSTOM_HTML_FOOTER_CNX = "" SCO_ENCODING = "utf-8" # used by Excel, XML, PDF, ... -# Attention: encodage lié au codage Zope et aussi à celui de postgresql -# et aussi a celui des fichiers sources Python (comme celui-ci). - -# def to_utf8(s): -# return unicode(s, SCO_ENCODING).encode('utf-8') SCO_DEFAULT_SQL_USER = "www-data" # should match Zope process UID @@ -321,6 +316,7 @@ LOGOS_IMAGES_ALLOWED_TYPES = ("jpg", "png") # remind that PIL does not read pdf TYPE_ADMISSION_DEFAULT = "Inconnue" TYPES_ADMISSION = (TYPE_ADMISSION_DEFAULT, "APB", "APB-PC", "CEF", "Direct") +BULLETINS_VERSIONS = ("short", "selectedevals", "long") # Support for ScoDoc7 compatibility def get_dept_id(): @@ -823,7 +819,7 @@ def _sco_error_response(context, msg, format="html", REQUEST=None): elif format == "xml": REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) doc = ElementTree.Element("error", msg=msg) - return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(scu.SCO_ENCODING) + return sco_xml.XML_HEADER + ElementTree.tostring(doc).decode(SCO_ENCODING) elif format == "json": REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE) return "undefined" # XXX voir quoi faire en cas d'erreur json diff --git a/app/views/absences.py b/app/views/absences.py index c7f280a2..f6e66a68 100644 --- a/app/views/absences.py +++ b/app/views/absences.py @@ -35,14 +35,14 @@ Code dérivé de la partie la plus ancienne de ScoDoc, et à revoir. L'API de plus bas niveau est en gros: AnnuleAbsencesDatesNoJust(etudid, dates) - CountAbs(etudid, debut, fin, matin=None, moduleimpl_id=None) - CountAbsJust(etudid, debut, fin, matin=None, moduleimpl_id=None) - ListeAbsJust(etudid, datedebut) [pas de fin ?] - ListeAbsNonJust(etudid, datedebut) [pas de fin ?] - ListeJustifs(etudid, datedebut, datefin=None, only_no_abs=True) + count_abs(etudid, debut, fin, matin=None, moduleimpl_id=None) + count_abs_just(etudid, debut, fin, matin=None, moduleimpl_id=None) + list_abs_just(etudid, datedebut) [pas de fin ?] + list_abs_non_just(etudid, datedebut) [pas de fin ?] + list_abs_justifs(etudid, datedebut, datefin=None, only_no_abs=True) - ListeAbsJour(date, am=True, pm=True, is_abs=None, is_just=None) - ListeAbsNonJustJour(date, am=True, pm=True) + list_abs_jour(date, am=True, pm=True, is_abs=None, is_just=None) + list_abs_non_just_jour(date, am=True, pm=True) """ @@ -84,8 +84,8 @@ from app.scodoc import html_sco_header from app.scodoc import sco_abs from app.scodoc import sco_abs_notification from app.scodoc import sco_abs_views +from app.scodoc import sco_cache from app.scodoc import sco_compute_moy -from app.scodoc import sco_core from app.scodoc import sco_etud from app.scodoc import sco_excel from app.scodoc import sco_find_etud @@ -261,9 +261,10 @@ sco_publish("/ListeAbsEtud", sco_abs_views.ListeAbsEtud, Permission.ScoView) # # -------------------------------------------------------------------- - -sco_publish("/CountAbs", sco_abs.CountAbs, Permission.ScoView) -sco_publish("/CountAbsJust", sco_abs.CountAbsJust, Permission.ScoView) +# API backward compatibility +sco_publish("/CountAbs", sco_abs.count_abs, Permission.ScoView) +sco_publish("/CountAbsJust", sco_abs.count_abs_just, Permission.ScoView) +# TODO nouvel appel rendnat les deux valeurs et utilisant le cache @bp.route("/doSignaleAbsenceGrSemestre", methods=["GET", "POST"]) @@ -361,7 +362,7 @@ def SignaleAbsenceGrHebdo( else: # Si aucun etudiant n'est inscrit au module choisi... moduleimpl_id = None - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) sem = sco_formsemestre.do_formsemestre_list( context, {"formsemestre_id": formsemestre_id} )[0] @@ -534,7 +535,7 @@ def SignaleAbsenceGrSemestre( base_url = base_url_noweeks + "&nbweeks=%s" % nbweeks # sans le moduleimpl_id if etuds: - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) sem = sco_formsemestre.do_formsemestre_list( context, {"formsemestre_id": formsemestre_id} )[0] @@ -749,8 +750,8 @@ def _gen_form_saisie_groupe( # UE capitalisee dans semestre courant ? cap = [] if etud["cursem"]: - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, etud["cursem"]["formsemestre_id"] + nt = sco_cache.NotesTableCache.get( + etud["cursem"]["formsemestre_id"] ) # > get_ues, get_etud_ue_status for ue in nt.get_ues(): status = nt.get_etud_ue_status(etudid, ue["ue_id"]) @@ -775,7 +776,7 @@ def _gen_form_saisie_groupe( ) ) etud_abs = sco_abs.list_abs_in_range( - context, etudid, begin, end, moduleimpl_id=moduleimpl_id, cursor=cursor + etudid, begin, end, moduleimpl_id=moduleimpl_id, cursor=cursor ) for d in odates: date = d.strftime("%Y-%m-%d") @@ -879,15 +880,13 @@ def EtatAbsencesGr( T = [] for m in groups_infos.members: etud = sco_etud.get_etud_info(etudid=m["etudid"], filled=True)[0] - nbabs = sco_abs.CountAbs( - context, etudid=etud["etudid"], debut=datedebut, fin=datefin - ) - nbabsjust = sco_abs.CountAbsJust( - context, etudid=etud["etudid"], debut=datedebut, fin=datefin + nbabs = sco_abs.count_abs(etudid=etud["etudid"], debut=datedebut, fin=datefin) + nbabsjust = sco_abs.count_abs_just( + etudid=etud["etudid"], debut=datedebut, fin=datefin ) nbjustifs_noabs = len( - sco_abs.ListeJustifs( - context, etudid=etud["etudid"], datedebut=datedebut, only_no_abs=True + sco_abs.list_abs_justifs( + etudid=etud["etudid"], datedebut=datedebut, only_no_abs=True ) ) # retrouve sem dans etud['sems'] @@ -1027,19 +1026,19 @@ def EtatAbsencesDate( """ ) for etud in groups_infos.members: - nbabsam = sco_abs.CountAbs( - context, etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=1 + nbabsam = sco_abs.count_abs( + etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=1 ) - nbabspm = sco_abs.CountAbs( - context, etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=0 + nbabspm = sco_abs.count_abs( + etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=0 ) if (nbabsam != 0) or (nbabspm != 0): nbetud += 1 - nbabsjustam = sco_abs.CountAbsJust( - context, etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=1 + nbabsjustam = sco_abs.count_abs_just( + etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=1 ) - nbabsjustpm = sco_abs.CountAbsJust( - context, etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=0 + nbabsjustpm = sco_abs.count_abs_just( + etudid=etud["etudid"], debut=dateiso, fin=dateiso, matin=0 ) H.append( """ @@ -1516,7 +1515,7 @@ def XMLgetAbsEtud(context, beg_date="", end_date="", REQUEST=None): if not exp.match(end_date): raise ScoValueError("invalid date: %s" % end_date) - Abs = sco_abs.ListeAbsDate(context, etud["etudid"], beg_date, end_date) + Abs = sco_abs.list_abs_date(etud["etudid"], beg_date, end_date) REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) doc = ElementTree.Element( diff --git a/app/views/essais.py b/app/views/essais.py index e82cd6b0..4f4280fb 100644 --- a/app/views/essais.py +++ b/app/views/essais.py @@ -24,7 +24,7 @@ from app.auth.models import Permission from app.views import essais_bp as bp # import sco_core deviendra: -from app.scodoc import sco_core +from app.scodoc import sco_cache context = ScoDoc7Context(globals()) @@ -47,11 +47,11 @@ def sco_exemple(etudid="NON"): # En ScoDoc 7, on avait des vues qui en appellaient d'autres # avec context.sco_exemple( etudid="E12" ) -@bp.route("//Scolarite/sco_exemple2") -@login_required -@scodoc7func(context) -def sco_exemple2(): - return "Exemple 2" + context.sco_exemple(etudid="deux") +# @bp.route("//Scolarite/sco_exemple2") +# @login_required +# @scodoc7func(context) +# def sco_exemple2(): +# return "Exemple 2" + context.sco_exemple(etudid="deux") @bp.route("//Scolarite/sco_exemple3") @@ -72,7 +72,7 @@ def sco_exemple4(toto): @bp.route("//Scolarite/sco_get_version") @scodoc7func(context) def sco_get_version(REQUEST): - return sco_core.sco_get_version(REQUEST) + return "ok" # Fonction ressemblant à une méthode Zope protégée diff --git a/app/views/notes.py b/app/views/notes.py index 5584cc56..d6935fec 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -83,7 +83,6 @@ from app.scodoc import sco_bulletins_pdf from app.scodoc import sco_cache from app.scodoc import sco_codes_parcours from app.scodoc import sco_compute_moy -from app.scodoc import sco_core from app.scodoc import sco_cost_formation from app.scodoc import sco_debouche from app.scodoc import sco_edit_formation @@ -951,8 +950,8 @@ def edit_moduleimpl_expr(context, REQUEST, moduleimpl_id): }, formsemestre_id=sem["formsemestre_id"], ) - sco_core.inval_cache( - context, formsemestre_id=sem["formsemestre_id"] + sco_cache.invalidate_formsemestre( + formsemestre_id=sem["formsemestre_id"] ) # > modif regle calcul return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=" @@ -976,16 +975,14 @@ def view_module_abs(context, REQUEST, moduleimpl_id, format="html"): T = [] for etudid in list_insc: - nb_abs = sco_abs.CountAbs( - context, + nb_abs = sco_abs.count_abs( etudid=etudid, debut=debut_sem, fin=fin_sem, moduleimpl_id=moduleimpl_id, ) if nb_abs: - nb_abs_just = sco_abs.CountAbsJust( - context, + nb_abs_just = sco_abs.count_abs_just( etudid=etudid, debut=debut_sem, fin=fin_sem, @@ -1109,8 +1106,8 @@ def edit_ue_expr(context, REQUEST, formsemestre_id, ue_id): else: sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, tf[2]) - sco_core.inval_cache( - context, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > modif regle calcul return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=" @@ -1274,7 +1271,7 @@ def formsemestre_desinscription( raise ScoValueError("desinscription impossible: semestre verrouille") # -- Si décisions de jury, désinscription interdite - nt = sco_core.get_notes_cache(context).get_NotesTable(context, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) if nt.etud_has_decision(etudid): raise ScoValueError( """Désinscription impossible: l'étudiant a une décision de jury @@ -1733,9 +1730,7 @@ def formsemestre_bulletins_mailetuds( ): "envoi a chaque etudiant (inscrit et ayant un mail) son bulletin" prefer_mail_perso = int(prefer_mail_perso) - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etudids + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etudids etudids = nt.get_etudids() # if not sco_bulletins.can_send_bulletin_by_mail(context, formsemestre_id, REQUEST): @@ -1891,8 +1886,8 @@ def appreciation_add_form( msg=tf[2]["comment"], ) # ennuyeux mais necessaire (pour le PDF seulement) - sco_core.inval_cache( - context, pdfonly=True, formsemestre_id=formsemestre_id + sco_cache.invalidate_formsemestre( + pdfonly=True, formsemestre_id=formsemestre_id ) # > appreciation_add return REQUEST.RESPONSE.redirect(bull_url) @@ -2131,9 +2126,7 @@ def formsemestre_validation_suppress_etud( if not dialog_confirmed: sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) etud = sco_etud.get_etud_info(etudid=etudid, filled=1)[0] - nt = sco_core.get_notes_cache(context).get_NotesTable( - context, formsemestre_id - ) # > get_etud_decision_sem + nt = sco_cache.NotesTableCache.get(formsemestre_id) # > get_etud_decision_sem decision_jury = nt.get_etud_decision_sem(etudid) if decision_jury: existing = ( diff --git a/app/views/scolar.py b/app/views/scolar.py index 8600badf..03f2f3d1 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -83,7 +83,7 @@ from app.scodoc import sco_import_etuds from app.scodoc import sco_abs from app.scodoc import sco_archives_etud from app.scodoc import sco_codes_parcours -from app.scodoc import sco_core +from app.scodoc import sco_cache from app.scodoc import sco_debouche from app.scodoc import sco_dept from app.scodoc import sco_dump_db @@ -246,8 +246,11 @@ def showEtudLog(context, etudid, format="html", REQUEST=None): page_title="Opérations sur %(nomprenom)s" % etud, html_title="

Opérations effectuées sur l'étudiant %(nomprenom)s

" % etud, filename="log_" + scu.make_filename(etud["nomprenom"]), - html_next_section='' - % url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid), + html_next_section=f""" + """, preferences=sco_preferences.SemPreferences( context, ), @@ -1497,9 +1500,9 @@ def _etudident_create_or_edit_form(context, REQUEST, edit): sco_etud.fill_etuds_info([etud]) # Inval semesters with this student: to_inval = [s["formsemestre_id"] for s in etud["sems"]] - if to_inval: - sco_core.inval_cache( - context, formsemestre_id_list=to_inval + for formsemestre_id in to_inval: + sco_cache.invalidate_formsemestre( + formsemestre_id=formsemestre_id ) # > etudident_create_or_edit # return REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid) @@ -1574,8 +1577,8 @@ def etudident_delete(context, etudid, dialog_confirmed=False, REQUEST=None): cnx.commit() # Inval semestres où il était inscrit: to_inval = [s["formsemestre_id"] for s in etud["sems"]] - if to_inval: - sco_core.inval_cache(context, formsemestre_id_list=to_inval) # > + for formsemestre_id in to_inval: + sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id) # > return REQUEST.RESPONSE.redirect( scu.ScoURL() + r"?head_message=Etudiant%20supprimé" ) diff --git a/misc/ArreteDUT2005.txt b/misc/ArreteDUT2005.txt old mode 100644 new mode 100755 diff --git a/requirements-3.7.txt b/requirements-3.7.txt index ccaf72da..60d8cd14 100644 --- a/requirements-3.7.txt +++ b/requirements-3.7.txt @@ -1,34 +1,61 @@ -asn1crypto==0.24.0 -certifi==2018.8.24 -chardet==3.0.4 -configparser==3.5.0b2 -cracklib==2.9.6 -cryptography==2.6.1 -docutils==0.14 -entrypoints==0.3 -enum34==1.1.6 -gyp==0.1 -icalendar==4.0.3 -idna==2.6 -ipaddress==1.0.17 -jaxml==3.1 -keyring==17.1.1 -keyrings.alt==3.1.1 -olefile==0.46 -Pillow==5.4.1 -psycopg2==2.7.7 -pycrypto==2.6.1 -Pygments==2.3.1 -PyGObject==3.30.4 -pyOpenSSL==19.0.0 +alembic==1.6.5 +astroid==2.6.2 +Babel==2.9.1 +blinker==1.4 +certifi==2021.5.30 +chardet==4.0.0 +click==8.0.1 +cracklib==2.9.3 +dnspython==2.1.0 +dominate==2.6.0 +email-validator==1.1.3 +Flask==2.0.1 +Flask-Babel==2.0.0 +Flask-Bootstrap==3.3.7.1 +Flask-Caching==1.10.1 +Flask-Login==0.5.0 +Flask-Mail==0.9.1 +Flask-Migrate==3.0.1 +Flask-Moment==1.0.1 +Flask-SQLAlchemy==2.5.1 +Flask-WTF==0.15.1 +greenlet==1.1.0 +html2text==2020.1.16 +icalendar==4.0.7 +idna==2.10 +importlib-metadata==4.6.1 +isort==5.9.2 +itsdangerous==2.0.1 +Jinja2==3.0.1 +lazy-object-proxy==1.6.0 +Mako==1.1.4 +MarkupSafe==2.0.1 +mccabe==0.6.1 +Pillow==8.3.1 +pkg-resources==0.0.0 +psycopg2==2.9.1 +pydot==1.4.2 +PyJWT==2.1.0 +pylibmc==1.6.1 +pylint==2.9.3 +pylint-flask-sqlalchemy==0.2.0 +pymemcache==3.5.0 +pyparsing==2.4.7 PyRSS2Gen==1.1 -python-dateutil==2.7.3 -pytz==2019.1 -pyxdg==0.25 -reportlab==3.5.13 -requests==2.21.0 -roman==2.0.0 -SecretStorage==2.3.1 -six==1.12.0 -urllib3==1.24.1 -virtualenv==15.1.0 +python-dateutil==2.8.1 +python-dotenv==0.18.0 +python-editor==1.0.4 +pytz==2021.1 +reportlab==3.5.68 +requests==2.25.1 +six==1.16.0 +SQLAlchemy==1.4.20 +toml==0.10.2 +typed-ast==1.4.3 +typing-extensions==3.10.0.0 +urllib3==1.26.6 +visitor==0.1.3 +Werkzeug==2.0.1 +wrapt==1.12.1 +WTForms==2.3.3 +zipp==3.5.0 diff --git a/scodoc_manager.py b/scodoc_manager.py old mode 100644 new mode 100755 diff --git a/scotests/test-all-moys.py b/scotests/test-all-moys.py index 7471539f..b94e6190 100644 --- a/scotests/test-all-moys.py +++ b/scotests/test-all-moys.py @@ -12,6 +12,8 @@ from __future__ import print_function from debug import go_dept import time +from app.scodoc import sco_cache + DeptName = "CJ" context = go_dept(app, DeptName) @@ -23,7 +25,7 @@ L = [] n = 0 for sem in sems: formsemestre_id = sem["formsemestre_id"] - nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_id) + nt = sco_cache.NotesTableCache.get(formsemestre_id) etudids = nt.get_etudids() use_ue_coef = sco_preferences.get_preference( context, "use_ue_coefs", formsemestre_id diff --git a/scotests/test_CountAbs.py b/scotests/test_CountAbs.py index 25057b52..05949395 100644 --- a/scotests/test_CountAbs.py +++ b/scotests/test_CountAbs.py @@ -53,44 +53,62 @@ for debut, fin, demijournee in [ ("15/01/2021", "15/01/2021", 1), ("18/01/2021", "18/01/2021", 0), ("19/01/2021", "19/01/2021", 2), - ("22/01/2021", "22/01/2021", 1) -] : - sco_abs_views.doSignaleAbsence(context.Absences, datedebut=debut, datefin=fin, demijournee=demijournee, etudid=etudid, REQUEST=REQUEST) + ("22/01/2021", "22/01/2021", 1), +]: + sco_abs_views.doSignaleAbsence( + context.Absences, + datedebut=debut, + datefin=fin, + demijournee=demijournee, + etudid=etudid, + REQUEST=REQUEST, + ) # --- Justification de certaines absences -for debut, fin, demijournee in [ +for debut, fin, demijournee in [ ("15/01/2021", "15/01/2021", 1), ("18/01/2021", "18/01/2021", 0), - ("19/01/2021", "19/01/2021", 2) -] : - sco_abs_views.doJustifAbsence(context.Absences, datedebut=debut, datefin=fin, demijournee=demijournee, etudid=etudid, REQUEST=REQUEST) + ("19/01/2021", "19/01/2021", 2), +]: + sco_abs_views.doJustifAbsence( + context.Absences, + datedebut=debut, + datefin=fin, + demijournee=demijournee, + etudid=etudid, + REQUEST=REQUEST, + ) -# --- Utilisation de CountAbs() de sco_abs +# --- Utilisation de get_abs_count() de sco_abs + +nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) -a = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) -nb_abs = a.CountAbs() -nb_absj = a.CountAbsJust() # --- Utilisation de CountAbs() de ZAbsences nb_abs2 = context.Absences.CountAbs(etudid=etudid, debut="01/01/2021", fin="06/30/2021") -nb_absj2 = context.Absences.CountAbsJust(etudid=etudid, debut="01/01/2021", fin="06/30/2021") +nb_absj2 = context.Absences.CountAbsJust( + etudid=etudid, debut="01/01/2021", fin="06/30/2021" +) -assert nb_abs == nb_abs2 == 5 -assert nb_absj == nb_absj2 == 4 +assert nbabs == nb_abs2 == 5 +assert nbabsjust == nb_absj2 == 4 -# --- Supression d'absence +# --- Suppression d'absence -_ = sco_abs_views.doAnnuleAbsence(context.Absences, "19/01/2021", "19/01/2021", 2, etudid=etudid, REQUEST=REQUEST) -b = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) +_ = sco_abs_views.doAnnuleAbsence( + context.Absences, "19/01/2021", "19/01/2021", 2, etudid=etudid, REQUEST=REQUEST +) # --- Vérification -new_nbabs = b.CountAbs() -new_nbabs2 = context.Absences.CountAbs(etudid=etudid, debut="01/01/2021", fin="06/30/2021") +new_nbabs, _ = sco_abs.get_abs_count(etudid, sem) +new_nbabs2 = context.Absences.CountAbs( + etudid=etudid, debut="01/01/2021", fin="06/30/2021" +) print(new_nbabs) print(new_nbabs2) diff --git a/scotests/test_abs_demijournee.py b/scotests/test_abs_demijournee.py index 84582a24..a66a11be 100644 --- a/scotests/test_abs_demijournee.py +++ b/scotests/test_abs_demijournee.py @@ -104,14 +104,16 @@ _ = sco_abs_views.doJustifAbsence( # --- Test -a = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) -assert a.CountAbs() == 4 #l'étudiant a été absent le 15 journée compléte (2 abs : 1 matin, 1 apres midi) et le 18 (1 matin), et le 19 (1 apres midi). -assert a.CountAbsJust() == 2 # Justifie abs du matin + abs après midi +nbabs, nbabs_just = sco_abs.get_abs_count(etudid, sem) +assert ( + nbabs == 4 +) # l'étudiant a été absent le 15 journée compléte (2 abs : 1 matin, 1 apres midi) et le 18 (1 matin), et le 19 (1 apres midi). +assert nbabs_just == 2 # Justifie abs du matin + abs après midi """ Commentaire : Pb : le 2 ne peut pas être pris en tant que int car string dans la fonction ------> Pb regler +-----> Pb reglé """ \ No newline at end of file diff --git a/scotests/test_absence.py b/scotests/test_absence.py index 6c2fdd92..9913cc46 100644 --- a/scotests/test_absence.py +++ b/scotests/test_absence.py @@ -6,11 +6,9 @@ Fonctions de l'API utilisé : - doSignaleAbsence - doAnnuleAbsence - doJustifAbsence - - getAbsSemEtud - get_partition_groups - get_partitions_list - - CountAbs - - CountAbsJust + - sco_abs.get_abs_count(etudid, sem) - ListeAbsEtud - partition_create - createGroup @@ -71,7 +69,7 @@ mi = G.create_moduleimpl( for etud in etuds: G.inscrit_etudiant(sem, etud) -#--- Création d'une évaluation +# --- Création d'une évaluation e = G.create_evaluation( moduleimpl_id=mi["moduleimpl_id"], jour="22/01/2021", @@ -151,23 +149,26 @@ _ = sco_abs_views.doJustifAbsence( # --- Test b = sco_abs.is_work_saturday(context.Absences) -assert b == 0 #samedi ne sont pas compris -a = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) -assert a.CountAbs() == 5 #l'étudiant a été absent le 15 (apres midi) , (16 et 17 we), 18 (matin) et 19 janvier (matin et apres midi), et 22 (matin) -assert a.CountAbsJust() == 4 #l'étudiant justifie ses abs du 15, 18 et 19 - +assert b == 0 # samedi ne sont pas compris +nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) +assert ( + nbabs == 5 +) # l'étudiant a été absent le 15 (apres midi) , (16 et 17 we), 18 (matin) et 19 janvier (matin et apres midi), et 22 (matin) +assert nbabsjust == 4 # l'étudiant justifie ses abs du 15, 18 et 19 + # + vérification à l'aide de ScoDoc WEB : ok! # --- Supression d'une absence et d'une justification -_ = sco_abs_views.doAnnuleAbsence(context.Absences, "19/01/2021", "19/01/2021", 2, etudid=etudid, REQUEST=REQUEST) -a = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) -print(a.CountAbs()) #lors du print cela affiche 5 or cela devrait afficher 3 - -#assert a.CountAbs() == 3 -# + vérification à l'aide de ScoDoc WEB : il y a bien plus que 3 abs, 2 justifiés et 1 non justifié. +_ = sco_abs_views.doAnnuleAbsence( + context.Absences, "19/01/2021", "19/01/2021", 2, etudid=etudid, REQUEST=REQUEST +) +nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) +print(nbabs) # lors du print cela affiche 5 or cela devrait afficher 3 +# assert nbabs == 3 +# + vérification à l'aide de ScoDoc WEB : il y a bien plus que 3 abs, 2 justifiés et 1 non justifié. # --- supression d'une justification pas encore disponible à l'aide de python. @@ -175,8 +176,12 @@ print(a.CountAbs()) #lors du print cela affiche 5 or cela devrait afficher 3 # --- Création d'une liste d'abs -liste_abs = sco_abs_views.ListeAbsEtud(context.Absences, etudid, format='json', absjust_only=1, REQUEST=REQUEST) -liste_abs2 = sco_abs_views.ListeAbsEtud(context.Absences, etudid, format='json', REQUEST=REQUEST) +liste_abs = sco_abs_views.ListeAbsEtud( + context.Absences, etudid, format="json", absjust_only=1, REQUEST=REQUEST +) +liste_abs2 = sco_abs_views.ListeAbsEtud( + context.Absences, etudid, format="json", REQUEST=REQUEST +) load_liste_abs = json.loads(liste_abs) load_liste_abs2 = json.loads(liste_abs2) @@ -191,61 +196,78 @@ assert load_liste_abs2[0]["exams"] == mod["code"] # --- Création d'un groupe -_ = sco_groups.partition_create(context.Scolarite, formsemestre_id=sem["formsemestre_id"], partition_name="Eleve", REQUEST=REQUEST) +_ = sco_groups.partition_create( + context.Scolarite, + formsemestre_id=sem["formsemestre_id"], + partition_name="Eleve", + REQUEST=REQUEST, +) li1 = sco_groups.get_partitions_list(context.Scolarite, sem["formsemestre_id"]) -_ = sco_groups.createGroup(context.Scolarite, li1[0]["partition_id"], "Groupe 1", REQUEST=REQUEST) +_ = sco_groups.createGroup( + context.Scolarite, li1[0]["partition_id"], "Groupe 1", REQUEST=REQUEST +) # --- Affectation des élèves dans des groupes li_grp1 = sco_groups.get_partition_groups(context.Scolarite, li1[0]) -for etud in etuds : +for etud in etuds: sco_groups.set_group(context.Scolarite, etud["etudid"], li_grp1[0]["group_id"]) # --- Test de EtatAbsencesGroupes -grp1_abs = context.Absences.EtatAbsencesGr(group_ids=[li_grp1[0]["group_id"]], debut="01/01/2021", fin ="30/06/2021", format="json", REQUEST=REQUEST) +grp1_abs = context.Absences.EtatAbsencesGr( + group_ids=[li_grp1[0]["group_id"]], + debut="01/01/2021", + fin="30/06/2021", + format="json", + REQUEST=REQUEST, +) load_grp1_abs = json.loads(grp1_abs) assert len(load_grp1_abs) == 10 -tab_id=[] #tab des id present dans load_grp1_abs -for un_etud in load_grp1_abs : +tab_id = [] # tab des id present dans load_grp1_abs +for un_etud in load_grp1_abs: tab_id.append(un_etud["etudid"]) - -for etud in etuds : #verification si tous les etudiants sont present dans la liste du groupe d'absence + +for ( + etud +) in ( + etuds +): # verification si tous les etudiants sont present dans la liste du groupe d'absence assert etud["etudid"] in tab_id -for un_etud in load_grp1_abs : - if un_etud["etudid"] == etudid : +for un_etud in load_grp1_abs: + if un_etud["etudid"] == etudid: assert un_etud["nbabs"] == "3" assert un_etud["nbjustifs_noabs"] == "2" assert un_etud["nbabsjust"] == "2" assert un_etud["nbabsnonjust"] == "1" assert un_etud["nomprenom"] == etuds[0]["nomprenom"] -# --- Création de billets +# --- Création de billets b1 = context.Absences.AddBilletAbsence( - begin="2021-01-22 00:00", - end="2021-01-22 23:59", - etudid=etudid, - description = "abs du 22", - justified=False, - code_nip=etuds[0]["code_nip"], - code_ine=etuds[0]["code_ine"], - REQUEST=REQUEST, - ) + begin="2021-01-22 00:00", + end="2021-01-22 23:59", + etudid=etudid, + description="abs du 22", + justified=False, + code_nip=etuds[0]["code_nip"], + code_ine=etuds[0]["code_ine"], + REQUEST=REQUEST, +) b2 = context.Absences.AddBilletAbsence( - begin="2021-01-15 00:00", - end="2021-01-15 23:59", - etudid=etudid, - description = "abs du 15", - code_nip=etuds[0]["code_nip"], - code_ine=etuds[0]["code_ine"], - REQUEST=REQUEST, - ) + begin="2021-01-15 00:00", + end="2021-01-15 23:59", + etudid=etudid, + description="abs du 15", + code_nip=etuds[0]["code_nip"], + code_ine=etuds[0]["code_ine"], + REQUEST=REQUEST, +) li_bi = context.Absences.listeBilletsEtud(etudid=etudid, REQUEST=REQUEST, format="json") diff --git a/scotests/test_absence2.py b/scotests/test_absence2.py index 2cb303cb..d141b0f4 100644 --- a/scotests/test_absence2.py +++ b/scotests/test_absence2.py @@ -12,11 +12,11 @@ Fonction de l'API utilisé : - AddBilletAbs - XMLgetBilletAbsence - listeBilletEtud - - ListeAbsJust + - list_abs_just - CountAbsJust - ListAbsNonJust - ListJustifs - - ListeAbsJour + - list_abs_jour - ListAbsInRange Fonction renvoyant du code HTML : @@ -83,14 +83,21 @@ for etud in etuds: # --- Création d'un groupe -_ = sco_groups.partition_create(context.Scolarite, formsemestre_id=sem["formsemestre_id"], partition_name="Eleve", REQUEST=REQUEST) +_ = sco_groups.partition_create( + context.Scolarite, + formsemestre_id=sem["formsemestre_id"], + partition_name="Eleve", + REQUEST=REQUEST, +) li1 = sco_groups.get_partitions_list(context.Scolarite, sem["formsemestre_id"]) -_ = sco_groups.createGroup(context.Scolarite, li1[0]["partition_id"], "Groupe 1", REQUEST=REQUEST) +_ = sco_groups.createGroup( + context.Scolarite, li1[0]["partition_id"], "Groupe 1", REQUEST=REQUEST +) # --- Affectation des élèves dans des groupes li_grp1 = sco_groups.get_partition_groups(context.Scolarite, li1[0]) -for etud in etuds : +for etud in etuds: sco_groups.set_group(context.Scolarite, etud["etudid"], li_grp1[0]["group_id"]) # --- Saisie absences @@ -100,9 +107,16 @@ for debut, fin, demijournee in [ ("15/01/2021", "15/01/2021", 1), ("18/01/2021", "18/01/2021", 0), ("19/01/2021", "19/01/2021", 2), - ("22/01/2021", "22/01/2021", 1) -] : - sco_abs_views.doSignaleAbsence(context.Absences, datedebut=debut, datefin=fin, demijournee=demijournee, etudid=etudid, REQUEST=REQUEST) + ("22/01/2021", "22/01/2021", 1), +]: + sco_abs_views.doSignaleAbsence( + context.Absences, + datedebut=debut, + datefin=fin, + demijournee=demijournee, + etudid=etudid, + REQUEST=REQUEST, + ) _ = sco_abs_views.doSignaleAbsence( context.Absences, @@ -115,44 +129,51 @@ _ = sco_abs_views.doSignaleAbsence( # --- Justification de certaines absences -for debut, fin, demijournee in [ +for debut, fin, demijournee in [ ("15/01/2021", "15/01/2021", 1), ("18/01/2021", "18/01/2021", 0), - ("19/01/2021", "19/01/2021", 2) -] : - sco_abs_views.doJustifAbsence(context.Absences, datedebut=debut, datefin=fin, demijournee=demijournee, etudid=etudid, REQUEST=REQUEST) + ("19/01/2021", "19/01/2021", 2), +]: + sco_abs_views.doJustifAbsence( + context.Absences, + datedebut=debut, + datefin=fin, + demijournee=demijournee, + etudid=etudid, + REQUEST=REQUEST, + ) # --- Test _ = context.Absences.doSignaleAbsenceGrSemestre( - dates="2021-01-13,2021-01-25", - etudids= etuds[5]["etudid"]+","+etuds[6]["etudid"], - destination="", - REQUEST=REQUEST - ) # <----- rien ne se passe (pb parametre ?) + dates="2021-01-13,2021-01-25", + etudids=etuds[5]["etudid"] + "," + etuds[6]["etudid"], + destination="", + REQUEST=REQUEST, +) # <----- rien ne se passe (pb parametre ?) -# --- Création de billets +# --- Création de billets b1 = context.Absences.AddBilletAbsence( - begin="2021-01-22 00:00", - end="2021-01-22 23:59", - etudid=etudid, - description = "abs du 22", - justified=False, - code_nip=etuds[0]["code_nip"], - code_ine=etuds[0]["code_ine"], - REQUEST=REQUEST, - ) + begin="2021-01-22 00:00", + end="2021-01-22 23:59", + etudid=etudid, + description="abs du 22", + justified=False, + code_nip=etuds[0]["code_nip"], + code_ine=etuds[0]["code_ine"], + REQUEST=REQUEST, +) b2 = context.Absences.AddBilletAbsence( - begin="2021-01-15 00:00", - end="2021-01-15 23:59", - etudid=etudid, - description = "abs du 15", - code_nip=etuds[0]["code_nip"], - code_ine=etuds[0]["code_ine"], - REQUEST=REQUEST, - ) + begin="2021-01-15 00:00", + end="2021-01-15 23:59", + etudid=etudid, + description="abs du 15", + code_nip=etuds[0]["code_nip"], + code_ine=etuds[0]["code_ine"], + REQUEST=REQUEST, +) # --- XMLgetBilletEtud @@ -161,22 +182,24 @@ print(1) print(xml_bi) print(1) -# --- Supression de billet +# --- Supression de billet li_bi = context.Absences.listeBilletsEtud(etudid=etudid, REQUEST=REQUEST, format="json") load_li_bi = json.loads(li_bi) -#_ = context.Absences.deleteBilletAbsence(load_li_bi[1]["billet_id"], REQUEST=REQUEST) +# _ = context.Absences.deleteBilletAbsence(load_li_bi[1]["billet_id"], REQUEST=REQUEST) -li_bi2 = context.Absences.listeBilletsEtud(etudid=etudid, REQUEST=REQUEST, format="json") +li_bi2 = context.Absences.listeBilletsEtud( + etudid=etudid, REQUEST=REQUEST, format="json" +) load_li_bi2 = json.loads(li_bi) -#assert len(load_li_bi2) == 1 -#assert load_li_bi2[0]["description"] == "abs du 22" +# assert len(load_li_bi2) == 1 +# assert load_li_bi2[0]["description"] == "abs du 22" # --- Créaton de listes -li_abs_just = context.Absences.ListeAbsJust(etudid = etudid, datedebut="01/01/2021") -nb_abs_just = context.Absences.CountAbsJust(etudid, debut="01/01/2021", fin="06/30/2021") +li_abs_just = sco_abs.list_abs_just(etudid=etudid, datedebut="01/01/2021") +nb_abs_just = sco_abs.count_abs_just(etudid, debut="01/01/2021", fin="06/30/2021") assert len(li_abs_just) == nb_abs_just assert li_abs_just[0]["etudid"] == etudid assert li_abs_just[0]["matin"] == True @@ -193,57 +216,64 @@ assert li_abs_njust[0]["etudid"] == etudid assert li_abs_njust[0]["jour"] == datetime.date(2021, 1, 22) -li_just = context.Absences.ListeJustifs(etudid=etudid, datedebut="01/01/2021") +li_just = sco_abs.list_abs_justifs(etudid=etudid, datedebut="2021-01-01") assert len(li_just) == 4 -li_just2 = context.Absences.ListeJustifs(etudid=etudid, datedebut="01/01/2021", datefin="01/18/2021") +li_just2 = context.Absences.list_abs_justifs( + etudid=etudid, datedebut="2021-01-01", datefin="2021-01-18" +) assert len(li_just2) == 2 -li_jour = context.Absences.ListeAbsJour(date="01/22/2021") +li_jour = sco_abs.list_abs_jour(date="01/22/2021") assert len(li_jour) == 2 -li_jour2 = context.Absences.ListeAbsJour(date="01/18/2021") +li_jour2 = sco_abs.list_abs_jour(date="01/18/2021") assert len(li_jour2) == 1 li_range = context.Absences.ListAbsInRange(etudid, debut="01/01/2021", fin="06/01/2021") assert len(li_range) == 5 -#li_xml = context.Absences.XMLgetAbsEtud(beg_date="01/01/2021", end_date="01/06/2021", REQUEST=REQUEST) -#print(li_xml) need etudid +# li_xml = context.Absences.XMLgetAbsEtud(beg_date="01/01/2021", end_date="01/06/2021", REQUEST=REQUEST) +# print(li_xml) need etudid # --- Annulation d'absence -#context.Absences.AnnuleAbsencesDatesNoJust(etudid, dates="22/01/2021", REQUEST=REQUEST) +# context.Absences.AnnuleAbsencesDatesNoJust(etudid, dates="22/01/2021", REQUEST=REQUEST) # --- Fonction renvoyant du code HTML etat_abs = context.Absences.EtatAbsences(REQUEST=REQUEST) -#cal_abs = sco_abs_views.CalAbs(context.Absences, REQUEST=REQUEST) #<--- retourne html + need etudid : how? +# cal_abs = sco_abs_views.CalAbs(context.Absences, REQUEST=REQUEST) #<--- retourne html + need etudid : how? sag = context.Absences.SignaleAbsenceGrSemestre( - datedebut="15/01/2021", - datefin="22/01/2021", - group_ids=[li_grp1[0]["group_id"]], - REQUEST=REQUEST, - ) + datedebut="15/01/2021", + datefin="22/01/2021", + group_ids=[li_grp1[0]["group_id"]], + REQUEST=REQUEST, +) sagh = context.Absences.SignaleAbsenceGrHebdo( - datelundi="18/01/2021", group_ids=[li_grp1[0]["group_id"]], destination="", REQUEST=REQUEST - ) + datelundi="18/01/2021", + group_ids=[li_grp1[0]["group_id"]], + destination="", + REQUEST=REQUEST, +) -grp_abs_d = context.Absences.EtatAbsencesDate(group_ids=[li_grp1[0]["group_id"]], date="22/01/2021", REQUEST=REQUEST) +grp_abs_d = context.Absences.EtatAbsencesDate( + group_ids=[li_grp1[0]["group_id"]], date="22/01/2021", REQUEST=REQUEST +) billet_form = context.Absences.AddBilletAbsenceForm(etudid=etudid, REQUEST=REQUEST) -#an_abs = AnnuleAbsenceEtud(context.Absences, REQUEST=REQUEST) #<- retourne html + need etudid : how? +# an_abs = AnnuleAbsenceEtud(context.Absences, REQUEST=REQUEST) #<- retourne html + need etudid : how? -#proc = context.Absences.ProcessBilletAbsenceForm(billet_id=load_li_bi[0]["billet_id"], REQUEST=REQUEST) #error +# proc = context.Absences.ProcessBilletAbsenceForm(billet_id=load_li_bi[0]["billet_id"], REQUEST=REQUEST) #error -#just_form = sco_abs_views.JustifAbsenceEtud(context.Absences, REQUEST=REQUEST) +# just_form = sco_abs_views.JustifAbsenceEtud(context.Absences, REQUEST=REQUEST) -#delete_just = sco_abs_views.doAnnuleJustif(context.Absences, datedebut0="22/01/2021", datefin0="22/01/2021", demijournee=2, REQUEST=REQUEST) +# delete_just = sco_abs_views.doAnnuleJustif(context.Absences, datedebut0="22/01/2021", datefin0="22/01/2021", demijournee=2, REQUEST=REQUEST) """ @@ -263,5 +293,3 @@ XMLgetBilletsEtud, deleteBilletAbsence -> fonction get ne retourne rien et delet AnnuleAbsencesDatesNoJust -> error line 323, jour='2' (2 doit être un int et non un string?) """ - - diff --git a/scotests/test_basic.py b/scotests/test_basic.py index 22899885..8cf0018b 100644 --- a/scotests/test_basic.py +++ b/scotests/test_basic.py @@ -152,9 +152,9 @@ _ = sco_abs_views.doJustifAbsence( REQUEST=REQUEST, ) -a = sco_abs.getAbsSemEtud(context, sem, etudid) -assert a.CountAbs() == 6, "incorrect CountAbs (%d)" % a.CountAbs() -assert a.CountAbsJust() == 2, "incorrect CountAbsJust (%s)" % a.CountAbsJust() +nbabs, nbabsjust = sco_abs.get_abs_count(etudid, sem) +assert nbabs == 6, "incorrect nbabs (%d)" % nbabs +assert nbabsjust == 2, "incorrect nbabsjust (%s)" % nbabsjust # --- Permission saisie notes et décisions de jury, avec ou sans démission ou défaillance # on n'a pas encore saisi de décisions