Modifie l'implémentation des préférences pour ScoDoc 9

This commit is contained in:
Emmanuel Viennet 2021-09-07 22:03:33 +02:00
parent af77a2a389
commit 998f28d4a4
3 changed files with 243 additions and 214 deletions

View File

@ -147,6 +147,52 @@ def get_preference(name, formsemestre_id=None):
return get_base_preferences().get(formsemestre_id, name) return get_base_preferences().get(formsemestre_id, name)
def _convert_pref_type(p, pref_spec):
"""p est une ligne de la bd
{'id': , 'dept_id': , 'name': '', 'value': '', 'formsemestre_id': }
converti la valeur chane en le type désiré spécifié par pref_spec
"""
if "type" in pref_spec:
typ = pref_spec["type"]
if typ == "float":
# special case for float values (where NULL means 0)
if p["value"]:
p["value"] = float(p["value"])
else:
p["value"] = 0.0
else:
func = eval(typ)
p["value"] = func(p["value"])
if pref_spec.get("input_type", None) == "boolcheckbox":
# boolcheckbox: la valeur stockée en base est une chaine "0" ou "1"
# que l'on ressort en True|False
if p["value"]:
try:
p["value"] = bool(int(p["value"]))
except ValueError:
log(
f"""Warning: invalid value for boolean pref in db: '{p["value"]}'"""
)
p["value"] = False
else:
p["value"] = False # NULL (backward compat)
def _get_pref_default_value_from_config(name, pref_spec):
"""get default value store in application level config.
If not found, use defalut value hardcoded in pref_spec.
"""
# XXX va changer avec la nouvelle base
# search in scu.CONFIG
if hasattr(scu.CONFIG, name):
value = getattr(scu.CONFIG, name)
log("sco_preferences: found default value in config for %s=%s" % (name, value))
else:
# uses hardcoded default
value = pref_spec["initvalue"]
return value
PREF_CATEGORIES = ( PREF_CATEGORIES = (
# sur page "Paramètres" # sur page "Paramètres"
("general", {}), ("general", {}),
@ -469,21 +515,27 @@ class BasePreferences(object):
"abs_notification_mail_tmpl", "abs_notification_mail_tmpl",
{ {
"initvalue": """ "initvalue": """
--- Ceci est un message de notification automatique issu de ScoDoc --- --- Ceci est un message de notification automatique issu de ScoDoc ---
L'étudiant %(nomprenom)s
L'étudiant %(nomprenom)s L'étudiant %(nomprenom)s
L'étudiant %(nomprenom)s
inscrit en %(inscription)s)
inscrit en %(inscription)s) inscrit en %(inscription)s)
inscrit en %(inscription)s)
a cumulé %(nbabsjust)s absences justifiées
a cumulé %(nbabsjust)s absences justifiées a cumulé %(nbabsjust)s absences justifiées
et %(nbabsnonjust)s absences NON justifiées. a cumulé %(nbabsjust)s absences justifiées
et %(nbabsnonjust)s absences NON justifiées.
Le compte a pu changer depuis cet envoi, voir la fiche sur %(url_ficheetud)s. Le compte a pu changer depuis cet envoi, voir la fiche sur %(url_ficheetud)s.
Votre dévoué serveur ScoDoc. Votre dévoué serveur ScoDoc.
PS: Au dela de %(abs_notify_abs_threshold)s, un email automatique est adressé toutes les %(abs_notify_abs_increment)s absences. Ces valeurs sont modifiables dans les préférences de ScoDoc. PS: Au dela de %(abs_notify_abs_threshold)s, un email automatique est adressé toutes les %(abs_notify_abs_increment)s absences. Ces valeurs sont modifiables dans les préférences de ScoDoc.
""", """,
"title": """Message notification e-mail""", "title": """Message notification e-mail""",
"explanation": """Balises remplacées, voir la documentation""", "explanation": """Balises remplacées, voir la documentation""",
"input_type": "textarea", "input_type": "textarea",
@ -826,14 +878,18 @@ class BasePreferences(object):
"PV_INTRO", "PV_INTRO",
{ {
"initvalue": """<bullet>-</bullet> "initvalue": """<bullet>-</bullet>
Vu l'arrêté du 3 août 2005 relatif au diplôme universitaire de technologie et notamment son article 4 et 6; Vu l'arrêté du 3 août 2005 relatif au diplôme universitaire de technologie et notamment son article 4 et 6;
</para> </para>
<para><bullet>-</bullet>
<para><bullet>-</bullet> <para><bullet>-</bullet>
vu l'arrêté n° %(Decnum)s du Président de l'%(UnivName)s; <para><bullet>-</bullet>
</para> vu l'arrêté n° %(Decnum)s du Président de l'%(UnivName)s;
</para>
<para><bullet>-</bullet>
<para><bullet>-</bullet> <para><bullet>-</bullet>
vu la délibération de la commission %(Type)s en date du %(Date)s présidée par le Chef du département; <para><bullet>-</bullet>
""", vu la délibération de la commission %(Type)s en date du %(Date)s présidée par le Chef du département;
""",
"title": """Paragraphe d'introduction sur le PV""", "title": """Paragraphe d'introduction sur le PV""",
"explanation": """Balises remplacées: %(Univname)s = nom de l'université, %(DecNum)s = numéro de l'arrêté, %(Date)s = date de la commission, %(Type)s = type de commission (passage ou délivrance), %(VDICode)s = code diplôme""", "explanation": """Balises remplacées: %(Univname)s = nom de l'université, %(DecNum)s = numéro de l'arrêté, %(Date)s = date de la commission, %(Type)s = type de commission (passage ou délivrance), %(VDICode)s = code diplôme""",
"input_type": "textarea", "input_type": "textarea",
@ -940,8 +996,8 @@ class BasePreferences(object):
"PV_LETTER_PASSAGE_SIGNATURE", "PV_LETTER_PASSAGE_SIGNATURE",
{ {
"initvalue": """Pour le Directeur de l'IUT<br/> "initvalue": """Pour le Directeur de l'IUT<br/>
et par délégation<br/> et par délégation<br/>
Le Chef du département""", Le Chef du département""",
"title": """Signature des lettres individuelles de passage d'un semestre à l'autre""", "title": """Signature des lettres individuelles de passage d'un semestre à l'autre""",
"explanation": """%(DirectorName)s et %(DirectorTitle)s remplacés""", "explanation": """%(DirectorName)s et %(DirectorTitle)s remplacés""",
"input_type": "textarea", "input_type": "textarea",
@ -965,43 +1021,45 @@ class BasePreferences(object):
"PV_LETTER_TEMPLATE", "PV_LETTER_TEMPLATE",
{ {
"initvalue": """<para spaceBefore="1mm"> </para> "initvalue": """<para spaceBefore="1mm"> </para>
<para spaceBefore="20mm" leftindent="%(pv_htab1)s">%(INSTITUTION_CITY)s, le %(date_jury)s <para spaceBefore="20mm" leftindent="%(pv_htab1)s">%(INSTITUTION_CITY)s, le %(date_jury)s
</para> </para>
<para leftindent="%(pv_htab1)s" spaceBefore="10mm"> <para leftindent="%(pv_htab1)s" spaceBefore="10mm">
à <b>%(nomprenom)s</b> à <b>%(nomprenom)s</b>
</para> </para>
<para leftindent="%(pv_htab1)s">%(domicile)s</para> <para leftindent="%(pv_htab1)s">%(domicile)s</para>
<para leftindent="%(pv_htab1)s">%(codepostaldomicile)s %(villedomicile)s</para> <para leftindent="%(pv_htab1)s">%(codepostaldomicile)s %(villedomicile)s</para>
<para spaceBefore="25mm" fontSize="14" alignment="center"> <para spaceBefore="25mm" fontSize="14" alignment="center">
<b>Jury de %(type_jury)s <br/> %(titre_formation)s</b> <b>Jury de %(type_jury)s <br/> %(titre_formation)s</b>
</para> </para>
<para spaceBefore="10mm" fontSize="14" leftindent="0"> <para spaceBefore="10mm" fontSize="14" leftindent="0">
Le jury de %(type_jury_abbrv)s du département %(DeptName)s Le jury de %(type_jury_abbrv)s du département %(DeptName)s
s'est réuni le %(date_jury)s.
s'est réuni le %(date_jury)s. s'est réuni le %(date_jury)s.
</para> s'est réuni le %(date_jury)s.
<para fontSize="14" leftindent="0">Les décisions vous concernant sont : </para>
</para> <para fontSize="14" leftindent="0">Les décisions vous concernant sont :
</para>
<para leftindent="%(pv_htab2)s" spaceBefore="5mm" fontSize="14">%(prev_decision_sem_txt)s</para> <para leftindent="%(pv_htab2)s" spaceBefore="5mm" fontSize="14">%(prev_decision_sem_txt)s</para>
<para leftindent="%(pv_htab2)s" spaceBefore="5mm" fontSize="14"> <para leftindent="%(pv_htab2)s" spaceBefore="5mm" fontSize="14">
<b>Décision %(decision_orig)s :</b> %(decision_sem_descr)s <b>Décision %(decision_orig)s :</b> %(decision_sem_descr)s
</para> </para>
<para leftindent="%(pv_htab2)s" spaceBefore="0mm" fontSize="14"> <para leftindent="%(pv_htab2)s" spaceBefore="0mm" fontSize="14">
%(decision_ue_txt)s %(decision_ue_txt)s
</para> </para>
<para leftindent="%(pv_htab2)s" spaceBefore="0mm" fontSize="14"> <para leftindent="%(pv_htab2)s" spaceBefore="0mm" fontSize="14">
%(observation_txt)s %(observation_txt)s
</para> </para>
<para spaceBefore="10mm" fontSize="14">%(autorisations_txt)s</para> <para spaceBefore="10mm" fontSize="14">%(autorisations_txt)s</para>
<para spaceBefore="10mm" fontSize="14">%(diplome_txt)s</para> <para spaceBefore="10mm" fontSize="14">%(diplome_txt)s</para>
""", """,
"title": """Lettre individuelle""", "title": """Lettre individuelle""",
"explanation": """Balises remplacées et balisage XML, voir la documentation""", "explanation": """Balises remplacées et balisage XML, voir la documentation""",
"input_type": "textarea", "input_type": "textarea",
@ -1362,24 +1420,24 @@ class BasePreferences(object):
"bul_pdf_title", "bul_pdf_title",
{ {
"initvalue": """<para fontSize="14" align="center"> "initvalue": """<para fontSize="14" align="center">
<b>%(UnivName)s</b> <b>%(UnivName)s</b>
</para> </para>
<para fontSize="16" align="center" spaceBefore="2mm"> <para fontSize="16" align="center" spaceBefore="2mm">
<b>%(InstituteName)s</b> <b>%(InstituteName)s</b>
</para> </para>
<para fontSize="16" align="center" spaceBefore="4mm"> <para fontSize="16" align="center" spaceBefore="4mm">
<b>RELEVÉ DE NOTES</b> <b>RELEVÉ DE NOTES</b>
</para> </para>
<para fontSize="15" spaceBefore="3mm"> <para fontSize="15" spaceBefore="3mm">
%(nomprenom)s <b>%(demission)s</b> %(nomprenom)s <b>%(demission)s</b>
</para> </para>
<para fontSize="14" spaceBefore="3mm"> <para fontSize="14" spaceBefore="3mm">
Formation: %(titre_num)s</para> Formation: %(titre_num)s</para>
<para fontSize="14" spaceBefore="2mm"> <para fontSize="14" spaceBefore="2mm">
Année scolaire: %(anneescolaire)s Année scolaire: %(anneescolaire)s
</para>""", </para>""",
"title": "Bulletins PDF: paragraphe de titre", "title": "Bulletins PDF: paragraphe de titre",
"explanation": "(balises interprétées, voir documentation)", "explanation": "(balises interprétées, voir documentation)",
"input_type": "textarea", "input_type": "textarea",
@ -1404,10 +1462,10 @@ class BasePreferences(object):
"bul_pdf_sig_left", "bul_pdf_sig_left",
{ {
"initvalue": """<para>La direction des études "initvalue": """<para>La direction des études
<br/> <br/>
%(responsable)s %(responsable)s
</para> </para>
""", """,
"title": "Bulletins PDF: signature gauche", "title": "Bulletins PDF: signature gauche",
"explanation": "(balises interprétées, voir documentation)", "explanation": "(balises interprétées, voir documentation)",
"input_type": "textarea", "input_type": "textarea",
@ -1420,10 +1478,10 @@ class BasePreferences(object):
"bul_pdf_sig_right", "bul_pdf_sig_right",
{ {
"initvalue": """<para>Le chef de département "initvalue": """<para>Le chef de département
<br/> <br/>
%(ChiefDeptName)s %(ChiefDeptName)s
</para> </para>
""", """,
"title": "Bulletins PDF: signature droite", "title": "Bulletins PDF: signature droite",
"explanation": "(balises interprétées, voir documentation)", "explanation": "(balises interprétées, voir documentation)",
"input_type": "textarea", "input_type": "textarea",
@ -1799,88 +1857,57 @@ class BasePreferences(object):
def load(self): def load(self):
"""Load all preferences from db""" """Load all preferences from db"""
log(f"loading preferences for dept_id={self.dept_id}") log(f"loading preferences for dept_id={self.dept_id}")
try:
scu.GSL.acquire()
cnx = ndb.GetDBConnexion()
preflist = self._editor.list(cnx, {"dept_id": self.dept_id})
self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
self.default = {} # { name : default_value }
for p in preflist:
if not p["formsemestre_id"] in self.prefs:
self.prefs[p["formsemestre_id"]] = {}
# Ignore les noms de préférences non utilisés dans le code:
if p["name"] not in self.prefs_dict:
continue
# Convert types:
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)
if p["value"]:
p["value"] = float(p["value"])
else:
p["value"] = 0.0
else:
func = eval(typ)
p["value"] = func(p["value"])
if (
p["name"] in self.prefs_dict
and self.prefs_dict[p["name"]].get("input_type", None)
== "boolcheckbox"
):
# boolcheckbox: la valeur stockée en base est une chaine "0" ou "1"
# que l'on ressort en True|False
if p["value"]:
try:
p["value"] = bool(int(p["value"]))
except ValueError:
log(
f"""Warning: invalid value for boolean pref in db: '{p["value"]}'"""
)
p["value"] = False
else:
p["value"] = False # NULL (backward compat)
self.prefs[p["formsemestre_id"]][p["name"]] = p["value"]
# add defaults for missing prefs cnx = ndb.GetDBConnexion()
for pref in self.prefs_definition: preflist = self._editor.list(cnx, {"dept_id": self.dept_id})
name = pref[0] self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } }
# search preferences in configuration file self.default = {} # { name : default_value }
if name and name[0] != "_" and name not in self.prefs[None]: for p in preflist:
# search in scu.CONFIG if not p["formsemestre_id"] in self.prefs:
if hasattr(scu.CONFIG, name): self.prefs[p["formsemestre_id"]] = {}
value = getattr(scu.CONFIG, name) # Ignore les noms de préférences non utilisés dans le code:
log( if p["name"] not in self.prefs_dict:
"sco_preferences: found default value in config for %s=%s" continue
% (name, value)
)
else:
# uses hardcoded default
value = pref[1]["initvalue"]
self.default[name] = value # Convert types:
self.prefs[None][name] = value if p["name"] in self.prefs_dict:
log("creating missing preference for %s=%s" % (name, value)) _convert_pref_type(p, self.prefs_dict[p["name"]])
# add to db table
self._editor.create( self.prefs[p["formsemestre_id"]][p["name"]] = p["value"]
cnx, {"dept_id": self.dept_id, "name": name, "value": value}
) # add defaults for missing prefs
finally: for pref in self.prefs_definition:
scu.GSL.release() name = pref[0]
# search preferences in configuration file
if name and name[0] != "_" and name not in self.prefs[None]:
value = _get_pref_default_value_from_config(name, pref[1])
self.default[name] = value
self.prefs[None][name] = value
log("creating missing preference for %s=%s" % (name, value))
# add to db table
self._editor.create(
cnx, {"dept_id": self.dept_id, "name": name, "value": value}
)
def get(self, formsemestre_id, name): def get(self, formsemestre_id, name):
"""Returns preference value. """Returns preference value.
If no value defined for this semestre, returns global value. If global_lookup, when no value defined for this semestre, returns global value.
""" """
if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]: params = {
return self.prefs[formsemestre_id][name] "dept_id": self.dept_id,
elif name in self.prefs[None]: "name": name,
return self.prefs[None][name] "formsemestre_id": formsemestre_id,
else: }
return self.default[name] cnx = ndb.GetDBConnexion()
plist = self._editor.list(cnx, params)
if not plist:
del params["formsemestre_id"]
plist = self._editor.list(cnx, params)
if not plist:
return self.default[name]
p = plist[0]
_convert_pref_type(p, self.prefs_dict[name])
return p["value"]
def __contains__(self, item): def __contains__(self, item):
return item in self.prefs[None] return item in self.prefs[None]
@ -1890,74 +1917,75 @@ class BasePreferences(object):
def is_global(self, formsemestre_id, name): def is_global(self, formsemestre_id, name):
"True if name if not defined for semestre" "True if name if not defined for semestre"
if ( params = {
not (formsemestre_id in self.prefs) "dept_id": self.dept_id,
or not name in self.prefs[formsemestre_id] "name": name,
): "formsemestre_id": formsemestre_id,
return True }
else: cnx = ndb.GetDBConnexion()
return False plist = self._editor.list(cnx, params)
return len(plist) == 0
def save(self, formsemestre_id=None, name=None): def save(self, formsemestre_id=None, name=None):
"""Write one or all (if name is None) values to db""" """Write one or all (if name is None) values to db"""
try: modif = False
scu.GSL.acquire() cnx = ndb.GetDBConnexion()
modif = False if name is None:
cnx = ndb.GetDBConnexion() names = list(self.prefs[formsemestre_id].keys())
if name is None: else:
names = list(self.prefs[formsemestre_id].keys()) names = [name]
else: for name in names:
names = [name] value = self.prefs[formsemestre_id][name]
for name in names: if self.prefs_dict[name].get("input_type", None) == "boolcheckbox":
value = self.get(formsemestre_id, name) # repasse les booleens en chaines "0":"1"
if self.prefs_dict[name].get("input_type", None) == "boolcheckbox": value = "1" if value else "0"
# repasse les booleens en chaines "0":"1" # existe deja ?
value = "1" if value else "0" pdb = self._editor.list(
# existe deja ? cnx,
pdb = self._editor.list( args={
"dept_id": self.dept_id,
"formsemestre_id": formsemestre_id,
"name": name,
},
)
if not pdb:
# crée préférence
log("create pref sem=%s %s=%s" % (formsemestre_id, name, value))
self._editor.create(
cnx, cnx,
args={ {
"dept_id": self.dept_id, "dept_id": self.dept_id,
"formsemestre_id": formsemestre_id,
"name": name, "name": name,
"value": value,
"formsemestre_id": formsemestre_id,
}, },
) )
if not pdb: modif = True
# crée préférence log("create pref sem=%s %s=%s" % (formsemestre_id, name, value))
log("create pref sem=%s %s=%s" % (formsemestre_id, name, value)) else:
self._editor.create( # edit existing value
existing_value = pdb[0]["value"] # old stored value
if (
(existing_value != value)
and (existing_value != str(value))
and (existing_value or str(value))
):
self._editor.edit(
cnx, cnx,
{ {
"dept_id": self.dept_id, "pref_id": pdb[0]["pref_id"],
"formsemestre_id": formsemestre_id,
"name": name, "name": name,
"value": value, "value": value,
"formsemestre_id": formsemestre_id,
}, },
) )
modif = True modif = True
log("create pref sem=%s %s=%s" % (formsemestre_id, name, value)) log("save pref sem=%s %s=%s" % (formsemestre_id, name, value))
else:
# edit existing value
if pdb[0]["value"] != str(value) and (
pdb[0]["value"] or str(value)
):
self._editor.edit(
cnx,
{
"pref_id": pdb[0]["pref_id"],
"formsemestre_id": formsemestre_id,
"name": name,
"value": value,
},
)
modif = True
log("save pref sem=%s %s=%s" % (formsemestre_id, name, value))
# les preferences peuvent affecter les PDF cachés et les notes calculées: # les preferences peuvent affecter les PDF cachés et les notes calculées:
if modif: if modif:
sco_cache.invalidate_formsemestre() sco_cache.invalidate_formsemestre()
finally:
scu.GSL.release()
def set(self, formsemestre_id, name, value): def set(self, formsemestre_id, name, value):
if not name or name[0] == "_" or name not in self.prefs_name: if not name or name[0] == "_" or name not in self.prefs_name:
@ -1972,26 +2000,24 @@ class BasePreferences(object):
def delete(self, formsemestre_id, name): def delete(self, formsemestre_id, name):
if not formsemestre_id: if not formsemestre_id:
raise ScoException() raise ScoException()
try:
scu.GSL.acquire() if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]:
if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]: del self.prefs[formsemestre_id][name]
del self.prefs[formsemestre_id][name] cnx = ndb.GetDBConnexion()
cnx = ndb.GetDBConnexion() pdb = self._editor.list(
pdb = self._editor.list( cnx, args={"formsemestre_id": formsemestre_id, "name": name}
cnx, args={"formsemestre_id": formsemestre_id, "name": name} )
) if pdb:
if pdb: log("deleting pref sem=%s %s" % (formsemestre_id, name))
log("deleting pref sem=%s %s" % (formsemestre_id, name)) assert pdb[0]["dept_id"] == self.dept_id
assert pdb[0]["dept_id"] == self.dept_id self._editor.delete(cnx, pdb[0]["pref_id"])
self._editor.delete(cnx, pdb[0]["pref_id"]) sco_cache.invalidate_formsemestre() # > modif preferences
sco_cache.invalidate_formsemestre() # > modif preferences
finally:
scu.GSL.release()
def edit(self, REQUEST): def edit(self, REQUEST):
"""HTML dialog: edit global preferences""" """HTML dialog: edit global preferences"""
from app.scodoc import html_sco_header from app.scodoc import html_sco_header
self.load()
H = [ H = [
html_sco_header.sco_header(page_title="Préférences"), html_sco_header.sco_header(page_title="Préférences"),
"<h2>Préférences globales pour %s</h2>" % scu.ScoURL(), "<h2>Préférences globales pour %s</h2>" % scu.ScoURL(),

View File

@ -40,11 +40,11 @@ from app.scodoc.sco_exceptions import ScoValueError
random.seed(12345) # tests reproductibles random.seed(12345) # tests reproductibles
DEMO_DIR = Config.SCODOC_DIR + "/tools/demo/" NOMS_DIR = Config.SCODOC_DIR + "/tools/fakeportal/nomsprenoms"
NOMS = [x.strip() for x in open(DEMO_DIR + "/noms.txt").readlines()] NOMS = [x.strip() for x in open(NOMS_DIR + "/noms.txt").readlines()]
PRENOMS_H = [x.strip() for x in open(DEMO_DIR + "/prenoms-h.txt").readlines()] PRENOMS_H = [x.strip() for x in open(NOMS_DIR + "/prenoms-h.txt").readlines()]
PRENOMS_F = [x.strip() for x in open(DEMO_DIR + "/prenoms-f.txt").readlines()] PRENOMS_F = [x.strip() for x in open(NOMS_DIR + "/prenoms-f.txt").readlines()]
PRENOMS_X = [x.strip() for x in open(DEMO_DIR + "/prenoms-x.txt").readlines()] PRENOMS_X = [x.strip() for x in open(NOMS_DIR + "/prenoms-x.txt").readlines()]
def id_generator(size=6, chars=string.ascii_uppercase + string.digits): def id_generator(size=6, chars=string.ascii_uppercase + string.digits):

View File

@ -73,6 +73,8 @@ def test_preferences(test_client):
assert len(prefs2) == len(prefs) assert len(prefs2) == len(prefs)
prefs2.set(None, "abs_notification_mail_tmpl", "toto") prefs2.set(None, "abs_notification_mail_tmpl", "toto")
assert prefs2.get(None, "abs_notification_mail_tmpl") == "toto" assert prefs2.get(None, "abs_notification_mail_tmpl") == "toto"
# Vérifie que les prefs sont bien sur un seul département:
app.set_sco_dept(current_dept.acronym)
assert prefs.get(None, "abs_notification_mail_tmpl") != "toto" assert prefs.get(None, "abs_notification_mail_tmpl") != "toto"
orm_val = ( orm_val = (
ScoPreference.query.filter_by(dept_id=d.id, name="abs_notification_mail_tmpl") ScoPreference.query.filter_by(dept_id=d.id, name="abs_notification_mail_tmpl")
@ -82,6 +84,7 @@ def test_preferences(test_client):
assert orm_val == "toto" assert orm_val == "toto"
# --- Preferences d'un semestre # --- Preferences d'un semestre
# rejoue ce test pour avoir un semestre créé # rejoue ce test pour avoir un semestre créé
app.set_sco_dept("D2")
test_sco_basic.run_sco_basic() test_sco_basic.run_sco_basic()
sem = sco_formsemestre.do_formsemestre_list()[0] sem = sco_formsemestre.do_formsemestre_list()[0]
formsemestre_id = sem["formsemestre_id"] formsemestre_id = sem["formsemestre_id"]