nouvelle implementation des caches

This commit is contained in:
Emmanuel Viennet 2021-07-19 20:53:01 +03:00
parent e345561d43
commit 5b2d4e47ec
71 changed files with 840 additions and 970 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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 = {}

View File

@ -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"

View File

@ -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()

View File

@ -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)
# ------------------------------------------------------------------------------------------------------------------

View File

@ -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)

View File

@ -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)
@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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",
},
),

View File

@ -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"] = ""

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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 (

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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"

View File

@ -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"],

View File

@ -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.

View File

@ -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):

View File

@ -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):

View File

@ -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:

View File

@ -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')

View File

@ -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 = []

View File

@ -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é ?

View File

@ -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

View File

@ -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("</ul>")
else:
z = ["""<h3>Aucune modification</h3>"""]
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(

View File

@ -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(

View File

@ -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:

View File

@ -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):
),
"""<p><b style="font-size: 130%">Tableau de bord: </b><span class="help">cliquez sur un module pour saisir des notes</span></p>""",
]
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(

View File

@ -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(
'<td class="rcp_moy">%s</td>' % 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('<td class="rcp_abs">%d</td>' % (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)

View File

@ -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:

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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}
)

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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())

View File

@ -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()

View File

@ -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]

View File

@ -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:

View File

@ -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 !")

View File

@ -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"] = {

View File

@ -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

View File

@ -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()
"""

View File

@ -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 }

View File

@ -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

View File

@ -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(
"""<tr bgcolor="#FFFFFF"><td>
@ -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(

View File

@ -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("/<scodoc_dept>/Scolarite/sco_exemple2")
@login_required
@scodoc7func(context)
def sco_exemple2():
return "Exemple 2" + context.sco_exemple(etudid="deux")
# @bp.route("/<scodoc_dept>/Scolarite/sco_exemple2")
# @login_required
# @scodoc7func(context)
# def sco_exemple2():
# return "Exemple 2" + context.sco_exemple(etudid="deux")
@bp.route("/<scodoc_dept>/Scolarite/sco_exemple3")
@ -72,7 +72,7 @@ def sco_exemple4(toto):
@bp.route("/<scodoc_dept>/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

View File

@ -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 = (

View File

@ -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="<h2>Opérations effectuées sur l'étudiant %(nomprenom)s</h2>" % etud,
filename="log_" + scu.make_filename(etud["nomprenom"]),
html_next_section='<ul><li><a href="%s">fiche de %(nomprenom)s</a></li></ul>'
% url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid),
html_next_section=f"""
<ul><li>
<a href="{url_for("scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=etudid)}">
fiche de {etud['nomprenom']}</a></li>
</ul>""",
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é"
)

0
misc/ArreteDUT2005.txt Normal file → Executable file
View File

View File

@ -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

0
scodoc_manager.py Normal file → Executable file
View File

View File

@ -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

View File

@ -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)

View File

@ -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é
"""

View File

@ -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,32 +149,39 @@ _ = 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
_ = 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 a.CountAbs() == 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.
# --- 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,33 +196,50 @@ 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"
@ -227,25 +249,25 @@ for un_etud in load_grp1_abs :
# --- 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")

View File

@ -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
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
@ -165,18 +186,20 @@ print(1)
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?)
"""

View File

@ -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