From a4173e1877d6c9b014b44bf5163ce67b3099a04f Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Mon, 1 Feb 2021 16:23:11 +0100 Subject: [PATCH 01/18] Fix bulletins legacy + refactoring --- VERSION.py | 2 +- ZScolar.py | 2 +- sco_bulletins.py | 103 ++++++++++++++++++---------------- sco_bulletins_example.py | 8 ++- sco_bulletins_json.py | 104 ++++++++++++++++++---------------- sco_bulletins_legacy.py | 34 ++++++------ sco_bulletins_pdf.py | 42 ++++++++------ sco_bulletins_signature.py | 84 ++++++++++++++-------------- sco_bulletins_ucac.py | 14 +++-- sco_bulletins_xml.py | 111 +++++++++++++++++++++---------------- 10 files changed, 274 insertions(+), 230 deletions(-) diff --git a/VERSION.py b/VERSION.py index 4e1ce13c..68853baa 100644 --- a/VERSION.py +++ b/VERSION.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "7.20a" +SCOVERSION = "7.21" SCONAME = "ScoDoc" diff --git a/ZScolar.py b/ZScolar.py index 71414d48..cf4655c6 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -392,7 +392,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo Système de gestion scolarité -

© Emmanuel Viennet 1997-2020

+

© Emmanuel Viennet 1997-2021

Version %s (subversion %s)

""" % (SCOVERSION, get_svn_version(file_path)) diff --git a/sco_bulletins.py b/sco_bulletins.py index 9d2a8139..83c39f07 100644 --- a/sco_bulletins.py +++ b/sco_bulletins.py @@ -28,6 +28,9 @@ """Génération des bulletins de notes """ +from types import StringType +import pprint +import urllib from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error MIMEMultipart, ) @@ -40,8 +43,13 @@ import time import htmlutils from reportlab.lib.colors import Color -from sco_utils import * -from notes_table import * +import sco_utils as scu +import notesdb as ndb +from notes_log import log +import scolars +from sco_permissions import ScoImplement, ScoEtudInscrit +from sco_exceptions import AccessDenied +import sco_codes_parcours import sco_formsemestre import sco_groups import sco_pvjury @@ -114,7 +122,7 @@ def formsemestre_bulletinetud_dict( context, formsemestre_id ) # > toutes notes - I = DictDefault(defaultvalue="") + I = scu.DictDefault(defaultvalue="") I["etudid"] = etudid I["formsemestre_id"] = formsemestre_id I["sem"] = nt.sem @@ -182,7 +190,7 @@ def formsemestre_bulletinetud_dict( if I["etud_etat"] == "D": I["demission"] = "(Démission)" I["filigranne"] = "Démission" - elif I["etud_etat"] == DEF: + elif I["etud_etat"] == sco_codes_parcours.DEF: I["demission"] = "(Défaillant)" I["filigranne"] = "Défaillant" elif (prefs["bul_show_temporary"] and not I["decision_sem"]) or prefs[ @@ -206,16 +214,16 @@ def formsemestre_bulletinetud_dict( modimpls = nt.get_modimpls() moy_gen = nt.get_etud_moy_gen(etudid) I["nb_inscrits"] = len(nt.rangs) - I["moy_gen"] = fmt_note(moy_gen) - I["moy_min"] = fmt_note(nt.moy_min) - I["moy_max"] = fmt_note(nt.moy_max) + I["moy_gen"] = scu.fmt_note(moy_gen) + I["moy_min"] = scu.fmt_note(nt.moy_min) + I["moy_max"] = scu.fmt_note(nt.moy_max) I["mention"] = "" if dpv: decision_sem = dpv["decisions"][0]["decision_sem"] if decision_sem and sco_codes_parcours.code_semestre_validant( decision_sem["code"] ): - I["mention"] = get_mention(moy_gen) + I["mention"] = scu.get_mention(moy_gen) if dpv and dpv["decisions"][0]: I["sum_ects"] = dpv["decisions"][0]["sum_ects"] @@ -223,7 +231,7 @@ def formsemestre_bulletinetud_dict( else: I["sum_ects"] = 0 I["sum_ects_capitalises"] = 0 - I["moy_moy"] = fmt_note(nt.moy_moy) # moyenne des moyennes generales + I["moy_moy"] = scu.fmt_note(nt.moy_moy) # moyenne des moyennes generales if type(moy_gen) != StringType and type(nt.moy_moy) != StringType: I["moy_gen_bargraph_html"] = " " + htmlutils.horizontal_bargraph( moy_gen * 5, nt.moy_moy * 5 @@ -243,8 +251,8 @@ def formsemestre_bulletinetud_dict( if nt.get_moduleimpls_attente(): # n'affiche pas le rang sur le bulletin s'il y a des # notes en attente dans ce semestre - rang = RANG_ATTENTE_STR - rang_gr = DictDefault(defaultvalue=RANG_ATTENTE_STR) + rang = scu.RANG_ATTENTE_STR + rang_gr = scu.DictDefault(defaultvalue=scu.RANG_ATTENTE_STR) I["rang"] = rang I["rang_gr"] = rang_gr I["gr_name"] = gr_name @@ -270,17 +278,17 @@ def formsemestre_bulletinetud_dict( u = ue.copy() ue_status = nt.get_etud_ue_status(etudid, ue["ue_id"]) u["ue_status"] = ue_status # { 'moy', 'coef_ue', ...} - if ue["type"] != UE_SPORT: - u["cur_moy_ue_txt"] = fmt_note(ue_status["cur_moy_ue"]) + if ue["type"] != sco_codes_parcours.UE_SPORT: + u["cur_moy_ue_txt"] = scu.fmt_note(ue_status["cur_moy_ue"]) else: - x = fmt_note(nt.bonus[etudid], keep_numeric=True) + x = scu.fmt_note(nt.bonus[etudid], keep_numeric=True) if type(x) == StringType: u["cur_moy_ue_txt"] = "pas de bonus" else: u["cur_moy_ue_txt"] = "bonus de %.3g points" % x - u["moy_ue_txt"] = fmt_note(ue_status["moy"]) + u["moy_ue_txt"] = scu.fmt_note(ue_status["moy"]) if ue_status["coef_ue"] != None: - u["coef_ue_txt"] = fmt_coef(ue_status["coef_ue"]) + u["coef_ue_txt"] = scu.fmt_coef(ue_status["coef_ue"]) else: # C'est un bug: log("u=" + pprint.pformat(u)) @@ -292,7 +300,7 @@ def formsemestre_bulletinetud_dict( and ue["ue_id"] in dpv["decisions"][0]["decisions_ue"] ): u["ects"] = dpv["decisions"][0]["decisions_ue"][ue["ue_id"]]["ects"] - if ue["type"] == UE_ELECTIVE: + if ue["type"] == sco_codes_parcours.UE_ELECTIVE: u["ects"] = ( "%g+" % u["ects"] ) # ajoute un "+" pour indiquer ECTS d'une UE élective @@ -316,7 +324,7 @@ def formsemestre_bulletinetud_dict( sem_origin = sco_formsemestre.get_formsemestre( context, ue_status["formsemestre_id"] ) - u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY( + u["ue_descr_txt"] = "Capitalisée le %s" % ndb.DateISOtoDMY( ue_status["event_date"] ) u[ @@ -334,7 +342,7 @@ def formsemestre_bulletinetud_dict( context, ue_status["formsemestre_id"] ) # > toutes notes - u["modules_capitalized"], junk = _ue_mod_bulletin( + u["modules_capitalized"], _ = _ue_mod_bulletin( context, etudid, formsemestre_id, @@ -347,10 +355,10 @@ def formsemestre_bulletinetud_dict( _sort_mod_by_matiere(u["modules_capitalized"], nt_cap, etudid) ) else: - if prefs["bul_show_ue_rangs"] and ue["type"] != UE_SPORT: + if prefs["bul_show_ue_rangs"] and ue["type"] != sco_codes_parcours.UE_SPORT: if ue_attente: # nt.get_moduleimpls_attente(): u["ue_descr_txt"] = "%s/%s" % ( - RANG_ATTENTE_STR, + scu.RANG_ATTENTE_STR, nt.ue_rangs[ue["ue_id"]][1], ) else: @@ -386,7 +394,7 @@ def _sort_mod_by_matiere(modlist, nt, etudid): "titre": mod["mat"]["titre"], "modules": mod, "moy": moy, - "moy_txt": fmt_note(moy), + "moy_txt": scu.fmt_note(moy), } return matmod @@ -402,8 +410,8 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers ) if bul_show_abs_modules: sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - debut_sem = DateDMYtoISO(sem["date_debut"]) - fin_sem = DateDMYtoISO(sem["date_fin"]) + debut_sem = ndb.DateDMYtoISO(sem["date_debut"]) + fin_sem = ndb.DateDMYtoISO(sem["date_fin"]) ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue_id] mods = [] # result @@ -414,7 +422,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers mod_moy = nt.get_etud_mod_moy( modimpl["moduleimpl_id"], etudid ) # peut etre 'NI' - is_malus = mod["module"]["module_type"] == MODULE_MALUS + is_malus = mod["module"]["module_type"] == scu.MODULE_MALUS if bul_show_abs_modules: mod_abs = [ context.Absences.CountAbs( @@ -430,25 +438,25 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers moduleimpl_id=modimpl["moduleimpl_id"], ), ] - mod["mod_abs_txt"] = fmt_abs(mod_abs) + mod["mod_abs_txt"] = scu.fmt_abs(mod_abs) else: mod["mod_abs_txt"] = "" - mod["mod_moy_txt"] = fmt_note(mod_moy) + mod["mod_moy_txt"] = scu.fmt_note(mod_moy) if mod["mod_moy_txt"][:2] == "NA": mod["mod_moy_txt"] = "-" if is_malus: if mod_moy > 0: - mod["mod_moy_txt"] = fmt_note(mod_moy) + mod["mod_moy_txt"] = scu.fmt_note(mod_moy) mod["mod_coef_txt"] = "Malus" elif mod_moy < 0: - mod["mod_moy_txt"] = fmt_note(-mod_moy) + mod["mod_moy_txt"] = scu.fmt_note(-mod_moy) mod["mod_coef_txt"] = "Bonus" else: mod["mod_moy_txt"] = "-" mod["mod_coef_txt"] = "-" else: - mod["mod_coef_txt"] = fmt_coef(modimpl["module"]["coefficient"]) + mod["mod_coef_txt"] = scu.fmt_coef(modimpl["module"]["coefficient"]) if mod["mod_moy_txt"] != "NI": # ne montre pas les modules 'non inscrit' mods.append(mod) if is_malus: # n'affiche pas les statistiques sur les modules malus @@ -464,7 +472,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers mod["stats"] = nt.get_mod_stats(modimpl["moduleimpl_id"]) mod["mod_descr_txt"] = "Module %s, coef. %s (%s)" % ( modimpl["module"]["titre"], - fmt_coef(modimpl["module"]["coefficient"]), + scu.fmt_coef(modimpl["module"]["coefficient"]), context.Users.user_info(modimpl["responsable_id"])["nomcomplet"], ) link_mod = ( @@ -483,7 +491,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers mod_descr = "Module %s, coef. %s (%s)" % ( modimpl["module"]["titre"], - fmt_coef(modimpl["module"]["coefficient"]), + scu.fmt_coef(modimpl["module"]["coefficient"]), context.Users.user_info(modimpl["responsable_id"])["nomcomplet"], ) link_mod = ( @@ -527,18 +535,18 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers if val == "NP": e["note_txt"] = "nd" e["note_html"] = 'nd' - e["coef_txt"] = fmt_coef(e["coefficient"]) + e["coef_txt"] = scu.fmt_coef(e["coefficient"]) else: # (-0.15) s'affiche "bonus de 0.15" if is_malus: val = abs(val) - e["note_txt"] = fmt_note(val, note_max=e["note_max"]) + e["note_txt"] = scu.fmt_note(val, note_max=e["note_max"]) e["note_html"] = e["note_txt"] if is_malus: e["coef_txt"] = "" else: - e["coef_txt"] = fmt_coef(e["coefficient"]) - if e["evaluation_type"] == EVALUATION_RATTRAPAGE: + e["coef_txt"] = scu.fmt_coef(e["coefficient"]) + if e["evaluation_type"] == scu.EVALUATION_RATTRAPAGE: e["coef_txt"] = "rat." if e["etat"]["evalattente"]: mod_attente = True # une eval en attente dans ce module @@ -569,12 +577,12 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers e["name"], ) e["note_txt"] = e["note_html"] = "" - e["coef_txt"] = fmt_coef(e["coefficient"]) + e["coef_txt"] = scu.fmt_coef(e["coefficient"]) # Classement if bul_show_mod_rangs and mod["mod_moy_txt"] != "-" and not is_malus: rg = nt.mod_rangs[modimpl["moduleimpl_id"]] if mod_attente: # nt.get_moduleimpls_attente(): - mod["mod_rang"] = RANG_ATTENTE_STR + mod["mod_rang"] = scu.RANG_ATTENTE_STR else: mod["mod_rang"] = rg[0][etudid] mod["mod_eff"] = rg[1] # effectif dans ce module @@ -639,7 +647,7 @@ def etud_descr_situation_semestre( descr_mention : 'Mention Bien', ou vide si pas de mention ou si pas show_mention """ cnx = context.GetDBConnexion() - infos = DictDefault(defaultvalue="") + infos = scu.DictDefault(defaultvalue="") # --- Situation et décisions jury @@ -650,7 +658,6 @@ def etud_descr_situation_semestre( date_inscr = None date_dem = None date_def = None - date_echec = None for event in events: event_type = event["event_type"] if event_type == "INSCRIPTION": @@ -767,7 +774,7 @@ def formsemestre_bulletinetud( etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] etudid = etud["etudid"] except: - return log_unknown_etud(context, REQUEST, format=format) + return scu.log_unknown_etud(context, REQUEST, format=format) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) @@ -889,7 +896,7 @@ def do_formsemestre_bulletinetud( etud = I["etud"] if format == "html": - htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud( + htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud( context, I, version=version, format="html", REQUEST=REQUEST ) return htm, I["filigranne"] @@ -905,7 +912,7 @@ def do_formsemestre_bulletinetud( ) if format == "pdf": return ( - sendPDFFile(REQUEST, bul, filename), + scu.sendPDFFile(REQUEST, bul, filename), I["filigranne"], ) # unused ret. value else: @@ -920,7 +927,7 @@ def do_formsemestre_bulletinetud( if nohtml: htm = "" # speed up if html version not needed else: - htm, junk = sco_bulletins_generator.make_formsemestre_bulletinetud( + htm, _ = sco_bulletins_generator.make_formsemestre_bulletinetud( context, I, version=version, format="html", REQUEST=REQUEST ) @@ -964,7 +971,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr """ etud = I["etud"] webmaster = context.get_preference("bul_mail_contact_addr", formsemestre_id) - dept = unescape_html(context.get_preference("DeptName", formsemestre_id)) + dept = scu.unescape_html(context.get_preference("DeptName", formsemestre_id)) copy_addr = context.get_preference("email_copy_bulletins", formsemestre_id) intro_mail = context.get_preference("bul_intro_mail", formsemestre_id) @@ -983,7 +990,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr ) msg = MIMEMultipart() - subj = Header("Relevé de notes de %s" % etud["nomprenom"], SCO_ENCODING) + subj = Header("Relevé de notes de %s" % etud["nomprenom"], scu.SCO_ENCODING) recipients = [recipient_addr] msg["Subject"] = subj msg["From"] = context.get_preference("email_from_addr", formsemestre_id) @@ -993,7 +1000,7 @@ def mail_bulletin(context, formsemestre_id, I, pdfdata, filename, recipient_addr # Guarantees the message ends in a newline msg.epilogue = "" # Text - txt = MIMEText(hea, "plain", SCO_ENCODING) + txt = MIMEText(hea, "plain", scu.SCO_ENCODING) # log('hea:\n' + hea) msg.attach(txt) # Attach pdf @@ -1157,7 +1164,7 @@ def _formsemestre_bulletinetud_header_html( url + "?formsemestre_id=%s&etudid=%s&format=pdf&version=%s" % (formsemestre_id, etudid, version), - ICON_PDF, + scu.ICON_PDF, ) ) H.append("""""") diff --git a/sco_bulletins_example.py b/sco_bulletins_example.py index 03000bfe..7fb1e902 100644 --- a/sco_bulletins_example.py +++ b/sco_bulletins_example.py @@ -28,12 +28,14 @@ """Generation bulletins de notes: exemple minimal pour les programmeurs """ -# Quelques modules ScoDoc utiles: -from sco_pdf import * +import VERSION +import sco_utils as scu +import sco_pdf import sco_preferences from notes_log import log import sco_bulletins_generator import sco_bulletins_standard +from reportlab.platypus import Paragraph class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard): @@ -59,7 +61,7 @@ class BulletinGeneratorExample(sco_bulletins_standard.BulletinGeneratorStandard) assert format == "pdf" # garde fou return [ Paragraph( - SU( + sco_pdf.SU( "L'étudiant %(nomprenom)s a une moyenne générale de %(moy_gen)s" % self.infos ), diff --git a/sco_bulletins_json.py b/sco_bulletins_json.py index 1d19a8c0..9a86c583 100644 --- a/sco_bulletins_json.py +++ b/sco_bulletins_json.py @@ -28,9 +28,12 @@ """Génération du bulletin en format JSON (beta, non completement testé) """ +import datetime import json -from notes_table import * +import sco_utils as scu +import notesdb as ndb +import scolars import sco_formsemestre import sco_groups import sco_photos @@ -62,9 +65,9 @@ def make_json_formsemestre_bulletinetud( ) if REQUEST: - REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE) + REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE) - return json.dumps(d, cls=ScoDocJSONEncoder, encoding=SCO_ENCODING) + return json.dumps(d, cls=scu.ScoDocJSONEncoder, encoding=scu.SCO_ENCODING) # (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict() @@ -119,14 +122,14 @@ def formsemestre_bulletinetud_published_dict( etudid=etudid, code_nip=etudinfo["code_nip"], code_ine=etudinfo["code_ine"], - nom=quote_xml_attr(etudinfo["nom"]), - prenom=quote_xml_attr(etudinfo["prenom"]), - sexe=quote_xml_attr(etudinfo["sexe"]), - photo_url=quote_xml_attr( + nom=scu.quote_xml_attr(etudinfo["nom"]), + prenom=scu.quote_xml_attr(etudinfo["prenom"]), + sexe=scu.quote_xml_attr(etudinfo["sexe"]), + photo_url=scu.quote_xml_attr( sco_photos.etud_photo_url(context, etudinfo, fast=True) ), - email=quote_xml_attr(etudinfo["email"]), - emailperso=quote_xml_attr(etudinfo["emailperso"]), + email=scu.quote_xml_attr(etudinfo["email"]), + emailperso=scu.quote_xml_attr(etudinfo["emailperso"]), ) # Disponible pour publication ? @@ -150,7 +153,7 @@ def formsemestre_bulletinetud_published_dict( ues = nt.get_ues() modimpls = nt.get_modimpls() nbetuds = len(nt.rangs) - mg = fmt_note(nt.get_etud_moy_gen(etudid)) + mg = scu.fmt_note(nt.get_etud_moy_gen(etudid)) if ( nt.get_moduleimpls_attente() or context.get_preference("bul_show_rangs", formsemestre_id) == 0 @@ -168,9 +171,9 @@ def formsemestre_bulletinetud_published_dict( d["note"] = dict( value=mg, - min=fmt_note(nt.moy_min), - max=fmt_note(nt.moy_max), - moy=fmt_note(nt.moy_moy), + min=scu.fmt_note(nt.moy_min), + max=scu.fmt_note(nt.moy_max), + moy=scu.fmt_note(nt.moy_moy), ) d["rang"] = dict(value=rang, ninscrits=nbetuds) d["rang_group"] = [] @@ -199,25 +202,27 @@ def formsemestre_bulletinetud_published_dict( ects_txt = "" u = dict( id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), note=dict( - value=fmt_note(ue_status["cur_moy_ue"]), - min=fmt_note(ue["min"]), - max=fmt_note(ue["max"]), + value=scu.fmt_note(ue_status["cur_moy_ue"]), + min=scu.fmt_note(ue["min"]), + max=scu.fmt_note(ue["max"]), ), rang=str(nt.ue_rangs[ue["ue_id"]][0][etudid]), effectif=str(nt.ue_rangs[ue["ue_id"]][1]), ects=ects_txt, - code_apogee=quote_xml_attr(ue["code_apogee"]), + code_apogee=scu.quote_xml_attr(ue["code_apogee"]), ) d["ue"].append(u) u["module"] = [] # Liste les modules de l'UE ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]] for modimpl in ue_modimpls: - mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)) + mod_moy = scu.fmt_note( + nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid) + ) if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit continue mod = modimpl["module"] @@ -232,15 +237,15 @@ def formsemestre_bulletinetud_published_dict( code=mod["code"], coefficient=mod["coefficient"], numero=mod["numero"], - titre=quote_xml_attr(mod["titre"]), - abbrev=quote_xml_attr(mod["abbrev"]), + titre=scu.quote_xml_attr(mod["titre"]), + abbrev=scu.quote_xml_attr(mod["abbrev"]), # ects=ects, ects des modules maintenant inutilisés note=dict(value=mod_moy), - code_apogee=quote_xml_attr(mod["code_apogee"]), + code_apogee=scu.quote_xml_attr(mod["code_apogee"]), ) m["note"].update(modstat) for k in ("min", "max", "moy"): # formatte toutes les notes - m["note"][k] = fmt_note(m["note"][k]) + m["note"][k] = scu.fmt_note(m["note"][k]) u["module"].append(m) if context.get_preference("bul_show_mod_rangs", formsemestre_id): @@ -258,19 +263,19 @@ def formsemestre_bulletinetud_published_dict( val = e["notes"].get(etudid, {"value": "NP"})[ "value" ] # NA si etud demissionnaire - val = fmt_note(val, note_max=e["note_max"]) + val = scu.fmt_note(val, note_max=e["note_max"]) m["evaluation"].append( dict( - jour=DateDMYtoISO(e["jour"], null_is_empty=True), - heure_debut=TimetoISO8601( + jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True), + heure_debut=ndb.TimetoISO8601( e["heure_debut"], null_is_empty=True ), - heure_fin=TimetoISO8601( + heure_fin=ndb.TimetoISO8601( e["heure_fin"], null_is_empty=True ), coefficient=e["coefficient"], evaluation_type=e["evaluation_type"], - description=quote_xml_attr(e["description"]), + description=scu.quote_xml_attr(e["description"]), note=val, ) ) @@ -285,15 +290,17 @@ def formsemestre_bulletinetud_published_dict( if e["evaluation_id"] not in complete_eval_ids: m["evaluation"].append( dict( - jour=DateDMYtoISO(e["jour"], null_is_empty=True), - heure_debut=TimetoISO8601( + jour=ndb.DateDMYtoISO( + e["jour"], null_is_empty=True + ), + heure_debut=ndb.TimetoISO8601( e["heure_debut"], null_is_empty=True ), - heure_fin=TimetoISO8601( + heure_fin=ndb.TimetoISO8601( e["heure_fin"], null_is_empty=True ), coefficient=e["coefficient"], - description=quote_xml_attr(e["description"]), + description=scu.quote_xml_attr(e["description"]), incomplete="1", ) ) @@ -307,20 +314,18 @@ def formsemestre_bulletinetud_published_dict( d["ue_capitalisee"].append( dict( id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), - note=fmt_note(ue_status["moy"]), - coefficient_ue=fmt_note(ue_status["coef_ue"]), - date_capitalisation=DateDMYtoISO(ue_status["event_date"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), + note=scu.fmt_note(ue_status["moy"]), + coefficient_ue=scu.fmt_note(ue_status["coef_ue"]), + date_capitalisation=ndb.DateDMYtoISO(ue_status["event_date"]), ects=ects_txt, ) ) # --- Absences if context.get_preference("bul_show_abs", formsemestre_id): - debut_sem = DateDMYtoISO(sem["date_debut"]) - fin_sem = DateDMYtoISO(sem["date_fin"]) AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) nbabs = AbsEtudSem.CountAbs() nbabsjust = AbsEtudSem.CountAbsJust() @@ -339,7 +344,7 @@ def formsemestre_bulletinetud_published_dict( format="xml", show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id), ) - d["situation"] = quote_xml_attr(infos["situation"]) + d["situation"] = scu.quote_xml_attr(infos["situation"]) if dpv: decision = dpv["decisions"][0] etat = decision["etat"] @@ -366,11 +371,11 @@ def formsemestre_bulletinetud_published_dict( d["decision_ue"].append( dict( ue_id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), code=decision["decisions_ue"][ue_id]["code"], - ects=quote_xml_attr(ue["ects"] or ""), + ects=scu.quote_xml_attr(ue["ects"] or ""), ) ) d["autorisation_inscription"] = [] @@ -389,7 +394,10 @@ def formsemestre_bulletinetud_published_dict( d["appreciation"] = [] for app in apprecs: d["appreciation"].append( - dict(comment=quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"])) + dict( + comment=scu.quote_xml_attr(app["comment"]), + date=ndb.DateDMYtoISO(app["date"]), + ) ) # diff --git a/sco_bulletins_legacy.py b/sco_bulletins_legacy.py index 84dc40cb..85d13bf2 100644 --- a/sco_bulletins_legacy.py +++ b/sco_bulletins_legacy.py @@ -37,8 +37,13 @@ import traceback, re +import sco_utils as scu +from sco_permissions import ScoEtudInscrit import sco_formsemestre -from sco_pdf import * +import sco_pdf +from sco_pdf import Color, Paragraph, Spacer, Table +from sco_pdf import blue, cm, mm +from sco_pdf import SU import sco_preferences from notes_log import log import sco_bulletins_generator @@ -81,9 +86,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): def bul_table_html(self): """Génère la table centrale du bulletin de notes: chaine HTML""" - format = "html" I = self.infos - authuser = self.authuser formsemestre_id = self.infos["formsemestre_id"] context = self.context @@ -98,8 +101,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): bgcolor = "background-color: rgb(255,255,240)" linktmpl = '%s' - minuslink = linktmpl % icontag("minus_img", border="0", alt="-") - pluslink = linktmpl % icontag("plus_img", border="0", alt="+") + minuslink = linktmpl % scu.icontag("minus_img", border="0", alt="-") + pluslink = linktmpl % scu.icontag("plus_img", border="0", alt="+") H = ['' % bgcolor] @@ -131,8 +134,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): if context.get_preference("bul_show_minmax_mod", formsemestre_id): rang_minmax = '%s [%s, %s]' % ( mod["mod_rang_txt"], - fmt_note(mod["stats"]["min"]), - fmt_note(mod["stats"]["max"]), + scu.fmt_note(mod["stats"]["min"]), + scu.fmt_note(mod["stats"]["max"]), ) else: rang_minmax = mod["mod_rang_txt"] # vide si pas option rang @@ -209,9 +212,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator): moy_txt = ( '%s [%s, %s]' % ( - fmt_note(ue["cur_moy_ue_txt"]), - fmt_note(ue["min"]), - fmt_note(ue["max"]), + scu.fmt_note(ue["cur_moy_ue_txt"]), + scu.fmt_note(ue["min"]), + scu.fmt_note(ue["max"]), ) ) else: @@ -441,7 +444,6 @@ def _bulletin_pdf_table_legacy(context, I, version="long"): S = BulTableStyle() P = [] # elems pour gen. pdf formsemestre_id = I["formsemestre_id"] - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) bul_show_abs_modules = context.get_preference( "bul_show_abs_modules", formsemestre_id ) @@ -460,7 +462,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"): ] if bul_show_abs_modules: t.append("Abs (J. / N.J.)") - P.append(bold_paras(t)) + P.append(sco_pdf.bold_paras(t)) def list_modules(ue_modules, ue_type=None): "ajoute les lignes decrivant les modules d'une UE, avec eventuellement les évaluations de chacun" @@ -471,8 +473,8 @@ def _bulletin_pdf_table_legacy(context, I, version="long"): if context.get_preference("bul_show_minmax_mod", formsemestre_id): rang_minmax = '%s [%s, %s]' % ( mod["mod_rang_txt"], - fmt_note(mod["stats"]["min"]), - fmt_note(mod["stats"]["max"]), + scu.fmt_note(mod["stats"]["min"]), + scu.fmt_note(mod["stats"]["max"]), ) else: rang_minmax = mod["mod_rang_txt"] # vide si pas option rang @@ -504,7 +506,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"): t = [ue["acronyme"], ue["moy_ue_txt"], ue_descr, "", coef_ue] if bul_show_abs_modules: t.append("") - P.append(bold_paras(t)) + P.append(sco_pdf.bold_paras(t)) coef_ue = "" ue_descr = "(en cours, non prise en compte)" S.ueline() @@ -523,7 +525,7 @@ def _bulletin_pdf_table_legacy(context, I, version="long"): t = [ue["acronyme"], moy_txt, ue_descr, "", coef_ue] if bul_show_abs_modules: t.append("") - P.append(bold_paras(t)) + P.append(sco_pdf.bold_paras(t)) S.ueline() list_modules(ue["modules"], ue_type=ue_type) diff --git a/sco_bulletins_pdf.py b/sco_bulletins_pdf.py index e01dca0d..a704c0c0 100644 --- a/sco_bulletins_pdf.py +++ b/sco_bulletins_pdf.py @@ -50,13 +50,21 @@ Pour définir un nouveau type de bulletin: Chaque semestre peut si nécessaire utiliser un type de bulletin différent. """ -import htmlutils, time -import pprint, traceback +import htmlutils +import time +import pprint +import traceback +import re +import cStringIO +from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate -from notes_table import * +import VERSION +import sco_utils as scu +from notes_log import log +import sco_formsemestre import sco_bulletins -from sco_pdf import * +import sco_pdf import os @@ -84,10 +92,10 @@ def pdfassemblebulletins( report = cStringIO.StringIO() # in-memory document, no disk file document = BaseDocTemplate(report) document.addPageTemplates( - ScolarsPageTemplate( + sco_pdf.ScolarsPageTemplate( document, context=context, - author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION), + author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION), title="Bulletin %s" % bul_title, subject="Bulletin de note", server_name=server_name, @@ -117,7 +125,7 @@ def process_field( If format = 'html', replaces by

. HTML does not allow logos. """ try: - text = (field or "") % WrapDict( + text = (field or "") % scu.WrapDict( cdict ) # note that None values are mapped to empty strings except: @@ -135,9 +143,9 @@ def process_field( return text # --- PDF format: # handle logos: - image_dir = SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/" + image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/" if not os.path.exists(image_dir): - image_dir = SCODOC_LOGOS_DIR + "/" # use global logos + image_dir = scu.SCODOC_LOGOS_DIR + "/" # use global logos text = re.sub( r"<(\s*)logo(.*?)src\s*=\s*(.*?)>", r"<\1logo\2\3>", text ) # remove forbidden src attribute @@ -150,7 +158,7 @@ def process_field( # tentatives d'acceder à d'autres fichiers ! # log('field: %s' % (text)) - return makeParas(text, style, suppress_empty=suppress_empty_pars) + return sco_pdf.makeParas(text, style, suppress_empty=suppress_empty_pars) def get_formsemestre_bulletins_pdf( @@ -180,7 +188,7 @@ def get_formsemestre_bulletins_pdf( ) fragments += frag filigrannes[i] = filigranne - bookmarks[i] = suppress_accents(nt.get_sexnom(etudid)) + bookmarks[i] = scu.suppress_accents(nt.get_sexnom(etudid)) i = i + 1 # infos = {"DeptName": context.get_preference("DeptName", formsemestre_id)} @@ -189,7 +197,7 @@ def get_formsemestre_bulletins_pdf( else: server_name = "" try: - PDFLOCK.acquire() + sco_pdf.PDFLOCK.acquire() pdfdoc = pdfassemblebulletins( formsemestre_id, fragments, @@ -201,11 +209,11 @@ def get_formsemestre_bulletins_pdf( context=context, ) finally: - PDFLOCK.release() + sco_pdf.PDFLOCK.release() # dt = time.strftime("%Y-%m-%d") filename = "bul-%s-%s.pdf" % (sem["titre_num"], dt) - filename = unescape_html(filename).replace(" ", "_").replace("&", "") + filename = scu.unescape_html(filename).replace(" ", "_").replace("&", "") # fill cache context._getNotesCache().store_bulletins_pdf( formsemestre_id, version, filename, pdfdoc @@ -239,7 +247,7 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"): else: server_name = "" try: - PDFLOCK.acquire() + sco_pdf.PDFLOCK.acquire() pdfdoc = pdfassemblebulletins( None, fragments, @@ -251,11 +259,11 @@ def get_etud_bulletins_pdf(context, etudid, REQUEST, version="selectedevals"): context=context, ) finally: - PDFLOCK.release() + sco_pdf.PDFLOCK.release() # filename = "bul-%s" % (etud["nomprenom"]) filename = ( - unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "") + scu.unescape_html(filename).replace(" ", "_").replace("&", "").replace(".", "") + ".pdf" ) diff --git a/sco_bulletins_signature.py b/sco_bulletins_signature.py index 403526f3..ade30e2e 100644 --- a/sco_bulletins_signature.py +++ b/sco_bulletins_signature.py @@ -53,53 +53,53 @@ Lien sur Scolarite/edit_preferences (sans formsemestre_id) et sur page "réglages bulletin" (avec formsemestre_id) """ -import os +# import os -def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None): - """Change pdf signature""" - filename = _get_sig_existing_filename( - context, side, formsemestre_id=formsemestre_id - ) - if side == "left": - sidetxt = "gauche" - elif side == "right": - sidetxt = "droite" - else: - raise ValueError("invalid value for 'side' parameter") - signatureloc = get_bul_sig_img() - H = [ - self.sco_header(REQUEST, page_title="Changement de signature"), - """

Changement de la signature bulletin de %(sidetxt)s

- """ - % (sidetxt,), - ] - "

Photo actuelle (%(signatureloc)s): " +# def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None): +# """Change pdf signature""" +# filename = _get_sig_existing_filename( +# context, side, formsemestre_id=formsemestre_id +# ) +# if side == "left": +# sidetxt = "gauche" +# elif side == "right": +# sidetxt = "droite" +# else: +# raise ValueError("invalid value for 'side' parameter") +# signatureloc = get_bul_sig_img() +# H = [ +# self.sco_header(REQUEST, page_title="Changement de signature"), +# """

Changement de la signature bulletin de %(sidetxt)s

+# """ +# % (sidetxt,), +# ] +# "

Photo actuelle (%(signatureloc)s): " -def get_bul_sig_img(context, side, formsemestre_id=None): - "send back signature image data" - # slow, not cached, used for unfrequent access (do not bypass python) +# def get_bul_sig_img(context, side, formsemestre_id=None): +# "send back signature image data" +# # slow, not cached, used for unfrequent access (do not bypass python) -def _sig_filename(context, side, formsemestre_id=None): - if not side in ("left", "right"): - raise ValueError("side must be left or right") - dirs = [SCODOC_LOGOS_DIR, context.DeptId()] - if formsemestre_id: - dirs.append(formsemestre_id) - dirs.append("bul_sig_{}".format(side)) - return os.path.join(*dirs) +# def _sig_filename(context, side, formsemestre_id=None): +# if not side in ("left", "right"): +# raise ValueError("side must be left or right") +# dirs = [SCODOC_LOGOS_DIR, context.DeptId()] +# if formsemestre_id: +# dirs.append(formsemestre_id) +# dirs.append("bul_sig_{}".format(side)) +# return os.path.join(*dirs) -def _get_sig_existing_filename(context, side, formsemestre_id=None): - "full path to signature to use, or None if no signature available" - if formsemestre_id: - filename = _sig_filename(context, side, formsemestre_id=formsemestre_id) - if os.path.exists(filename): - return filename - filename = _sig_filename(context, side) - if os.path.exists(filename): - return filename - else: - return None +# def _get_sig_existing_filename(context, side, formsemestre_id=None): +# "full path to signature to use, or None if no signature available" +# if formsemestre_id: +# filename = _sig_filename(context, side, formsemestre_id=formsemestre_id) +# if os.path.exists(filename): +# return filename +# filename = _sig_filename(context, side) +# if os.path.exists(filename): +# return filename +# else: +# return None diff --git a/sco_bulletins_ucac.py b/sco_bulletins_ucac.py index 381486ad..87510bf4 100644 --- a/sco_bulletins_ucac.py +++ b/sco_bulletins_ucac.py @@ -34,8 +34,12 @@ E. Viennet, juillet 2011 """ import traceback +import sco_utils as scu import sco_formsemestre -from sco_pdf import * +import sco_pdf +from sco_pdf import blue, cm, mm +from sco_pdf import Color, Paragraph, Spacer, Table + import sco_preferences from notes_log import log @@ -72,7 +76,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard): I = self.infos context = self.context formsemestre_id = I["formsemestre_id"] - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) prefs = context.get_preferences(formsemestre_id) P = [] # elems pour générer table avec gen_table (liste de dicts) @@ -134,7 +137,7 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard): total_pt_ue_v = ( ue["ue_status"]["cur_moy_ue"] * ue["ue_status"]["coef_ue"] ) - total_pt_ue = fmt_note(total_pt_ue_v) + total_pt_ue = scu.fmt_note(total_pt_ue_v) # log('total_pt_ue = %s' % total_pt_ue) except: # log("ue['ue_status']['cur_moy_ue'] = %s" % ue['ue_status']['cur_moy_ue'] ) @@ -212,7 +215,6 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard): ue_descr = "(en cours, non prise en compte)" ue_type = "cur" - rowstyle = " bul_ucac_row_ue_cur" # --- UE ordinaire pt = list_ue(ue, ue_descr) @@ -228,8 +230,8 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard): { "code_ue": "Total", "moyenne_ue": I["moy_gen"], - "coef": fmt_note(sum_coef_ues), - "total": fmt_note(sum_pt_sem), + "coef": scu.fmt_note(sum_coef_ues), + "total": scu.fmt_note(sum_pt_sem), "_code_ue_colspan": 4, "_css_row_class": "bul_ucac_row_total", "_pdf_row_markup": ["b"], diff --git a/sco_bulletins_xml.py b/sco_bulletins_xml.py index 7edd20ae..95d9454c 100644 --- a/sco_bulletins_xml.py +++ b/sco_bulletins_xml.py @@ -37,7 +37,14 @@ Malheureusement, le code de génération JSON et XML sont séparés, ce qui est Je propose de considérer le XMl comme "deprecated" et de ne plus le modifier, sauf nécessité. """ -from notes_table import * +import datetime +import jaxml + +import sco_utils as scu +import notesdb as ndb +from notes_log import log +import scolars +import sco_codes_parcours import sco_formsemestre import sco_groups import sco_photos @@ -62,9 +69,9 @@ def make_xml_formsemestre_bulletinetud( "bulletin au format XML" log("xml_bulletin( formsemestre_id=%s, etudid=%s )" % (formsemestre_id, etudid)) if REQUEST: - REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) + REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) if not doc: - doc = jaxml.XML_document(encoding=SCO_ENCODING) + doc = jaxml.XML_document(encoding=scu.SCO_ENCODING) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) if sem["bul_hide_xml"] == "0" or force_publishing: @@ -98,12 +105,12 @@ def make_xml_formsemestre_bulletinetud( etudid=etudid, code_nip=etudinfo["code_nip"], code_ine=etudinfo["code_ine"], - nom=quote_xml_attr(etudinfo["nom"]), - prenom=quote_xml_attr(etudinfo["prenom"]), - sexe=quote_xml_attr(etudinfo["sexe"]), - photo_url=quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)), - email=quote_xml_attr(etudinfo["email"]), - emailperso=quote_xml_attr(etudinfo["emailperso"]), + nom=scu.quote_xml_attr(etudinfo["nom"]), + prenom=scu.quote_xml_attr(etudinfo["prenom"]), + sexe=scu.quote_xml_attr(etudinfo["sexe"]), + photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)), + email=scu.quote_xml_attr(etudinfo["email"]), + emailperso=scu.quote_xml_attr(etudinfo["emailperso"]), ) doc._pop() @@ -128,7 +135,7 @@ def make_xml_formsemestre_bulletinetud( ues = nt.get_ues() modimpls = nt.get_modimpls() nbetuds = len(nt.rangs) - mg = fmt_note(nt.get_etud_moy_gen(etudid)) + mg = scu.fmt_note(nt.get_etud_moy_gen(etudid)) if ( nt.get_moduleimpls_attente() or context.get_preference("bul_show_rangs", formsemestre_id) == 0 @@ -147,9 +154,9 @@ def make_xml_formsemestre_bulletinetud( doc._push() doc.note( value=mg, - min=fmt_note(nt.moy_min), - max=fmt_note(nt.moy_max), - moy=fmt_note(nt.moy_moy), + min=scu.fmt_note(nt.moy_min), + max=scu.fmt_note(nt.moy_max), + moy=scu.fmt_note(nt.moy_moy), ) doc._pop() doc._push() @@ -177,17 +184,21 @@ def make_xml_formsemestre_bulletinetud( doc._push() doc.ue( id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), - code_apogee=quote_xml_attr(ue["code_apogee"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), + code_apogee=scu.quote_xml_attr(ue["code_apogee"]), ) doc._push() - if ue["type"] != UE_SPORT: + if ue["type"] != sco_codes_parcours.UE_SPORT: v = ue_status["cur_moy_ue"] else: v = nt.bonus[etudid] - doc.note(value=fmt_note(v), min=fmt_note(ue["min"]), max=fmt_note(ue["max"])) + doc.note( + value=scu.fmt_note(v), + min=scu.fmt_note(ue["min"]), + max=scu.fmt_note(ue["max"]), + ) doc._pop() try: ects_txt = str(int(ue["ects"])) @@ -205,7 +216,9 @@ def make_xml_formsemestre_bulletinetud( # Liste les modules de l'UE ue_modimpls = [mod for mod in modimpls if mod["module"]["ue_id"] == ue["ue_id"]] for modimpl in ue_modimpls: - mod_moy = fmt_note(nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid)) + mod_moy = scu.fmt_note( + nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid) + ) if mod_moy == "NI": # ne mentionne pas les modules ou n'est pas inscrit continue mod = modimpl["module"] @@ -219,18 +232,18 @@ def make_xml_formsemestre_bulletinetud( code=mod["code"], coefficient=mod["coefficient"], numero=mod["numero"], - titre=quote_xml_attr(mod["titre"]), - abbrev=quote_xml_attr(mod["abbrev"]), - code_apogee=quote_xml_attr(mod["code_apogee"]) + titre=scu.quote_xml_attr(mod["titre"]), + abbrev=scu.quote_xml_attr(mod["abbrev"]), + code_apogee=scu.quote_xml_attr(mod["code_apogee"]) # ects=ects ects des modules maintenant inutilisés ) doc._push() modstat = nt.get_mod_stats(modimpl["moduleimpl_id"]) doc.note( value=mod_moy, - min=fmt_note(modstat["min"]), - max=fmt_note(modstat["max"]), - moy=fmt_note(modstat["moy"]), + min=scu.fmt_note(modstat["min"]), + max=scu.fmt_note(modstat["max"]), + moy=scu.fmt_note(modstat["moy"]), ) doc._pop() if context.get_preference("bul_show_mod_rangs", formsemestre_id): @@ -247,14 +260,16 @@ def make_xml_formsemestre_bulletinetud( if int(e["visibulletin"]) == 1 or version == "long": doc._push() doc.evaluation( - jour=DateDMYtoISO(e["jour"], null_is_empty=True), - heure_debut=TimetoISO8601( + jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True), + heure_debut=ndb.TimetoISO8601( e["heure_debut"], null_is_empty=True ), - heure_fin=TimetoISO8601(e["heure_fin"], null_is_empty=True), + heure_fin=ndb.TimetoISO8601( + e["heure_fin"], null_is_empty=True + ), coefficient=e["coefficient"], evaluation_type=e["evaluation_type"], - description=quote_xml_attr(e["description"]), + description=scu.quote_xml_attr(e["description"]), note_max_origin=e[ "note_max" ], # notes envoyées sur 20, ceci juste pour garder trace @@ -262,7 +277,7 @@ def make_xml_formsemestre_bulletinetud( val = e["notes"].get(etudid, {"value": "NP"})[ "value" ] # NA si etud demissionnaire - val = fmt_note(val, note_max=e["note_max"]) + val = scu.fmt_note(val, note_max=e["note_max"]) doc.note(value=val) doc._pop() # Evaluations incomplètes ou futures: @@ -276,15 +291,15 @@ def make_xml_formsemestre_bulletinetud( if e["evaluation_id"] not in complete_eval_ids: doc._push() doc.evaluation( - jour=DateDMYtoISO(e["jour"], null_is_empty=True), - heure_debut=TimetoISO8601( + jour=ndb.DateDMYtoISO(e["jour"], null_is_empty=True), + heure_debut=ndb.TimetoISO8601( e["heure_debut"], null_is_empty=True ), - heure_fin=TimetoISO8601( + heure_fin=ndb.TimetoISO8601( e["heure_fin"], null_is_empty=True ), coefficient=e["coefficient"], - description=quote_xml_attr(e["description"]), + description=scu.quote_xml_attr(e["description"]), incomplete="1", note_max_origin=e[ "note_max" @@ -302,27 +317,25 @@ def make_xml_formsemestre_bulletinetud( doc._push() doc.ue_capitalisee( id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), ) doc._push() - doc.note(value=fmt_note(ue_status["moy"])) + doc.note(value=scu.fmt_note(ue_status["moy"])) doc._pop() doc._push() doc.ects(value=ects_txt) doc._pop() doc._push() - doc.coefficient_ue(value=fmt_note(ue_status["coef_ue"])) + doc.coefficient_ue(value=scu.fmt_note(ue_status["coef_ue"])) doc._pop() doc._push() - doc.date_capitalisation(value=DateDMYtoISO(ue_status["event_date"])) + doc.date_capitalisation(value=ndb.DateDMYtoISO(ue_status["event_date"])) doc._pop() doc._pop() # --- Absences if context.get_preference("bul_show_abs", formsemestre_id): - debut_sem = DateDMYtoISO(sem["date_debut"]) - fin_sem = DateDMYtoISO(sem["date_fin"]) AbsEtudSem = sco_abs.getAbsSemEtud(context, sem, etudid) nbabs = AbsEtudSem.CountAbs() nbabsjust = AbsEtudSem.CountAbsJust() @@ -341,7 +354,7 @@ def make_xml_formsemestre_bulletinetud( format="xml", show_uevalid=context.get_preference("bul_show_uevalid", formsemestre_id), ) - doc.situation(quote_xml_attr(infos["situation"])) + doc.situation(scu.quote_xml_attr(infos["situation"])) if dpv: decision = dpv["decisions"][0] etat = decision["etat"] @@ -375,9 +388,9 @@ def make_xml_formsemestre_bulletinetud( doc._push() doc.decision_ue( ue_id=ue["ue_id"], - numero=quote_xml_attr(ue["numero"]), - acronyme=quote_xml_attr(ue["acronyme"]), - titre=quote_xml_attr(ue["titre"]), + numero=scu.quote_xml_attr(ue["numero"]), + acronyme=scu.quote_xml_attr(ue["acronyme"]), + titre=scu.quote_xml_attr(ue["titre"]), code=decision["decisions_ue"][ue_id]["code"], ) doc._pop() @@ -396,5 +409,7 @@ def make_xml_formsemestre_bulletinetud( cnx, args={"etudid": etudid, "formsemestre_id": formsemestre_id} ) for app in apprecs: - doc.appreciation(quote_xml_attr(app["comment"]), date=DateDMYtoISO(app["date"])) + doc.appreciation( + scu.quote_xml_attr(app["comment"]), date=ndb.DateDMYtoISO(app["date"]) + ) return doc From 1576a64ccd13ea51f096014a5a8dda48ce8652eb Mon Sep 17 00:00:00 2001 From: IDK Date: Mon, 1 Feb 2021 23:54:46 +0100 Subject: [PATCH 02/18] pylinting --- ZNotes.py | 1 - ZScolar.py | 163 +++++++++++++++++++++++--------------- pe_avislatex.py | 56 ++++++------- pe_jurype.py | 21 ++--- pe_semestretag.py | 32 ++++---- sco_apogee_csv.py | 35 +++++--- sco_bulletins_standard.py | 5 +- sco_edit_ue.py | 2 +- sco_edt_cal.py | 8 +- sco_placement.py | 7 +- sco_prepajury.py | 10 ++- sco_report.py | 2 +- sco_trombino.py | 73 +---------------- 13 files changed, 205 insertions(+), 210 deletions(-) diff --git a/ZNotes.py b/ZNotes.py index c962e6b6..bc8b54d6 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -35,7 +35,6 @@ import pprint from sco_zope import * # pylint: disable=unused-wildcard-import # --------------- -# from sco_utils import * import sco_utils as scu import notesdb as ndb from notes_log import log, sendAlarm diff --git a/ZScolar.py b/ZScolar.py index cf4655c6..314b9bb2 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -30,8 +30,15 @@ import sys import traceback -import time, string, glob, re -import urllib, urllib2, cgi, xml +import time +import string +import glob +import re +import urllib +import urllib2 +import cgi +import xml +import jaxml try: from cStringIO import StringIO @@ -41,7 +48,7 @@ from zipfile import ZipFile import thread import psycopg2 -from sco_zope import * +from sco_zope import * # pylint: disable=unused-wildcard-import # --------------- @@ -53,12 +60,40 @@ log("restarting...") log("ZScolar home=%s" % file_path) -from sco_utils import * -import notesdb -from notesdb import * +import sco_utils as scu +import notesdb as ndb from scolog import logdb - +from sco_permissions import ( + ScoAbsChange, + ScoView, + ScoEnsView, + ScoImplement, + ScoChangeFormation, + ScoChangePreferences, + ScoObservateur, + ScoEtudAddAnnotations, + ScoEtudInscrit, + ScoEtudChangeGroups, + ScoEtudChangeAdr, + ScoEtudSupprAnnotations, + ScoEditAllEvals, + ScoEditAllNotes, + ScoEditFormationTags, + ScoEditApo, + ScoSuperAdmin, +) +import sco_permissions +from sco_exceptions import ( + AccessDenied, + ScoException, + ScoValueError, + ScoInvalidDateError, + ScoLockedFormError, + ScoGenError, +) +from TrivialFormulator import TrivialFormulator, tf_error_message import scolars +import sco_codes_parcours import sco_preferences import sco_formations from scolars import ( @@ -110,9 +145,9 @@ import sco_dump_db from VERSION import SCOVERSION, SCONEWS -if hasattr(CONFIG, "ABSOLUTE_URL") and CONFIG.ABSOLUTE_URL: - log("ScoDoc: ABSOLUTE_URL='%s'" % CONFIG.ABSOLUTE_URL) -log("ScoDoc: using encoding %s" % SCO_ENCODING) +if hasattr(scu.CONFIG, "ABSOLUTE_URL") and scu.CONFIG.ABSOLUTE_URL: + log("ScoDoc: ABSOLUTE_URL='%s'" % scu.CONFIG.ABSOLUTE_URL) +log("ScoDoc: using encoding %s" % scu.SCO_ENCODING) # import essai_cas @@ -197,8 +232,10 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp H.append(r) ok = False - for permission in Sco_Default_Permissions.keys(): - roles = [r + DeptId for r in Sco_Default_Permissions[permission]] + for permission in sco_permissions.Sco_Default_Permissions.keys(): + roles = [ + r + DeptId for r in sco_permissions.Sco_Default_Permissions[permission] + ] roles.append("Manager") log("granting '%s' to %s" % (permission, roles)) try: @@ -271,7 +308,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo © Emmanuel Viennet 1997-2021

Version %s (subversion %s)

""" - % (SCOVERSION, get_svn_version(file_path)) + % (SCOVERSION, scu.get_svn_version(file_path)) ] H.append( '

Logiciel libre écrit en Python.

Utilise ReportLab pour générer les documents PDF, et pyExcelerator pour le traitement des documents Excel.

' @@ -403,7 +440,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo Dernières évolutions" + SCONEWS) H.append( '" ) d = "" @@ -417,12 +454,12 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo now() order by S.date_debut desc;", {"etudid": etudid}, @@ -1350,7 +1387,6 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo Date de la %s (J/M/AAAA):  """ - % (operation_method, strlower(operation_name)) + % (operation_method, scu.strlower(operation_name)) ) H.append( """ @@ -1410,7 +1446,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo " + aggregat) # listeTags = jury.get_allTagForAggregat(aggregat) # les tags de l'aggrégat listeTags = [ @@ -366,25 +369,20 @@ def get_bilanParTag(donnees_etudiant, groupe="groupe"): ("\\textit{" + rang + "}") if note else "" ) # rang masqué si pas de notes - # pprint.pprint(valeurs) - # print(len(entete)) code_latex = u"\\begin{tabular}{|c|" + "|c" * (len(entete)) + "|}\n" code_latex += u"\\hline \n" code_latex += ( u" & " - + " & ".join( - ["\\textbf{" + intitule + "}" for (agg, intitule, ordre) in entete] - ) + + " & ".join(["\\textbf{" + intitule + "}" for (agg, intitule, _) in entete]) + " \\\\ \n" ) code_latex += u"\\hline" code_latex += u"\\hline \n" for (i, ligne_val) in enumerate(valeurs["note"]): titre = lignes[i] # règle le pb d'encodage - # print titre, ligne_val code_latex += ( u"\\textbf{" - + titre.decode(SCO_ENCODING) + + titre.decode(scu.SCO_ENCODING) + u"} & " + " & ".join(ligne_val) + u"\\\\ \n" @@ -412,9 +410,11 @@ def get_avis_poursuite_par_etudiant( if pe_tools.PE_DEBUG: pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + etudid) - sexe = jury.syntheseJury[etudid]["sexe"].decode(SCO_ENCODING) - nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-").decode(SCO_ENCODING) - prenom = jury.syntheseJury[etudid]["prenom"].replace(" ", "-").decode(SCO_ENCODING) + sexe = jury.syntheseJury[etudid]["sexe"].decode(scu.SCO_ENCODING) + nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-").decode(scu.SCO_ENCODING) + prenom = ( + jury.syntheseJury[etudid]["prenom"].replace(" ", "-").decode(scu.SCO_ENCODING) + ) nom_fichier = ( u"avis_poursuite_" @@ -460,11 +460,11 @@ def get_templates_from_distrib(template="avis"): if template in ["avis", "footer"]: # pas de preference pour le template: utilise fichier du serveur - p = os.path.join(SCO_SRCDIR, pe_local_tmpl) + p = os.path.join(scu.SCO_SRCDIR, pe_local_tmpl) if os.path.exists(p): template_latex = get_code_latex_from_modele(p) else: - p = os.path.join(SCO_SRCDIR, pe_default_tmpl) + p = os.path.join(scu.SCO_SRCDIR, pe_default_tmpl) if os.path.exists(p): template_latex = get_code_latex_from_modele(p) else: @@ -534,7 +534,9 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe): annotationPE = get_annotation_PE( context, etudid, tag_annotation_pe=tag_annotation_pe ) - row["Annotation PE"] = annotationPE.encode(SCO_ENCODING) if annotationPE else "" + row["Annotation PE"] = ( + annotationPE.encode(scu.SCO_ENCODING) if annotationPE else "" + ) rows.append(row) T = GenTable( diff --git a/pe_jurype.py b/pe_jurype.py index cc000237..fe43e7d1 100644 --- a/pe_jurype.py +++ b/pe_jurype.py @@ -42,6 +42,7 @@ Created on Fri Sep 9 09:15:05 2016 # a l'edition d'un jury de poursuites d'etudes # ---------------------------------------------------------- +import os try: from cStringIO import StringIO @@ -54,10 +55,9 @@ from zipfile import ZipFile, BadZipfile import pprint from gen_tables import GenTable, SeqGenTable - +import sco_utils as scu import sco_codes_parcours # sco_codes_parcours.NEXT -> sem suivant import sco_report -from sco_utils import * import pe_tagtable, pe_tools, pe_avislatex, pe_semestretag, pe_settag @@ -450,15 +450,15 @@ class JuryPE: end="", ) - if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: - print + # if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: + # print # ------------------------------------------------------------------------------------------------------------------ def est_un_etudiant_reoriente_ou_demissionnaire(self, etudid): """Renvoie True si l'étudiant est réorienté (NAR) ou démissionnaire (DEM)""" reponse = False etud = self.get_cache_etudInfo_d_un_etudiant(self.context, etudid) - (code, parcours) = sco_report.get_codeparcoursetud(self.context.Notes, etud) + (_, parcours) = sco_report.get_codeparcoursetud(self.context.Notes, etud) if ( len(set(sco_codes_parcours.CODES_SEM_REO.keys()) & set(parcours.values())) > 0 @@ -862,13 +862,13 @@ class JuryPE: def get_dateEntree(self, etudid): """Renvoie l'année d'entrée de l'étudiant à l'IUT""" - etudinfo = self.ETUDINFO_DICT[etudid] + # etudinfo = self.ETUDINFO_DICT[etudid] semDeb = self.get_semestresDUT_d_un_etudiant(etudid)[-1] # le 1er sem à l'IUT return semDeb["annee_debut"] def get_parcoursIUT(self, etudid): """Renvoie une liste d'infos sur les semestres du parcours d'un étudiant""" - etudinfo = self.ETUDINFO_DICT[etudid] + # etudinfo = self.ETUDINFO_DICT[etudid] sems = self.get_semestresDUT_d_un_etudiant(etudid) infos = [] @@ -1073,7 +1073,7 @@ class JuryPE: if mode == "singlesheet" else "%s " % (sem) ) - row[champ + "note"] = fmt_note(resgroupe[0]) + row[champ + "note"] = scu.fmt_note(resgroupe[0]) row[champ + "class groupe"] = "%s / %s" % ( resgroupe[2], resgroupe[3], @@ -1083,11 +1083,12 @@ class JuryPE: respromo[3], ) row[champ + "min/moy/max groupe"] = "%s / %s / %s" % tuple( - fmt_note(x) + scu.fmt_note(x) for x in (resgroupe[6], resgroupe[4], resgroupe[5]) ) row[champ + "min/moy/max promo"] = "%s / %s / %s" % tuple( - fmt_note(x) for x in (respromo[6], respromo[4], respromo[5]) + scu.fmt_note(x) + for x in (respromo[6], respromo[4], respromo[5]) ) rows.append(row) diff --git a/pe_semestretag.py b/pe_semestretag.py index cfb47ce7..919110a1 100644 --- a/pe_semestretag.py +++ b/pe_semestretag.py @@ -35,8 +35,10 @@ Created on Fri Sep 9 09:15:05 2016 @author: barasc """ -import notes_table import datetime + +from notes_log import log +import notes_table import sco_codes_parcours import sco_tag_module import sco_utils @@ -57,14 +59,14 @@ class SemestreTag(pe_tagtable.TableTag): Attributs supplémentaires : - inscrlist/identdict: étudiants inscrits hors démissionnaires ou défaillants - _tagdict : Dictionnaire résumant les tags et les modules du semestre auxquels ils sont liés - - _sum_coeff_semestre : la somme des coeffs du semestre + Attributs hérités de TableTag : - nom : - resultats: {tag: { etudid: (note_moy, somme_coff), ...} , ...} - rang - statistiques - + Redéfinition : - get_etudids() : les etudids des étudiants non défaillants ni démissionnaires """ @@ -136,8 +138,7 @@ class SemestreTag(pe_tagtable.TableTag): # ----------------------------------------------------------------------------- def get_etudids(self): - """Renvoie la liste des etud_id des étudiants inscrits au semestre - """ + """Renvoie la liste des etud_id des étudiants inscrits au semestre""" return [etud["etudid"] for etud in self.inscrlist] # ----------------------------------------------------------------------------- @@ -154,7 +155,7 @@ class SemestreTag(pe_tagtable.TableTag): Renvoie le dictionnaire ainsi construit. Rq: choix fait de repérer les modules par rapport à leur modimpl_id (valable uniquement pour un semestre), car - correspond à la majorité des calculs de moyennes pour les étudiants + correspond à la majorité des calculs de moyennes pour les étudiants (seuls ceux qui ont capitalisé des ue auront un régime de calcul différent). """ tagdict = {} @@ -227,7 +228,7 @@ class SemestreTag(pe_tagtable.TableTag): # ----------------------------------------------------------------------------- def get_noteEtCoeff_modimpl(self, modimpl_id, etudid, profondeur=2): - """ Renvoie un couple donnant la note et le coeff normalisé d'un étudiant à un module d'id modimpl_id. + """Renvoie un couple donnant la note et le coeff normalisé d'un étudiant à un module d'id modimpl_id. La note et le coeff sont extraits : 1) soit des données du semestre en normalisant le coefficient par rapport à la somme des coefficients des modules du semestre, 2) soit des données des UE précédemment capitalisées, en recherchant un module de même CODE que le modimpl_id proposé, @@ -313,10 +314,10 @@ class SemestreTag(pe_tagtable.TableTag): # ----------------------------------------------------------------------------- def get_listesNotesEtCoeffsTagEtudiant(self, tag, etudid): """Renvoie un triplet (notes, coeffs_norm, ponderations) où notes, coeff_norm et ponderation désignent trois listes - donnant -pour un tag donné- les note, coeff et ponderation de chaque modimpl à prendre en compte dans - le calcul de la moyenne du tag. - Les notes et coeff_norm sont extraits grâce à SemestreTag.get_noteEtCoeff_modimpl (donc dans semestre courant ou UE capitalisée). - Les pondérations sont celles déclarées avec le tag (cf. _tagdict). """ + donnant -pour un tag donné- les note, coeff et ponderation de chaque modimpl à prendre en compte dans + le calcul de la moyenne du tag. + Les notes et coeff_norm sont extraits grâce à SemestreTag.get_noteEtCoeff_modimpl (donc dans semestre courant ou UE capitalisée). + Les pondérations sont celles déclarées avec le tag (cf. _tagdict).""" notes = [] coeffs_norm = [] @@ -382,7 +383,7 @@ class SemestreTag(pe_tagtable.TableTag): + ( "%1.5f" % (coeff * self.somme_coeffs) if coeff != None and isinstance(coeff, float) - else str(coeff * self._sum_coeff_semestre) + else "???" # str(coeff * self._sum_coeff_semestre) # voir avec Cléo ) + delim ) @@ -471,14 +472,15 @@ def comp_coeff_pond(coeffs, ponderations): # ----------------------------------------------------------------------------- def get_moduleimpl(nt, modimpl_id): """Renvoie l'objet modimpl dont l'id est modimpl_id fourni dans la note table nt, - en utilisant l'attribut nt._modimpls""" + en utilisant l'attribut nt._modimpls""" modimplids = [ modimpl["moduleimpl_id"] for modimpl in nt._modimpls ] # la liste de id des modules (modimpl_id) if modimpl_id not in modimplids: if SemestreTag.DEBUG: - print "SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas" % ( - modimpl_id + log( + "SemestreTag.get_moduleimpl( %s ) : le modimpl recherche n'existe pas" + % (modimpl_id) ) return None return nt._modimpls[modimplids.index(modimpl_id)] diff --git a/sco_apogee_csv.py b/sco_apogee_csv.py index 45b71e92..55ccc145 100644 --- a/sco_apogee_csv.py +++ b/sco_apogee_csv.py @@ -27,9 +27,7 @@ """Exportation des résultats des étudiants vers Apogée. -EXPERIMENTAL / PRECAUTIONS ! - -Code inspiré par les travaux de Damien Mascré, scodoc2apogee (en Java). +Ce code a été au départ inspiré par les travaux de Damien Mascré, scodoc2apogee (en Java). A utiliser en fin de semestre, après les jury. @@ -81,6 +79,13 @@ XXX A vérifier: AJAC car 1 sem. validé et pas de NAR """ + +import collections +from types import FloatType +import re +import time +import datetime +import os from cStringIO import StringIO from zipfile import ZipFile import pprint @@ -90,6 +95,10 @@ try: except: chardet_detect = None +import sco_utils as scu +import notesdb as ndb +from notes_log import log +from sco_exceptions import ScoValueError, FormatError import sco_formsemestre from sco_formsemestre import ApoEtapeVDI import sco_formsemestre_status @@ -98,8 +107,6 @@ import sco_codes_parcours from sco_codes_parcours import code_semestre_validant from sco_codes_parcours import ATT, ATB, ADM, ADC, ADJ, ATJ, ATB, AJ, CMP, NAR, RAT, DEF from gen_tables import GenTable -from notesdb import * -from sco_utils import * APO_PORTAL_ENCODING = ( "utf8" # encodage du fichier CSV Apogée (était 'ISO-8859-1' avant jul. 2016) @@ -347,10 +354,10 @@ class ApoEtud(dict): for col_id in apo_data.col_ids[:4]: self.new_cols[col_id] = self.cols[col_id] - def unassociated_codes(self, apo_data): - "list of apo elements for this student without a value in ScoDoc" - codes = set([apo_data.cols[col_id].code for col_id in apo_data.col_ids]) - return codes - set(sco_elts) + # def unassociated_codes(self, apo_data): + # "list of apo elements for this student without a value in ScoDoc" + # codes = set([apo_data.cols[col_id].code for col_id in apo_data.col_ids]) + # return codes - set(sco_elts) def search_elt_in_sem(self, context, code, sem, cur_sem, autre_sem): """ @@ -749,7 +756,7 @@ class ApoData: if not data: raise FormatError("Fichier Apogée vide !") - data_utf8 = data.decode(APO_INPUT_ENCODING).encode(SCO_ENCODING) + data_utf8 = data.decode(APO_INPUT_ENCODING).encode(scu.SCO_ENCODING) f = StringIOFileLineWrapper(data_utf8) # pour traiter comme un fichier # check that we are at the begining of Apogee CSV line = f.readline().strip() @@ -1023,7 +1030,7 @@ def _apo_read_cols(f): line = f.readline().strip(" " + APO_NEWLINE) fs = line.split(APO_SEP) if fs[0] != "apoL_a01_code": - raise FormatError("invalid line: %s (expecting apoL_a01_code)"(line, i)) + raise FormatError("invalid line: %s (expecting apoL_a01_code)" % line) col_keys = fs while True: # skip premiere partie (apoL_a02_nom, ...) @@ -1046,7 +1053,9 @@ def _apo_read_cols(f): raise FormatError("duplicate column definition: %s" % col_id) m = re.match(r"^apoL_c([0-9]{4})$", col_id) if not m: - raise FormatError("invalid column id: %s (expecting apoL_c%04d)"(line, i)) + raise FormatError( + "invalid column id: %s (expecting apoL_c%04d)" % (line, col_id) + ) if int(m.group(1)) != i: raise FormatError("invalid column id: %s for index %s" % (col_id, i)) @@ -1281,7 +1290,7 @@ def export_csv_to_apogee( ) log(logf.getvalue()) # sortie aussi sur le log ScoDoc - csv_data = f.getvalue().decode(SCO_ENCODING).encode(APO_OUTPUT_ENCODING) + csv_data = f.getvalue().decode(scu.SCO_ENCODING).encode(APO_OUTPUT_ENCODING) # Write data to ZIP dest_zip.writestr(csv_filename, csv_data) diff --git a/sco_bulletins_standard.py b/sco_bulletins_standard.py index 5bc89845..eb937a2f 100644 --- a/sco_bulletins_standard.py +++ b/sco_bulletins_standard.py @@ -46,7 +46,10 @@ de la forme %(XXX)s sont remplacées par la valeur de XXX, pour XXX dans: Balises img: actuellement interdites. """ -import traceback, re +import datetime +import traceback +import re +import jaxml import sco_utils as scu import sco_formsemestre diff --git a/sco_edit_ue.py b/sco_edit_ue.py index b29c613c..4fa62624 100644 --- a/sco_edit_ue.py +++ b/sco_edit_ue.py @@ -217,7 +217,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): REQUEST, ) else: - ue_id = do_ue_edit(context, tf[2]) + do_ue_edit(context, tf[2]) return REQUEST.RESPONSE.redirect( REQUEST.URL1 + "/ue_list?formation_id=" + formation_id ) diff --git a/sco_edt_cal.py b/sco_edt_cal.py index 33a70de9..c1b7554f 100644 --- a/sco_edt_cal.py +++ b/sco_edt_cal.py @@ -84,10 +84,10 @@ def formsemestre_load_ics(context, sem): return cal -def formsemestre_edt_groups_used(context, sem): - """L'ensemble des groupes EDT utilisés dans l'emplois du temps publié""" - cal = formsemestre_load_ics(context, sem) - return {e["X-GROUP-ID"].decode("utf8") for e in events} +# def formsemestre_edt_groups_used(context, sem): +# """L'ensemble des groupes EDT utilisés dans l'emploi du temps publié""" +# cal = formsemestre_load_ics(context, sem) +# return {e["X-GROUP-ID"].decode("utf8") for e in events} def get_edt_transcodage_groups(context, formsemestre_id): diff --git a/sco_placement.py b/sco_placement.py index 62c51ec2..7917a60d 100644 --- a/sco_placement.py +++ b/sco_placement.py @@ -31,8 +31,8 @@ Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016 """ -from notesdb import * -from sco_utils import * +import sco_utils as scu +import notesdb as ndb from notes_log import log import scolars import sco_formsemestre @@ -260,7 +260,6 @@ def do_placement(context, REQUEST): if None in [g["group_name"] for g in groups]: # tous les etudiants getallstudents = True - gr_title = "tous" gr_title_filename = "tous" else: getallstudents = False @@ -273,7 +272,7 @@ def do_placement(context, REQUEST): M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] Mod = context.do_module_list(args={"module_id": M["module_id"]})[0] sem = sco_formsemestre.get_formsemestre(context, M["formsemestre_id"]) - evalname = "%s-%s" % (Mod["code"], DateDMYtoISO(E["jour"])) + evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) if E["description"]: evaltitre = E["description"] else: diff --git a/sco_prepajury.py b/sco_prepajury.py index 11f33a54..16fe212f 100644 --- a/sco_prepajury.py +++ b/sco_prepajury.py @@ -136,11 +136,17 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): # Codes des UE "semestre précédent": ue_prev_codes = prev_moy_ue.keys() ue_prev_codes.sort( - lambda x, y, prev_ue_acro=prev_ue_acro: cmp(prev_ue_acro[x], prev_ue_acro[y]) + lambda x, y, prev_ue_acro=prev_ue_acro: cmp( # pylint: disable=undefined-variable + prev_ue_acro[x], prev_ue_acro[y] + ) ) # Codes des UE "semestre courant": ue_codes = moy_ue.keys() - ue_codes.sort(lambda x, y, ue_acro=ue_acro: cmp(ue_acro[x], ue_acro[y])) + ue_codes.sort( + lambda x, y, ue_acro=ue_acro: cmp( # pylint: disable=undefined-variable + ue_acro[x], ue_acro[y] + ) + ) sid = sem["semestre_id"] sn = sp = "" diff --git a/sco_report.py b/sco_report.py index 3f4a69b0..55927dfa 100644 --- a/sco_report.py +++ b/sco_report.py @@ -1242,7 +1242,7 @@ def graph_parcours( dem_nodes = {} # formsemestre_id : noeud pour demissionnaires nar_nodes = {} # formsemestre_id : noeud pour NAR for etud in etuds: - nxt = None + nxt = {} etudid = etud["etudid"] for s in etud["sems"]: # du plus recent au plus ancien nt = context._getNotesCache().get_NotesTable( diff --git a/sco_trombino.py b/sco_trombino.py index 798b2368..c4beb229 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -385,8 +385,8 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): sem = groups_infos.formsemestre # suppose 1 seul semestre PHOTOWIDTH = 2 * cm - COLWIDTH = 3.6 * cm - ROWS_PER_PAGE = 26 # XXX should be in ScoDoc preferences + # COLWIDTH = 3.6 * cm + # ROWS_PER_PAGE = 26 # XXX should be in ScoDoc preferences StyleSheet = styles.getSampleStyleSheet() report = StringIO() # in-memory document, no disk file @@ -460,71 +460,6 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): return sendPDFFile(REQUEST, data, filename) - objects = [] - StyleSheet = styles.getSampleStyleSheet() - report = StringIO() # in-memory document, no disk file - filename = ("trombino-%s.pdf" % ng).replace( - " ", "_" - ) # XXX should sanitize this filename - objects.append( - Paragraph(SU("Liste " + sem["titreannee"] + " " + ng), StyleSheet["Heading3"]) - ) - PHOTOWIDTH = 3 * cm - COLWIDTH = 3.6 * cm - - L = [] # cells - n = 0 - currow = [] - for t in T: - n = n + 1 - img = _get_etud_platypus_image(context, t, image_width=2 * cm) - currow += [ - Paragraph( - SU( - scolars.format_sexe(t["sexe"]) - + " " - + scolars.format_prenom(t["prenom"]) - + " " - + scolars.format_nom(t["nom"]) - ), - StyleSheet["Normal"], - ), - "", # empty cell (signature ou autre info a remplir sur papier) - img, - ] - - if not L: - table = Paragraph(SU("Aucune photo à exporter !"), StyleSheet["Normal"]) - else: - table = Table( - L, - colWidths=[COLWIDTH] * 7, - style=TableStyle( - [ - ("VALIGN", (0, 0), (-1, -1), "TOP"), - ("GRID", (0, 0), (2, -1), 0.25, colors.grey), - ("GRID", (2, 0), (-1, -1), 0.25, colors.red), # <<< - ] - ), - ) - objects.append(table) - - # Réduit sur une page - objects = [KeepInFrame(0, 0, objects, mode="shrink")] - - # --- Build document - document = BaseDocTemplate(report) - document.addPageTemplates( - ScolarsPageTemplate( - document, - context=context, - preferences=context.get_preferences(sem["formsemestre_id"]), - ) - ) - document.build(objects) - data = report.getvalue() - return sendPDFFile(REQUEST, data, filename) - # --------------------- Upload des photos de tout un groupe def photos_generate_excel_sample(context, group_ids=[], REQUEST=None): @@ -614,7 +549,7 @@ def photos_import_files( def callback(context, etud, data, filename, REQUEST): sco_photos.store_photo(context, etud, data, REQUEST) - r = zip_excel_import_files( + zip_excel_import_files( context, xlsfile, zipfile, REQUEST, callback, filename_title, page_title ) return REQUEST.RESPONSE.redirect(back_url + "&head_message=photos%20 importees") @@ -638,7 +573,7 @@ def zip_excel_import_files( exceldata = xlsfile.read() if not exceldata: raise ScoValueError("Fichier excel vide ou invalide") - diag, data = sco_excel.Excel_to_list(exceldata) + _, data = sco_excel.Excel_to_list(exceldata) if not data: # probably a bug raise ScoValueError("Fichier excel vide !") # on doit avoir une colonne etudid et une colonne filename_title ('fichier_photo') From b86c815b02e9bb2da4ba72df39bab290b29940c7 Mon Sep 17 00:00:00 2001 From: IDK Date: Tue, 2 Feb 2021 14:49:49 +0100 Subject: [PATCH 03/18] pylinting --- csv2rules.py | 28 +++++++++++++++++++---- notes_log.py | 18 +++++++++++---- notesdb.py | 14 +++++++----- pe_tagtable.py | 2 +- sco_abs_notification.py | 12 ++++++---- sco_dump_db.py | 16 ++++++++----- sco_import_users.py | 14 ++++++------ test_jurype.py => scotests/test_jurype.py | 0 8 files changed, 71 insertions(+), 33 deletions(-) rename test_jurype.py => scotests/test_jurype.py (100%) diff --git a/csv2rules.py b/csv2rules.py index be06c95d..1bf8ed57 100755 --- a/csv2rules.py +++ b/csv2rules.py @@ -45,7 +45,27 @@ HEAD = """# -*- coding: utf-8 -*- # # Command: %s %s # -from sco_codes_parcours import * +from sco_codes_parcours import ( + DUTRule, + ADC, + ADJ, + ADM, + AJ, + ALL, + ATB, + ATJ, + ATT, + CMP, + NAR, + NEXT, + RA_OR_NEXT, + RA_OR_RS, + RAT, + REO, + REDOANNEE, + REDOSEM, + RS_OR_NEXT, +) rules_source_file='%s' @@ -55,15 +75,15 @@ rules_source_file='%s' sourcefile, ) -from sco_codes_parcours import * +import sco_utils as scu def _fmt(s): if not s: return None - if strlower(s) in ("ok", "oui", "o", "y", "yes"): + if scu.strlower(s) in ("ok", "oui", "o", "y", "yes"): return True - if strlower(s) in ("no", "non"): + if scu.strlower(s) in ("no", "non"): return False if s == "*": return ALL diff --git a/notes_log.py b/notes_log.py index de2d4619..03852f9e 100644 --- a/notes_log.py +++ b/notes_log.py @@ -1,12 +1,22 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -import pdb, os, sys, time, re, inspect -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.Header import Header +import pdb +import sys +import os +import re +import inspect +import time import traceback +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error + # Simple & stupid file logguer, used only to debug # (logging to SQL is done in scolog) diff --git a/notesdb.py b/notesdb.py index 09e51a3b..fb073abf 100644 --- a/notesdb.py +++ b/notesdb.py @@ -5,6 +5,7 @@ import pdb, os, sys, string import traceback import psycopg2 import psycopg2.pool +import psycopg2.extras import thread from notes_log import log from sco_exceptions import * @@ -67,16 +68,17 @@ def GetUsersDBConnexion(context, autocommit=True): return cnx +# Nota: on pourrait maintenant utiliser psycopg2.extras.DictCursor class ScoDocCursor(psycopg2.extensions.cursor): """A database cursor emulating some methods of psycopg v1 cursors""" - def dictfetchall(cursor): - col_names = [d[0] for d in cursor.description] - return [dict(zip(col_names, row)) for row in cursor.fetchall()] + def dictfetchall(self): + col_names = [d[0] for d in self.description] + return [dict(zip(col_names, row)) for row in self.fetchall()] - def dictfetchone(cursor): - col_names = [d[0] for d in cursor.description] - row = cursor.fetchone() + def dictfetchone(self): + col_names = [d[0] for d in self.description] + row = self.fetchone() if row: return dict(zip(col_names, row)) else: diff --git a/pe_tagtable.py b/pe_tagtable.py index fcdcd178..56ea883c 100644 --- a/pe_tagtable.py +++ b/pe_tagtable.py @@ -210,7 +210,7 @@ class TableTag: ] nb_notes_valides = len(notes_valides) if nb_notes_valides > 0: - (moy, coeff) = moyenne_ponderee_terme_a_terme(notes_valides, force=True) + (moy, _) = moyenne_ponderee_terme_a_terme(notes_valides, force=True) self.statistiques[tag] = (moy, max(notes_valides), min(notes_valides)) # ************************************************************************ diff --git a/sco_abs_notification.py b/sco_abs_notification.py index 7dfa682e..e26e3d12 100644 --- a/sco_abs_notification.py +++ b/sco_abs_notification.py @@ -31,11 +31,13 @@ Il suffit d'appeler abs_notify() après chaque ajout d'absence. """ - -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.Header import Header -from email import Encoders +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error from notesdb import * from sco_utils import * diff --git a/sco_dump_db.py b/sco_dump_db.py index 621fd96b..9cea7407 100644 --- a/sco_dump_db.py +++ b/sco_dump_db.py @@ -50,11 +50,15 @@ pg_dump SCORT | psql ANORT import fcntl import subprocess import requests -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.MIMEBase import MIMEBase -from email.Header import Header -from email import Encoders + +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error + from notesdb import * from sco_utils import * @@ -74,7 +78,7 @@ def sco_dump_and_send_db(context, REQUEST=None): try: x = open(SCO_DUMP_LOCK, "w+") fcntl.flock(x, fcntl.LOCK_EX | fcntl.LOCK_NB) - except fcntl.BlockingIOError: + except (IOError, OSError): # exception changed from Python 2 to 3 raise ScoValueError( "Un envoi de la base " + db_name diff --git a/sco_import_users.py b/sco_import_users.py index c6da8d29..e974dbca 100644 --- a/sco_import_users.py +++ b/sco_import_users.py @@ -27,6 +27,13 @@ """Import d'utilisateurs via fichier Excel """ +from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error + MIMEMultipart, +) +from email.MIMEText import MIMEText # pylint: disable=no-name-in-module,import-error +from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import-error +from email.Header import Header # pylint: disable=no-name-in-module,import-error +from email import Encoders # pylint: disable=no-name-in-module,import-error from notesdb import * from sco_utils import * @@ -163,13 +170,6 @@ def generate_password(): return "".join(RNG.sample(l, PASSLEN)) -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.MIMEBase import MIMEBase -from email.Header import Header -from email import Encoders - - def mail_password(u, context=None, reset=False): "Send password by email" if not u["email"]: diff --git a/test_jurype.py b/scotests/test_jurype.py similarity index 100% rename from test_jurype.py rename to scotests/test_jurype.py From aefd14b420f3a2396244247ea333daa1e11f971f Mon Sep 17 00:00:00 2001 From: IDK Date: Wed, 3 Feb 2021 22:00:41 +0100 Subject: [PATCH 04/18] refactoring: notesdb usage --- ImportScolars.py | 28 +++++++--- ZScoUsers.py | 93 +++++++++++++++++++------------- debug.py | 7 ++- html_sco_header.py | 2 + html_sidebar.py | 6 +++ intervals.py | 16 +++--- notes_table.py | 22 +++++--- pe_semestretag.py | 2 +- sco_abs_notification.py | 18 +++---- sco_apogee_compare.py | 1 + sco_archives.py | 5 +- sco_archives_etud.py | 2 + sco_cost_formation.py | 2 +- sco_dept.py | 3 +- sco_dump_db.py | 5 +- sco_edit_formation.py | 5 +- sco_edit_matiere.py | 5 +- sco_edit_module.py | 6 ++- sco_edit_ue.py | 15 ++++-- sco_edt_cal.py | 1 + sco_etape_apogee.py | 1 + sco_etape_apogee_view.py | 1 + sco_export_results.py | 9 ++-- sco_find_etud.py | 12 +++-- sco_formations.py | 12 +++-- sco_formsemestre.py | 31 +++++------ sco_formsemestre_custommenu.py | 4 +- sco_formsemestre_edit.py | 20 +++---- sco_formsemestre_inscriptions.py | 13 +++-- sco_formsemestre_validation.py | 14 ++--- sco_groups.py | 65 ++++++++++++---------- sco_groups_edit.py | 3 +- sco_import_users.py | 3 +- sco_inscr_passage.py | 11 ++-- sco_liste_notes.py | 15 +++--- sco_lycee.py | 1 - sco_modalites.py | 2 +- sco_moduleimpl_inscriptions.py | 9 ++-- sco_news.py | 12 ++--- sco_page_etud.py | 14 +++-- sco_parcours_dut.py | 33 ++++++------ sco_placement.py | 3 +- sco_portal_apogee.py | 26 ++++----- sco_poursuite_dut.py | 2 +- sco_preferences.py | 5 +- sco_prepajury.py | 1 - sco_pvjury.py | 12 ++--- sco_saisie_notes.py | 23 +++----- sco_semset.py | 11 ++-- sco_synchro_etuds.py | 12 +++-- sco_tag_module.py | 36 +++++++------ sco_trombino.py | 1 + sco_ue_external.py | 10 ++-- sco_undo_notes.py | 6 +-- sco_utils.py | 52 ++++++++---------- sco_zope.py | 2 + scolog.py | 8 +-- 57 files changed, 426 insertions(+), 313 deletions(-) diff --git a/ImportScolars.py b/ImportScolars.py index 8713ac3c..8a417632 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -28,10 +28,15 @@ """ Importation des etudiants à partir de fichiers CSV """ -import os, sys, time, pdb +import os +import sys +import time +import pdb +import collections +import types from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log import scolars import sco_formsemestre @@ -42,6 +47,15 @@ import sco_news from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules from gen_tables import GenTable +from sco_exceptions import ( + AccessDenied, + FormatError, + ScoException, + ScoValueError, + ScoInvalidDateError, + ScoLockedFormError, + ScoGenError, +) # format description (relative to Product directory)) FORMAT_FILE = "misc/format_import_etudiants.txt" @@ -249,7 +263,7 @@ def scolars_import_excel_file( """ log("scolars_import_excel_file: formsemestre_id=%s" % formsemestre_id) cnx = context.GetDBConnexion(autocommit=False) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) annee_courante = time.localtime()[0] always_require_ine = context.get_preference("always_require_ine") exceldata = datafile.read() @@ -423,7 +437,7 @@ def scolars_import_excel_file( log("scolars_import_excel_file: aborting transaction !") # Nota: db transaction is sometimes partly commited... # here we try to remove all created students - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) for etudid in created_etudids: log("scolars_import_excel_file: deleting etudid=%s" % etudid) cursor.execute( @@ -729,19 +743,19 @@ def adm_get_fields(titles, formsemestre_id): def adm_convert_text(v): - if type(v) == FloatType: + if type(v) == types.FloatType: return "{:g}".format(v) # evite "1.0" return v def adm_convert_int(v): - if type(v) != IntType and not v: + if type(v) != types.IntType and not v: return None return int(float(v)) # accept "10.0" def adm_convert_real(v): - if type(v) != FloatType and not v: + if type(v) != types.FloatType and not v: return None return float(v) diff --git a/ZScoUsers.py b/ZScoUsers.py index 9e9dd924..64355f43 100644 --- a/ZScoUsers.py +++ b/ZScoUsers.py @@ -27,28 +27,45 @@ """ Gestion des utilisateurs (table SQL pour Zope User Folder) """ -import string, re +import string +import re import time -import md5, base64 +import md5 +import base64 +import jaxml - -from sco_zope import * +from sco_zope import * # pylint: disable=unused-wildcard-import # --------------- - -import notesdb -from notesdb import * +import sco_utils as scu +import notesdb as ndb from notes_log import log from scolog import logdb -from sco_utils import * from scolars import format_prenom, format_nom -import sco_import_users, sco_excel -from TrivialFormulator import TrivialFormulator, TF +import sco_import_users +import sco_excel +from TrivialFormulator import TrivialFormulator, TF, tf_error_message from gen_tables import GenTable import scolars import sco_cache import sco_users - +from sco_permissions import ( + ScoEditAllEvals, + ScoEditAllNotes, + ScoImplement, + ScoSuperAdmin, + ScoUsersAdmin, + ScoUsersView, + ScoView, +) +from sco_exceptions import ( + AccessDenied, + ScoException, + ScoValueError, + ScoInvalidDateError, + ScoLockedFormError, + ScoGenError, +) # --------------- # cache global: chaque instance, repérée par son URL, a un cache @@ -93,7 +110,7 @@ class ZScoUsers( # Ugly but necessary during transition out of Zope: _db_cnx_string = "dbname=SCOUSERS port=5432" security.declareProtected("Change DTML Documents", "GetUsersDBConnexion") - GetUsersDBConnexion = notesdb.GetUsersDBConnexion + GetUsersDBConnexion = ndb.GetUsersDBConnexion # -------------------------------------------------------------------- # @@ -162,7 +179,7 @@ class ZScoUsers( F = self.sco_footer(REQUEST) return "\n".join(H) + F - _userEditor = EditableTable( + _userEditor = ndb.EditableTable( "sco_users", "user_id", ( @@ -180,12 +197,12 @@ class ZScoUsers( "date_expiration", ), output_formators={ - "date_modif_passwd": DateISOtoDMY, - "date_expiration": DateISOtoDMY, + "date_modif_passwd": ndb.DateISOtoDMY, + "date_expiration": ndb.DateISOtoDMY, }, input_formators={ - "date_modif_passwd": DateDMYtoISO, - "date_expiration": DateDMYtoISO, + "date_modif_passwd": ndb.DateDMYtoISO, + "date_expiration": ndb.DateDMYtoISO, }, sortkey="nom", filter_nulls=False, @@ -217,12 +234,12 @@ class ZScoUsers( u = self._user_list(args={"user_name": user_name})[0] if u["status"] == "old" and u["roles"] and u["roles"][0] != "-": roles = ["-" + r for r in u["roles"].split(",")] - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) self.acl_users.scodoc_editUser(cursor, user_name, roles=roles) self.get_userlist_cache().inval_cache() elif not u["status"] and u["roles"] and u["roles"][0] == "-": roles = [r[1:] for r in u["roles"].split(",") if (r and r[0] == "-")] - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) self.acl_users.scodoc_editUser(cursor, user_name, roles=roles) self.get_userlist_cache().inval_cache() @@ -268,7 +285,7 @@ class ZScoUsers( "nom_fmt": user_name, "nomcomplet": user_name, "nomplogin": user_name, - "nomnoacc": suppress_accents(user_name), + "nomnoacc": scu.suppress_accents(user_name), "passwd_temp": 0, "status": "", "date_expiration": None, @@ -289,7 +306,7 @@ class ZScoUsers( else: n = user_name - prenom_abbrv = abbrev_prenom(p) + prenom_abbrv = scu.abbrev_prenom(p) # nomprenom est le nom capitalisé suivi de l'initiale du prénom info["nomprenom"] = (n + " " + prenom_abbrv).strip() # prenomnom est l'initiale du prénom suivie du nom @@ -301,9 +318,9 @@ class ZScoUsers( info["nomcomplet"] = info["prenom_fmt"] + " " + info["nom_fmt"] # nomplogin est le nom en majuscules suivi du prénom et du login # e.g. Dupont Pierre (dupont) - info["nomplogin"] = "%s %s (%s)" % (strupper(n), p, info["user_name"]) + info["nomplogin"] = "%s %s (%s)" % (scu.strupper(n), p, info["user_name"]) # nomnoacc est le nom en minuscules sans accents - info["nomnoacc"] = suppress_accents(strlower(info["nom"])) + info["nomnoacc"] = scu.suppress_accents(scu.strlower(info["nom"])) return info @@ -346,7 +363,7 @@ class ZScoUsers( assert len(user) == 1, "database inconsistency: len(user)=%d" % len(user) # should not occur, already tested in _can_handle_passwd cnx = self.GetUsersDBConnexion() # en mode autocommit - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "update sco_users set date_modif_passwd=now(), passwd_temp=0 where user_name=%(user_name)s", {"user_name": user_name}, @@ -417,7 +434,7 @@ class ZScoUsers(

Mot de passe changé !

""" - % (SCO_ENCODING, SCO_ENCODING) + % (scu.SCO_ENCODING, scu.SCO_ENCODING) + "\n".join(H) + 'Continuer' % self.ScoURL() @@ -536,7 +553,7 @@ class ZScoUsers( ) else: for p in scoperms: - permname, value = p[:2] + permname, _ = p[:2] if thisuser.has_permission(permname, self): b = "oui" else: @@ -903,7 +920,7 @@ class ZScoUsers( # Des noms/prénoms semblables existent ? cnx = self.GetUsersDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select * from sco_users where lower(nom) ~ %(nom)s and lower(prenom) ~ %(prenom)s;", {"nom": nom.lower().strip(), "prenom": prenom.lower().strip()}, @@ -1004,13 +1021,13 @@ class ZScoUsers( def create_user(self, args, REQUEST=None): "creation utilisateur zope" cnx = self.GetUsersDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) passwd = args["passwd"] args["passwd"] = "undefined" if "passwd2" in args: del args["passwd2"] log("create_user: args=%s" % args) # log apres supr. du mot de passe ! - r = self._userEditor.create(cnx, args) + _ = self._userEditor.create(cnx, args) self.get_userlist_cache().inval_cache() # > # call exUserFolder to set passwd @@ -1100,15 +1117,15 @@ class ZScoUsers( # Convert dates to ISO if XML output if format == "xml" and u["date_modif_passwd"] != "NA": - u["date_modif_passwd"] = DateDMYtoISO(u["date_modif_passwd"]) or "" + u["date_modif_passwd"] = ndb.DateDMYtoISO(u["date_modif_passwd"]) or "" # Convert date_expiration and date_modif_passwd to ISO to ease sorting if u["date_expiration"]: - u["date_expiration_iso"] = DateDMYtoISO(u["date_expiration"]) + u["date_expiration_iso"] = ndb.DateDMYtoISO(u["date_expiration"]) else: u["date_expiration_iso"] = "" if u["date_modif_passwd"]: - u["date_modif_passwd_iso"] = DateDMYtoISO(u["date_expiration"]) + u["date_modif_passwd_iso"] = ndb.DateDMYtoISO(u["date_expiration"]) else: u["date_modif_passwd_iso"] = "" @@ -1202,13 +1219,13 @@ class ZScoUsers( """Returns XML list of users with name (nomplogin) starting with start. Used for forms auto-completion.""" userlist = self.get_userlist(dept=dept) - start = suppression_diacritics(unicode(start, "utf-8")) - start = strlower(str(start)) + start = scu.suppression_diacritics(unicode(start, "utf-8")) + start = scu.strlower(str(start)) userlist = [user for user in userlist if user["nomnoacc"].startswith(start)] if REQUEST: - REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) - doc = jaxml.XML_document(encoding=SCO_ENCODING) + REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) + doc = jaxml.XML_document(encoding=scu.SCO_ENCODING) doc.results() for user in userlist[:limit]: doc._push() @@ -1269,14 +1286,14 @@ Il devra ensuite se connecter et le changer. log("reset_password: %s" % user_name) # Check that user has valid mail info = self.user_info(user_name=user_name) - if not is_valid_mail(info["email"]): + if not scu.is_valid_mail(info["email"]): raise Exception("pas de mail valide associé à l'utilisateur") # Generate random password password = sco_import_users.generate_password() self.do_change_password(user_name, password) # Flag it as temporary: cnx = self.GetUsersDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) ui = {"user_name": user_name} cursor.execute( "update sco_users set passwd_temp=1 where user_name='%(user_name)s'" % ui diff --git a/debug.py b/debug.py index 55c64e26..d0b8a4dd 100644 --- a/debug.py +++ b/debug.py @@ -32,10 +32,13 @@ nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_i """ import pdb +import pprint -from notesdb import * +import notesdb as ndb +from notesdb import * # pylint: disable=unused-wildcard-import from notes_log import log -from sco_utils import * +import sco_utils as scu +from sco_utils import * # pylint: disable=unused-wildcard-import from gen_tables import GenTable import sco_archives diff --git a/html_sco_header.py b/html_sco_header.py index 05ef45f2..d66a875b 100644 --- a/html_sco_header.py +++ b/html_sco_header.py @@ -25,6 +25,8 @@ # ############################################################################## +import cgi + from sco_utils import * from sco_formsemestre_status import formsemestre_page_title diff --git a/html_sidebar.py b/html_sidebar.py index df7bb59b..1c11cf57 100644 --- a/html_sidebar.py +++ b/html_sidebar.py @@ -27,6 +27,12 @@ from sco_utils import * from sco_abs import getAbsSemEtud +from sco_permissions import ( + ScoUsersAdmin, + ScoUsersView, + ScoChangePreferences, + ScoAbsChange, +) """ Génération de la "sidebar" (marge gauche des pages HTML) diff --git a/intervals.py b/intervals.py index 74140c0a..7517e603 100644 --- a/intervals.py +++ b/intervals.py @@ -173,17 +173,17 @@ if __name__ == "__main__": repr(i) == "{[None, 3] => 'My,', [3, 5] => 'Hello', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}" ) - i[5.5:6] = "Cruel" + i[5.5:6] = "Cruel" # pylint: disable=invalid-slice-index assert ( repr(i) == "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}" ) - i[6:6.5] = "And Harsh" + i[6:6.5] = "And Harsh" # pylint: disable=invalid-slice-index assert ( repr(i) == "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 6] => 'Cruel', [6, 6.5] => 'And Harsh', [6.5, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}" ) - i[5.9:6.6] = None + i[5.9:6.6] = None # pylint: disable=invalid-slice-index assert ( repr(i) == "{[None, 3] => 'My,', [3, 5] => 'Hello', [5.5, 5.9000000000000004] => 'Cruel', [6.5999999999999996, 7] => 'World', [8, 10] => '(Test)', [10, None] => '!'}" @@ -222,9 +222,13 @@ if __name__ == "__main__": print("Test 3 skipped") else: i = intervalmap() - i[: datetime(2005, 10, 24)] = "A" - i[datetime(2005, 11, 11) : datetime(2005, 11, 17)] = "B" - i[datetime(2005, 11, 30) :] = "C" + i[: datetime(2005, 10, 24)] = "A" # pylint: disable=invalid-slice-index + i[ + datetime(2005, 11, 11) : datetime( # pylint: disable=invalid-slice-index + 2005, 11, 17 + ) + ] = "B" + i[datetime(2005, 11, 30) :] = "C" # pylint: disable=invalid-slice-index assert i[datetime(2005, 9, 25)] == "A" assert i[datetime(2005, 10, 23)] == "A" assert i[datetime(2005, 10, 26)] == None diff --git a/notes_table.py b/notes_table.py index 550b65b9..236ae3b9 100644 --- a/notes_table.py +++ b/notes_table.py @@ -27,16 +27,18 @@ """Calculs sur les notes et cache des resultats """ -from types import StringType +from types import StringType, FloatType import pdb import inspect + import scolars import sco_groups from notes_log import log, logCallStack from sco_utils import * -from notesdb import * +import notesdb as ndb import sco_codes_parcours +from sco_codes_parcours import DEF, UE_SPORT, UE_is_fondamentale, UE_is_professionnelle from sco_parcours_dut import formsemestre_get_etud_capitalisation from sco_parcours_dut import list_formsemestre_utilisateurs_uecap import sco_parcours_dut @@ -46,6 +48,12 @@ import sco_moduleimpl import sco_evaluations import sco_compute_moy from sco_formulas import NoteVector +from sco_exceptions import ( + AccessDenied, + NoteProcessError, + ScoException, + ScoValueError, +) # Support for old user-written "bonus" functions with 2 args: BONUS_TWO_ARGS = len(inspect.getargspec(CONFIG.compute_bonus)[0]) == 2 @@ -107,7 +115,7 @@ def comp_etud_sum_coef_modules_ue(context, formsemestre_id, etudid, ue_id): (nécessaire pour éviter appels récursifs de nt, qui peuvent boucler) """ - infos = SimpleDictFetch( + infos = ndb.SimpleDictFetch( context, """SELECT mod.coefficient FROM notes_modules mod, notes_moduleimpl mi, notes_moduleimpl_inscription ins @@ -1023,7 +1031,7 @@ class NotesTable: Si l'étudiant est défaillant, met un code DEF sur toutes les UE """ cnx = self.context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select etudid, code, assidu, compense_formsemestre_id, event_date from scolar_formsemestre_validation where formsemestre_id=%(formsemestre_id)s and ue_id is NULL;", {"formsemestre_id": self.formsemestre_id}, @@ -1040,7 +1048,7 @@ class NotesTable: "code": code, "assidu": assidu, "compense_formsemestre_id": compense_formsemestre_id, - "event_date": DateISOtoDMY(event_date), + "event_date": ndb.DateISOtoDMY(event_date), } self.decisions_jury = decisions_jury @@ -1089,7 +1097,7 @@ class NotesTable: decisions_jury_ues[etudid][ue_id] = { "code": code, "ects": ects, # 0. si non UE validée ou si mode de calcul different (?) - "event_date": DateISOtoDMY(event_date), + "event_date": ndb.DateISOtoDMY(event_date), } self.decisions_jury_ues = decisions_jury_ues @@ -1281,7 +1289,7 @@ class NotesTable: (ne compte que les notes en attente dans des évaluation avec coef. non nul). """ cnx = self.context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select n.* from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_moduleimpl_inscription i where n.etudid = %(etudid)s and n.value = %(code_attente)s and n.evaluation_id=e.evaluation_id and e.moduleimpl_id=m.moduleimpl_id and m.formsemestre_id=%(formsemestre_id)s and e.coefficient != 0 and m.moduleimpl_id=i.moduleimpl_id and i.etudid=%(etudid)s", { diff --git a/pe_semestretag.py b/pe_semestretag.py index 919110a1..7509ea90 100644 --- a/pe_semestretag.py +++ b/pe_semestretag.py @@ -113,7 +113,7 @@ class SemestreTag(pe_tagtable.TableTag): self.modimpls = [ modimpl for modimpl in self.nt._modimpls - if modimpl["ue"]["type"] == sco_utils.UE_STANDARD + if modimpl["ue"]["type"] == sco_codes_parcours.UE_STANDARD ] # la liste des modules (objet modimpl) # self._modimpl_ids = [modimpl['moduleimpl_id'] for modimpl in self._modimpls] # la liste de id des modules (modimpl_id) self.somme_coeffs = sum( diff --git a/sco_abs_notification.py b/sco_abs_notification.py index e26e3d12..ec4ecc7d 100644 --- a/sco_abs_notification.py +++ b/sco_abs_notification.py @@ -39,7 +39,7 @@ from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import- from email.Header import Header # pylint: disable=no-name-in-module,import-error from email import Encoders # pylint: disable=no-name-in-module,import-error -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from scolog import logdb @@ -57,8 +57,8 @@ def abs_notify(context, etudid, date): if not sem: return # non inscrit a la date, pas de notification - debut_sem = DateDMYtoISO(sem["date_debut"]) - fin_sem = DateDMYtoISO(sem["date_fin"]) + debut_sem = ndb.DateDMYtoISO(sem["date_debut"]) + fin_sem = ndb.DateDMYtoISO(sem["date_fin"]) nbabs = context.CountAbs(etudid, debut=debut_sem, fin=fin_sem) nbabsjust = context.CountAbsJust(etudid, debut=debut_sem, fin=fin_sem) @@ -111,12 +111,12 @@ def abs_notify_send( """Actually send the notification by email, and register it in database""" cnx = context.GetDBConnexion() log("abs_notify: sending notification to %s" % destinations) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) for email in destinations: del msg["To"] msg["To"] = email context.sendEmail(msg) - SimpleQuery( + ndb.SimpleQuery( context, """insert into absences_notifications (etudid, email, nbabs, nbabsjust, formsemestre_id) values (%(etudid)s, %(email)s, %(nbabs)s, %(nbabsjust)s, %(formsemestre_id)s)""", vars(), @@ -203,7 +203,7 @@ def etud_nbabs_last_notified(context, etudid, formsemestre_id=None): """nbabs lors de la dernière notification envoyée pour cet étudiant dans ce semestre ou sans semestre (ce dernier cas est nécessaire pour la transition au nouveau code)""" cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """select * from absences_notifications where etudid = %(etudid)s and (formsemestre_id = %(formsemestre_id)s or formsemestre_id is NULL) order by notification_date desc""", vars(), @@ -218,7 +218,7 @@ def etud_nbabs_last_notified(context, etudid, formsemestre_id=None): def user_nbdays_since_last_notif(context, email_addr, etudid): """nb days since last notification to this email, or None if no previous notification""" cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """select * from absences_notifications where email = %(email_addr)s and etudid=%(etudid)s order by notification_date desc""", {"email_addr": email_addr, "etudid": etudid}, @@ -273,7 +273,7 @@ def retreive_current_formsemestre(context, etudid, cur_date): WHERE sem.formsemestre_id = i.formsemestre_id AND i.etudid=%(etudid)s AND (%(cur_date)s >= sem.date_debut) AND (%(cur_date)s <= sem.date_fin)""" - r = SimpleDictFetch(context, req, {"etudid": etudid, "cur_date": cur_date}) + r = ndb.SimpleDictFetch(context, req, {"etudid": etudid, "cur_date": cur_date}) if not r: return None # s'il y a plusieurs semestres, prend le premier (rarissime et non significatif): @@ -286,5 +286,5 @@ def mod_with_evals_at_date(context, date_abs, etudid): req = """SELECT m.* FROM notes_moduleimpl m, notes_evaluation e, notes_moduleimpl_inscription i WHERE m.moduleimpl_id = e.moduleimpl_id AND e.moduleimpl_id = i.moduleimpl_id AND i.etudid = %(etudid)s AND e.jour = %(date_abs)s""" - r = SimpleDictFetch(context, req, {"etudid": etudid, "date_abs": date_abs}) + r = ndb.SimpleDictFetch(context, req, {"etudid": etudid, "date_abs": date_abs}) return r diff --git a/sco_apogee_compare.py b/sco_apogee_compare.py index 221e707a..5f36d13f 100644 --- a/sco_apogee_compare.py +++ b/sco_apogee_compare.py @@ -50,6 +50,7 @@ from sco_utils import * from notes_log import log import sco_apogee_csv from gen_tables import GenTable +from sco_exceptions import ScoValueError _help_txt = """
diff --git a/sco_archives.py b/sco_archives.py index e328d4fb..0a7f2b33 100644 --- a/sco_archives.py +++ b/sco_archives.py @@ -52,7 +52,7 @@ import shutil import glob from sco_utils import * -from notesdb import * +import notesdb as ndb import sco_formsemestre import sco_pvjury @@ -62,6 +62,9 @@ import sco_groups import sco_groups_view from sco_recapcomplet import make_formsemestre_recapcomplet import sco_bulletins_pdf +from sco_exceptions import ( + AccessDenied, +) class BaseArchiver: diff --git a/sco_archives_etud.py b/sco_archives_etud.py index 01e2db6a..f1cf2a83 100644 --- a/sco_archives_etud.py +++ b/sco_archives_etud.py @@ -38,6 +38,8 @@ import sco_groups import sco_trombino import sco_excel import sco_archives +from sco_permissions import ScoEtudAddAnnotations +from sco_exceptions import AccessDenied class EtudsArchiver(sco_archives.BaseArchiver): diff --git a/sco_cost_formation.py b/sco_cost_formation.py index 22693867..3bfc618b 100644 --- a/sco_cost_formation.py +++ b/sco_cost_formation.py @@ -30,7 +30,7 @@ (coût théorique en heures équivalent TD) """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from gen_tables import GenTable diff --git a/sco_dept.py b/sco_dept.py index f7c95c0a..ce83313c 100644 --- a/sco_dept.py +++ b/sco_dept.py @@ -27,7 +27,7 @@ """Page accueil département (liste des semestres, etc) """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log import sco_modalites @@ -35,6 +35,7 @@ import sco_news import sco_up_to_date import sco_formsemestre from gen_tables import GenTable +from sco_permissions import ScoEtudInscrit, ScoEditApo def index_html(context, REQUEST=None, showcodes=0, showsemtable=0): diff --git a/sco_dump_db.py b/sco_dump_db.py index 9cea7407..36dbf37d 100644 --- a/sco_dump_db.py +++ b/sco_dump_db.py @@ -60,9 +60,10 @@ from email.Header import Header # pylint: disable=no-name-in-module,import-erro from email import Encoders # pylint: disable=no-name-in-module,import-error -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log +from sco_exceptions import ScoValueError SCO_DUMP_LOCK = "/tmp/scodump.lock" @@ -71,7 +72,7 @@ def sco_dump_and_send_db(context, REQUEST=None): """Dump base de données du département courant et l'envoie anonymisée pour debug""" H = [context.sco_header(REQUEST, page_title="Assistance technique")] # get currect (dept) DB name: - cursor = SimpleQuery(context, "SELECT current_database()", {}) + cursor = ndb.SimpleQuery(context, "SELECT current_database()", {}) db_name = cursor.fetchone()[0] ano_db_name = "ANO" + db_name # Lock diff --git a/sco_edit_formation.py b/sco_edit_formation.py index 96c318e3..f5665574 100644 --- a/sco_edit_formation.py +++ b/sco_edit_formation.py @@ -28,12 +28,13 @@ """Ajout/Modification/Supression formations (portage from DTML) """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_codes_parcours import sco_formsemestre +from sco_exceptions import ScoValueError def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None): @@ -202,7 +203,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None): "titre": tf[2]["titre"], "version": version, } - quote_dict(args) + ndb.quote_dict(args) others = context.formation_list(args=args) if others and ((len(others) > 1) or others[0]["formation_id"] != formation_id): return ( diff --git a/sco_edit_matiere.py b/sco_edit_matiere.py index 2cdda893..7b041805 100644 --- a/sco_edit_matiere.py +++ b/sco_edit_matiere.py @@ -28,11 +28,12 @@ """Ajout/Modification/Supression matieres (portage from DTML) """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre +from sco_exceptions import ScoValueError def matiere_create(context, ue_id=None, REQUEST=None): @@ -202,7 +203,7 @@ associé. # changement d'UE ? if tf[2]["ue_id"] != F["ue_id"]: log("attaching mat %s to new UE %s" % (matiere_id, tf[2]["ue_id"])) - SimpleQuery( + ndb.SimpleQuery( context, "UPDATE notes_modules SET ue_id = %(ue_id)s WHERE matiere_id=%(matiere_id)s", {"ue_id": tf[2]["ue_id"], "matiere_id": matiere_id}, diff --git a/sco_edit_module.py b/sco_edit_module.py index 64b51b6b..c7aa3f5c 100644 --- a/sco_edit_module.py +++ b/sco_edit_module.py @@ -28,7 +28,7 @@ """Ajout/Modification/Supression UE (portage from DTML) """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log import sco_codes_parcours @@ -36,6 +36,8 @@ from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre import sco_edit_ue import sco_tag_module +from sco_permissions import ScoChangeFormation +from sco_exceptions import ScoValueError _MODULE_HELP = """

Les modules sont décrits dans le programme pédagogique. Un module est pour ce @@ -227,7 +229,7 @@ def module_edit(context, module_id=None, REQUEST=None): unlocked = not context.module_is_locked(module_id) Fo = context.formation_list(args={"formation_id": Mod["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"]) - M = SimpleDictFetch( + M = ndb.SimpleDictFetch( context, "SELECT ue.acronyme, mat.* FROM notes_matieres mat, notes_ue ue WHERE mat.ue_id = ue.ue_id AND ue.formation_id = %(formation_id)s ORDER BY ue.numero, mat.numero", {"formation_id": Mod["formation_id"]}, diff --git a/sco_edit_ue.py b/sco_edit_ue.py index 4fa62624..593cda1c 100644 --- a/sco_edit_ue.py +++ b/sco_edit_ue.py @@ -28,7 +28,7 @@ """Ajout/Modification/Supression UE """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF @@ -38,6 +38,8 @@ import sco_formsemestre import sco_formsemestre_validation import sco_codes_parcours import sco_tag_module +from sco_permissions import ScoChangeFormation, ScoEditFormationTags, ScoImplement +from sco_exceptions import ScoValueError, ScoLockedFormError def ue_create(context, formation_id=None, REQUEST=None): @@ -84,7 +86,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): ue_types = parcours.ALLOWED_UE_TYPES ue_types.sort() - ue_types_names = [UE_TYPE_NAME[k] for k in ue_types] + ue_types_names = [sco_codes_parcours.UE_TYPE_NAME[k] for k in ue_types] ue_types = [str(x) for x in ue_types] fw = [ @@ -424,7 +426,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module cur_ue_semestre_id = UE["semestre_id"] if iue > 0: H.append("") - if UE["semestre_id"] == UE_SEM_DEFAULT: + if UE["semestre_id"] == sco_codes_parcours.UE_SEM_DEFAULT: lab = "Pas d'indication de semestre:" else: lab = "Semestre %s:" % UE["semestre_id"] @@ -456,8 +458,11 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module % UE ) - if UE["type"] != UE_STANDARD: - H.append('%s' % UE_TYPE_NAME[UE["type"]]) + if UE["type"] != sco_codes_parcours.UE_STANDARD: + H.append( + '%s' + % sco_codes_parcours.UE_TYPE_NAME[UE["type"]] + ) ue_editable = editable and not context.ue_is_locked(UE["ue_id"]) if ue_editable: H.append( diff --git a/sco_edt_cal.py b/sco_edt_cal.py index c1b7554f..b41bd34b 100644 --- a/sco_edt_cal.py +++ b/sco_edt_cal.py @@ -36,6 +36,7 @@ XXX incompatible avec les ics HyperPlanning Paris 13 (était pour GPU). import urllib2 import traceback import icalendar +import pprint from sco_utils import * import sco_formsemestre diff --git a/sco_etape_apogee.py b/sco_etape_apogee.py index 1a60edca..4755cfc8 100644 --- a/sco_etape_apogee.py +++ b/sco_etape_apogee.py @@ -83,6 +83,7 @@ import sco_groups import sco_groups_view import sco_archives import sco_apogee_csv +from sco_exceptions import ScoValueError class ApoCSVArchiver(sco_archives.BaseArchiver): diff --git a/sco_etape_apogee_view.py b/sco_etape_apogee_view.py index d03b5107..78f444f2 100644 --- a/sco_etape_apogee_view.py +++ b/sco_etape_apogee_view.py @@ -43,6 +43,7 @@ import sco_apogee_csv import sco_portal_apogee from sco_apogee_csv import APO_PORTAL_ENCODING, APO_INPUT_ENCODING import sco_archives +from sco_exceptions import ScoValueError def apo_semset_maq_status( diff --git a/sco_export_results.py b/sco_export_results.py index d330a9a8..c71fc2a5 100644 --- a/sco_export_results.py +++ b/sco_export_results.py @@ -27,6 +27,7 @@ """Export d'une table avec les résultats de tous les étudiants """ +from types import ListType import scolars import sco_bac @@ -35,7 +36,7 @@ import sco_parcours_dut import sco_codes_parcours from sco_codes_parcours import NO_SEMESTRE_ID import sco_excel -from notesdb import * +import notesdb as ndb from sco_utils import * from gen_tables import GenTable import sco_pvjury @@ -202,7 +203,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos): def get_set_formsemestre_id_dates(context, start_date, end_date): """Ensemble des formsemestre_id entre ces dates""" - s = SimpleDictFetch( + s = ndb.SimpleDictFetch( context, "SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s", {"start_date": start_date, "end_date": end_date}, @@ -224,9 +225,9 @@ def scodoc_table_results( if not isinstance(types_parcours, ListType): types_parcours = [types_parcours] if start_date: - start_date_iso = DateDMYtoISO(start_date) + start_date_iso = ndb.DateDMYtoISO(start_date) if end_date: - end_date_iso = DateDMYtoISO(end_date) + end_date_iso = ndb.DateDMYtoISO(end_date) types_parcours = [int(x) for x in types_parcours if x] if start_date and end_date: diff --git a/sco_find_etud.py b/sco_find_etud.py index d8137c4c..f003128d 100644 --- a/sco_find_etud.py +++ b/sco_find_etud.py @@ -27,17 +27,19 @@ """Recherche d'étudiants """ - -from sco_utils import * +from types import ListType import xml.dom.minidom -from notesdb import * +from sco_utils import * + +import notesdb as ndb from notes_log import log from gen_tables import GenTable import scolars import sco_formsemestre import sco_groups +from sco_permissions import ScoView def form_search_etud( @@ -251,7 +253,7 @@ def search_etud_by_name(context, term, REQUEST=None): data = [] else: if may_be_nip: - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT nom, prenom, code_nip FROM identite WHERE code_nip LIKE %(beginning)s ORDER BY nom", {"beginning": term + "%"}, @@ -265,7 +267,7 @@ def search_etud_by_name(context, term, REQUEST=None): for x in r ] else: - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT nom, prenom FROM identite WHERE nom LIKE %(beginning)s ORDER BY nom", {"beginning": term + "%"}, diff --git a/sco_formations.py b/sco_formations.py index 3756cd1d..87cc2c0e 100644 --- a/sco_formations.py +++ b/sco_formations.py @@ -28,16 +28,18 @@ """Import / Export de formations """ from operator import itemgetter - -from sco_utils import * import xml.dom.minidom -from notesdb import * +from sco_utils import * + +import notesdb as ndb from notes_log import log import sco_codes_parcours import sco_formsemestre import sco_tag_module from gen_tables import GenTable +from sco_exceptions import ScoValueError +from sco_permissions import ScoChangeFormation def formation_export( @@ -131,11 +133,11 @@ def formation_import_xml( F = D[1] F_quoted = F.copy() log("F=%s" % F) - quote_dict(F_quoted) + ndb.quote_dict(F_quoted) log("F_quoted=%s" % F_quoted) # find new version number cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) log( "select max(version) from notes_formations where acronyme=%(acronyme)s and titre=%(titre)s" % F_quoted diff --git a/sco_formsemestre.py b/sco_formsemestre.py index 6ad764e1..826a9efd 100644 --- a/sco_formsemestre.py +++ b/sco_formsemestre.py @@ -29,14 +29,15 @@ """ from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log from gen_tables import GenTable import sco_codes_parcours from sco_codes_parcours import NO_SEMESTRE_ID +from sco_exceptions import ScoValueError -_formsemestreEditor = EditableTable( +_formsemestreEditor = ndb.EditableTable( "notes_formsemestre", "formsemestre_id", ( @@ -60,16 +61,16 @@ _formsemestreEditor = EditableTable( ), sortkey="date_debut", output_formators={ - "date_debut": DateISOtoDMY, - "date_fin": DateISOtoDMY, + "date_debut": ndb.DateISOtoDMY, + "date_fin": ndb.DateISOtoDMY, "gestion_compensation": str, "gestion_semestrielle": str, "etat": str, "bul_hide_xml": str, }, input_formators={ - "date_debut": DateDMYtoISO, - "date_fin": DateDMYtoISO, + "date_debut": ndb.DateDMYtoISO, + "date_fin": ndb.DateDMYtoISO, "gestion_compensation": int, "gestion_semestrielle": int, "etat": int, @@ -144,9 +145,9 @@ def formsemestre_enrich(context, sem): sem["semestre_id"], ) # eg "DUT Informatique semestre 2" - sem["dateord"] = DateDMYtoISO(sem["date_debut"]) - sem["date_debut_iso"] = DateDMYtoISO(sem["date_debut"]) - sem["date_fin_iso"] = DateDMYtoISO(sem["date_fin"]) + sem["dateord"] = ndb.DateDMYtoISO(sem["date_debut"]) + sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"]) + sem["date_fin_iso"] = ndb.DateDMYtoISO(sem["date_fin"]) try: mois_debut, annee_debut = sem["date_debut"].split("/")[1:] except: @@ -229,7 +230,7 @@ def read_formsemestre_responsables(context, formsemestre_id): """recupere liste des responsables de ce semestre :returns: liste de chaines """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT responsable_id FROM notes_formsemestre_responsables WHERE formsemestre_id = %(formsemestre_id)s", {"formsemestre_id": formsemestre_id}, @@ -243,7 +244,7 @@ def write_formsemestre_responsables(context, sem): # ---------------------- Coefs des UE -_formsemestre_uecoef_editor = EditableTable( +_formsemestre_uecoef_editor = ndb.EditableTable( "notes_formsemestre_uecoef", "formsemestre_uecoef_id", ("formsemestre_uecoef_id", "formsemestre_id", "ue_id", "coefficient"), @@ -292,7 +293,7 @@ def read_formsemestre_etapes(context, formsemestre_id): """recupere liste des codes etapes associés à ce semestre :returns: liste d'instance de ApoEtapeVDI """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT etape_apo FROM notes_formsemestre_etapes WHERE formsemestre_id = %(formsemestre_id)s", {"formsemestre_id": formsemestre_id}, @@ -311,7 +312,7 @@ def _write_formsemestre_aux(context, sem, fieldname, valuename): if not "etapes" in sem: return cnx = context.GetDBConnexion(autocommit=False) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) tablename = "notes_formsemestre_" + fieldname try: cursor.execute( @@ -481,8 +482,8 @@ def sem_une_annee(context, sem): def sem_est_courant(context, sem): """Vrai si la date actuelle (now) est dans le semestre (les dates de début et fin sont incluses)""" now = time.strftime("%Y-%m-%d") - debut = DateDMYtoISO(sem["date_debut"]) - fin = DateDMYtoISO(sem["date_fin"]) + debut = ndb.DateDMYtoISO(sem["date_debut"]) + fin = ndb.DateDMYtoISO(sem["date_fin"]) return (debut <= now) and (now <= fin) diff --git a/sco_formsemestre_custommenu.py b/sco_formsemestre_custommenu.py index 5365aa5c..bae26e39 100644 --- a/sco_formsemestre_custommenu.py +++ b/sco_formsemestre_custommenu.py @@ -30,14 +30,14 @@ from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre import sco_formsemestre_status import sco_edt_cal -_custommenuEditor = EditableTable( +_custommenuEditor = ndb.EditableTable( "notes_formsemestre_custommenu", "custommenu_id", ("custommenu_id", "formsemestre_id", "title", "url", "idx"), diff --git a/sco_formsemestre_edit.py b/sco_formsemestre_edit.py index 7850202e..27d64d11 100644 --- a/sco_formsemestre_edit.py +++ b/sco_formsemestre_edit.py @@ -28,7 +28,7 @@ """Form choix modules / responsables et creation formsemestre """ -from notesdb import * +import notesdb as ndb from sco_utils import * import sco_groups from notes_log import log @@ -43,6 +43,8 @@ import sco_modalites import sco_formsemestre import sco_moduleimpl from sco_formsemestre import ApoEtapeVDI +from sco_permissions import ScoImplement +from sco_exceptions import AccessDenied, ScoValueError def _default_sem_title(F): @@ -176,7 +178,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): # Liste des ID de semestres cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute("select semestre_id from notes_semestres") semestre_id_list = [str(x[0]) for x in cursor.fetchall()] semestre_id_labels = [] @@ -639,7 +641,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): msg = "" if tf[0] == 1: # check dates - if DateDMYtoISO(tf[2]["date_debut"]) > DateDMYtoISO(tf[2]["date_fin"]): + if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]): msg = '

  • Dates de début et fin incompatibles !
' if context.get_preference("always_require_apo_sem_codes") and not any( [tf[2]["etape_apo" + str(n)] for n in range(0, EDIT_NB_ETAPES + 1)] @@ -942,7 +944,7 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None): msg = "" if tf[0] == 1: # check dates - if DateDMYtoISO(tf[2]["date_debut"]) > DateDMYtoISO(tf[2]["date_fin"]): + if ndb.DateDMYtoISO(tf[2]["date_debut"]) > ndb.DateDMYtoISO(tf[2]["date_fin"]): msg = '
  • Dates de début et fin incompatibles !
' if tf[0] == 0 or msg: return "".join(H) + msg + tf[1] + context.sco_footer(REQUEST) @@ -1293,7 +1295,7 @@ def formsemestre_has_decisions_or_compensations(context, formsemestre_id): """True if decision de jury dans ce semestre ou bien compensation de ce semestre par d'autre ssemestres. """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT v.* FROM scolar_formsemestre_validation v WHERE v.formsemestre_id = %(formsemestre_id)s OR v.compense_formsemestre_id = %(formsemestre_id)s", {"formsemestre_id": formsemestre_id}, @@ -1314,17 +1316,17 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): # evaluations evals = context.do_evaluation_list(args={"moduleimpl_id": mod["moduleimpl_id"]}) for e in evals: - SimpleQuery( + ndb.SimpleQuery( context, "DELETE FROM notes_notes WHERE evaluation_id=%(evaluation_id)s", e, ) - SimpleQuery( + ndb.SimpleQuery( context, "DELETE FROM notes_notes_log WHERE evaluation_id=%(evaluation_id)s", e, ) - SimpleQuery( + ndb.SimpleQuery( context, "DELETE FROM notes_evaluation WHERE evaluation_id=%(evaluation_id)s", e, @@ -1335,7 +1337,7 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST): context, mod["moduleimpl_id"], formsemestre_id=formsemestre_id ) # --- Desinscription des etudiants - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) req = "DELETE FROM notes_formsemestre_inscription WHERE formsemestre_id=%(formsemestre_id)s" cursor.execute(req, {"formsemestre_id": formsemestre_id}) # --- Suppression des evenements diff --git a/sco_formsemestre_inscriptions.py b/sco_formsemestre_inscriptions.py index 44f2d137..e3c127e3 100644 --- a/sco_formsemestre_inscriptions.py +++ b/sco_formsemestre_inscriptions.py @@ -28,8 +28,11 @@ """Opérations d'inscriptions aux semestres et modules """ -from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault -from sco_utils import UE_STANDARD, UE_SPORT, UE_TYPE_NAME +import sco_utils as scu +from notes_log import log +from sco_exceptions import ScoValueError +from sco_permissions import ScoEtudInscrit +from sco_codes_parcours import UE_STANDARD, UE_SPORT, UE_TYPE_NAME from notesdb import ScoDocCursor, DateISOtoDMY, DateDMYtoISO from TrivialFormulator import TrivialFormulator, TF @@ -287,8 +290,10 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No ) inscr = sco_moduleimpl.do_moduleimpl_inscription_list(context, etudid=etudid) # Formulaire - modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ] - modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ] + modimpls_by_ue_ids = scu.DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ] + modimpls_by_ue_names = scu.DictDefault( + defaultvalue=[] + ) # ue_id : [ moduleimpl_name ] ues = [] ue_ids = set() initvalues = {} diff --git a/sco_formsemestre_validation.py b/sco_formsemestre_validation.py index 8ca807de..71b01db2 100644 --- a/sco_formsemestre_validation.py +++ b/sco_formsemestre_validation.py @@ -29,7 +29,7 @@ """ import urllib, time, datetime -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from scolog import logdb @@ -1035,7 +1035,7 @@ def formsemestre_validation_suppress_etud(context, formsemestre_id, etudid): """Suppression des decisions de jury pour un etudiant.""" log("formsemestre_validation_suppress_etud( %s, %s)" % (formsemestre_id, etudid)) cnx = context.GetDBConnexion(autocommit=False) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) args = {"formsemestre_id": formsemestre_id, "etudid": etudid} try: # -- Validation du semestre et des UEs @@ -1246,7 +1246,7 @@ def do_formsemestre_validate_previous_ue( def _invalidate_etud_formation_caches(context, etudid, formation_id): "Invalide tous les semestres de cette formation où l'etudiant est inscrit..." - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, """SELECT sem.* FROM notes_formsemestre sem, notes_formsemestre_inscription i @@ -1264,7 +1264,7 @@ def _invalidate_etud_formation_caches(context, etudid, formation_id): def get_etud_ue_cap_html(context, etudid, formsemestre_id, ue_id, REQUEST=None): """Ramene bout de HTML pour pouvoir supprimer une validation de cette UE""" - valids = SimpleDictFetch( + valids = ndb.SimpleDictFetch( context, """SELECT SFV.* FROM scolar_formsemestre_validation SFV WHERE ue_id=%(ue_id)s AND etudid=%(etudid)s""", @@ -1276,7 +1276,7 @@ def get_etud_ue_cap_html(context, etudid, formsemestre_id, ue_id, REQUEST=None): '
Validations existantes pour cette UE:
    ' ] for valid in valids: - valid["event_date"] = DateISOtoDMY(valid["event_date"]) + valid["event_date"] = ndb.DateISOtoDMY(valid["event_date"]) if valid["moy_ue"] != None: valid["m"] = ", moyenne %(moy_ue)g/20" % valid else: @@ -1301,7 +1301,7 @@ def etud_ue_suppress_validation(context, etudid, formsemestre_id, ue_id, REQUEST """Suppress a validation (ue_id, etudid) and redirect to formsemestre""" log("etud_ue_suppress_validation( %s, %s, %s)" % (etudid, formsemestre_id, ue_id)) cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "DELETE FROM scolar_formsemestre_validation WHERE etudid=%(etudid)s and ue_id=%(ue_id)s", {"etudid": etudid, "ue_id": ue_id}, @@ -1327,7 +1327,7 @@ def check_formation_ues(context, formation_id): ue_multiples = {} # { ue_id : [ liste des formsemestre ] } for ue in ues: # formsemestres utilisant cette ue ? - sems = SimpleDictFetch( + sems = ndb.SimpleDictFetch( context, """SELECT DISTINCT sem.* FROM notes_formsemestre sem, notes_modules mod, notes_moduleimpl mi diff --git a/sco_groups.py b/sco_groups.py index 71a6456f..ebf6501f 100644 --- a/sco_groups.py +++ b/sco_groups.py @@ -34,7 +34,9 @@ Optimisation possible: """ -import re, sets +import collections +import re +import sets import operator # XML generation package (apt-get install jaxml) @@ -42,13 +44,16 @@ import jaxml import xml.dom.minidom from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log from scolog import logdb from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre import scolars import sco_parcours_dut +import sco_codes_parcours +from sco_permissions import ScoEtudChangeGroups +from sco_exceptions import ScoException, AccessDenied, ScoValueError def can_change_groups(context, REQUEST, formsemestre_id): @@ -76,7 +81,7 @@ def checkGroupName( raise ValueError("invalid group name: " + groupName) -partitionEditor = EditableTable( +partitionEditor = ndb.EditableTable( "partition", "partition_id", ( @@ -90,7 +95,7 @@ partitionEditor = EditableTable( ), ) -groupEditor = EditableTable( +groupEditor = ndb.EditableTable( "group_descr", "group_id", ("group_id", "partition_id", "group_name") ) @@ -99,7 +104,7 @@ group_list = groupEditor.list def get_group(context, group_id): """Returns group object, with partition""" - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.group_id=%(group_id)s AND p.partition_id = gd.partition_id", {"group_id": group_id}, @@ -114,15 +119,17 @@ def group_delete(context, group, force=False): # if not group['group_name'] and not force: # raise ValueError('cannot suppress this group') # remove memberships: - SimpleQuery( + ndb.SimpleQuery( context, "DELETE FROM group_membership WHERE group_id=%(group_id)s", group ) # delete group: - SimpleQuery(context, "DELETE FROM group_descr WHERE group_id=%(group_id)s", group) + ndb.SimpleQuery( + context, "DELETE FROM group_descr WHERE group_id=%(group_id)s", group + ) def get_partition(context, partition_id): - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT p.* FROM partition p WHERE p.partition_id = %(partition_id)s", {"partition_id": partition_id}, @@ -134,7 +141,7 @@ def get_partition(context, partition_id): def get_partitions_list(context, formsemestre_id, with_default=True): """Liste des partitions pour ce semestre (list of dicts)""" - partitions = SimpleDictFetch( + partitions = ndb.SimpleDictFetch( context, "SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s order by numero", {"formsemestre_id": formsemestre_id}, @@ -148,7 +155,7 @@ def get_partitions_list(context, formsemestre_id, with_default=True): def get_default_partition(context, formsemestre_id): """Get partition for 'all' students (this one always exists, with NULL name)""" - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT * FROM partition WHERE formsemestre_id=%(formsemestre_id)s AND partition_name is NULL", {"formsemestre_id": formsemestre_id}, @@ -176,7 +183,7 @@ def get_formsemestre_groups(context, formsemestre_id, with_default=False): def get_partition_groups(context, partition): """List of groups in this partition (list of dicts). Some groups may be empty.""" - return SimpleDictFetch( + return ndb.SimpleDictFetch( context, "SELECT gd.*, p.* FROM group_descr gd, partition p WHERE gd.partition_id=%(partition_id)s AND gd.partition_id=p.partition_id ORDER BY group_name", partition, @@ -185,7 +192,7 @@ def get_partition_groups(context, partition): def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=None): """Returns group_id for default ('tous') group""" - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT gd.group_id FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_name is NULL AND p.partition_id = gd.partition_id", {"formsemestre_id": formsemestre_id}, @@ -217,7 +224,7 @@ def get_default_group(context, formsemestre_id, fix_if_missing=False, REQUEST=No def get_sem_groups(context, formsemestre_id): """Returns groups for this sem (in all partitions).""" - return SimpleDictFetch( + return ndb.SimpleDictFetch( context, "SELECT gd.*, p.* FROM group_descr gd, partition p WHERE p.formsemestre_id=%(formsemestre_id)s AND p.partition_id = gd.partition_id", {"formsemestre_id": formsemestre_id}, @@ -233,7 +240,7 @@ def get_group_members(context, group_id, etat=None): if etat is not None: req += " and ins.etat = %(etat)s" - r = SimpleDictFetch(context, req, {"group_id": group_id, "etat": etat}) + r = ndb.SimpleDictFetch(context, req, {"group_id": group_id, "etat": etat}) for etud in r: scolars.format_etud_ident(etud) @@ -294,7 +301,7 @@ def get_group_infos(context, group_id, etat=None): # was _getlisteetud else: t["etath"] = "(dem.)" nbdem += 1 - elif t["etat"] == DEF: + elif t["etat"] == sco_codes_parcours.DEF: t["etath"] = "Défaillant" else: t["etath"] = t["etat"] @@ -329,7 +336,7 @@ def get_etud_groups(context, etudid, sem, exclude_default=False): req = "SELECT p.*, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s" if exclude_default: req += " and p.partition_name is not NULL" - groups = SimpleDictFetch( + groups = ndb.SimpleDictFetch( context, req + " ORDER BY p.numero", {"etudid": etudid, "formsemestre_id": sem["formsemestre_id"]}, @@ -357,7 +364,7 @@ def formsemestre_get_etud_groupnames(context, formsemestre_id, attr="group_name" """Recupere les groupes de tous les etudiants d'un semestre { etudid : { partition_id : group_name }} (attr=group_name or group_id) """ - infos = SimpleDictFetch( + infos = ndb.SimpleDictFetch( context, "select i.etudid, p.partition_id, gd.group_name, gd.group_id from notes_formsemestre_inscription i, partition p, group_descr gd, group_membership gm where i.formsemestre_id=%(formsemestre_id)s and i.formsemestre_id=p.formsemestre_id and p.partition_id=gd.partition_id and gm.etudid=i.etudid and gm.group_id = gd.group_id and p.partition_name is not NULL", {"formsemestre_id": formsemestre_id}, @@ -380,7 +387,7 @@ def etud_add_group_infos(context, etud, sem, sep=" "): etud["groupes"] = "" return etud - infos = SimpleDictFetch( + infos = ndb.SimpleDictFetch( context, "SELECT p.partition_name, g.* from group_descr g, partition p, group_membership gm WHERE gm.etudid=%(etudid)s and gm.group_id = g.group_id and g.partition_id = p.partition_id and p.formsemestre_id = %(formsemestre_id)s ORDER BY p.numero", {"etudid": etud["etudid"], "formsemestre_id": sem["formsemestre_id"]}, @@ -407,7 +414,7 @@ def etud_add_group_infos(context, etud, sem, sep=" "): def get_etud_groups_in_partition(context, partition_id): """Returns { etudid : group }, with all students in this partition""" - infos = SimpleDictFetch( + infos = ndb.SimpleDictFetch( context, "SELECT gd.*, etudid from group_descr gd, group_membership gm where gd.partition_id = %(partition_id)s and gm.group_id = gd.group_id", {"partition_id": partition_id}, @@ -530,10 +537,10 @@ def set_group(context, etudid, group_id): Warning: don't check if group_id exists (the caller should check). """ cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) args = {"etudid": etudid, "group_id": group_id} # déjà inscrit ? - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT * FROM group_membership gm WHERE etudid=%(etudid)s and group_id=%(group_id)s", args, @@ -542,7 +549,7 @@ def set_group(context, etudid, group_id): if len(r): return False # inscrit - SimpleQuery( + ndb.SimpleQuery( context, "INSERT INTO group_membership (etudid, group_id) VALUES (%(etudid)s, %(group_id)s)", args, @@ -569,7 +576,7 @@ def change_etud_group_in_partition( else: partition = get_partition(context, group["partition_id"]) # 1- Supprime membership dans cette partition - SimpleQuery( + ndb.SimpleQuery( context, """DELETE FROM group_membership WHERE group_membership_id IN (SELECT gm.group_membership_id @@ -651,10 +658,10 @@ def setGroups( ) # Retire les anciens membres: cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) for etudid in old_members_set: log("removing %s from group %s" % (etudid, group_id)) - SimpleQuery( + ndb.SimpleQuery( context, "DELETE FROM group_membership WHERE etudid=%(etudid)s and group_id=%(group_id)s", {"etudid": etudid, "group_id": group_id}, @@ -1079,7 +1086,7 @@ def partition_set_name(context, partition_id, partition_name, REQUEST=None, redi formsemestre_id = partition["formsemestre_id"] # check unicity - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT p.* FROM partition p WHERE p.partition_name = %(partition_name)s AND formsemestre_id = %(formsemestre_id)s", {"partition_name": partition_name, "formsemestre_id": formsemestre_id}, @@ -1374,7 +1381,7 @@ def do_evaluation_listeetuds_groups( req += " and Isem.etat='I'" req += r cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute(req, {"evaluation_id": evaluation_id}) # log('listeetuds_groups: getallstudents=%s groups=%s' % (getallstudents,groups)) # log('req=%s' % (req % { 'evaluation_id' : "'"+evaluation_id+"'" })) @@ -1393,7 +1400,7 @@ def do_evaluation_listegroupes(context, evaluation_id, include_default=False): else: c = " AND p.partition_name is not NULL" cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "SELECT DISTINCT gd.group_id FROM group_descr gd, group_membership gm, partition p, notes_moduleimpl m, notes_evaluation e WHERE gm.group_id = gd.group_id and gd.partition_id = p.partition_id and p.formsemestre_id = m.formsemestre_id and m.moduleimpl_id = e.moduleimpl_id and e.evaluation_id = %(evaluation_id)s" + c, @@ -1406,7 +1413,7 @@ def do_evaluation_listegroupes(context, evaluation_id, include_default=False): def listgroups(context, group_ids): cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) groups = [] for group_id in group_ids: cursor.execute( diff --git a/sco_groups_edit.py b/sco_groups_edit.py index c1d0b38e..be2e1f30 100644 --- a/sco_groups_edit.py +++ b/sco_groups_edit.py @@ -31,10 +31,11 @@ import re from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log import sco_formsemestre import sco_groups +from sco_exceptions import AccessDenied def affectGroups(context, partition_id, REQUEST=None): diff --git a/sco_import_users.py b/sco_import_users.py index e974dbca..654f2bed 100644 --- a/sco_import_users.py +++ b/sco_import_users.py @@ -35,12 +35,13 @@ from email.MIMEBase import MIMEBase # pylint: disable=no-name-in-module,import- from email.Header import Header # pylint: disable=no-name-in-module,import-error from email import Encoders # pylint: disable=no-name-in-module,import-error -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_news import sco_excel +from sco_exceptions import AccessDenied, ScoValueError, ScoException TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept") diff --git a/sco_inscr_passage.py b/sco_inscr_passage.py index 0da58a1f..5c65e361 100644 --- a/sco_inscr_passage.py +++ b/sco_inscr_passage.py @@ -31,7 +31,7 @@ from gen_tables import GenTable -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log import sco_codes_parcours @@ -41,6 +41,7 @@ import sco_formsemestre_inscriptions import sco_formsemestre import sco_groups import scolars +from sco_exceptions import ScoValueError def list_authorized_etuds_by_sem(context, sem, delai=274): @@ -60,7 +61,9 @@ def list_authorized_etuds_by_sem(context, sem, delai=274): auth_used = False # autorisation deja utilisée ? etud = context.getEtudInfo(etudid=e["etudid"], filled=True)[0] for isem in etud["sems"]: - if DateDMYtoISO(isem["date_debut"]) >= DateDMYtoISO(src["date_fin"]): + if ndb.DateDMYtoISO(isem["date_debut"]) >= ndb.DateDMYtoISO( + src["date_fin"] + ): auth_used = True if not auth_used: candidats[e["etudid"]] = etud @@ -134,8 +137,8 @@ def list_inscrits_date(context, sem): SAUF sem à la date de début de sem. """ cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) - sem["date_debut_iso"] = DateDMYtoISO(sem["date_debut"]) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) + sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"]) cursor.execute( """select I.etudid from notes_formsemestre_inscription I, notes_formsemestre S diff --git a/sco_liste_notes.py b/sco_liste_notes.py index b130d78f..35e5a87a 100644 --- a/sco_liste_notes.py +++ b/sco_liste_notes.py @@ -27,8 +27,12 @@ """Liste des notes d'une évaluation """ +import urllib -from notesdb import * +from htmlutils import histogram_notes + + +import notesdb as ndb from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF @@ -40,7 +44,6 @@ import sco_evaluations import htmlutils import sco_excel from gen_tables import GenTable -from htmlutils import histogram_notes def do_evaluation_listenotes(context, REQUEST): @@ -432,7 +435,7 @@ def _make_table_notes( if with_emails: gl = "&with_emails%3Alist=yes" + gl if len(evals) == 1: - evalname = "%s-%s" % (Mod["code"], DateDMYtoISO(E["jour"])) + evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudids)) filename = make_filename("notes_%s_%s" % (evalname, gr_title_filename)) caption = hh @@ -721,12 +724,12 @@ def evaluation_check_absences(context, evaluation_id): am, pm, demijournee = _eval_demijournee(E) # Liste les absences à ce moment: - A = context.Absences.ListeAbsJour(DateDMYtoISO(E["jour"]), am=am, pm=pm) + A = context.Absences.ListeAbsJour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) As = set([x["etudid"] for x in A]) # ensemble des etudiants absents - NJ = context.Absences.ListeAbsNonJustJour(DateDMYtoISO(E["jour"]), am=am, pm=pm) + NJ = context.Absences.ListeAbsNonJustJour(ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm) NJs = set([x["etudid"] for x in NJ]) # ensemble des etudiants absents non justifies Just = context.Absences.ListeAbsJour( - DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True + ndb.DateDMYtoISO(E["jour"]), am=am, pm=pm, is_abs=None, is_just=True ) Justs = set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif diff --git a/sco_lycee.py b/sco_lycee.py index d6272737..fe60885e 100644 --- a/sco_lycee.py +++ b/sco_lycee.py @@ -32,7 +32,6 @@ import tempfile, urllib, re -from notesdb import * from sco_utils import * from notes_log import log import scolars diff --git a/sco_modalites.py b/sco_modalites.py index 396184c6..c8ed69a4 100644 --- a/sco_modalites.py +++ b/sco_modalites.py @@ -108,5 +108,5 @@ def do_modalite_edit(context, *args, **kw): "edit a modalite" cnx = context.GetDBConnexion() # check - m = do_modalite_list(context, {"form_modalite_id": args[0]["form_modalite_id"]})[0] + _ = do_modalite_list(context, {"form_modalite_id": args[0]["form_modalite_id"]})[0] _modaliteEditor.edit(cnx, *args, **kw) diff --git a/sco_moduleimpl_inscriptions.py b/sco_moduleimpl_inscriptions.py index 7815a715..4ee9acd1 100644 --- a/sco_moduleimpl_inscriptions.py +++ b/sco_moduleimpl_inscriptions.py @@ -29,7 +29,7 @@ """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log from scolog import logdb @@ -38,6 +38,7 @@ import sco_formsemestre import sco_moduleimpl import sco_groups import htmlutils +from sco_permissions import ScoEtudInscrit def moduleimpl_inscriptions_edit( @@ -481,7 +482,7 @@ def is_inscrit_ue(context, etudid, formsemestre_id, ue_id): """Modules de cette UE dans ce semestre auxquels l'étudiant est inscrit. """ - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, """SELECT mod.* FROM notes_moduleimpl mi, notes_modules mod, @@ -502,7 +503,7 @@ def is_inscrit_ue(context, etudid, formsemestre_id, ue_id): def do_etud_desinscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None): """Desincrit l'etudiant de tous les modules de cette UE dans ce semestre.""" cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """DELETE FROM notes_moduleimpl_inscription WHERE moduleimpl_inscription_id IN ( @@ -543,7 +544,7 @@ def do_etud_inscrit_ue(context, etudid, formsemestre_id, ue_id, REQUEST=None): raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid) cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """SELECT mi.moduleimpl_id FROM notes_moduleimpl mi, notes_modules mod, notes_formsemestre sem diff --git a/sco_news.py b/sco_news.py index a5860880..007a7f4d 100644 --- a/sco_news.py +++ b/sco_news.py @@ -41,20 +41,20 @@ from email.Header import Header # pylint: disable=no-name-in-module,import-erro from email import Encoders # pylint: disable=no-name-in-module,import-error -from notesdb import * # pylint: disable=unused-wildcard-import +import notesdb as ndb # pylint: disable=unused-wildcard-import from notes_log import log import scolars from sco_utils import SCO_ENCODING, SCO_ANNONCES_WEBSITE import sco_formsemestre import sco_moduleimpl -_scolar_news_editor = EditableTable( +_scolar_news_editor = ndb.EditableTable( "scolar_news", "news_id", ("date", "authenticated_user", "type", "object", "text", "url"), sortkey="date desc", - output_formators={"date": DateISOtoDMY}, - input_formators={"date": DateDMYtoISO}, + output_formators={"date": ndb.DateISOtoDMY}, + input_formators={"date": ndb.DateDMYtoISO}, html_quote=False, # no user supplied data, needed to store html links ) @@ -114,7 +114,7 @@ def scolar_news_summary(context, n=5): """ cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute("select * from scolar_news order by date desc limit 100") selected_news = {} # (type,object) : news dict news = cursor.dictfetchall() # la plus récente d'abord @@ -122,7 +122,7 @@ def scolar_news_summary(context, n=5): for r in reversed(news): # la plus ancienne d'abord # si on a deja une news avec meme (type,object) # et du meme jour, on la remplace - dmy = DateISOtoDMY(r["date"]) # round + dmy = ndb.DateISOtoDMY(r["date"]) # round key = (r["type"], r["object"], dmy) selected_news[key] = r diff --git a/sco_page_etud.py b/sco_page_etud.py index 737b3ac2..cbc7f8c8 100644 --- a/sco_page_etud.py +++ b/sco_page_etud.py @@ -32,7 +32,7 @@ """ from sco_utils import * -from notesdb import * +import notesdb as ndb import scolars import sco_bac import sco_photos @@ -43,9 +43,17 @@ import sco_formsemestre_status import htmlutils from sco_bulletins import etud_descr_situation_semestre import sco_parcours_dut +import sco_codes_parcours from sco_formsemestre_validation import formsemestre_recap_parcours_table import sco_archives_etud import sco_report +from sco_permissions import ( + ScoEtudChangeGroups, + ScoEtudInscrit, + ScoImplement, + ScoEtudChangeAdr, +) +from sco_exceptions import ScoValueError def _menuScolarite(context, authuser, sem, etudid): @@ -76,12 +84,12 @@ def _menuScolarite(context, authuser, sem, etudid): ) # Note: seul un etudiant inscrit (I) peut devenir défaillant. - if ins["etat"] != DEF: + if ins["etat"] != sco_codes_parcours.DEF: def_title = "Déclarer défaillance" def_url = ( "formDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" % args ) - elif ins["etat"] == DEF: + elif ins["etat"] == sco_codes_parcours.DEF: def_title = "Annuler la défaillance" def_url = ( "doCancelDef?etudid=%(etudid)s&formsemestre_id=%(formsemestre_id)s" diff --git a/sco_parcours_dut.py b/sco_parcours_dut.py index d4bd5bb8..3bdaca8e 100644 --- a/sco_parcours_dut.py +++ b/sco_parcours_dut.py @@ -27,12 +27,13 @@ """Semestres: gestion parcours DUT (Arreté du 13 août 2005) """ -from notesdb import * +import notesdb as ndb from notes_log import log from scolog import logdb import sco_formsemestre from sco_codes_parcours import * from dutrules import DUTRules # regles generees a partir du CSV +from sco_exceptions import ScoValueError class DecisionSem: @@ -607,7 +608,7 @@ class SituationEtudParcoursGeneric: ) # > modif decisions jury (sem, UE) # -- supprime autorisations venant de ce formsemestre - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) try: cursor.execute( """delete from scolar_autorisation_inscription @@ -742,7 +743,7 @@ def int_or_null(s): return int(s) -_scolar_formsemestre_validation_editor = EditableTable( +_scolar_formsemestre_validation_editor = ndb.EditableTable( "scolar_formsemestre_validation", "formsemestre_validation_id", ( @@ -758,8 +759,8 @@ _scolar_formsemestre_validation_editor = EditableTable( "semestre_id", "is_external", ), - output_formators={"event_date": DateISOtoDMY, "assidu": str}, - input_formators={"event_date": DateDMYtoISO, "assidu": int_or_null}, + output_formators={"event_date": ndb.DateISOtoDMY, "assidu": str}, + input_formators={"event_date": ndb.DateDMYtoISO, "assidu": int_or_null}, ) scolar_formsemestre_validation_create = _scolar_formsemestre_validation_editor.create @@ -779,7 +780,7 @@ def formsemestre_validate_sem( "Ajoute ou change validation semestre" args = {"formsemestre_id": formsemestre_id, "etudid": etudid} # delete existing - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) try: cursor.execute( """delete from scolar_formsemestre_validation @@ -827,7 +828,7 @@ def formsemestre_update_validation_sem( "assidu": int(assidu), } log("formsemestre_update_validation_sem: %s" % args) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) to_invalidate = [] # enleve compensations si necessaire @@ -945,7 +946,7 @@ def do_formsemestre_validate_ue( args["event_date"] = date # delete existing - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) try: cond = "etudid = %(etudid)s and ue_id=%(ue_id)s" if formsemestre_id: @@ -983,7 +984,7 @@ def formsemestre_has_decisions(context, formsemestre_id): def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id): """Vrai si l'étudiant est inscrit a au moins un module de cette UE dans ce semestre""" - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """select mi.* from notes_moduleimpl mi, notes_modules mo, notes_ue ue, notes_moduleimpl_inscription i where i.etudid = %(etudid)s and i.moduleimpl_id=mi.moduleimpl_id @@ -997,12 +998,12 @@ def etud_est_inscrit_ue(cnx, etudid, formsemestre_id, ue_id): return len(cursor.fetchall()) -_scolar_autorisation_inscription_editor = EditableTable( +_scolar_autorisation_inscription_editor = ndb.EditableTable( "scolar_autorisation_inscription", "autorisation_inscription_id", ("etudid", "formation_code", "semestre_id", "date", "origin_formsemestre_id"), - output_formators={"date": DateISOtoDMY}, - input_formators={"date": DateDMYtoISO}, + output_formators={"date": ndb.DateISOtoDMY}, + input_formators={"date": ndb.DateDMYtoISO}, ) scolar_autorisation_inscription_list = _scolar_autorisation_inscription_editor.list @@ -1033,7 +1034,7 @@ def formsemestre_get_etud_capitalisation(context, sem, etudid): } ] """ cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """select distinct SFV.*, ue.ue_code from notes_ue ue, notes_formations nf, notes_formations nf2, scolar_formsemestre_validation SFV, notes_formsemestre sem @@ -1058,7 +1059,7 @@ def formsemestre_get_etud_capitalisation(context, sem, etudid): "etudid": etudid, "formation_id": sem["formation_id"], "semestre_id": sem["semestre_id"], - "date_debut": DateDMYtoISO(sem["date_debut"]), + "date_debut": ndb.DateDMYtoISO(sem["date_debut"]), }, ) @@ -1072,7 +1073,7 @@ def list_formsemestre_utilisateurs_uecap(context, formsemestre_id): cnx = context.GetDBConnexion() sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( """select sem.formsemestre_id from notes_formsemestre sem, notes_formations F @@ -1086,7 +1087,7 @@ def list_formsemestre_utilisateurs_uecap(context, formsemestre_id): "formation_code": F["formation_code"], "semestre_id": sem["semestre_id"], "formsemestre_id": formsemestre_id, - "date_debut": DateDMYtoISO(sem["date_debut"]), + "date_debut": ndb.DateDMYtoISO(sem["date_debut"]), }, ) return [x[0] for x in cursor.fetchall()] diff --git a/sco_placement.py b/sco_placement.py index 7917a60d..646230b9 100644 --- a/sco_placement.py +++ b/sco_placement.py @@ -30,6 +30,8 @@ Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016 """ +import urllib +import random import sco_utils as scu import notesdb as ndb @@ -43,7 +45,6 @@ import sco_saisie_notes import sco_excel from sco_excel import * from gen_tables import GenTable -import random def do_placement_selectetuds(context, REQUEST): diff --git a/sco_portal_apogee.py b/sco_portal_apogee.py index a760362b..2aaae513 100644 --- a/sco_portal_apogee.py +++ b/sco_portal_apogee.py @@ -35,11 +35,13 @@ import xml.sax.saxutils import xml.dom.minidom import datetime -import sco_utils -from sco_utils import ScoEtudInscrit, log, ScoValueError, DictDefault -from sco_utils import SCO_TMPDIR, SCO_ENCODING +import sco_utils as scu +from sco_utils import SCO_ENCODING +from sco_permissions import ScoEtudInscrit +from sco_exceptions import ScoValueError +from notes_log import log -SCO_CACHE_ETAPE_FILENAME = os.path.join(SCO_TMPDIR, "last_etapes.xml") +SCO_CACHE_ETAPE_FILENAME = os.path.join(scu.SCO_TMPDIR, "last_etapes.xml") def has_portal(context): @@ -162,7 +164,7 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2): if portal_timeout > 0: actual_timeout = max(1, actual_timeout) for _ntrial in range(ntrials): - doc = sco_utils.query_portal(req, timeout=actual_timeout) + doc = scu.query_portal(req, timeout=actual_timeout) if doc: break if not doc: @@ -203,7 +205,7 @@ def query_apogee_portal(context, **args): return [] portal_timeout = context.get_preference("portal_timeout") req = etud_url + "?" + urllib.urlencode(args.items()) - doc = sco_utils.query_portal(req, timeout=portal_timeout) # sco_utils + doc = scu.query_portal(req, timeout=portal_timeout) # sco_utils return xml_to_list_of_dicts(doc, req=req) @@ -259,7 +261,7 @@ def get_infos_apogee_allaccents(context, nom, prenom): "essai recup infos avec differents codages des accents" if nom: unom = unicode(nom, SCO_ENCODING) - nom_noaccents = str(sco_utils.suppression_diacritics(unom)) + nom_noaccents = str(scu.suppression_diacritics(unom)) nom_utf8 = unom.encode("utf-8") else: nom_noaccents = nom @@ -267,7 +269,7 @@ def get_infos_apogee_allaccents(context, nom, prenom): if prenom: uprenom = unicode(prenom, SCO_ENCODING) - prenom_noaccents = str(sco_utils.suppression_diacritics(uprenom)) + prenom_noaccents = str(scu.suppression_diacritics(uprenom)) prenom_utf8 = uprenom.encode("utf-8") else: prenom_noaccents = prenom @@ -323,7 +325,7 @@ def get_etud_apogee(context, code_nip): return {} portal_timeout = context.get_preference("portal_timeout") req = etud_url + "?" + urllib.urlencode((("nip", code_nip),)) - doc = sco_utils.query_portal(req, timeout=portal_timeout) + doc = scu.query_portal(req, timeout=portal_timeout) d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req)) if not d: return None @@ -387,7 +389,7 @@ def get_etapes_apogee(context): "get_etapes_apogee: requesting '%s' with timeout=%s" % (etapes_url, portal_timeout) ) - doc = sco_utils.query_portal(etapes_url, timeout=portal_timeout) + doc = scu.query_portal(etapes_url, timeout=portal_timeout) try: infos = _parse_etapes_from_xml(context, doc) # cache le resultat (utile si le portail repond de façon intermitente) @@ -482,7 +484,7 @@ def _normalize_apo_fields(infolist): for infos in infolist: if infos.has_key("paiementinscription"): infos["paiementinscription"] = ( - sco_utils.strlower(infos["paiementinscription"]) == "true" + scu.strlower(infos["paiementinscription"]) == "true" ) if infos["paiementinscription"]: infos["paiementinscription_str"] = "ok" @@ -562,5 +564,5 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""): + "?" + urllib.urlencode((("etape", etape), ("annee", annee_scolaire))) ) - doc = sco_utils.query_portal(req, timeout=portal_timeout) + doc = scu.query_portal(req, timeout=portal_timeout) return doc diff --git a/sco_poursuite_dut.py b/sco_poursuite_dut.py index c845ea04..9eed9c7d 100644 --- a/sco_poursuite_dut.py +++ b/sco_poursuite_dut.py @@ -29,8 +29,8 @@ Recapitule tous les semestres validés dans une feuille excel. """ +import collections -from notesdb import * from sco_utils import * from notes_log import log from gen_tables import GenTable diff --git a/sco_preferences.py b/sco_preferences.py index be6fbc16..2a66eaa8 100644 --- a/sco_preferences.py +++ b/sco_preferences.py @@ -29,10 +29,11 @@ """ from sco_utils import * -from notesdb import * +import notesdb as ndb from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre import sco_bulletins_generator +from sco_exceptions import ScoValueError, ScoException """Global/Semestre Preferences for ScoDoc (version dec 2008) @@ -1729,7 +1730,7 @@ PREFS_DICT = dict(PREFS) class sco_base_preferences: - _editor = EditableTable( + _editor = ndb.EditableTable( "sco_prefs", "pref_id", ("pref_id", "name", "value", "formsemestre_id"), diff --git a/sco_prepajury.py b/sco_prepajury.py index 16fe212f..a70f366d 100644 --- a/sco_prepajury.py +++ b/sco_prepajury.py @@ -28,7 +28,6 @@ """Feuille excel pour preparation des jurys """ -from notesdb import * from sco_utils import * from notes_log import log import notes_table diff --git a/sco_pvjury.py b/sco_pvjury.py index d275a2b0..ca5fe0ac 100644 --- a/sco_pvjury.py +++ b/sco_pvjury.py @@ -36,7 +36,7 @@ import sco_parcours_dut import sco_codes_parcours from sco_codes_parcours import NO_SEMESTRE_ID import sco_excel -from notesdb import * +import notesdb as ndb from sco_utils import * from gen_tables import GenTable import sco_pvpdf @@ -71,7 +71,7 @@ def _descr_decisions_ues(context, nt, etudid, decisions_ue, decision_sem): for ue_id in decisions_ue.keys(): try: if decisions_ue[ue_id] and ( - decisions_ue[ue_id]["code"] == ADM + decisions_ue[ue_id]["code"] == sco_codes_parcours.ADM or ( CONFIG.CAPITALIZE_ALL_UES and sco_codes_parcours.code_semestre_validant(decision_sem["code"]) @@ -310,13 +310,13 @@ def dict_pvjury( # Cherche la date de decision (sem ou UE) la plus récente: if d["decision_sem"]: - date = DateDMYtoISO(d["decision_sem"]["event_date"]) + date = ndb.DateDMYtoISO(d["decision_sem"]["event_date"]) if date > max_date: # decision plus recente max_date = date if d["decisions_ue"]: for dec_ue in d["decisions_ue"].values(): if dec_ue: - date = DateDMYtoISO(dec_ue["event_date"]) + date = ndb.DateDMYtoISO(dec_ue["event_date"]) if date > max_date: # decision plus recente max_date = date # Code semestre precedent @@ -343,7 +343,7 @@ def dict_pvjury( D[etudid] = d return { - "date": DateISOtoDMY(max_date), + "date": ndb.DateISOtoDMY(max_date), "formsemestre": sem, "has_prev": has_prev, "semestre_non_terminal": semestre_non_terminal, @@ -434,7 +434,7 @@ def pvjury_table( "ue_cap": e["decisions_ue_descr"], "validation_parcours_code": "ADM" if e["validation_parcours"] else "AJ", "devenir": e["autorisations_descr"], - "observations": unquote(e["observation"]), + "observations": ndb.unquote(e["observation"]), "mention": e["mention"], "ects": str(e["sum_ects"]), } diff --git a/sco_saisie_notes.py b/sco_saisie_notes.py index 7284a008..9602faea 100644 --- a/sco_saisie_notes.py +++ b/sco_saisie_notes.py @@ -33,7 +33,6 @@ import time import datetime import psycopg2 -# from notesdb import * import sco_utils as scu from notes_log import log from TrivialFormulator import TrivialFormulator, TF @@ -258,9 +257,7 @@ def do_evaluation_upload_xls(context, REQUEST): ) raise InvalidNoteValue() # -- check values - L, invalids, withoutnotes, absents, tosuppress = _check_notes( - notes, E, M["module"] - ) + L, invalids, withoutnotes, absents, _ = _check_notes(notes, E, M["module"]) if len(invalids): diag.append( "Erreur: la feuille contient %d notes invalides

    " % len(invalids) @@ -339,7 +336,7 @@ def do_evaluation_set_missing( if not NotesDB.has_key(etudid): # pas de note notes.append((etudid, value)) # Check value - L, invalids, withoutnotes, absents, tosuppress = _check_notes(notes, E, M["module"]) + L, invalids, _, _, _ = _check_notes(notes, E, M["module"]) diag = "" if len(invalids): diag = "Valeur %s invalide" % value @@ -368,9 +365,7 @@ def do_evaluation_set_missing( ) # ok comment = "Initialisation notes manquantes" - nb_changed, nb_suppress, existing_decisions = _notes_add( - context, authuser, evaluation_id, L, comment - ) + nb_changed, _, _ = _notes_add(context, authuser, evaluation_id, L, comment) # news M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] mod = context.do_module_list(args={"module_id": M["module_id"]})[0] @@ -479,7 +474,7 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True): psycopg2.Timestamp, time.localtime()[:6] ) # datetime.datetime.now().isoformat() # Verifie inscription et valeur note - inscrits = {}.fromkeys( + _ = {}.fromkeys( sco_groups.do_evaluation_listeetuds_groups( context, evaluation_id, getallstudents=True, include_dems=True ) @@ -806,10 +801,10 @@ def feuille_saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None): ) groups = sco_groups.listgroups(context, groups_infos.group_ids) gr_title_filename = sco_groups.listgroups_filename(groups) - gr_title = sco_groups.listgroups_abbrev(groups) + # gr_title = sco_groups.listgroups_abbrev(groups) if None in [g["group_name"] for g in groups]: # tous les etudiants getallstudents = True - gr_title = "tous" + # gr_title = "tous" gr_title_filename = "tous" else: getallstudents = False @@ -1240,11 +1235,9 @@ def save_note( if not can_edit_notes(context, authuser, E["moduleimpl_id"]): result["status"] = "unauthorized" else: - L, invalids, withoutnotes, absents, tosuppress = _check_notes( - [(etudid, value)], E, Mod - ) + L, _, _, _, _ = _check_notes([(etudid, value)], E, Mod) if L: - nbchanged, nbsuppress, existing_decisions = _notes_add( + nbchanged, _, existing_decisions = _notes_add( context, authuser, evaluation_id, L, comment=comment, do_it=True ) sco_news.add( diff --git a/sco_semset.py b/sco_semset.py index e655c518..f5df6055 100644 --- a/sco_semset.py +++ b/sco_semset.py @@ -40,7 +40,7 @@ sem_set_list(context) """ from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log import sco_formsemestre from sco_formsemestre import ApoEtapeVDI @@ -49,9 +49,10 @@ import sco_etape_apogee from sco_etape_bilan import EtapeBilan import sco_portal_apogee from gen_tables import GenTable +from sco_exceptions import ScoValueError -_semset_editor = EditableTable( +_semset_editor = ndb.EditableTable( "notes_semset", "semset_id", ("semset_id", "title", "annee_scolaire", "sem_id") ) @@ -81,7 +82,7 @@ class SemSet(dict): self["title"] = L[0]["title"] self["annee_scolaire"] = L[0]["annee_scolaire"] self["sem_id"] = L[0]["sem_id"] - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT formsemestre_id FROM notes_semset_formsemestre WHERE semset_id = %(semset_id)s", {"semset_id": semset_id}, @@ -150,7 +151,7 @@ class SemSet(dict): % (formsemestre_id, self.semset_id) ) - SimpleQuery( + ndb.SimpleQuery( self.context, "INSERT INTO notes_semset_formsemestre (formsemestre_id, semset_id) VALUES (%(formsemestre_id)s, %(semset_id)s)", {"formsemestre_id": formsemestre_id, "semset_id": self.semset_id}, @@ -158,7 +159,7 @@ class SemSet(dict): self.load_sems() # update our list def remove(self, formsemestre_id): - SimpleQuery( + ndb.SimpleQuery( self.context, "DELETE FROM notes_semset_formsemestre WHERE semset_id=%(semset_id)s AND formsemestre_id=%(formsemestre_id)s", {"formsemestre_id": formsemestre_id, "semset_id": self.semset_id}, diff --git a/sco_synchro_etuds.py b/sco_synchro_etuds.py index c9070a2b..14fe953a 100644 --- a/sco_synchro_etuds.py +++ b/sco_synchro_etuds.py @@ -31,9 +31,11 @@ import time import pprint -from sco_utils import ScoEtudInscrit, annee_scolaire_debut, log, ScoValueError +import sco_utils as scu +from sco_permissions import ScoEtudInscrit +from sco_exceptions import ScoValueError from notesdb import ScoDocCursor - +from notes_log import log import sco_portal_apogee import sco_inscr_passage import scolars @@ -111,7 +113,7 @@ def formsemestre_synchro_etuds( if anneeapogee == None: # année d'inscription par défaut anneeapogee = str( - annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]) + scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]) ) if type(etuds) == type(""): @@ -791,7 +793,9 @@ def formsemestre_import_etud_admission( # Essaie de recuperer les etudiants des étapes, car # la requete get_inscrits_etape est en général beaucoup plus # rapide que les requetes individuelles get_etud_apogee - anneeapogee = str(annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])) + anneeapogee = str( + scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"]) + ) apo_etuds = {} # nip : etud apo for etape in sem["etapes"]: etudsapo = sco_portal_apogee.get_inscrits_etape( diff --git a/sco_tag_module.py b/sco_tag_module.py index e886ccba..d1fe3fdc 100644 --- a/sco_tag_module.py +++ b/sco_tag_module.py @@ -34,9 +34,13 @@ Pour l'UI, voir https://goodies.pixabay.com/jquery/tag-editor/demo.html """ +import types + from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log +from sco_exceptions import ScoValueError, AccessDenied +from sco_permissions import ScoEditFormationTags, ScoChangeFormation # Opérations à implementer: # + liste des modules des formations de code donné (formation_code) avec ce tag @@ -66,7 +70,7 @@ class ScoTag: self.title = title.strip() if not self.title: raise ScoValueError("invalid empty tag") - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT * FROM " + self.tag_table + " WHERE title = %(title)s", {"title": self.title}, @@ -77,8 +81,10 @@ class ScoTag: # Create new tag: log("creating new tag: %s" % self.title) cnx = context.GetDBConnexion() - oid = DBInsertDict(cnx, self.tag_table, {"title": self.title}, commit=True) - self.tag_id = SimpleDictFetch( + oid = ndb.DBInsertDict( + cnx, self.tag_table, {"title": self.title}, commit=True + ) + self.tag_id = ndb.SimpleDictFetch( context, "SELECT tag_id FROM " + self.tag_table + " WHERE oid=%(oid)s", {"oid": oid}, @@ -94,7 +100,7 @@ class ScoTag: This object should not be used after this call ! """ args = {"tag_id": self.tag_id} - SimpleQuery( + ndb.SimpleQuery( self.context, "DELETE FROM " + self.tag_table + " t WHERE t.tag_id = %(tag_id)s", args, @@ -103,7 +109,7 @@ class ScoTag: def tag_object(self, object_id): """Associate tag to given object""" args = {self.obj_colname: object_id, "tag_id": self.tag_id} - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self.context, "SELECT * FROM " + self.assoc_table @@ -117,7 +123,7 @@ class ScoTag: if not r: log("tag %s with %s" % (object_id, self.title)) cnx = self.context.GetDBConnexion() - DBInsertDict(cnx, self.assoc_table, args, commit=True) + ndb.DBInsertDict(cnx, self.assoc_table, args, commit=True) def remove_tag_from_object(self, object_id): """Remove tag from module. @@ -126,7 +132,7 @@ class ScoTag: """ log("removing tag %s from %s" % (self.title, object_id)) args = {"object_id": object_id, "tag_id": self.tag_id} - SimpleQuery( + ndb.SimpleQuery( self.context, "DELETE FROM " + self.assoc_table @@ -135,7 +141,7 @@ class ScoTag: + " = %(object_id)s AND a.tag_id = %(tag_id)s", args, ) - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self.context, """SELECT * FROM notes_modules_tags mt WHERE tag_id = %(tag_id)s """, @@ -143,7 +149,7 @@ class ScoTag: ) if not r: # tag no more used, delete - SimpleQuery( + ndb.SimpleQuery( self.context, """DELETE FROM notes_tags t WHERE t.tag_id = %(tag_id)s""", args, @@ -162,7 +168,7 @@ class ModuleTag(ScoTag): args = {"tag_id": self.tag_id} if not formation_code: # tous les modules de toutes les formations ! - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self.context, "SELECT " + self.obj_colname @@ -174,7 +180,7 @@ class ModuleTag(ScoTag): else: args["formation_code"] = formation_code - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( self.context, """SELECT mt.module_id FROM notes_modules_tags mt, notes_modules m, notes_formations f @@ -197,7 +203,7 @@ def module_tag_search(context, term, REQUEST=None): if not ALPHANUM_EXP.match(term.decode(SCO_ENCODING)): data = [] else: - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, "SELECT title FROM notes_tags WHERE title LIKE %(term)s", {"term": term + "%"}, @@ -209,7 +215,7 @@ def module_tag_search(context, term, REQUEST=None): def module_tag_list(context, module_id=""): """les noms de tags associés à ce module""" - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, """SELECT t.title FROM notes_modules_tags mt, notes_tags t @@ -237,7 +243,7 @@ def module_tag_set(context, module_id="", taglist=[], REQUEST=None): # if not taglist: taglist = [] - elif type(taglist) == StringType: + elif type(taglist) == types.StringType: taglist = taglist.split(",") taglist = [t.strip() for t in taglist] log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist)) diff --git a/sco_trombino.py b/sco_trombino.py index c4beb229..09b0b96e 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -38,6 +38,7 @@ import tempfile from notes_log import log from sco_utils import * +from sco_exceptions import ScoValueError import scolars import sco_photos import sco_formsemestre diff --git a/sco_ue_external.py b/sco_ue_external.py index ba7bb931..3906d10c 100644 --- a/sco_ue_external.py +++ b/sco_ue_external.py @@ -54,7 +54,7 @@ Solution proposée (nov 2014): """ -from notesdb import * +import notesdb as ndb from sco_utils import * from notes_log import log import sco_formsemestre @@ -62,6 +62,8 @@ import sco_moduleimpl import sco_edit_ue import sco_saisie_notes import sco_codes_parcours +from sco_permissions import ScoImplement +from sco_exceptions import AccessDenied, ScoValueError def external_ue_create( @@ -69,7 +71,7 @@ def external_ue_create( formsemestre_id, titre="", acronyme="", - ue_type=UE_STANDARD, + ue_type=sco_codes_parcours.UE_STANDARD, ects=0.0, REQUEST=None, ): @@ -178,7 +180,7 @@ def get_existing_external_ue(context, formation_id): def get_external_moduleimpl_id(context, formsemestre_id, ue_id): "moduleimpl correspondant à l'UE externe indiquée de ce formsemestre" - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, """ SELECT moduleimpl_id FROM notes_moduleimpl mi, notes_modules mo @@ -235,7 +237,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None): parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"]) ue_types = parcours.ALLOWED_UE_TYPES ue_types.sort() - ue_types_names = [UE_TYPE_NAME[k] for k in ue_types] + ue_types_names = [sco_codes_parcours.UE_TYPE_NAME[k] for k in ue_types] ue_types = [str(x) for x in ue_types] if existing_external_ue: diff --git a/sco_undo_notes.py b/sco_undo_notes.py index 43f6e730..0e6df989 100644 --- a/sco_undo_notes.py +++ b/sco_undo_notes.py @@ -49,7 +49,7 @@ import datetime from intervals import intervalmap from sco_utils import * -from notesdb import * +import notesdb as ndb from notes_log import log from gen_tables import GenTable import sco_formsemestre @@ -166,7 +166,7 @@ def formsemestre_list_saisies_notes( ): """Table listant toutes les operations de saisies de notes, dans toutes les evaluations du semestre.""" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - r = SimpleDictFetch( + r = ndb.SimpleDictFetch( context, """select i.nom, n.*, mod.titre, e.description, e.jour from notes_notes n, notes_evaluation e, notes_moduleimpl m, notes_modules mod, identite i where m.moduleimpl_id = e.moduleimpl_id and m.module_id = mod.module_id and e.evaluation_id=n.evaluation_id and i.etudid=n.etudid and m.formsemestre_id=%(formsemestre_id)s order by date desc""", {"formsemestre_id": formsemestre_id}, @@ -212,7 +212,7 @@ def get_note_history(context, evaluation_id, etudid, REQUEST=None, fmt=""): [ { 'value', 'date', 'comment', 'uid' } ] """ cnx = context.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) # Valeur courante cursor.execute( diff --git a/sco_utils.py b/sco_utils.py index b7ff1e53..eb9f86ca 100644 --- a/sco_utils.py +++ b/sco_utils.py @@ -28,30 +28,19 @@ """ Common definitions """ -import pdb -import os, sys, copy, re -import pprint -import traceback -from types import ( - StringType, - IntType, - FloatType, - UnicodeType, - ListType, - TupleType, - InstanceType, -) -import operator, bisect -import collections +import os +import sys +import copy +import re + +import bisect +import types import numbers import thread -import urllib import urllib2 -import socket import xml.sax.saxutils -import xml, xml.dom.minidom -import time, datetime, cgi -import mx +import time +import datetime try: import six @@ -59,7 +48,7 @@ try: STRING_TYPES = six.string_types except ImportError: # fallback for very old ScoDoc instances - STRING_TYPES = StringType + STRING_TYPES = types.StringType from PIL import Image as PILImage @@ -72,12 +61,13 @@ from VERSION import SCOVERSION import VERSION from SuppressAccents import suppression_diacritics -from sco_exceptions import * -from sco_permissions import * + +# from sco_exceptions import * +# from sco_permissions import * from TrivialFormulator import TrivialFormulator, TF, tf_error_message from notes_log import log, logCallStack -from sco_codes_parcours import * +from sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL # ----- CALCUL ET PRESENTATION DES NOTES NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis @@ -140,7 +130,7 @@ def fmt_note(val, note_max=None, keep_numeric=False): return "EXC" # excuse, note neutralise if val == NOTES_ATTENTE: return "ATT" # attente, note neutralisee - if type(val) == FloatType or type(val) == IntType: + if type(val) == types.FloatType or type(val) == types.IntType: if note_max != None and note_max > 0: val = val * 20.0 / note_max if keep_numeric: @@ -382,7 +372,7 @@ def unescape_html_dict(d): indices = range(len(d)) for k in indices: v = d[k] - if type(v) == StringType: + if type(v) == types.StringType: d[k] = unescape_html(v) elif isiterable(v): unescape_html_dict(v) @@ -427,11 +417,11 @@ def simple_dictlist2xml(dictlist, doc=None, tagname=None, quote=False): raise ValueError("invalid empty tagname !") if not doc: doc = jaxml.XML_document(encoding=SCO_ENCODING) - scalar_types = [StringType, UnicodeType, IntType, FloatType] + scalar_types = [types.StringType, types.UnicodeType, types.IntType, types.FloatType] for d in dictlist: doc._push() if ( - type(d) == InstanceType or type(d) in scalar_types + type(d) == types.InstanceType or type(d) in scalar_types ): # pour ApoEtapeVDI et listes de chaines getattr(doc, tagname)(code=str(d)) else: @@ -448,7 +438,7 @@ def simple_dictlist2xml(dictlist, doc=None, tagname=None, quote=False): [(k, v) for (k, v) in d.items() if type(v) in scalar_types] ) getattr(doc, tagname)(**d_scalar) - d_list = dict([(k, v) for (k, v) in d.items() if type(v) == ListType]) + d_list = dict([(k, v) for (k, v) in d.items() if type(v) == types.ListType]) if d_list: for (k, v) in d_list.items(): simple_dictlist2xml(v, doc=doc, tagname=k, quote=quote) @@ -580,7 +570,7 @@ def sendJSON(REQUEST, data): def sendXML(REQUEST, data, tagname=None, force_outer_xml_tag=True): - if type(data) != ListType: + if type(data) != types.ListType: data = [data] # always list-of-dicts if force_outer_xml_tag: root_tagname = tagname + "_list" @@ -776,7 +766,7 @@ def scodoc_html2txt(html): def is_valid_mail(email): """True if well-formed email address""" - return re.match("^.+@.+\..{2,3}$", email) + return re.match(r"^.+@.+\..{2,3}$", email) ICONSIZES = {} # name : (width, height) cache image sizes diff --git a/sco_zope.py b/sco_zope.py index 73f58129..2de7484f 100644 --- a/sco_zope.py +++ b/sco_zope.py @@ -27,6 +27,8 @@ """Imports et configuration des composants Zope """ +# Avoid pylint warnings when linting without Zope +# pylint: skip-file from OFS.SimpleItem import Item # Basic zope object from OFS.PropertyManager import PropertyManager # provide the 'Properties' tab with the diff --git a/scolog.py b/scolog.py index 35ce038c..1ee852da 100644 --- a/scolog.py +++ b/scolog.py @@ -28,7 +28,7 @@ import pdb, os, sys from sco_exceptions import * -from notesdb import * +import notesdb as ndb from notes_log import retreive_request @@ -46,8 +46,8 @@ def logdb(REQUEST=None, cnx=None, method=None, etudid=None, msg=None, commit=Tru else: args = {"authenticated_user": None, "remote_addr": None, "remote_host": None} args.update({"method": method, "etudid": etudid, "msg": msg}) - quote_dict(args) - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + ndb.quote_dict(args) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "insert into scolog (authenticated_user,remote_addr,remote_host,method,etudid,msg) values (%(authenticated_user)s,%(remote_addr)s,%(remote_host)s,%(method)s,%(etudid)s,%(msg)s)", args, @@ -58,7 +58,7 @@ def logdb(REQUEST=None, cnx=None, method=None, etudid=None, msg=None, commit=Tru def loglist(cnx, method=None, authenticated_user=None): """List of events logged for these method and user""" - cursor = cnx.cursor(cursor_factory=ScoDocCursor) + cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) cursor.execute( "select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s", {"method": method, "authenticated_user": authenticated_user}, From 284257e5e1d5a953bd6b7ba54058d4352c685897 Mon Sep 17 00:00:00 2001 From: IDK Date: Wed, 3 Feb 2021 22:13:03 +0100 Subject: [PATCH 05/18] code cleaning --- sco_utils.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/sco_utils.py b/sco_utils.py index eb9f86ca..7c946d17 100644 --- a/sco_utils.py +++ b/sco_utils.py @@ -32,7 +32,6 @@ import os import sys import copy import re - import bisect import types import numbers @@ -41,6 +40,10 @@ import urllib2 import xml.sax.saxutils import time import datetime +import json + +# XML generation package (apt-get install jaxml) +import jaxml try: import six @@ -52,21 +55,11 @@ except ImportError: from PIL import Image as PILImage -# XML generation package (apt-get install jaxml) -import jaxml - -import json - from VERSION import SCOVERSION import VERSION from SuppressAccents import suppression_diacritics - -# from sco_exceptions import * -# from sco_permissions import * -from TrivialFormulator import TrivialFormulator, TF, tf_error_message -from notes_log import log, logCallStack - +from notes_log import log from sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL # ----- CALCUL ET PRESENTATION DES NOTES From 2835777ea609a58719cdd34fb8e940f1fc8d02d9 Mon Sep 17 00:00:00 2001 From: IDK Date: Thu, 4 Feb 2021 20:02:44 +0100 Subject: [PATCH 06/18] Changed sco_utils import --- ImportScolars.py | 23 +++++----- html_sco_header.py | 10 +++-- html_sidebar.py | 6 +-- notes_table.py | 36 ++++++++------- pe_tools.py | 8 ++-- pe_view.py | 6 +-- sco_abs_notification.py | 7 +-- sco_apogee_compare.py | 2 +- sco_archives.py | 45 ++++++++++--------- sco_archives_etud.py | 11 ++--- sco_cost_formation.py | 5 ++- sco_dept.py | 12 ++--- sco_dump_db.py | 33 +++++++------- sco_edit_formation.py | 4 +- sco_edit_matiere.py | 6 +-- sco_edit_module.py | 14 +++--- sco_edit_ue.py | 22 ++++----- sco_edt_cal.py | 5 ++- sco_etape_apogee.py | 6 ++- sco_etape_apogee_view.py | 12 ++--- sco_excel.py | 81 ++++++++++++++++++++-------------- sco_export_results.py | 14 +++--- sco_find_etud.py | 21 +++++---- sco_formations.py | 15 ++++--- sco_formsemestre.py | 13 +++--- sco_formsemestre_custommenu.py | 2 +- sco_formsemestre_edit.py | 16 +++---- sco_formsemestre_validation.py | 19 ++++---- sco_formulas.py | 2 +- sco_groups.py | 27 ++++++------ sco_groups_edit.py | 2 +- sco_import_users.py | 14 +++--- sco_inscr_passage.py | 16 ++----- sco_liste_notes.py | 39 +++++++--------- sco_lycee.py | 8 ++-- sco_moduleimpl_inscriptions.py | 6 +-- sco_page_etud.py | 11 ++--- sco_placement.py | 31 ++++++++----- sco_poursuite_dut.py | 16 +++---- sco_preferences.py | 21 ++++----- sco_prepajury.py | 12 ++--- sco_pvjury.py | 20 +++++---- sco_pvpdf.py | 10 ++--- sco_recapcomplet.py | 53 +++++++++++++--------- sco_semset.py | 6 +-- sco_tag_module.py | 6 +-- sco_trombino.py | 13 +++--- sco_trombino_tours.py | 6 +-- sco_ue_external.py | 5 ++- sco_undo_notes.py | 11 ++--- sco_up_to_date.py | 11 +++-- 51 files changed, 430 insertions(+), 370 deletions(-) diff --git a/ImportScolars.py b/ImportScolars.py index 8a417632..4502abd3 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -34,8 +34,9 @@ import time import pdb import collections import types +import re -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log import scolars @@ -107,7 +108,7 @@ ADMISSION_MODIFIABLE_FIELDS = ( def sco_import_format(with_codesemestre=True): "returns tuples (Attribut, Type, Table, AllowNulls, Description)" r = [] - for l in open(SCO_SRCDIR + "/" + FORMAT_FILE): + for l in open(scu.SCO_SRCDIR + "/" + FORMAT_FILE): l = l.strip() if l and l[0] != "#": fs = l.split(";") @@ -166,10 +167,10 @@ def sco_import_generate_excel_sample( titles = [] titlesStyles = [] for l in fmt: - name = strlower(l[0]) + name = scu.strlower(l[0]) if (not with_codesemestre) and name == "codesemestre": continue # pas de colonne codesemestre - if only_tables is not None and strlower(l[2]) not in only_tables: + if only_tables is not None and scu.strlower(l[2]) not in only_tables: continue # table non demandée if name in exclude_cols: continue # colonne exclue @@ -206,7 +207,7 @@ def sco_import_generate_excel_sample( ) l.append(etud["partitionsgroupes"]) else: - key = strlower(field).split()[0] + key = scu.strlower(field).split()[0] l.append(etud.get(key, "")) lines.append(l) else: @@ -279,7 +280,7 @@ def scolars_import_excel_file( titles = {} fmt = sco_import_format() for l in fmt: - tit = strlower(l[0]).split()[0] # titles in lowercase, and take 1st word + tit = scu.strlower(l[0]).split()[0] # titles in lowercase, and take 1st word if ( (not formsemestre_id) or (tit != "codesemestre") ) and tit not in exclude_cols: @@ -288,7 +289,7 @@ def scolars_import_excel_file( # log("titles=%s" % titles) # remove quotes, downcase and keep only 1st word try: - fs = [strlower(stripquotes(s)).split()[0] for s in data[0]] + fs = [scu.strlower(scu.stripquotes(s)).split()[0] for s in data[0]] except: raise ScoValueError("Titres de colonnes invalides (ou vides ?)") # log("excel: fs='%s'\ndata=%s" % (str(fs), str(data))) @@ -365,7 +366,7 @@ def scolars_import_excel_file( % (val, linenum, titleslist[i]) ) # xxx Ad-hoc checks (should be in format description) - if strlower(titleslist[i]) == "sexe": + if scu.strlower(titleslist[i]) == "sexe": try: val = scolars.normalize_sexe(val) except: @@ -374,13 +375,13 @@ def scolars_import_excel_file( % (val, linenum, titleslist[i]) ) # Excel date conversion: - if strlower(titleslist[i]) == "date_naissance": + if scu.strlower(titleslist[i]) == "date_naissance": if val: if re.match("^[0-9]*\.?[0-9]*$", str(val)): val = sco_excel.xldate_as_datetime(float(val)) # INE if ( - strlower(titleslist[i]) == "code_ine" + scu.strlower(titleslist[i]) == "code_ine" and always_require_ine and not val ): @@ -703,7 +704,7 @@ _ADM_PATTERN = re.compile(r"[\W]+", re.UNICODE) # supprime tout sauf alphanum def adm_normalize_string(s): # normalize unicode title - return suppression_diacritics(_ADM_PATTERN.sub("", s.strip().lower())).replace( + return scu.suppression_diacritics(_ADM_PATTERN.sub("", s.strip().lower())).replace( "_", "" ) diff --git a/html_sco_header.py b/html_sco_header.py index d66a875b..89003b66 100644 --- a/html_sco_header.py +++ b/html_sco_header.py @@ -27,7 +27,7 @@ import cgi -from sco_utils import * +import sco_utils as scu from sco_formsemestre_status import formsemestre_page_title """ @@ -97,7 +97,7 @@ def sco_header( "page_title": page_title or context.title_or_id(), "no_side_bar": no_side_bar, "ScoURL": context.ScoURL(), - "encoding": SCO_ENCODING, + "encoding": scu.SCO_ENCODING, "titrebandeau_mkup": "
", "authuser": str(REQUEST.AUTHENTICATED_USER), } @@ -226,7 +226,7 @@ def sco_header( # Body et bandeau haut: H.append("""""" % params) - H.append(CUSTOM_HTML_HEADER) + H.append(scu.CUSTOM_HTML_HEADER) # if not no_side_bar: H.append(context.sidebar(REQUEST)) @@ -260,4 +260,6 @@ def sco_header( def sco_footer(context, REQUEST=None): """Main HTMl pages footer""" - return """""" + CUSTOM_HTML_FOOTER + """""" + return ( + """""" + scu.CUSTOM_HTML_FOOTER + """""" + ) diff --git a/html_sidebar.py b/html_sidebar.py index 1c11cf57..7c50d5c3 100644 --- a/html_sidebar.py +++ b/html_sidebar.py @@ -25,7 +25,7 @@ # ############################################################################## -from sco_utils import * +import sco_utils as scu from sco_abs import getAbsSemEtud from sco_permissions import ( ScoUsersAdmin, @@ -82,7 +82,7 @@ def sidebar_common(context, REQUEST=None): def sidebar(context, REQUEST=None): "Main HTML page sidebar" # rewritten from legacy DTML code - params = {"ScoURL": context.ScoURL(), "SCO_USER_MANUAL": SCO_USER_MANUAL} + params = {"ScoURL": context.ScoURL(), "SCO_USER_MANUAL": scu.SCO_USER_MANUAL} H = ['
 ") # /etud-insidebar # Logo - scologo_img = icontag("scologo_img") + scologo_img = scu.icontag("scologo_img") H.append('
" + titrebandeau + "
' % sd) H.append( '' - % icontag("plus18_img", width=18, height=18, border=0, title="", alt="+") + % scu.icontag("plus18_img", width=18, height=18, border=0, title="", alt="+") ) H.append("") # titres des UE @@ -591,7 +591,7 @@ def formsemestre_recap_parcours_table( else: default_sem_info = "" if sem["etat"] != "1": # locked - lockicon = icontag("lock32_img", title="verrouillé", border="0") + lockicon = scu.icontag("lock32_img", title="verrouillé", border="0") default_sem_info += lockicon if sem["formation_code"] != Se.formation["formation_code"]: default_sem_info += "Autre formation: %s" % sem["formation_code"] @@ -601,8 +601,7 @@ def formsemestre_recap_parcours_table( ) # Moy Gen (sous le code decision) H.append( - '' - % notes_table.fmt_note(nt.get_etud_moy_gen(etudid)) + '' % scu.fmt_note(nt.get_etud_moy_gen(etudid)) ) # Absences (nb d'abs non just. dans ce semestre) AbsEtudSem = getAbsSemEtud(context, sem, etudid) @@ -642,7 +641,7 @@ def formsemestre_recap_parcours_table( H.append( '' - % (class_ue, " ".join(explanation_ue), notes_table.fmt_note(moy_ue)) + % (class_ue, " ".join(explanation_ue), scu.fmt_note(moy_ue)) ) if len(ues) < Se.nb_max_ue: H.append('' % (Se.nb_max_ue - len(ues))) diff --git a/sco_formulas.py b/sco_formulas.py index fa663438..ccac9df8 100644 --- a/sco_formulas.py +++ b/sco_formulas.py @@ -32,7 +32,7 @@ import operator import traceback from types import FloatType, IntType, LongType, StringType -from sco_utils import * +import sco_utils as scu from notes_log import log diff --git a/sco_groups.py b/sco_groups.py index ebf6501f..26a2e677 100644 --- a/sco_groups.py +++ b/sco_groups.py @@ -33,7 +33,7 @@ Optimisation possible: et éviter ainsi l'appel ulterieur à get_etud_groups() dans _make_table_notes """ - +import time import collections import re import sets @@ -43,7 +43,7 @@ import operator import jaxml import xml.dom.minidom -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log from scolog import logdb @@ -75,7 +75,8 @@ def checkGroupName( ): # XXX unused: now allow any string as a group or partition name "Raises exception if not a valid group name" if groupName and ( - not re.match(r"^\w+$", groupName) or (simplesqlquote(groupName) != groupName) + not re.match(r"^\w+$", groupName) + or (scu.simplesqlquote(groupName) != groupName) ): log("!!! invalid group name: " + groupName) raise ValueError("invalid group name: " + groupName) @@ -247,7 +248,7 @@ def get_group_members(context, group_id, etat=None): r.sort(key=operator.itemgetter("nom_disp", "prenom")) # tri selon nom_usuel ou nom - if CONFIG.ALLOW_NULL_PRENOM: + if scu.CONFIG.ALLOW_NULL_PRENOM: for x in r: x["prenom"] = x["prenom"] or "" @@ -433,7 +434,7 @@ def formsemestre_partition_list(context, formsemestre_id, format="xml", REQUEST= # Ajoute les groupes for p in partitions: p["group"] = get_partition_groups(context, p) - return sendResult(REQUEST, partitions, name="partition", format=format) + return scu.sendResult(REQUEST, partitions, name="partition", format=format) def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetGroupesTD @@ -454,8 +455,8 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG ) # > inscrdict etuds_set = set(nt.inscrdict) # XML response: - REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) - doc = jaxml.XML_document(encoding=SCO_ENCODING) + REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) + doc = jaxml.XML_document(encoding=scu.SCO_ENCODING) doc._text('') doc._push() @@ -687,7 +688,7 @@ def setGroups( if not group_name: continue # ajax arguments are encoded in utf-8: - group_name = unicode(group_name, "utf-8").encode(SCO_ENCODING) + group_name = unicode(group_name, "utf-8").encode(scu.SCO_ENCODING) group_id = createGroup(context, partition_id, group_name, REQUEST=REQUEST) # Place dans ce groupe les etudiants indiqués: for etudid in fs[1:-1]: @@ -695,7 +696,7 @@ def setGroups( context, etudid, group_id, partition, REQUEST=REQUEST ) - REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) + REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) return ( 'Groupes enregistrés' ) @@ -797,9 +798,9 @@ def partition_create( def getArrowIconsTags(context, REQUEST): """returns html tags for arrows""" # - arrow_up = icontag("arrow_up", title="remonter") - arrow_down = icontag("arrow_down", title="descendre") - arrow_none = icontag("arrow_none", title="") + arrow_up = scu.icontag("arrow_up", title="remonter") + arrow_down = scu.icontag("arrow_down", title="descendre") + arrow_none = scu.icontag("arrow_none", title="") return arrow_up, arrow_down, arrow_none @@ -811,7 +812,7 @@ def editPartitionForm(context, formsemestre_id=None, REQUEST=None): raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") partitions = get_partitions_list(context, formsemestre_id) arrow_up, arrow_down, arrow_none = getArrowIconsTags(context, REQUEST) - suppricon = icontag( + suppricon = scu.icontag( "delete_small_img", border="0", alt="supprimer", title="Supprimer" ) # diff --git a/sco_groups_edit.py b/sco_groups_edit.py index be2e1f30..9cdb578b 100644 --- a/sco_groups_edit.py +++ b/sco_groups_edit.py @@ -30,7 +30,7 @@ import re -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log import sco_formsemestre diff --git a/sco_import_users.py b/sco_import_users.py index 654f2bed..4b6b315c 100644 --- a/sco_import_users.py +++ b/sco_import_users.py @@ -36,7 +36,7 @@ from email.Header import Header # pylint: disable=no-name-in-module,import-erro from email import Encoders # pylint: disable=no-name-in-module,import-error import notesdb as ndb -from sco_utils import * +import sco_utils as scu from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_news @@ -74,11 +74,11 @@ def import_excel_file(datafile, REQUEST=None, context=None): exceldata = datafile.read() if not exceldata: raise ScoValueError("Ficher excel vide ou invalide") - diag, data = sco_excel.Excel_to_list(exceldata) + _, data = sco_excel.Excel_to_list(exceldata) if not data: # probably a bug raise ScoException("import_excel_file: empty file !") # 1- --- check title line - fs = [strlower(stripquotes(s)) for s in data[0]] + fs = [scu.strlower(scu.stripquotes(s)) for s in data[0]] log("excel: fs='%s'\ndata=%s" % (str(fs), str(data))) # check cols cols = {}.fromkeys(TITLES) @@ -221,16 +221,16 @@ ScoDoc est un logiciel libre développé à l'Université Paris 13 par Emmanuel Pour plus d'informations sur ce logiciel, voir %s """ - % SCO_WEBSITE + % scu.SCO_WEBSITE ) msg = MIMEMultipart() if reset: - msg["Subject"] = Header("Mot de passe ScoDoc", SCO_ENCODING) + msg["Subject"] = Header("Mot de passe ScoDoc", scu.SCO_ENCODING) else: - msg["Subject"] = Header("Votre accès ScoDoc", SCO_ENCODING) + msg["Subject"] = Header("Votre accès ScoDoc", scu.SCO_ENCODING) msg["From"] = context.get_preference("email_from_addr") msg["To"] = u["email"] msg.epilogue = "" - txt = MIMEText(txt, "plain", SCO_ENCODING) + txt = MIMEText(txt, "plain", scu.SCO_ENCODING) msg.attach(txt) context.sendEmail(msg) diff --git a/sco_inscr_passage.py b/sco_inscr_passage.py index 5c65e361..f746238e 100644 --- a/sco_inscr_passage.py +++ b/sco_inscr_passage.py @@ -28,12 +28,12 @@ """Form. pour inscription rapide des etudiants d'un semestre dans un autre Utilise les autorisations d'inscription délivrées en jury. """ - -from gen_tables import GenTable +import datetime import notesdb as ndb -from sco_utils import * +import sco_utils as scu from notes_log import log +from gen_tables import GenTable import sco_codes_parcours import sco_pvjury import sco_formsemestre @@ -226,14 +226,9 @@ def list_source_sems(context, sem, delai=None): othersems = [] d, m, y = [int(x) for x in sem["date_debut"].split("/")] date_debut_dst = datetime.date(y, m, d) - d, m, y = [int(x) for x in sem["date_fin"].split("/")] - date_fin_dst = datetime.date(y, m, d) delais = datetime.timedelta(delai) for s in sems: - # pdb.set_trace() - # if s['etat'] != '1': - # continue # saute semestres pas ouverts if s["formsemestre_id"] == sem["formsemestre_id"]: continue # saute le semestre destination if s["date_fin"]: @@ -279,9 +274,6 @@ def formsemestre_inscr_passage( """ inscrit_groupes = int(inscrit_groupes) - # log('formsemestre_inscr_passage: formsemestre_id=%s submitted=%s, dialog_confirmed=%s len(etuds)=%d' - # % (formsemestre_id, submitted, dialog_confirmed, len(etuds)) ) - cnx = context.GetDBConnexion() sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # -- check lock if sem["etat"] != "1": @@ -561,7 +553,7 @@ def etuds_select_boxes( if base_url and etuds: H.append( '%s ' - % (base_url, src_cat, ICON_XLS) + % (base_url, src_cat, scu.ICON_XLS) ) H.append("") for etud in etuds: diff --git a/sco_liste_notes.py b/sco_liste_notes.py index 35e5a87a..66dfbf61 100644 --- a/sco_liste_notes.py +++ b/sco_liste_notes.py @@ -28,15 +28,12 @@ """Liste des notes d'une évaluation """ import urllib +from types import StringType -from htmlutils import histogram_notes - - +import sco_utils as scu import notesdb as ndb -from sco_utils import * from notes_log import log from TrivialFormulator import TrivialFormulator, TF -from notes_table import * import sco_formsemestre import sco_moduleimpl import sco_groups @@ -44,6 +41,8 @@ import sco_evaluations import htmlutils import sco_excel from gen_tables import GenTable +from htmlutils import histogram_notes +import VERSION def do_evaluation_listenotes(context, REQUEST): @@ -52,7 +51,6 @@ def do_evaluation_listenotes(context, REQUEST): args: evaluation_id """ - cnx = context.GetDBConnexion() mode = None if REQUEST.form.has_key("evaluation_id"): evaluation_id = REQUEST.form["evaluation_id"] @@ -69,9 +67,6 @@ def do_evaluation_listenotes(context, REQUEST): format = REQUEST.form.get("format", "html") E = evals[0] # il y a au moins une evaluation - M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - formsemestre_id = M["formsemestre_id"] - # description de l'evaluation if mode == "eval": H = [ @@ -318,11 +313,11 @@ def _make_table_notes( "code": code, "_code_td_attrs": 'style="padding-left: 1em; padding-right: 2em;"', "etudid": etudid, - "nom": strupper(etud["nom"]), + "nom": scu.strupper(etud["nom"]), "_nomprenom_target": "formsemestre_bulletinetud?formsemestre_id=%s&etudid=%s" % (M["formsemestre_id"], etudid), "_nomprenom_td_attrs": 'id="%s" class="etudinfo"' % (etud["etudid"]), - "prenom": strcapitalize(strlower(etud["prenom"])), + "prenom": scu.strcapitalize(scu.strlower(etud["prenom"])), "nomprenom": etud["nomprenom"], "group": grc, "email": etud["email"], @@ -437,7 +432,7 @@ def _make_table_notes( if len(evals) == 1: evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) hh = "%s, %s (%d étudiants)" % (E["description"], gr_title, len(etudids)) - filename = make_filename("notes_%s_%s" % (evalname, gr_title_filename)) + filename = scu.make_filename("notes_%s_%s" % (evalname, gr_title_filename)) caption = hh pdf_title = "%(description)s (%(jour)s)" % e html_title = "" @@ -447,7 +442,7 @@ def _make_table_notes( % (nb_abs, nb_att) ) else: - filename = make_filename("notes_%s_%s" % (Mod["code"], gr_title_filename)) + filename = scu.make_filename("notes_%s_%s" % (Mod["code"], gr_title_filename)) title = "Notes du module %(code)s %(titre)s" % Mod title += " semestre %(titremois)s" % sem if gr_title and gr_title != "tous": @@ -470,7 +465,7 @@ def _make_table_notes( html_sortable=True, base_url=base_url, filename=filename, - origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "", caption=caption, html_next_section=html_next_section, page_title="Notes de " + sem["titremois"], @@ -552,10 +547,10 @@ def _add_eval_columns( val = NotesDB[etudid]["value"] if val is None: nb_abs += 1 - if val == NOTES_ATTENTE: + if val == scu.NOTES_ATTENTE: nb_att += 1 # calcul moyenne SANS LES ABSENTS - if val != None and val != NOTES_NEUTRALISE and val != NOTES_ATTENTE: + if val != None and val != scu.NOTES_NEUTRALISE and val != scu.NOTES_ATTENTE: if e["note_max"] > 0: valsur20 = val * 20.0 / e["note_max"] # remet sur 20 else: @@ -565,7 +560,7 @@ def _add_eval_columns( val = valsur20 # affichage notes / 20 demandé nb_notes = nb_notes + 1 sum_notes += val - val_fmt = fmt_note(val, keep_numeric=keep_numeric) + val_fmt = scu.fmt_note(val, keep_numeric=keep_numeric) comment = NotesDB[etudid]["comment"] if comment is None: comment = "" @@ -661,7 +656,7 @@ def _add_moymod_column( val = nt.get_etud_mod_moy( e["moduleimpl_id"], etudid ) # note sur 20, ou 'NA','NI' - row[col_id] = fmt_note(val, keep_numeric=keep_numeric) + row[col_id] = scu.fmt_note(val, keep_numeric=keep_numeric) row["_" + col_id + "_td_attrs"] = ' class="moyenne" ' if type(val) != StringType: notes.append(val) @@ -715,8 +710,6 @@ def evaluation_check_absences(context, evaluation_id): if not E["jour"]: return [], [], [], [], [] # evaluation sans date - M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] - formsemestre_id = M["formsemestre_id"] etudids = sco_groups.do_evaluation_listeetuds_groups( context, evaluation_id, getallstudents=True ) @@ -744,17 +737,17 @@ def evaluation_check_absences(context, evaluation_id): if NotesDB.has_key(etudid): val = NotesDB[etudid]["value"] if ( - val != None and val != NOTES_NEUTRALISE and val != NOTES_ATTENTE + val != None and val != scu.NOTES_NEUTRALISE and val != scu.NOTES_ATTENTE ) and etudid in As: # note valide et absent ValButAbs.append(etudid) if val is None and not etudid in As: # absent mais pas signale comme tel AbsNonSignalee.append(etudid) - if val == NOTES_NEUTRALISE and not etudid in As: + if val == scu.NOTES_NEUTRALISE and not etudid in As: # Neutralisé mais pas signale absent ExcNonSignalee.append(etudid) - if val == NOTES_NEUTRALISE and etudid in NJs: + if val == scu.NOTES_NEUTRALISE and etudid in NJs: # EXC mais pas justifié ExcNonJust.append(etudid) if val is None and etudid in Justs: diff --git a/sco_lycee.py b/sco_lycee.py index fe60885e..8d25650e 100644 --- a/sco_lycee.py +++ b/sco_lycee.py @@ -32,13 +32,14 @@ import tempfile, urllib, re -from sco_utils import * +import sco_utils as scu from notes_log import log import scolars import sco_groups import sco_report from gen_tables import GenTable import sco_formsemestre +import VERSION def formsemestre_table_etuds_lycees( @@ -99,7 +100,7 @@ def _table_etuds_lycees( context, etuds, group_lycees, title, preferences, no_links=False ): etuds = [scolars.etud_add_lycee_infos(e) for e in etuds] - etuds_by_lycee = group_by_key(etuds, "codelycee") + etuds_by_lycee = scu.group_by_key(etuds, "codelycee") # if group_lycees: L = [etuds_by_lycee[codelycee][0] for codelycee in etuds_by_lycee] @@ -156,7 +157,7 @@ def _table_etuds_lycees( "nomlycee": "Lycée", "villelycee": "Commune", }, - origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "", caption=title, page_title="Carte lycées d'origine", html_sortable=True, @@ -176,7 +177,6 @@ def formsemestre_etuds_lycees( REQUEST=None, ): """Table des lycées d'origine""" - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) tab, etuds_by_lycee = formsemestre_table_etuds_lycees( context, formsemestre_id, only_primo=only_primo, group_lycees=not no_grouping ) diff --git a/sco_moduleimpl_inscriptions.py b/sco_moduleimpl_inscriptions.py index 4ee9acd1..3a4c535b 100644 --- a/sco_moduleimpl_inscriptions.py +++ b/sco_moduleimpl_inscriptions.py @@ -30,15 +30,15 @@ import notesdb as ndb -from sco_utils import * +import sco_utils as scu from notes_log import log from scolog import logdb -from notes_table import * import sco_formsemestre import sco_moduleimpl import sco_groups import htmlutils from sco_permissions import ScoEtudInscrit +from sco_exceptions import ScoValueError def moduleimpl_inscriptions_edit( @@ -454,7 +454,7 @@ def get_etuds_with_capitalized_ue(context, formsemestre_id): """For each UE, computes list of students capitalizing the UE. returns { ue_id : [ { infos } ] } """ - UECaps = DictDefault(defaultvalue=[]) + UECaps = scu.DictDefault(defaultvalue=[]) nt = context._getNotesCache().get_NotesTable( context, formsemestre_id ) # > get_ues, get_etud_ue_status diff --git a/sco_page_etud.py b/sco_page_etud.py index cbc7f8c8..8fb242dd 100644 --- a/sco_page_etud.py +++ b/sco_page_etud.py @@ -31,8 +31,9 @@ """ -from sco_utils import * +import sco_utils as scu import notesdb as ndb +from notes_log import log import scolars import sco_bac import sco_photos @@ -62,7 +63,7 @@ def _menuScolarite(context, authuser, sem, etudid): """ locked = sem["etat"] != "1" if locked: - lockicon = icontag("lock32_img", title="verrouillé", border="0") + lockicon = scu.icontag("lock32_img", title="verrouillé", border="0") return lockicon # no menu if not authuser.has_permission( ScoEtudInscrit, context @@ -220,7 +221,7 @@ def ficheEtud(context, etudid=None, REQUEST=None): sem_info = {} for sem in info["sems"]: if sem["ins"]["etat"] != "I": - descr, junk = etud_descr_situation_semestre( + descr, _ = etud_descr_situation_semestre( context.Notes, etudid, sem["formsemestre_id"], @@ -288,7 +289,7 @@ def ficheEtud(context, etudid=None, REQUEST=None): ] = '' % ( etudid, a["id"], - icontag( + scu.icontag( "delete_img", border="0", alt="suppress", @@ -387,7 +388,7 @@ def ficheEtud(context, etudid=None, REQUEST=None): else: info["tit_anno"] = "" # Inscriptions - if info["sems"]: + if info["sems"]: # XXX rcl unused ? à voir rcl = ( """(récapitulatif parcours)""" % info diff --git a/sco_placement.py b/sco_placement.py index 646230b9..3c50b19f 100644 --- a/sco_placement.py +++ b/sco_placement.py @@ -44,7 +44,9 @@ import sco_evaluations import sco_saisie_notes import sco_excel from sco_excel import * +from TrivialFormulator import TrivialFormulator from gen_tables import GenTable +import VERSION def do_placement_selectetuds(context, REQUEST): @@ -125,7 +127,10 @@ def do_placement_selectetuds(context, REQUEST): ( "group_ids", { - "default": [g["group_id"] for g in groups], + "default": [ + g["group_id"] # pylint: disable=invalid-sequence-index + for g in groups + ], "input_type": "hidden", "type": "list", }, @@ -297,8 +302,8 @@ def do_placement(context, REQUEST): {"etudid": etudid, "formsemestre_id": M["formsemestre_id"]} )[0] if inscr["etat"] != "D": - nom = strupper(ident["nom"]) - prenom = strcapitalize(strlower(ident["prenom"])) + nom = scu.strupper(ident["nom"]) + prenom = scu.strcapitalize(scu.strlower(ident["prenom"])) listetud.append((nom, prenom)) random.shuffle(listetud) @@ -374,7 +379,9 @@ def do_placement(context, REQUEST): columns_ids=columns_ids, rows=rows, filename=filename, - origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", + origin="Généré par %s le " % VERSION.SCONAME + + scu.timedate_human_repr() + + "", pdf_title=pdf_title, # pdf_shorttitle = '', preferences=context.get_preferences(M["formsemestre_id"]), @@ -444,7 +451,7 @@ def Excel_feuille_placement( wb = Workbook() SheetName0 = "Emargement" - ws0 = wb.add_sheet(SheetName0.decode(SCO_ENCODING)) + ws0 = wb.add_sheet(SheetName0.decode(scu.SCO_ENCODING)) # ajuste largeurs colonnes (unite inconnue, empirique) width = 4500 if nbcolumns > 5: @@ -455,7 +462,7 @@ def Excel_feuille_placement( ws0.col(0).width = 750 SheetName1 = "Positions" - ws1 = wb.add_sheet(SheetName1.decode(SCO_ENCODING)) + ws1 = wb.add_sheet(SheetName1.decode(scu.SCO_ENCODING)) if numbering == "coordinate": ws1.col(0).width = 4000 ws1.col(1).width = 4500 @@ -654,8 +661,8 @@ def Excel_feuille_placement( else: li += 1 line += 1 - ws0.write(li, 0, desceval[0].decode(SCO_ENCODING), style_titres) - ws1.write(li, 0, desceval[0].decode(SCO_ENCODING), style_titres) + ws0.write(li, 0, desceval[0].decode(scu.SCO_ENCODING), style_titres) + ws1.write(li, 0, desceval[0].decode(scu.SCO_ENCODING), style_titres) li += 1 ws0.write( li, @@ -727,8 +734,8 @@ def Excel_feuille_placement( ws0.write(li0, 0, line, style2b) col = 1 for etudid in linetud: - ws0.write(li0, col, (etudid[0]).decode(SCO_ENCODING), style1t) - ws0.write(li0 + 1, col, (etudid[1]).decode(SCO_ENCODING), style1m) + ws0.write(li0, col, (etudid[0]).decode(scu.SCO_ENCODING), style1t) + ws0.write(li0 + 1, col, (etudid[1]).decode(scu.SCO_ENCODING), style1m) ws0.row(li0 + 2).height = space if numbering == "coordinate": ws0.write(li0 + 2, col, " ", style1bb) @@ -757,8 +764,8 @@ def Excel_feuille_placement( for etudid in orderetud: li1 += 1 line += 1 - ws1.write(li1, col, (etudid[0]).decode(SCO_ENCODING), style2l) - ws1.write(li1, col + 1, (etudid[1]).decode(SCO_ENCODING), style2m1) + ws1.write(li1, col, (etudid[0]).decode(scu.SCO_ENCODING), style2l) + ws1.write(li1, col + 1, (etudid[1]).decode(scu.SCO_ENCODING), style2m1) if numbering == "coordinate": ws1.write(li1, col + 2, etudid[2], style2m2) ws1.write(li1, col + 3, etudid[3], style2r) diff --git a/sco_poursuite_dut.py b/sco_poursuite_dut.py index 9eed9c7d..97c3a14a 100644 --- a/sco_poursuite_dut.py +++ b/sco_poursuite_dut.py @@ -31,13 +31,14 @@ Recapitule tous les semestres validés dans une feuille excel. """ import collections -from sco_utils import * +import sco_utils as scu from notes_log import log from gen_tables import GenTable import sco_formsemestre import sco_groups import sco_abs from sco_codes_parcours import code_semestre_validant, code_semestre_attente +import VERSION def etud_get_poursuite_info(context, sem, etud): @@ -62,7 +63,7 @@ def etud_get_poursuite_info(context, sem, etud): moy_ues = [ ( ue["acronyme"], - fmt_note(nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]), + scu.fmt_note(nt.get_etud_ue_status(etudid, ue["ue_id"])["moy"]), ) for ue in ues ] @@ -79,7 +80,7 @@ def etud_get_poursuite_info(context, sem, etud): for modimpl in modimpls: # dans chaque UE les modules if modimpl["module"]["ue_id"] == ue["ue_id"]: codeModule = modimpl["module"]["code"] - noteModule = fmt_note( + noteModule = scu.fmt_note( nt.get_etud_mod_moy(modimpl["moduleimpl_id"], etudid) ) if noteModule != "NI": # si étudiant inscrit au module @@ -103,8 +104,8 @@ def etud_get_poursuite_info(context, sem, etud): and nt.get_etud_etat(etudid) == "I" ): d = [ - ("moy", fmt_note(nt.get_etud_moy_gen(etudid))), - ("moy_promo", fmt_note(nt.moy_moy)), + ("moy", scu.fmt_note(nt.get_etud_moy_gen(etudid))), + ("moy_promo", scu.fmt_note(nt.moy_moy)), ("rang", nt.get_etud_rang(etudid)), ("effectif", len(nt.T)), ("date_debut", s["date_debut"]), @@ -154,7 +155,6 @@ def formsemestre_poursuite_report( ): """Table avec informations "poursuite" """ sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) etuds = context.getEtudInfoGroupes( [sco_groups.get_default_group(context, formsemestre_id)] ) @@ -191,9 +191,9 @@ def formsemestre_poursuite_report( pdf_link=False, # pas d'export pdf preferences=context.get_preferences(formsemestre_id), ) - tab.filename = make_filename("poursuite " + sem["titreannee"]) + tab.filename = scu.make_filename("poursuite " + sem["titreannee"]) - tab.origin = "Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "" + tab.origin = "Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "" tab.caption = "Récapitulatif %s." % sem["titreannee"] tab.html_caption = "Récapitulatif %s." % sem["titreannee"] tab.base_url = "%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id) diff --git a/sco_preferences.py b/sco_preferences.py index 2a66eaa8..d7bb3ed3 100644 --- a/sco_preferences.py +++ b/sco_preferences.py @@ -28,8 +28,9 @@ """ScoDoc preferences (replaces old Zope properties) """ -from sco_utils import * +import sco_utils as scu import notesdb as ndb +from notes_log import log from TrivialFormulator import TrivialFormulator, TF import sco_formsemestre import sco_bulletins_generator @@ -1749,7 +1750,7 @@ class sco_base_preferences: """Load all preferences from db""" log("loading preferences") try: - GSL.acquire() + scu.GSL.acquire() cnx = self.context.GetDBConnexion() preflist = self._editor.list(cnx) self.prefs = {None: {}} # { formsemestre_id (or None) : { name : value } } @@ -1796,9 +1797,9 @@ class sco_base_preferences: % (name, value) ) except: - # search in CONFIG - if hasattr(CONFIG, name): - value = getattr(CONFIG, name) + # 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) @@ -1813,7 +1814,7 @@ class sco_base_preferences: # add to db table self._editor.create(cnx, {"name": name, "value": value}) finally: - GSL.release() + scu.GSL.release() def get(self, formsemestre_id, name): """Returns preference value. @@ -1845,7 +1846,7 @@ class sco_base_preferences: def save(self, formsemestre_id=None, name=None): """Write one or all (if name is None) values to db""" try: - GSL.acquire() + scu.GSL.acquire() modif = False cnx = self.context.GetDBConnexion() if name is None: @@ -1892,7 +1893,7 @@ class sco_base_preferences: if modif: self.context.Notes._inval_cache(pdfonly=False) # > modif preferences finally: - GSL.release() + scu.GSL.release() def set(self, formsemestre_id, name, value): if not name or name[0] == "_" or name not in PREFS_NAMES: @@ -1908,7 +1909,7 @@ class sco_base_preferences: if not formsemestre_id: raise ScoException() try: - GSL.acquire() + scu.GSL.acquire() if formsemestre_id in self.prefs and name in self.prefs[formsemestre_id]: del self.prefs[formsemestre_id][name] cnx = self.context.GetDBConnexion() @@ -1920,7 +1921,7 @@ class sco_base_preferences: self._editor.delete(cnx, pdb[0]["pref_id"]) self.context.Notes._inval_cache(pdfonly=False) # > modif preferences finally: - GSL.release() + scu.GSL.release() def edit(self, REQUEST): """HTML dialog: edit global preferences""" diff --git a/sco_prepajury.py b/sco_prepajury.py index a70f366d..4845defc 100644 --- a/sco_prepajury.py +++ b/sco_prepajury.py @@ -27,8 +27,9 @@ """Feuille excel pour preparation des jurys """ +import time -from sco_utils import * +import sco_utils as scu from notes_log import log import notes_table import sco_groups @@ -38,6 +39,7 @@ import sco_parcours_dut import sco_codes_parcours from scolars import format_nom, format_prenom, format_sexe, format_lycee from sco_abs import getAbsSemEtud +import VERSION def feuille_preparation_jury(context, formsemestre_id, REQUEST): @@ -53,10 +55,10 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): context, formsemestre_id )["partition_id"] - prev_moy_ue = DictDefault(defaultvalue={}) # ue_code_s : { etudid : moy ue } + prev_moy_ue = scu.DictDefault(defaultvalue={}) # ue_code_s : { etudid : moy ue } prev_ue_acro = {} # ue_code_s : acronyme (à afficher) prev_moy = {} # moyennes gen sem prec - moy_ue = DictDefault(defaultvalue={}) # ue_acro : moyennes { etudid : moy ue } + moy_ue = scu.DictDefault(defaultvalue={}) # ue_acro : moyennes { etudid : moy ue } ue_acro = {} # ue_code_s : acronyme (à afficher) moy = {} # moyennes gen moy_inter = {} # moyenne gen. sur les 2 derniers semestres @@ -155,7 +157,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): sp = "S%s" % (sid - 1) L = sco_excel.ScoExcelSheet(sheet_name="Prepa Jury %s" % sn) - L.append(["Feuille préparation Jury %s" % unescape_html(sem["titreannee"])]) + L.append(["Feuille préparation Jury %s" % scu.unescape_html(sem["titreannee"])]) L.append([]) # empty line titles = ["Rang"] @@ -211,7 +213,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): def fmt(x): "reduit les notes a deux chiffres" - x = notes_table.fmt_note(x, keep_numeric=False) + x = scu.fmt_note(x, keep_numeric=False) try: return float(x) except: diff --git a/sco_pvjury.py b/sco_pvjury.py index ca5fe0ac..b28a45ff 100644 --- a/sco_pvjury.py +++ b/sco_pvjury.py @@ -28,6 +28,9 @@ """Edition des PV de jury """ +import sco_utils as scu +import notesdb as ndb + import scolars import sco_formsemestre import sco_groups @@ -36,8 +39,7 @@ import sco_parcours_dut import sco_codes_parcours from sco_codes_parcours import NO_SEMESTRE_ID import sco_excel -import notesdb as ndb -from sco_utils import * +from TrivialFormulator import TrivialFormulator from gen_tables import GenTable import sco_pvpdf from sco_pdf import * @@ -135,7 +137,7 @@ def _comp_ects_by_ue_code_and_type(nt, decision_ues): return {}, {} ects_by_ue_code = {} - ects_by_ue_type = DictDefault(defaultvalue=0) # { ue_type : ects validés } + ects_by_ue_type = scu.DictDefault(defaultvalue=0) # { ue_type : ects validés } for ue_id in decision_ues: d = decision_ues[ue_id] ue = nt.uedict[ue_id] @@ -245,7 +247,7 @@ def dict_pvjury( if d["decision_sem"] and sco_codes_parcours.code_semestre_validant( d["decision_sem"]["code"] ): - d["mention"] = get_mention(nt.get_etud_moy_gen(etudid)) + d["mention"] = scu.get_mention(nt.get_etud_moy_gen(etudid)) else: d["mention"] = "" # Versions "en français": (avec les UE capitalisées d'ailleurs) @@ -513,8 +515,8 @@ def formsemestre_pvjury( rows=rows, titles=titles, columns_ids=columns_ids, - filename=make_filename("decisions " + sem["titreannee"]), - origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", + filename=scu.make_filename("decisions " + sem["titreannee"]), + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "", caption="Décisions jury pour " + sem["titreannee"], html_class="table_leftalign", html_sortable=True, @@ -552,7 +554,7 @@ def formsemestre_pvjury( H.append(tab.html()) # Count number of cases for each decision - counts = DictDefault() + counts = scu.DictDefault() for row in rows: counts[row["decision"]] += 1 # add codes for previous (for explanation, without count) @@ -705,7 +707,7 @@ def formsemestre_pvjury_pdf( else: groups_filename = "" filename = "PV-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt) - return sendPDFFile(REQUEST, pdfdoc, filename) + return scu.sendPDFFile(REQUEST, pdfdoc, filename) def descrform_pvjury(context, sem): @@ -872,7 +874,7 @@ def formsemestre_lettres_individuelles( dt = time.strftime("%Y-%m-%d") groups_filename = "-" + groups_infos.groups_filename filename = "lettres-%s%s-%s.pdf" % (sem["titre_num"], groups_filename, dt) - return sendPDFFile(REQUEST, pdfdoc, filename) + return scu.sendPDFFile(REQUEST, pdfdoc, filename) def descrform_lettres_individuelles(): diff --git a/sco_pvpdf.py b/sco_pvpdf.py index fa276791..2a3d50bc 100644 --- a/sco_pvpdf.py +++ b/sco_pvpdf.py @@ -27,18 +27,18 @@ """Edition des PV de jury """ +import os +import types -import sco_formsemestre from sco_pdf import * +import sco_utils as scu +import sco_formsemestre import sco_pvjury import sco_codes_parcours -from sco_utils import * from sco_pdf import PDFLOCK import sco_preferences import sco_bulletins_pdf -import os -import types LOGO_FOOTER_ASPECT = CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER LOGO_FOOTER_HEIGHT = CONFIG.LOGO_FOOTER_HEIGHT * mm @@ -354,7 +354,7 @@ def pdf_lettres_individuelles( if e["decision_sem"]: # decision prise etud = context.getEtudInfo(e["identite"]["etudid"], filled=True)[0] params["nomEtud"] = etud["nomprenom"] - bookmarks[npages + 1] = suppress_accents(etud["nomprenom"]) + bookmarks[npages + 1] = scu.suppress_accents(etud["nomprenom"]) objects += pdf_lettre_individuelle( dpv["formsemestre"], e, etud, params, signature, context=context ) diff --git a/sco_recapcomplet.py b/sco_recapcomplet.py index b406ee00..63a8c8d7 100644 --- a/sco_recapcomplet.py +++ b/sco_recapcomplet.py @@ -27,8 +27,12 @@ """Tableau recapitulatif des notes d'un semestre """ +import time +import datetime +import jaxml -from notes_table import * +import sco_utils as scu +from notes_log import log import sco_bulletins, sco_excel import sco_groups import sco_evaluations @@ -37,6 +41,7 @@ import sco_formsemestre_status import sco_bulletins_xml import sco_bulletins_json import sco_codes_parcours +from sco_codes_parcours import DEF, UE_SPORT import sco_bac @@ -133,7 +138,7 @@ def formsemestre_recapcomplet( H.append("checked") H.append(""" >cacher bac""") if tabformat == "xml": - REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) + REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) H.append( do_formsemestre_recapcomplet( context, @@ -201,11 +206,11 @@ def do_formsemestre_recapcomplet( if format == "xml" or format == "html": return data elif format == "csv": - return sendCSVFile(REQUEST, data, filename) + return scu.sendCSVFile(REQUEST, data, filename) elif format[:3] == "xls": return sco_excel.sendExcelFile(REQUEST, data, filename) elif format == "json": - return sendJSON(REQUEST, data) + return scu.sendJSON(REQUEST, data) else: raise ValueError("unknown format %s" % format) @@ -345,7 +350,7 @@ def make_formsemestre_recapcomplet( return val # Compte les decisions de jury - codes_nb = DictDefault(defaultvalue=0) + codes_nb = scu.DictDefault(defaultvalue=0) # is_dem = {} # etudid : bool for t in T: @@ -396,7 +401,7 @@ def make_formsemestre_recapcomplet( else: l.append(gr_name) # groupe - l.append(fmtnum(fmt_note(t[0], keep_numeric=keep_numeric))) # moy_gen + l.append(fmtnum(scu.fmt_note(t[0], keep_numeric=keep_numeric))) # moy_gen # Ajoute rangs dans groupes seulement si CSV ou XLS if format[:3] == "xls" or format == "csv": rang_gr, ninscrits_gr, gr_name = sco_bulletins.get_etud_rangs_groups( @@ -410,7 +415,7 @@ def make_formsemestre_recapcomplet( i += 1 if ue["type"] != UE_SPORT: l.append( - fmtnum(fmt_note(t[i], keep_numeric=keep_numeric)) + fmtnum(scu.fmt_note(t[i], keep_numeric=keep_numeric)) ) # moyenne etud dans ue else: # UE_SPORT: # n'affiche pas la moyenne d'UE dans ce cas @@ -423,7 +428,9 @@ def make_formsemestre_recapcomplet( if modimpl["module"]["ue_id"] == ue["ue_id"]: l.append( fmtnum( - fmt_note(t[j + len(ues) + 1], keep_numeric=keep_numeric) + scu.fmt_note( + t[j + len(ues) + 1], keep_numeric=keep_numeric + ) ) ) # moyenne etud dans module if format == "xlsall": @@ -458,7 +465,7 @@ def make_formsemestre_recapcomplet( l += [""] l.append(corner_value) if format[:3] == "xls" or format == "csv": - for partition in partitions: + for _ in partitions: l += [""] # rangs dans les groupes for ue in ues: if ue["type"] != UE_SPORT: @@ -476,7 +483,7 @@ def make_formsemestre_recapcomplet( else: l.append(str(ue[key])) else: - l.append(fmt_note(ue[key], keep_numeric=keep_numeric)) + l.append(scu.fmt_note(ue[key], keep_numeric=keep_numeric)) else: # UE_SPORT: # n'affiche pas la moyenne d'UE dans ce cas if not hidemodules: @@ -500,7 +507,7 @@ def make_formsemestre_recapcomplet( ): # garde val numerique pour excel val = str(val) else: # moyenne du module - val = fmt_note(val, keep_numeric=keep_numeric) + val = scu.fmt_note(val, keep_numeric=keep_numeric) l.append(val) if format == "xlsall": @@ -514,13 +521,15 @@ def make_formsemestre_recapcomplet( F.append(l + ["", ""]) # ajoute cellules code_nip et etudid inutilisees ici add_bottom_stat( - "min", "Min", corner_value=fmt_note(nt.moy_min, keep_numeric=keep_numeric) + "min", "Min", corner_value=scu.fmt_note(nt.moy_min, keep_numeric=keep_numeric) ) add_bottom_stat( - "max", "Max", corner_value=fmt_note(nt.moy_max, keep_numeric=keep_numeric) + "max", "Max", corner_value=scu.fmt_note(nt.moy_max, keep_numeric=keep_numeric) ) add_bottom_stat( - "moy", "Moyennes", corner_value=fmt_note(nt.moy_moy, keep_numeric=keep_numeric) + "moy", + "Moyennes", + corner_value=scu.fmt_note(nt.moy_moy, keep_numeric=keep_numeric), ) add_bottom_stat("coef", "Coef") add_bottom_stat("nb_valid_evals", "Nb évals") @@ -645,7 +654,9 @@ def make_formsemestre_recapcomplet( idx_col_moy = idx_col_gr + 1 cssclass = "recap_col_moy" try: - if float(nsn[idx_col_moy]) < (nt.parcours.BARRE_MOY - NOTES_TOLERANCE): + if float(nsn[idx_col_moy]) < ( + nt.parcours.BARRE_MOY - scu.NOTES_TOLERANCE + ): cssclass = "recap_col_moy_inf" except: pass @@ -734,7 +745,7 @@ def make_formsemestre_recapcomplet( H.append("
%sSemestreEtatAbs%s%s%s%s
") return "\n".join(H), "", "html" elif format == "csv": - CSV = CSV_LINESEP.join([CSV_FIELDSEP.join(str(x)) for x in F]) + CSV = scu.CSV_LINESEP.join([scu.CSV_FIELDSEP.join(str(x)) for x in F]) semname = sem["titre_num"].replace(" ", "_") date = time.strftime("%d-%m-%Y") filename = "notes_modules-%s-%s.csv" % (semname, date) @@ -774,8 +785,8 @@ def _list_notes_evals(context, evals, etudid): val = NotesDB[etudid]["value"] else: # Note manquante mais prise en compte immédiate: affiche ATT - val = NOTES_ATTENTE - val_fmt = fmt_note(val, keep_numeric=True) + val = scu.NOTES_ATTENTE + val_fmt = scu.fmt_note(val, keep_numeric=True) L.append(val_fmt) return L @@ -806,7 +817,7 @@ def _list_notes_evals_stats(context, evals, key): ): if key == "moy": val = e["etat"]["moy_num"] - L.append(fmt_note(val, keep_numeric=True)) + L.append(scu.fmt_note(val, keep_numeric=True)) elif key == "max": L.append(e["note_max"]) elif key == "min": @@ -834,7 +845,7 @@ def _formsemestre_recapcomplet_xml( if not T: return "", "", "xml" - doc = jaxml.XML_document(encoding=SCO_ENCODING) + doc = jaxml.XML_document(encoding=scu.SCO_ENCODING) if xml_nodate: docdate = "" else: @@ -928,4 +939,4 @@ def formsemestres_bulletins(context, annee_scolaire, REQUEST=None): ) jslist.append(J) - return sendJSON(REQUEST, jslist) + return scu.sendJSON(REQUEST, jslist) diff --git a/sco_semset.py b/sco_semset.py index f5df6055..d0e3aa9b 100644 --- a/sco_semset.py +++ b/sco_semset.py @@ -39,7 +39,7 @@ sem_set_list(context) """ -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log import sco_formsemestre @@ -417,7 +417,7 @@ def semset_page(context, format="html", REQUEST=None): """ semsets = get_semsets_list(context) for s in semsets: - s["suppress"] = icontag( + s["suppress"] = scu.icontag( "delete_small_img", border="0", alt="supprimer", title="Supprimer" ) s["_suppress_target"] = "do_semset_delete?semset_id=%s" % (s["semset_id"]) @@ -479,7 +479,7 @@ def semset_page(context, format="html", REQUEST=None): ] H.append(tab.html()) - annee_courante = int(AnneeScolaire(REQUEST)) + annee_courante = int(scu.AnneeScolaire(REQUEST)) menu_annee = "\n".join( [ '' % (i, i) diff --git a/sco_tag_module.py b/sco_tag_module.py index d1fe3fdc..c4071a7f 100644 --- a/sco_tag_module.py +++ b/sco_tag_module.py @@ -36,7 +36,7 @@ import types -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log from sco_exceptions import ScoValueError, AccessDenied @@ -200,7 +200,7 @@ class ModuleTag(ScoTag): def module_tag_search(context, term, REQUEST=None): """List all used tag names (for auto-completion)""" # restrict charset to avoid injections - if not ALPHANUM_EXP.match(term.decode(SCO_ENCODING)): + if not scu.ALPHANUM_EXP.match(term.decode(scu.SCO_ENCODING)): data = [] else: r = ndb.SimpleDictFetch( @@ -210,7 +210,7 @@ def module_tag_search(context, term, REQUEST=None): ) data = [x["title"] for x in r] - return sendJSON(REQUEST, data) + return scu.sendJSON(REQUEST, data) def module_tag_list(context, module_id=""): diff --git a/sco_trombino.py b/sco_trombino.py index 09b0b96e..416e84af 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -37,8 +37,9 @@ import xml import tempfile from notes_log import log -from sco_utils import * +import sco_utils as scu from sco_exceptions import ScoValueError +from TrivialFormulator import TrivialFormulator import scolars import sco_photos import sco_formsemestre @@ -50,6 +51,7 @@ from sco_pdf import * import ImportScolars import sco_excel from reportlab.lib import colors +from PIL import Image as PILImage def trombino( @@ -166,8 +168,7 @@ def check_local_photos_availability(context, groups_infos, REQUEST, format=""): """ nb_missing = 0 for t in groups_infos.members: - etudid = t["etudid"] - url = sco_photos.etud_photo_url( + _ = sco_photos.etud_photo_url( context, t, REQUEST=REQUEST ) # -> copy distant files if needed if not sco_photos.etud_photo_is_local(context, t): @@ -376,7 +377,7 @@ def _trombino_pdf(context, groups_infos, REQUEST): document.build(objects) data = report.getvalue() - return sendPDFFile(REQUEST, data, filename) + return scu.sendPDFFile(REQUEST, data, filename) # --------------------- Sur une idée de l'IUT d'Orléans: @@ -459,7 +460,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): document.build(objects) data = report.getvalue() - return sendPDFFile(REQUEST, data, filename) + return scu.sendPDFFile(REQUEST, data, filename) # --------------------- Upload des photos de tout un groupe @@ -593,7 +594,7 @@ def zip_excel_import_files( fn = fn.replace("\\", "/") # not sure if this is necessary ? fn = fn.strip() if lowercase: - fn = strlower(fn) + fn = scu.strlower(fn) fn = fn.split("/")[-1] # use only last component, not directories return fn diff --git a/sco_trombino_tours.py b/sco_trombino_tours.py index 1b5a44ed..4f2cd780 100644 --- a/sco_trombino_tours.py +++ b/sco_trombino_tours.py @@ -38,8 +38,8 @@ from zipfile import ZipFile, BadZipfile import xml import tempfile +import sco_utils as scu from notes_log import log -from sco_utils import * import sco_abs import scolars import sco_photos @@ -283,7 +283,7 @@ def pdf_trombino_tours( document.build(objects) data = report.getvalue() - return sendPDFFile(REQUEST, data, filename) + return scu.sendPDFFile(REQUEST, data, filename) # Feuille d'absences en pdf avec photos: @@ -477,4 +477,4 @@ def pdf_feuille_releve_absences( document.build(objects) data = report.getvalue() - return sendPDFFile(REQUEST, data, filename) + return scu.sendPDFFile(REQUEST, data, filename) diff --git a/sco_ue_external.py b/sco_ue_external.py index 3906d10c..46d75a7d 100644 --- a/sco_ue_external.py +++ b/sco_ue_external.py @@ -55,13 +55,14 @@ Solution proposée (nov 2014): """ import notesdb as ndb -from sco_utils import * +import sco_utils as scu from notes_log import log import sco_formsemestre import sco_moduleimpl import sco_edit_ue import sco_saisie_notes import sco_codes_parcours +from TrivialFormulator import TrivialFormulator, tf_error_message from sco_permissions import ScoImplement from sco_exceptions import AccessDenied, ScoValueError @@ -164,7 +165,7 @@ def external_ue_inscrit_et_note( description="note externe", ) # Saisie des notes - nbchanged, nbsuppress, existing_decisions = sco_saisie_notes._notes_add( + _, _, _ = sco_saisie_notes._notes_add( context, REQUEST.AUTHENTICATED_USER, evaluation_id, diff --git a/sco_undo_notes.py b/sco_undo_notes.py index 0e6df989..5d3fe163 100644 --- a/sco_undo_notes.py +++ b/sco_undo_notes.py @@ -35,7 +35,7 @@ Pour une évaluation: - historique: table notes_notes_log saisie de notes == saisir ou supprimer une ou plusieurs notes (mêmes date et uid) -/!\ tolérance sur les dates (200ms ?) +! tolérance sur les dates (200ms ?) Chaque saisie affecte ou remplace une ou plusieurs notes. Opérations: @@ -48,12 +48,13 @@ Opérations: import datetime from intervals import intervalmap -from sco_utils import * +import sco_utils as scu import notesdb as ndb from notes_log import log from gen_tables import GenTable import sco_formsemestre import sco_moduleimpl +import VERSION # deux notes (de même uid) sont considérées comme de la même opération si # elles sont séparées de moins de 2*tolerance: @@ -121,7 +122,7 @@ def list_operations(context, evaluation_id): Ops = [] for uid in NotesDates.keys(): - for (t0, t1), notes in NotesDates[uid].items(): + for (t0, _), notes in NotesDates[uid].items(): Op = NotesOperation( evaluation_id=evaluation_id, date=t0, @@ -201,7 +202,7 @@ def formsemestre_list_saisies_notes( caption="Saisies de notes dans %s" % sem["titreannee"], preferences=context.get_preferences(formsemestre_id), base_url="%s?formsemestre_id=%s" % (REQUEST.URL0, formsemestre_id), - origin="Généré par %s le " % VERSION.SCONAME + timedate_human_repr() + "", + origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "", ) return tab.make_page(context, format=format, REQUEST=REQUEST) @@ -242,7 +243,7 @@ def get_note_history(context, evaluation_id, etudid, REQUEST=None, fmt=""): x["user_name"] = context.Users.user_info(x["uid"])["nomcomplet"] if fmt == "json": - return sendJSON(REQUEST, history) + return scu.sendJSON(REQUEST, history) else: return history diff --git a/sco_up_to_date.py b/sco_up_to_date.py index 614ee833..c3343f7d 100644 --- a/sco_up_to_date.py +++ b/sco_up_to_date.py @@ -29,8 +29,11 @@ """ Verification version logiciel vs version "stable" sur serveur N'effectue pas la mise à jour automatiquement, mais permet un affichage d'avertissement. """ +import datetime +import re -from sco_utils import * +import sco_utils as scu +from notes_log import log # Appel renvoyant la subversion "stable" # La notion de "stable" est juste là pour éviter d'afficher trop frequemment @@ -46,7 +49,9 @@ def get_last_stable_version(): (do not wait server answer more than 3 seconds) """ global _LAST_UP_TO_DATE_REQUEST - ans = query_portal(GET_VER_URL, msg="ScoDoc version server", timeout=3) # sco_utils + ans = scu.query_portal( + GET_VER_URL, msg="ScoDoc version server", timeout=3 + ) # sco_utils if ans: ans = ans.strip() _LAST_UP_TO_DATE_REQUEST = datetime.datetime.now() @@ -74,7 +79,7 @@ def is_up_to_date(context): return _UP_TO_DATE, _UP_TO_DATE_MSG last_stable_ver = get_last_stable_version() - cur_ver = get_svn_version(context.file_path) # in sco_utils + cur_ver = scu.get_svn_version(context.file_path) # in sco_utils cur_ver2 = cur_ver cur_ver_num = -1 # Convert versions to integers: From 66be2a41c99a0c488ed0ab3b4b8cfa02fe66632c Mon Sep 17 00:00:00 2001 From: IDK Date: Thu, 4 Feb 2021 23:16:18 +0100 Subject: [PATCH 07/18] test absences --- sco_abs_views.py | 40 +++++++++++++++++++++++++++++++++------- scotests/test_basic.py | 27 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/sco_abs_views.py b/sco_abs_views.py index aabab46f..70ada694 100644 --- a/sco_abs_views.py +++ b/sco_abs_views.py @@ -56,10 +56,21 @@ def doSignaleAbsence( demijournee=2, estjust=False, description=None, + etudid=False, REQUEST=None, ): # etudid implied - """Signalement d'une absence""" - etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] + """Signalement d'une absence. + + Args: + datedebut: dd/mm/yyyy + datefin: dd/mm/yyyy (non incluse) + moduleimpl_id: module auquel imputer les absences + demijournee: 2 si journée complète, 1 matin, 0 après-midi + estjust: absence justifiée + description: str + etudid: etudiant concerné. Si non spécifié, cherche dans REQUEST.form + """ + etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0] etudid = etud["etudid"] description_abs = description @@ -247,10 +258,25 @@ Raison: (optionnel) def doJustifAbsence( - context, datedebut, datefin, demijournee, description=None, REQUEST=None + context, + datedebut, + datefin, + demijournee, + description=None, + etudid=False, + REQUEST=None, ): # etudid implied - """Justification d'une absence""" - etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] + """Justification d'une absence + + Args: + datedebut: dd/mm/yyyy + datefin: dd/mm/yyyy (non incluse) + demijournee: 2 si journée complète, 1 matin, 0 après-midi + estjust: absence justifiée + description: str + etudid: etudiant concerné. Si non spécifié, cherche dans REQUEST.form + """ + etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0] etudid = etud["etudid"] description_abs = description dates = sco_abs.DateRangeISO(context, datedebut, datefin) @@ -370,10 +396,10 @@ Raison: (optionnel) def doAnnuleAbsence( - context, datedebut, datefin, demijournee, REQUEST=None + context, datedebut, datefin, demijournee, etudid=False, REQUEST=None ): # etudid implied """Annulation des absences pour une demi journée""" - etud = context.getEtudInfo(filled=1, REQUEST=REQUEST)[0] + etud = context.getEtudInfo(filled=1, etudid=etudid, REQUEST=REQUEST)[0] etudid = etud["etudid"] dates = sco_abs.DateRangeISO(context, datedebut, datefin) diff --git a/scotests/test_basic.py b/scotests/test_basic.py index fe1a9ad1..c98cb321 100644 --- a/scotests/test_basic.py +++ b/scotests/test_basic.py @@ -13,6 +13,8 @@ import random import scotests.sco_fake_gen as sco_fake_gen # pylint: disable=import-error import sco_utils +import sco_abs +import sco_abs_views G = sco_fake_gen.ScoFake(context.Notes) # pylint: disable=undefined-variable G.verbose = False @@ -64,3 +66,28 @@ for etud in etuds: nb_changed, nb_suppress, existing_decisions = G.create_note( evaluation=e, etud=etud, note=float(random.randint(0, 20)) ) + +# --- Saisie absences +etudid = etuds[0]["etudid"] + +_ = sco_abs_views.doSignaleAbsence( + context.Absences, + "15/01/2020", + "18/01/2020", + demijournee=2, + etudid=etudid, + REQUEST=REQUEST, +) + +_ = sco_abs_views.doJustifAbsence( + context.Absences, + "17/01/2020", + "18/01/2020", + demijournee=2, + etudid=etudid, + REQUEST=REQUEST, +) + +a = sco_abs.getAbsSemEtud(context.Absences, sem, etudid) +assert a.CountAbs() == 3 +assert a.CountAbsJust() == 1 From 6d17f030e25d67304a7a8ec5f41cda4d0715e96b Mon Sep 17 00:00:00 2001 From: IDK Date: Fri, 5 Feb 2021 18:21:34 +0100 Subject: [PATCH 08/18] removed old mxDateTime --- ZAbsences.py | 17 ++++++++--------- config/install_debian10.sh | 2 -- sco_abs_notification.py | 6 ++---- sco_archives.py | 5 ++--- sco_formsemestre_status.py | 1 - sco_liste_notes.py | 8 ++++---- sco_report.py | 16 +++++++--------- sco_utils.py | 4 ++-- 8 files changed, 25 insertions(+), 34 deletions(-) diff --git a/ZAbsences.py b/ZAbsences.py index 08cef678..9d44e344 100644 --- a/ZAbsences.py +++ b/ZAbsences.py @@ -44,17 +44,16 @@ L'API de plus bas niveau est en gros: """ -import urllib -import datetime -import jaxml -import cgi import string import re import time +import datetime +import dateutil +import dateutil.parser import calendar - -from mx.DateTime import DateTime as mxDateTime -from mx.DateTime.ISO import ParseDateTimeUTC +import urllib +import cgi +import jaxml # --------------- from sco_zope import * @@ -1542,8 +1541,8 @@ ou entrez une date pour visualiser les absents un jour donné : return scu.log_unknown_etud(self, REQUEST=REQUEST) etud = etuds[0] # check dates - begin_date = ParseDateTimeUTC(begin) # may raises ValueError - end_date = ParseDateTimeUTC(end) + begin_date = dateutil.parser.isoparse(begin) # may raises ValueError + end_date = dateutil.parser.isoparse(end) if begin_date > end_date: raise ValueError("invalid dates") # diff --git a/config/install_debian10.sh b/config/install_debian10.sh index 8e28134d..a7a6cd79 100755 --- a/config/install_debian10.sh +++ b/config/install_debian10.sh @@ -96,8 +96,6 @@ apt-get -y install python-cracklib # was python-crack apt-get -y install python-icalendar apt-get -y install python-requests -apt-get -y install python-egenix-mxtools python-egenix-mxdatetime - # ------------ SVNVERSION=$(cd ..; svnversion) diff --git a/sco_abs_notification.py b/sco_abs_notification.py index af9f1490..cc308057 100644 --- a/sco_abs_notification.py +++ b/sco_abs_notification.py @@ -226,10 +226,8 @@ def user_nbdays_since_last_notif(context, email_addr, etudid): ) res = cursor.dictfetchone() if res: - mxd = res["notification_date"] # mx.DateTime instance - lastdate = datetime.datetime(mxd.year, mxd.month, mxd.day) - now = datetime.datetime.now() - return (now - lastdate).days + now = datetime.datetime.now(res["notification_date"].tzinfo) + return (now - res["notification_date"]).days else: return None diff --git a/sco_archives.py b/sco_archives.py index fc50dc5d..987797a0 100644 --- a/sco_archives.py +++ b/sco_archives.py @@ -47,8 +47,7 @@ """ import os import time -from mx.DateTime import DateTime as mxDateTime -import mx.DateTime +import datetime import re import shutil import glob @@ -140,7 +139,7 @@ class BaseArchiver: def get_archive_date(self, archive_id): """Returns date (as a DateTime object) of an archive""" dt = [int(x) for x in os.path.split(archive_id)[1].split("-")] - return mxDateTime(*dt) + return datetime.datetime(*dt) def list_archive(self, archive_id): """Return list of filenames (without path) in archive""" diff --git a/sco_formsemestre_status.py b/sco_formsemestre_status.py index e71e4624..99267a29 100644 --- a/sco_formsemestre_status.py +++ b/sco_formsemestre_status.py @@ -29,7 +29,6 @@ """ # Rewritten from ancient DTML code -from mx.DateTime import DateTime as mxDateTime from notes_log import log import sco_utils as scu diff --git a/sco_liste_notes.py b/sco_liste_notes.py index 66dfbf61..55cd2e19 100644 --- a/sco_liste_notes.py +++ b/sco_liste_notes.py @@ -601,13 +601,13 @@ def _add_eval_columns( coefs[evaluation_id] = "coef. %s" % e["coefficient"] if note_sur_20: - nmx = 20.0 + nmax = 20.0 else: - nmx = e["note_max"] + nmax = e["note_max"] if keep_numeric: - note_max[evaluation_id] = nmx + note_max[evaluation_id] = nmax else: - note_max[evaluation_id] = "/ %s" % nmx + note_max[evaluation_id] = "/ %s" % nmax if nb_notes > 0: moys[evaluation_id] = "%.3g" % (sum_notes / nb_notes) diff --git a/sco_report.py b/sco_report.py index 55927dfa..ed795c53 100644 --- a/sco_report.py +++ b/sco_report.py @@ -34,9 +34,7 @@ import tempfile import urllib import re import time -import mx -import mx.DateTime -from mx.DateTime import DateTime as mxDateTime +import datetime import sco_utils as scu import VERSION @@ -435,8 +433,8 @@ def table_suivi_cohorte( # tri les semestres par date de debut for s in sems: d, m, y = [int(x) for x in s["date_debut"].split("/")] - s["date_debut_mx"] = mxDateTime(y, m, d) # pylint: disable=not-callable - sems.sort(lambda x, y: cmp(x["date_debut_mx"], y["date_debut_mx"])) + s["date_debut_dt"] = datetime.datetime(y, m, d) + sems.sort(lambda x, y: cmp(x["date_debut_dt"], y["date_debut_dt"])) # 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem logt("B: etuds sets") @@ -467,21 +465,21 @@ def table_suivi_cohorte( # semestre de depart: porigin = periodsem() d, m, y = [int(x) for x in sem["date_debut"].split("/")] - porigin.datedebut = mxDateTime(y, m, d) # pylint: disable=not-callable + porigin.datedebut = datetime.datetime(y, m, d) porigin.sems = [sem] # - tolerance = mx.DateTime.DateTimeDelta(45) # 45 days + tolerance = datetime.timedelta(days=45) for s in sems: merged = False for p in P: - if abs(s["date_debut_mx"] - p.datedebut) < tolerance: + if abs(s["date_debut_dt"] - p.datedebut) < tolerance: p.sems.append(s) merged = True break if not merged: p = periodsem() - p.datedebut = s["date_debut_mx"] + p.datedebut = s["date_debut_dt"] p.sems = [s] P.append(p) diff --git a/sco_utils.py b/sco_utils.py index 7c946d17..88c2a29a 100644 --- a/sco_utils.py +++ b/sco_utils.py @@ -543,15 +543,15 @@ class ScoDocJSONEncoder(json.JSONEncoder): def default(self, o): # pylint: disable=E0202 import sco_formsemestre - # horrible hack pour encoder les dates mx + # ScoDoc 7.22 n'utilise plus mx: if str(type(o)) == "": + log("Warning: mx.DateTime object detected !") return o.strftime("%Y-%m-%dT%H:%M:%S") if isinstance(o, (datetime.date, datetime.datetime)): return o.isoformat() elif isinstance(o, sco_formsemestre.ApoEtapeVDI): return str(o) else: - log("not mx: %s" % type(o)) return json.JSONEncoder.default(self, o) From de7d66e8e8333569dd418b6ac7059fa6d99c7f23 Mon Sep 17 00:00:00 2001 From: IDK Date: Fri, 5 Feb 2021 19:06:42 +0100 Subject: [PATCH 09/18] Fix: bug display selected students on export apo --- sco_etape_bilan.py | 11 ++++--- static/js/apo_semset_maq_status.js | 52 +++++++++++++++--------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/sco_etape_bilan.py b/sco_etape_bilan.py index 371cfc0b..7dcdcda8 100644 --- a/sco_etape_bilan.py +++ b/sco_etape_bilan.py @@ -90,6 +90,7 @@ l'inscrition de semestres décalés (S1 en septembre, ...). Le filtrage s'effctue sur la date et non plus sur la parité du semestre (1-3/2-4). """ +import json from sco_portal_apogee import get_inscrits_etape from notes_log import log @@ -540,7 +541,7 @@ class EtapeBilan: ind_col, comptage, "", - self.titres[ind_col].replace("
", " / "), + json.dumps(self.titres[ind_col].replace("
", " / "))[1:-1], ) elif ind_col == COL_CUMUL: javascript = "doFiltrage(%s, %s, '.%s', '*', '%s', '%s', '%s');" % ( @@ -548,7 +549,7 @@ class EtapeBilan: self.all_cols_str, ind_row, " (%d étudiants)" % count, - self.titres[ind_row], + json.dumps(self.titres[ind_row])[1:-1], "", ) else: @@ -558,10 +559,10 @@ class EtapeBilan: ind_row, ind_col, comptage, - self.titres[ind_row], - self.titres[ind_col].replace("
", " / "), + json.dumps(self.titres[ind_row])[1:-1], + json.dumps(self.titres[ind_col].replace("
", " / "))[1:-1], ) - return "%d" % (javascript, count) + return '%d' % (javascript, count) def _diagtable(self): H = [] diff --git a/static/js/apo_semset_maq_status.js b/static/js/apo_semset_maq_status.js index 3b2a3487..445bdf87 100644 --- a/static/js/apo_semset_maq_status.js +++ b/static/js/apo_semset_maq_status.js @@ -1,6 +1,6 @@ -$(function() { - $( "div#export_help" ).accordion( { +$(function () { + $("div#export_help").accordion({ heightStyle: "content", collapsible: true, active: false, @@ -21,8 +21,8 @@ function display(r, c, row, col) { function show_tag(all_rows, all_cols, tag) { // Filtrer tous les étudiants - all_rows.split(',').forEach(function(r) { - all_cols.split(',').forEach(function(c) { + all_rows.split(',').forEach(function (r) { + all_cols.split(',').forEach(function (c) { etudiants = r + c.substring(1); $(etudiants).css("display", "none"); }) @@ -34,36 +34,36 @@ function show_tag(all_rows, all_cols, tag) { function show_filtres(effectifs, filtre_row, filtre_col) { $("#compte").html(effectifs); if ((filtre_row == '') && (filtre_col == '')) { - $("#sans_filtre").css("display", ""); - $("#filtre_row").css("display", "none"); - $("#filtre_col").css("display", "none"); + $("#sans_filtre").css("display", ""); + $("#filtre_row").css("display", "none"); + $("#filtre_col").css("display", "none"); } else { - $("#sans_filtre").css("display", "none"); - if (filtre_row == '') { - $("#filtre_row").css("display", "none"); - $("#filtre_col").css("display", ""); - $("#filtre_col").html("Filtre sur code étape: " + filtre_col); - } else if (filtre_col == '') { - $("#filtre_row").css("display", ""); - $("#filtre_col").css("display", "none"); - $("#filtre_row").html("Filtre sur semestre: " + filtre_row); - } else { - $("#filtre_row").css("display", ""); - $("#filtre_col").css("display", ""); - $("#filtre_row").html("Filtre sur semestre: " + filtre_row); - $("#filtre_col").html("Filtre sur code étape: " + filtre_col); - } + $("#sans_filtre").css("display", "none"); + if (filtre_row == '') { + $("#filtre_row").css("display", "none"); + $("#filtre_col").css("display", ""); + $("#filtre_col").html("Filtre sur code étape: " + filtre_col); + } else if (filtre_col == '') { + $("#filtre_row").css("display", ""); + $("#filtre_col").css("display", "none"); + $("#filtre_row").html("Filtre sur semestre: " + filtre_row); + } else { + $("#filtre_row").css("display", ""); + $("#filtre_col").css("display", ""); + $("#filtre_row").html("Filtre sur semestre: " + filtre_row); + $("#filtre_col").html("Filtre sur code étape: " + filtre_col); + } } } function doFiltrage(all_rows, all_cols, row, col, effectifs, filtre_row, filtre_col) { show_filtres(effectifs, filtre_row, filtre_col) - all_rows.split(',').forEach(function(r) { - all_cols.split(',').forEach(function(c) { + all_rows.split(',').forEach(function (r) { + all_cols.split(',').forEach(function (c) { etudiants = r + c.substring(1); $(etudiants).css("display", display(r, c, row, col)); - }) - }) + }); + }); $('.repartition td').css("background-color", ""); $('.repartition th').css("background-color", ""); From c8c58e54c4d0a490a7a43ff283a03a7c8067d114 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 5 Feb 2021 21:34:26 +0100 Subject: [PATCH 10/18] Fix: controle affichage code et date naissance sur PV jury pdf --- sco_pvjury.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sco_pvjury.py b/sco_pvjury.py index b28a45ff..148ad1fb 100644 --- a/sco_pvjury.py +++ b/sco_pvjury.py @@ -675,10 +675,6 @@ def formsemestre_pvjury_pdf( tf[2]["showTitle"] = True else: tf[2]["showTitle"] = False - if tf[2]["with_paragraph_nom"]: - tf[2]["with_paragraph_nom"] = True - else: - tf[2]["with_paragraph_nom"] = False if tf[2]["anonymous"]: tf[2]["anonymous"] = True else: @@ -773,12 +769,10 @@ def descrform_pvjury(context, sem): ( "with_paragraph_nom", { - "input_type": "checkbox", + "input_type": "boolcheckbox", "title": "Avec date naissance et code", "explanation": "ajoute informations sous le nom", - "default": "1", - "labels": [""], - "allowed_values": ("1",), + "default": True, }, ), ( From 031c877afb899ed04b5aee21f06025af9d47e943 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Fri, 5 Feb 2021 21:35:21 +0100 Subject: [PATCH 11/18] pylint --- sco_edit_ue.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/sco_edit_ue.py b/sco_edit_ue.py index 758529f1..745a9920 100644 --- a/sco_edit_ue.py +++ b/sco_edit_ue.py @@ -206,7 +206,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): ) if parcours.UE_IS_MODULE: # dans ce mode, crée un (unique) module dans l'UE: - module_id = context.do_module_create( + _ = context.do_module_create( { "titre": tf[2]["titre"], "code": tf[2]["acronyme"], @@ -663,9 +663,7 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module ) #
  • (debug) Vérifier cohérence
  • - warn, ue_multiples = sco_formsemestre_validation.check_formation_ues( - context, formation_id - ) + warn, _ = sco_formsemestre_validation.check_formation_ues(context, formation_id) H.append(warn) H.append(context.sco_footer(REQUEST)) @@ -769,7 +767,6 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None): ues = context.do_ue_list(args={"ue_id": ue_id}) if not ues: return "ue invalide" - ue = ues[0] do_ue_edit( context, @@ -850,7 +847,9 @@ def formation_table_recap(context, formation_id, format="html", REQUEST=None): columns_ids=columns_ids, rows=T, titles=titles, - origin="Généré par %s le " % scu.VERSION.SCONAME + scu.timedate_human_repr() + "", + origin="Généré par %s le " % scu.VERSION.SCONAME + + scu.timedate_human_repr() + + "", caption=title, html_caption=title, html_class="table_leftalign", From 860ca5d8f7b55894610951da929f268601046aaf Mon Sep 17 00:00:00 2001 From: IDK Date: Fri, 5 Feb 2021 22:16:30 +0100 Subject: [PATCH 12/18] pylint --- TrivialFormulator.py | 10 ++----- VERSION.py | 6 +++- notesdb.py | 6 ++-- pe_settag.py | 2 +- pe_view.py | 2 +- sco_edit_module.py | 3 +- sco_parcours_dut.py | 32 +++++++++++++++++++-- sco_pvpdf.py | 67 ++++++++++++++++++++++++++------------------ sco_trombino.py | 26 +++++++++++------ scolog.py | 6 ++-- 10 files changed, 104 insertions(+), 56 deletions(-) diff --git a/TrivialFormulator.py b/TrivialFormulator.py index 788d95da..5cadf929 100644 --- a/TrivialFormulator.py +++ b/TrivialFormulator.py @@ -9,7 +9,7 @@ v 1.2 """ -from types import * +from types import BooleanType, StringType def TrivialFormulator( @@ -44,7 +44,7 @@ def TrivialFormulator( -1 cancel (if cancelbutton specified) HTML form: html string (form to insert in your web page) values: None or, when the form is submitted and correctly filled, - a dictionnary with the requeted values. + a dictionnary with the requeted values. formdescription: sequence [ (field, description), ... ] where description is a dict with following (optional) keys: default : default value for this field ('') @@ -63,7 +63,7 @@ def TrivialFormulator( withcheckbox: if true, place a checkbox at the left of the input elem. Checked items will be returned in 'tf-checked' attributes: a liste of strings to put in the HTML form element - template: HTML template for element + template: HTML template for element HTML elements: input_type : 'text', 'textarea', 'password', 'radio', 'menu', 'checkbox', @@ -368,9 +368,6 @@ class TF: idx = 0 for idx in range(len(self.formdescription)): (field, descr) = self.formdescription[idx] - nextitemname = None - if idx < len(self.formdescription) - 2: - nextitemname = self.formdescription[idx + 1][0] if descr.get("readonly", False): R.append(self._ReadOnlyElement(field, descr)) continue @@ -682,7 +679,6 @@ class TF: "Generate HTML for an element, read-only" R = [] title = descr.get("title", field.capitalize()) - withcheckbox = descr.get("withcheckbox", False) input_type = descr.get("input_type", "text") klass = descr.get("cssclass", "") klass = " " + klass diff --git a/VERSION.py b/VERSION.py index 68853baa..8e8a40a4 100644 --- a/VERSION.py +++ b/VERSION.py @@ -1,11 +1,15 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "7.21" +SCOVERSION = "7.22" SCONAME = "ScoDoc" SCONEWS = """ +

    Année 2021

    +
      +
    • Modernisation du code Python.
    • +

    Année 2020

    • Corrections d'erreurs, améliorations saise absences< et affichage bulletins
    • diff --git a/notesdb.py b/notesdb.py index fb073abf..5911978c 100644 --- a/notesdb.py +++ b/notesdb.py @@ -8,8 +8,8 @@ import psycopg2.pool import psycopg2.extras import thread from notes_log import log -from sco_exceptions import * -from types import * +from sco_exceptions import ScoException, ScoValueError, NoteProcessError +from types import StringType from cgi import escape import datetime @@ -175,7 +175,7 @@ def DBSelectArgs( cond = "" i = 1 cl = [] - for (aux_tab, aux_id) in aux_tables: + for (_, aux_id) in aux_tables: cl.append("T0.%s = T%d.%s" % (id_name, i, aux_id)) i = i + 1 cond += " and ".join(cl) diff --git a/pe_settag.py b/pe_settag.py index 38bfc566..7d46b7c6 100644 --- a/pe_settag.py +++ b/pe_settag.py @@ -36,7 +36,7 @@ Created on Fri Sep 9 09:15:05 2016 @author: barasc """ -from pe_tools import * +from pe_tools import pe_print, PE_DEBUG import pe_tagtable import pe_semestretag diff --git a/pe_view.py b/pe_view.py index a5dca1fd..39ee9758 100644 --- a/pe_view.py +++ b/pe_view.py @@ -44,7 +44,7 @@ from gen_tables import GenTable import sco_codes_parcours import pe_tools -from pe_tools import * +from pe_tools import PE_LATEX_ENCODING import pe_tagtable import pe_semestretag import pe_settag diff --git a/sco_edit_module.py b/sco_edit_module.py index a899cc0f..899f04f0 100644 --- a/sco_edit_module.py +++ b/sco_edit_module.py @@ -172,7 +172,7 @@ def module_create(context, matiere_id=None, REQUEST=None): if tf[0] == 0: return "\n".join(H) + tf[1] + context.sco_footer(REQUEST) else: - moduleid = context.do_module_create(tf[2], REQUEST) + context.do_module_create(tf[2], REQUEST) return REQUEST.RESPONSE.redirect( REQUEST.URL1 + "/ue_list?formation_id=" + UE["formation_id"] ) @@ -397,7 +397,6 @@ def edit_module_set_code_apogee(context, id=None, value=None, REQUEST=None): modules = context.do_module_list(args={"module_id": module_id}) if not modules: return "module invalide" # shoud not occur - module = modules[0] context.do_module_edit({"module_id": module_id, "code_apogee": value}) if not value: diff --git a/sco_parcours_dut.py b/sco_parcours_dut.py index 3bdaca8e..952ff6be 100644 --- a/sco_parcours_dut.py +++ b/sco_parcours_dut.py @@ -27,11 +27,37 @@ """Semestres: gestion parcours DUT (Arreté du 13 août 2005) """ +from types import FloatType + +import sco_utils as scu import notesdb as ndb from notes_log import log from scolog import logdb import sco_formsemestre -from sco_codes_parcours import * + +from sco_codes_parcours import ( + CMP, + ADC, + ADJ, + ADM, + AJ, + ATT, + NO_SEMESTRE_ID, + BUG, + NEXT, + NEXT2, + NEXT_OR_NEXT2, + REO, + REDOANNEE, + REDOSEM, + RA_OR_NEXT, + RA_OR_RS, + RS_OR_NEXT, + CODES_SEM_VALIDES, + NOTES_BARRE_GEN_COMPENSATION, + code_semestre_attente, + code_semestre_validant, +) from dutrules import DUTRules # regles generees a partir du CSV from sco_exceptions import ScoValueError @@ -166,7 +192,7 @@ class SituationEtudParcoursGeneric: if rule.conclusion[5] == BUG: log("get_possible_choices: inconsistency: state=%s" % str(state)) # - valid_semestre = code_semestre_validant(rule.conclusion[0]) + # valid_semestre = code_semestre_validant(rule.conclusion[0]) choices.append( DecisionSem( code_etat=rule.conclusion[0], @@ -391,7 +417,7 @@ class SituationEtudParcoursGeneric: ) self.moy_gen = self.nt.get_etud_moy_gen(self.etudid) self.barre_moy_ok = (type(self.moy_gen) == FloatType) and ( - self.moy_gen >= (self.parcours.BARRE_MOY - NOTES_TOLERANCE) + self.moy_gen >= (self.parcours.BARRE_MOY - scu.NOTES_TOLERANCE) ) # conserve etat UEs ue_ids = [ diff --git a/sco_pvpdf.py b/sco_pvpdf.py index 2a3d50bc..391e8c05 100644 --- a/sco_pvpdf.py +++ b/sco_pvpdf.py @@ -29,24 +29,37 @@ """ import os import types +import re +import cStringIO +import reportlab +from reportlab.lib.units import cm, mm +from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak +from reportlab.platypus import Table, TableStyle, Image, KeepInFrame +from reportlab.platypus.flowables import Flowable +from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate +from reportlab.lib.pagesizes import A4, landscape +from reportlab.lib import styles +from reportlab.lib.colors import Color -from sco_pdf import * import sco_utils as scu +import sco_pdf +from sco_pdf import SU import sco_formsemestre import sco_pvjury import sco_codes_parcours from sco_pdf import PDFLOCK import sco_preferences import sco_bulletins_pdf +import VERSION +LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER +LOGO_FOOTER_HEIGHT = scu.CONFIG.LOGO_FOOTER_HEIGHT * mm +LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * scu.CONFIG.LOGO_FOOTER_ASPECT -LOGO_FOOTER_ASPECT = CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER -LOGO_FOOTER_HEIGHT = CONFIG.LOGO_FOOTER_HEIGHT * mm -LOGO_FOOTER_WIDTH = LOGO_FOOTER_HEIGHT * CONFIG.LOGO_FOOTER_ASPECT - -LOGO_HEADER_ASPECT = CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER) -LOGO_HEADER_HEIGHT = CONFIG.LOGO_HEADER_HEIGHT * mm -LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * CONFIG.LOGO_HEADER_ASPECT +LOGO_HEADER_ASPECT = scu.CONFIG.LOGO_HEADER_ASPECT # XXX logo IUTV (A AUTOMATISER) +LOGO_HEADER_HEIGHT = scu.CONFIG.LOGO_HEADER_HEIGHT * mm +LOGO_HEADER_WIDTH = LOGO_HEADER_HEIGHT * scu.CONFIG.LOGO_HEADER_ASPECT def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True): @@ -76,7 +89,7 @@ def pageFooter(canvas, doc, logo, preferences, with_page_numbers=True): RightFootStyle.fontSize = preferences["SCOLAR_FONT_SIZE_FOOT"] RightFootStyle.alignment = TA_RIGHT - p = makeParas( + p = sco_pdf.makeParas( """%s%s""" % (preferences["INSTITUTION_NAME"], preferences["INSTITUTION_ADDRESS"]), LeftFootStyle, @@ -186,12 +199,12 @@ class CourrierIndividuelTemplate(PageTemplate): self.background_image_filename = None self.logo_footer = None self.logo_header = None - # Search logos in dept specific dir, then in global config dir + # Search logos in dept specific dir, then in global scu.CONFIG dir for image_dir in ( - SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/", - SCODOC_LOGOS_DIR + "/", # global logos + scu.SCODOC_LOGOS_DIR + "/logos_" + context.DeptId() + "/", + scu.SCODOC_LOGOS_DIR + "/", # global logos ): - for suffix in LOGOS_IMAGES_ALLOWED_TYPES: + for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES: if template_name == "PVJuryTemplate": fn = image_dir + "/pvjury_background" + "." + suffix else: @@ -377,7 +390,7 @@ def pdf_lettres_individuelles( CourrierIndividuelTemplate( document, context=context, - author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION), + author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION), title="Lettres décision %s" % sem["titreannee"], subject="Décision jury", margins=margins, @@ -514,7 +527,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context % params ) sig = _simulate_br(sig, '') - objects += makeParas( + objects += sco_pdf.makeParas( ( """""" + sig @@ -529,7 +542,7 @@ def pdf_lettre_individuelle(sem, decision, etud, params, signature=None, context % params ) sig = _simulate_br(sig, '') - objects += makeParas( + objects += sco_pdf.makeParas( ( """""" + sig @@ -650,7 +663,7 @@ def pvjury_pdf( PVTemplate( document, context=context, - author="%s %s (E. Viennet)" % (SCONAME, SCOVERSION), + author="%s %s (E. Viennet)" % (VERSION.SCONAME, VERSION.SCOVERSION), title=SU("PV du jury de %s" % sem["titre_num"]), subject="PV jury", preferences=context.get_preferences(formsemestre_id), @@ -683,7 +696,7 @@ def _pvjury_pdf_type( sem = dpv["formsemestre"] formsemestre_id = sem["formsemestre_id"] - titre_jury, titre_court_jury = _descr_jury(sem, diplome) + titre_jury, _ = _descr_jury(sem, diplome) titre_diplome = pv_title or dpv["formation"]["titre_officiel"] objects = [] @@ -708,7 +721,7 @@ def _pvjury_pdf_type( bulletStyle.spaceAfter = 5 * mm objects += [Spacer(0, 5 * mm)] - objects += makeParas( + objects += sco_pdf.makeParas( """ Procès-verbal de %s du département %s - Session unique %s """ @@ -720,7 +733,7 @@ def _pvjury_pdf_type( style, ) - objects += makeParas( + objects += sco_pdf.makeParas( """ %s """ @@ -729,20 +742,20 @@ def _pvjury_pdf_type( ) if showTitle: - objects += makeParas( + objects += sco_pdf.makeParas( """Semestre: %s""" % sem["titre"], style ) if context.get_preference("PV_TITLE_WITH_VDI", formsemestre_id): - objects += makeParas( + objects += sco_pdf.makeParas( """VDI et Code: %s""" % (VDICode or ""), style ) if date_jury: - objects += makeParas( + objects += sco_pdf.makeParas( """Jury tenu le %s""" % date_jury, style ) - objects += makeParas( + objects += sco_pdf.makeParas( "" + context.get_preference("PV_INTRO", formsemestre_id) % { @@ -757,7 +770,7 @@ def _pvjury_pdf_type( bulletStyle, ) - objects += makeParas( + objects += sco_pdf.makeParas( """Le jury propose les décisions suivantes :""", style ) objects += [Spacer(0, 4 * mm)] @@ -809,7 +822,7 @@ def _pvjury_pdf_type( objects.append(Table(Pt, repeatRows=1, colWidths=widths, style=table_style)) # Signature du directeur - objects += makeParas( + objects += sco_pdf.makeParas( """ Le %s, %s""" % ( @@ -822,7 +835,7 @@ def _pvjury_pdf_type( # Légende des codes codes = sco_codes_parcours.CODES_EXPL.keys() codes.sort() - objects += makeParas( + objects += sco_pdf.makeParas( """ Codes utilisés :""", style, diff --git a/sco_trombino.py b/sco_trombino.py index 416e84af..b529ea77 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -28,16 +28,27 @@ """Photos: trombinoscopes """ -try: - from cStringIO import StringIO -except: - from StringIO import StringIO +from cStringIO import StringIO from zipfile import ZipFile, BadZipfile import xml import tempfile +import reportlab +from reportlab.lib.units import cm, mm +from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak +from reportlab.platypus import Table, TableStyle, Image, KeepInFrame +from reportlab.platypus.flowables import Flowable +from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate +from reportlab.lib.pagesizes import A4, landscape +from reportlab.lib import styles +from reportlab.lib.colors import Color +from reportlab.lib import colors +from PIL import Image as PILImage from notes_log import log import sco_utils as scu +import sco_pdf +from sco_pdf import SU from sco_exceptions import ScoValueError from TrivialFormulator import TrivialFormulator import scolars @@ -47,11 +58,8 @@ import sco_groups import sco_groups_view import sco_portal_apogee import htmlutils -from sco_pdf import * import ImportScolars import sco_excel -from reportlab.lib import colors -from PIL import Image as PILImage def trombino( @@ -368,7 +376,7 @@ def _trombino_pdf(context, groups_infos, REQUEST): # Build document document = BaseDocTemplate(report) document.addPageTemplates( - ScolarsPageTemplate( + sco_pdf.ScolarsPageTemplate( document, context=context, preferences=context.get_preferences(sem["formsemestre_id"]), @@ -451,7 +459,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): # Build document document = BaseDocTemplate(report) document.addPageTemplates( - ScolarsPageTemplate( + sco_pdf.ScolarsPageTemplate( document, context, preferences=context.get_preferences(sem["formsemestre_id"]), diff --git a/scolog.py b/scolog.py index 1ee852da..6ce6e542 100644 --- a/scolog.py +++ b/scolog.py @@ -26,8 +26,10 @@ ############################################################################## -import pdb, os, sys -from sco_exceptions import * +import pdb +import os +import sys + import notesdb as ndb from notes_log import retreive_request From 154e7bf3e8a80822a6d8ab970165c4b160383189 Mon Sep 17 00:00:00 2001 From: IDK Date: Sun, 7 Feb 2021 09:10:26 +0100 Subject: [PATCH 13/18] Replaced Zope URL1 and URL2 --- ImportScolars.py | 2 +- ZAbsences.py | 6 +-- ZEntreprises.py | 46 ++++++++++---------- ZNotes.py | 10 +++-- ZScoDoc.py | 5 +-- ZScoUsers.py | 21 +++++---- ZScolar.py | 78 ++++++++++++++++++++++++++-------- debug.py | 1 - sco_archives_etud.py | 8 +++- sco_edit_formation.py | 8 ++-- sco_edit_matiere.py | 12 +++--- sco_edit_module.py | 6 +-- sco_edit_ue.py | 2 +- sco_formsemestre_custommenu.py | 9 ++-- sco_formsemestre_edit.py | 28 ++++++------ sco_groups.py | 7 +-- sco_placement.py | 4 +- sco_preferences.py | 18 ++++---- 18 files changed, 160 insertions(+), 111 deletions(-) diff --git a/ImportScolars.py b/ImportScolars.py index 4502abd3..8e06e93c 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -239,7 +239,7 @@ def students_import_excel( if formsemestre_id: dest = "formsemestre_status?formsemestre_id=%s" % formsemestre_id else: - dest = REQUEST.URL1 + dest = context.NotesURL() H = [context.sco_header(REQUEST, page_title="Import etudiants")] H.append("
        ") for d in diag: diff --git a/ZAbsences.py b/ZAbsences.py index 9d44e344..c67857c2 100644 --- a/ZAbsences.py +++ b/ZAbsences.py @@ -56,7 +56,7 @@ import cgi import jaxml # --------------- -from sco_zope import * +from sco_zope import * # pylint: disable=unused-wildcard-import # --------------- import sco_utils as scu @@ -1604,7 +1604,7 @@ ou entrez une date pour visualiser les absents un jour donné : if tf[0] == 0: return "\n".join(H) + tf[1] + self.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.ScoURL()) else: e = tf[2]["begin"].split("/") begin = e[2] + "-" + e[1] + "-" + e[0] + " 00:00:00" @@ -1865,7 +1865,7 @@ ou entrez une date pour visualiser les absents un jour donné : return "\n".join(H) + "
        " + tf[1] + F + self.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.ScoURL()) else: n = self._ProcessBilletAbsence( billet, tf[2]["estjust"], tf[2]["description"], REQUEST diff --git a/ZEntreprises.py b/ZEntreprises.py index 9df285a1..3da1ea12 100644 --- a/ZEntreprises.py +++ b/ZEntreprises.py @@ -296,7 +296,7 @@ class ZEntreprises( c[ "_date_target" ] = "%s/entreprise_contact_edit?entreprise_contact_id=%s" % ( - REQUEST.URL1, + self.EntreprisesURL(), c["entreprise_contact_id"], ) c["entreprise"] = sco_entreprises.do_entreprise_list( @@ -306,7 +306,7 @@ class ZEntreprises( c["etud"] = self.getEtudInfo(etudid=c["etudid"], filled=1)[0] c["etudnom"] = c["etud"]["nomprenom"] c["_etudnom_target"] = "%s/ficheEtud?etudid=%s" % ( - REQUEST.URL1, + self.ScoURL(), c["etudid"], ) else: @@ -374,7 +374,7 @@ class ZEntreprises( c[ "_nomprenom_target" ] = "%s/entreprise_correspondant_edit?entreprise_corresp_id=%s" % ( - REQUEST.URL1, + self.EntreprisesURL(), c["entreprise_corresp_id"], ) @@ -462,7 +462,7 @@ class ZEntreprises( )[0] link_create_corr = ( 'créer un nouveau correspondant' - % (REQUEST.URL1, c["entreprise_id"]) + % (self.EntreprisesURL(), c["entreprise_id"]) ) E = sco_entreprises.do_entreprise_list( self, args={"entreprise_id": c["entreprise_id"]} @@ -562,7 +562,7 @@ class ZEntreprises( % entreprise_contact_id ) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: etudok = sco_entreprises.do_entreprise_check_etudiant( self, tf[2]["etudiant"] @@ -573,7 +573,7 @@ class ZEntreprises( tf[2].update({"etudid": etudok[1]}) sco_entreprises.do_entreprise_contact_edit(self, tf[2]) REQUEST.RESPONSE.redirect( - REQUEST.URL1 + self.EntreprisesURL() + "/entreprise_contact_list?entreprise_id=" + str(c["entreprise_id"]) ) @@ -682,13 +682,13 @@ class ZEntreprises( elif tf[0] == -1: REQUEST.RESPONSE.redirect( "%s/entreprise_correspondant_list?entreprise_id=%s" - % (REQUEST.URL1, c["entreprise_id"]) + % (self.EntreprisesURL(), c["entreprise_id"]) ) else: sco_entreprises.do_entreprise_correspondant_edit(self, tf[2]) REQUEST.RESPONSE.redirect( "%s/entreprise_correspondant_list?entreprise_id=%s" - % (REQUEST.URL1, c["entreprise_id"]) + % (self.EntreprisesURL(), c["entreprise_id"]) ) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -708,7 +708,7 @@ class ZEntreprises( curtime = time.strftime("%d/%m/%Y") link_create_corr = ( 'créer un nouveau correspondant' - % (REQUEST.URL1, entreprise_id) + % (self.EntreprisesURL(), entreprise_id) ) H = [ entreprise_header(self, REQUEST=REQUEST, page_title="Suivi entreprises"), @@ -789,7 +789,7 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: etudok = sco_entreprises.do_entreprise_check_etudiant( self, tf[2]["etudiant"] @@ -799,7 +799,7 @@ class ZEntreprises( else: tf[2].update({"etudid": etudok[1]}) sco_entreprises.do_entreprise_contact_create(self, tf[2]) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -828,12 +828,12 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_contact_delete( self, c["entreprise_contact_id"] ) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -935,10 +935,10 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_correspondant_create(self, tf[2]) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -967,12 +967,12 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_correspondant_delete( self, c["entreprise_corresp_id"] ) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -1025,10 +1025,10 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_delete(self, E["entreprise_id"]) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -1120,10 +1120,10 @@ class ZEntreprises( if tf[0] == 0: return "\n".join(H) + tf[1] + entreprise_footer(self, REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_create(self, tf[2]) - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) security.declareProtected(ScoEntrepriseView, "entreprise_edit") @@ -1295,7 +1295,7 @@ class ZEntreprises( H.append("
      ") return "\n".join(H) + entreprise_footer(self, REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start) else: sco_entreprises.do_entreprise_edit(self, tf[2]) - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "?start=" + start) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL() + "?start=" + start) diff --git a/ZNotes.py b/ZNotes.py index bc8b54d6..553f3538 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -257,10 +257,12 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl sco_formsemestre_edit.formsemestre_createwithmodules ) - security.declareProtected(ScoView, "formsemestre_editwithmodules") + security.declareProtected( + ScoView, "formsemestre_editwithmodules" + ) # controle d'acces specifique pour dir. etud formsemestre_editwithmodules = sco_formsemestre_edit.formsemestre_editwithmodules - security.declareProtected(ScoView, "formsemestre_clone") + security.declareProtected(ScoImplement, "formsemestre_clone") formsemestre_clone = sco_formsemestre_edit.formsemestre_clone security.declareProtected(ScoChangeFormation, "formsemestre_associate_new_version") @@ -521,7 +523,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl if tf[0] == 0: return "\n".join(H) + tf[1] + footer elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.NotesURL()) else: formation_id, _, _ = self.formation_import_xml(tf[2]["xmlfile"], REQUEST) @@ -675,7 +677,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl # if not force: return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "/ue_list?formation_id=" + str(ue["formation_id"]) + self.NotesURL() + "/ue_list?formation_id=" + str(ue["formation_id"]) ) else: return None diff --git a/ZScoDoc.py b/ZScoDoc.py index 56204368..3de841af 100644 --- a/ZScoDoc.py +++ b/ZScoDoc.py @@ -335,8 +335,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp return ( "

      Département " + DeptId - + """ supprimé du serveur web (la base de données n'est pas affectée)!

      Continuer

      """ - % REQUEST.URL1 + + """ supprimé du serveur web (la base de données n'est pas affectée)!

      Continuer

      """ ) _top_level_css = """ @@ -973,5 +972,5 @@ def manage_addZScoDoc(self, id="ScoDoc", title="Site ScoDoc", REQUEST=None): ) # ne cree (presque rien), tout se passe lors du 1er accès self._setObject(id, zscodoc) if REQUEST is not None: - REQUEST.RESPONSE.redirect("%s/manage_workspace" % REQUEST.URL1) + REQUEST.RESPONSE.redirect("/ScoDoc/manage_workspace") return id diff --git a/ZScoUsers.py b/ZScoUsers.py index 64355f43..2550bb4f 100644 --- a/ZScoUsers.py +++ b/ZScoUsers.py @@ -792,11 +792,12 @@ class ZScoUsers( descr, initvalues=initvalues, submitlabel=submitlabel, + cancelbutton="Annuler", ) if tf[0] == 0: return "\n".join(H) + "\n" + tf[1] + F elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.UsersURL()) else: vals = tf[2] roles = set(vals["roles"]).intersection(editable_roles) @@ -997,7 +998,7 @@ class ZScoUsers( if tf[0] == 0: return "\n".join(H) + tf[1] + "" + help + F elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.UsersURL()) else: # IMPORT diag = sco_import_users.import_excel_file( @@ -1006,7 +1007,9 @@ class ZScoUsers( H = [head] H.append("

      Import excel: %s

      " % diag) H.append("

      OK, import terminé !

      ") - H.append('

      Continuer

      ' % REQUEST.URL1) + H.append( + '

      Continuer

      ' % self.UsersURL() + ) return "\n".join(H) + help + F security.declareProtected(ScoUsersAdmin, "import_users_generate_excel_sample") @@ -1037,7 +1040,7 @@ class ZScoUsers( ) if REQUEST: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(self.UsersURL()) security.declareProtected(ScoUsersAdmin, "delete_user_form") @@ -1065,11 +1068,13 @@ class ZScoUsers( % user_name, dest_url="", REQUEST=REQUEST, - cancel_url=REQUEST.URL1, + cancel_url=self.UsersURL(), parameters={"user_name": user_name}, ) self._user_delete(user_name) - REQUEST.RESPONSE.redirect(REQUEST.URL1) + REQUEST.RESPONSE.redirect( + self.UsersURL() + r"?head_message=Utilisateur%20supprimé" + ) security.declareProtected(ScoView, "list_users") @@ -1260,8 +1265,8 @@ Il devra ensuite se connecter et le changer. ) self.reset_password(user_name=user_name, REQUEST=REQUEST) return REQUEST.RESPONSE.redirect( - REQUEST.URL1 - + "?head_message=mot%20de%20passe%20de%20" + self.UsersURL() + + r"?head_message=mot%20de%20passe%20de%20" + user_name + "%20reinitialise" ) diff --git a/ZScolar.py b/ZScolar.py index 314b9bb2..0537b67e 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -294,11 +294,16 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp

      -UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo VRTU11) -[verrouillé] + +REQUEST.URL=%s
      +REQUEST.URL0=%s
      +

      - """ + """ % ( + REQUEST.URL, + REQUEST.URL0, + ) # return ( # self.sco_header(REQUEST) # + """
      %s
      """ % x @@ -315,7 +320,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo Erreur:' + diag + "

      ") return "\n".join(H) + self.sco_footer(REQUEST) @@ -1350,7 +1381,7 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo (code UCOD46, 16 ECTS, Apo - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect( + self.ScoURL() + r"?head_message=Etudiant%20supprimé" + ) security.declareProtected(ScoEtudInscrit, "check_group_apogee") @@ -2210,8 +2243,13 @@ UE11 Découverte métiers (code UCOD46, 16 ECTS, Apo " + "\n".join(S) + F elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(dest_url) else: return ImportScolars.students_import_excel( self, @@ -2464,7 +2502,11 @@ Les champs avec un astérisque (*) doivent être présents (nulls non autorisés if tf[0] == 0: return "\n".join(H) + tf[1] + help_text + F elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect( + self.ScoURL() + + "/formsemestre_status?formsemestre_id=" + + formsemestre_id + ) else: return self._students_import_admission( tf[2]["csvfile"], @@ -2673,7 +2715,7 @@ def manage_addZScolarForm(context, DeptId, REQUEST=None): if tf[0] == 0: return "\n".join(H) + tf[1] + context.standard_html_footer(context) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect("/ScoDoc") else: DeptId = tf[2]["DeptId"].strip() db_cnx_string = tf[2]["db_cnx_string"].strip() diff --git a/debug.py b/debug.py index d0b8a4dd..52a31f7a 100644 --- a/debug.py +++ b/debug.py @@ -109,7 +109,6 @@ class DummyRequest: self.AUTHENTICATED_USER = FakeUser("admin") self.form = {} self.URL = "http://scodoc/" - self.URL1 = self.URL self.URL0 = self.URL self.BASE0 = "localhost" self.REMOTE_HOST = "localhost" diff --git a/sco_archives_etud.py b/sco_archives_etud.py index 25abb068..0d69bfe6 100644 --- a/sco_archives_etud.py +++ b/sco_archives_etud.py @@ -164,7 +164,9 @@ def etud_upload_file_form(context, REQUEST, etudid): if tf[0] == 0: return "\n".join(H) + tf[1] + context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/ficheEtud?etudid=" + etudid) + return REQUEST.RESPONSE.redirect( + context.NotesURL() + "/ficheEtud?etudid=" + etudid + ) else: data = tf[2]["datafile"].read() descr = tf[2]["description"] @@ -172,7 +174,9 @@ def etud_upload_file_form(context, REQUEST, etudid): _store_etud_file_to_new_archive( context, REQUEST, etudid, data, filename, description=descr ) - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/ficheEtud?etudid=" + etudid) + return REQUEST.RESPONSE.redirect( + context.NotesURL() + "/ficheEtud?etudid=" + etudid + ) def _store_etud_file_to_new_archive( diff --git a/sco_edit_formation.py b/sco_edit_formation.py index 84fde691..6d249230 100644 --- a/sco_edit_formation.py +++ b/sco_edit_formation.py @@ -62,7 +62,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST '
    • %(titremois)s
    • ' % sem ) - H.append('

    Revenir

    ' % REQUEST.URL1) + H.append('

    Revenir

    ' % context.NotesURL()) else: if not dialog_confirmed: return context.confirmDialog( @@ -73,7 +73,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST % F, REQUEST=REQUEST, OK="Supprimer cette formation", - cancel_url=REQUEST.URL1, + cancel_url=context.NotesURL(), parameters={"formation_id": formation_id}, ) else: @@ -81,7 +81,7 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST H.append( """

    OK, formation supprimée.

    continuer

    """ - % REQUEST.URL1 + % context.NotesURL() ) H.append(context.sco_footer(REQUEST)) @@ -191,7 +191,7 @@ def formation_edit(context, formation_id=None, create=False, REQUEST=None): if tf[0] == 0: return "\n".join(H) + tf[1] + context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(context.NotesURL()) else: # check unicity : constraint UNIQUE(acronyme,titre,version) if create: diff --git a/sco_edit_matiere.py b/sco_edit_matiere.py index a0eec6f6..98a86dfe 100644 --- a/sco_edit_matiere.py +++ b/sco_edit_matiere.py @@ -75,7 +75,7 @@ associé. submitlabel="Créer cette matière", ) - dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + UE["formation_id"] + dest_url = context.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"] if tf[0] == 0: return "\n".join(H) + tf[1] + context.sco_footer(REQUEST) @@ -104,7 +104,7 @@ def matiere_delete(context, matiere_id=None, REQUEST=None): "

    Suppression de la matière %(titre)s" % M, " dans l'UE (%(acronyme)s))

    " % UE, ] - + dest_url = context.NotesURL() + "/ue_list?formation_id=" + str(UE["formation_id"]) tf = TrivialFormulator( REQUEST.URL0, REQUEST.form, @@ -116,12 +116,10 @@ def matiere_delete(context, matiere_id=None, REQUEST=None): if tf[0] == 0: return "\n".join(H) + tf[1] + context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(dest_url) else: context.do_matiere_delete(matiere_id, REQUEST) - return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "/ue_list?formation_id=" + str(UE["formation_id"]) - ) + return REQUEST.RESPONSE.redirect(dest_url) def matiere_edit(context, matiere_id=None, REQUEST=None): @@ -181,7 +179,7 @@ associé. submitlabel="Modifier les valeurs", ) - dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + U["formation_id"] + dest_url = context.NotesURL() + "/ue_list?formation_id=" + U["formation_id"] if tf[0] == 0: return "\n".join(H) + tf[1] + help + context.sco_footer(REQUEST) diff --git a/sco_edit_module.py b/sco_edit_module.py index 899f04f0..54ab900b 100644 --- a/sco_edit_module.py +++ b/sco_edit_module.py @@ -174,7 +174,7 @@ def module_create(context, matiere_id=None, REQUEST=None): else: context.do_module_create(tf[2], REQUEST) return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "/ue_list?formation_id=" + UE["formation_id"] + context.NotesURL() + "/ue_list?formation_id=" + UE["formation_id"] ) @@ -191,7 +191,7 @@ def module_delete(context, module_id=None, REQUEST=None): """

    Suppression du module %(titre)s (%(code)s)

    """ % Mod, ] - dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + Mod["formation_id"] + dest_url = context.NotesURL() + "/ue_list?formation_id=" + Mod["formation_id"] tf = TrivialFormulator( REQUEST.URL0, REQUEST.form, @@ -240,7 +240,7 @@ def module_edit(context, module_id=None, REQUEST=None): semestres_indices = range(1, parcours.NB_SEM + 1) - dest_url = REQUEST.URL1 + "/ue_list?formation_id=" + Mod["formation_id"] + dest_url = context.NotesURL() + "/ue_list?formation_id=" + Mod["formation_id"] H = [ context.sco_header( diff --git a/sco_edit_ue.py b/sco_edit_ue.py index 745a9920..8aaf3737 100644 --- a/sco_edit_ue.py +++ b/sco_edit_ue.py @@ -221,7 +221,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None): else: do_ue_edit(context, tf[2]) return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "/ue_list?formation_id=" + formation_id + context.NotesURL() + "/ue_list?formation_id=" + formation_id ) diff --git a/sco_formsemestre_custommenu.py b/sco_formsemestre_custommenu.py index 3b3a38ab..72e44bd4 100644 --- a/sco_formsemestre_custommenu.py +++ b/sco_formsemestre_custommenu.py @@ -80,6 +80,9 @@ def formsemestre_custommenu_html(context, formsemestre_id, base_url=""): def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): """Dialog to edit the custom menu""" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) + dest_url = ( + context.NotesURL() + "formsemestre_status?formsemestre_id=%s" % formsemestre_id + ) H = [ context.html_sem_header(REQUEST, "Modification du menu du semestre ", sem), """

    Ce menu, spécifique à chaque semestre, peut être utilisé pour placer des liens vers vos applications préférées.

    @@ -126,7 +129,7 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): if tf[0] == 0: return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(dest_url) else: # form submission cnx = context.GetDBConnexion() @@ -153,6 +156,4 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): "url": tf[2]["url_" + custommenu_id], }, ) - REQUEST.RESPONSE.redirect( - "formsemestre_status?formsemestre_id=%s" % formsemestre_id - ) + REQUEST.RESPONSE.redirect(dest_url) diff --git a/sco_formsemestre_edit.py b/sco_formsemestre_edit.py index 2a05e2f5..556b5121 100644 --- a/sco_formsemestre_edit.py +++ b/sco_formsemestre_edit.py @@ -72,9 +72,7 @@ def formsemestre_createwithmodules(context, REQUEST=None): def formsemestre_editwithmodules(context, REQUEST, formsemestre_id): """Page modification semestre""" # portage from dtml - authuser = REQUEST.AUTHENTICATED_USER sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] H = [ context.html_sem_header( REQUEST, @@ -711,7 +709,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False): "formsemestre_id": formsemestre_id, "responsable_id": tf[2][module_id], } - mid = sco_moduleimpl.do_moduleimpl_create(context, modargs) + _ = sco_moduleimpl.do_moduleimpl_create(context, modargs) return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=%s&head_message=Nouveau%%20semestre%%20créé" % formsemestre_id @@ -848,7 +846,6 @@ def formsemestre_clone(context, formsemestre_id, REQUEST=None): """ Formulaire clonage d'un semestre """ - authuser = REQUEST.AUTHENTICATED_USER sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # Liste des enseignants avec forme pour affichage / saisie avec suggestion userlist = context.Users.get_userlist() @@ -1019,7 +1016,7 @@ def do_formsemestre_clone( args = e.copy() del args["jour"] # erase date args["moduleimpl_id"] = mid - evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **args) + _ = context.do_evaluation_create(REQUEST=REQUEST, **args) # 3- copy uecoefs objs = sco_formsemestre.formsemestre_uecoef_list( @@ -1028,7 +1025,7 @@ def do_formsemestre_clone( for obj in objs: args = obj.copy() args["formsemestre_id"] = formsemestre_id - c = sco_formsemestre.formsemestre_uecoef_create(cnx, args) + _ = sco_formsemestre.formsemestre_uecoef_create(cnx, args) # NB: don't copy notes_formsemestre_custommenu (usually specific) @@ -1051,7 +1048,7 @@ def do_formsemestre_clone( for obj in objs: args = obj.copy() args["formsemestre_id"] = formsemestre_id - c = sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, args) + _ = sco_compute_moy.formsemestre_ue_computation_expr_create(cnx, args) # 5- Copy partitions if clone_partitions: @@ -1061,7 +1058,6 @@ def do_formsemestre_clone( for part in sco_groups.get_partitions_list(context, orig_formsemestre_id): if part["partition_name"] != None: partname = part["partition_name"] - orig_partition_id = part["partition_id"] new_partition_id = sco_groups.partition_create( context, formsemestre_id, @@ -1081,7 +1077,7 @@ def do_formsemestre_clone( if newpart["partition_id"] == g[0]: part_id = g[0] for group_name in g[1]: - group_id = sco_groups.createGroup( + _ = sco_groups.createGroup( context, part_id, group_name=group_name, REQUEST=REQUEST ) @@ -1263,7 +1259,11 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None): H.append(tf[1]) return "\n".join(H) + context.sco_footer(REQUEST) elif tf[0] == -1: # cancel - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect( + context.NotesURL() + + "formsemestre_status?formsemestre_id=" + + formsemestre_id + ) else: return REQUEST.RESPONSE.redirect( "formsemestre_delete2?formsemestre_id=" + formsemestre_id @@ -1274,9 +1274,6 @@ def formsemestre_delete2( context, formsemestre_id, dialog_confirmed=False, REQUEST=None ): """Delete a formsemestre (confirmation)""" - sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] - H = [context.html_sem_header(REQUEST, "Suppression du semestre", sem)] # Confirmation dialog if not dialog_confirmed: return context.confirmDialog( @@ -1288,7 +1285,9 @@ def formsemestre_delete2( ) # Bon, s'il le faut... do_formsemestre_delete(context, formsemestre_id, REQUEST) - return REQUEST.RESPONSE.redirect(REQUEST.URL2 + "?head_message=Semestre%20supprimé") + return REQUEST.RESPONSE.redirect( + context.ScoURL() + "?head_message=Semestre%20supprimé" + ) def formsemestre_has_decisions_or_compensations(context, formsemestre_id): @@ -1491,7 +1490,6 @@ def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST= if not ok: return err sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - F = context.formation_list(args={"formation_id": sem["formation_id"]})[0] footer = context.sco_footer(REQUEST) help = """

    diff --git a/sco_groups.py b/sco_groups.py index 26a2e677..c4746f60 100644 --- a/sco_groups.py +++ b/sco_groups.py @@ -1185,6 +1185,8 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None): """ partition = get_partition(context, partition_id) formsemestre_id = partition["formsemestre_id"] + # renvoie sur page édition groupes + dest_url = "affectGroups?partition_id=%s" % partition_id if not can_change_groups(context, REQUEST, formsemestre_id): raise AccessDenied("Vous n'avez pas le droit d'effectuer cette opération !") sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) @@ -1225,7 +1227,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None): if tf[0] == 0: return "\n".join(H) + "\n" + tf[1] + context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) + return REQUEST.RESPONSE.redirect(dest_url) else: # form submission log( @@ -1279,8 +1281,7 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None): context, etudid, group_id, partition, REQUEST=REQUEST ) log("%s in group %s" % (etudid, group_id)) - # envoie sur page edition groupes - return REQUEST.RESPONSE.redirect("affectGroups?partition_id=%s" % partition_id) + return REQUEST.RESPONSE.redirect(dest_url) def get_prev_moy(context, etudid, formsemestre_id): diff --git a/sco_placement.py b/sco_placement.py index 3c50b19f..9487db08 100644 --- a/sco_placement.py +++ b/sco_placement.py @@ -217,7 +217,9 @@ def do_placement_selectetuds(context, REQUEST): ) + "&".join(gs) ) - return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query) + return REQUEST.RESPONSE.redirect( + context.NotesURL() + "/do_placement?" + query + ) else: raise ValueError( "invalid placement_method (%s)" % tf[2]["placement_method"] diff --git a/sco_preferences.py b/sco_preferences.py index d7bb3ed3..49b29ff9 100644 --- a/sco_preferences.py +++ b/sco_preferences.py @@ -1943,13 +1943,13 @@ class sco_base_preferences: if tf[0] == 0: return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST) elif tf[0] == -1: - return REQUEST.RESPONSE.redirect(REQUEST.URL1) # cancel + return REQUEST.RESPONSE.redirect(self.context.ScoURL()) # cancel else: for pref in PREFS: self.prefs[None][pref[0]] = tf[2][pref[0]] self.save() return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "?head_message=Préférences modifiées" + self.context.ScoURL() + "?head_message=Préférences modifiées" ) @@ -1991,7 +1991,6 @@ class sem_preferences: # The dialog def edit(self, categories=[], REQUEST=None): """Dialog to edit semestre preferences in given categories""" - # log('XXX edit') if not self.formsemestre_id: raise ScoValueError( "sem_preferences.edit doit etre appele sur un semestre !" @@ -2038,7 +2037,6 @@ function set_global_pref(el, pref_name) { form.append(("create_local", {"input_type": "hidden"})) form.append(("destination", {"input_type": "hidden"})) form.append(("formsemestre_id", {"input_type": "hidden"})) - # log('REQUEST form=%s'%REQUEST.form) tf = TrivialFormulator( REQUEST.URL0, REQUEST.form, @@ -2047,17 +2045,19 @@ function set_global_pref(el, pref_name) { cssclass="sco_pref", submitlabel="Enregistrer les modifications", ) + dest_url = ( + self.context.NotesURL() + + "formsemestre_status?formsemestre_id=%s" % self.formsemestre_id + ) if tf[0] == 0: return "\n".join(H) + tf[1] + self.context.sco_footer(REQUEST) elif tf[0] == -1: return REQUEST.RESPONSE.redirect( - REQUEST.URL1 + "?head_message=Annulé" + dest_url + "&head_message=Annulé" ) # cancel else: - # log('tf[2]=%s' % tf[2]) # XXX # Supprime pref locale du semestre (retour à la valeur globale) if tf[2]["suppress"]: - # log('suppress %s' % tf[2]['suppress']) # XXX self.base_prefs.delete(self.formsemestre_id, tf[2]["suppress"]) # Cree pref local (copie valeur globale) if tf[2]["create_local"]: @@ -2089,9 +2089,7 @@ function set_global_pref(el, pref_name) { destination = tf[2]["destination"] if destination == "done" or destination == "": return REQUEST.RESPONSE.redirect( - REQUEST.URL1 - + "/formsemestre_status?head_message=Préférences modifiées&formsemestre_id=" - + self.formsemestre_id + dest_url + "&head_message=Préférences modifiées" ) elif destination == "again": return REQUEST.RESPONSE.redirect( From 8d7ec2faeaf914fe1087882dc5f477c09dbb1219 Mon Sep 17 00:00:00 2001 From: IDK Date: Sun, 7 Feb 2021 15:31:35 +0100 Subject: [PATCH 14/18] Fix all redirects for Flask compatibility --- ZEntreprises.py | 28 ++++++------- ZNotes.py | 2 +- ZScoDoc.py | 2 +- ZScoUsers.py | 2 +- ZScolar.py | 76 +++++++++++++++++----------------- sco_edit_module.py | 2 +- sco_formsemestre_custommenu.py | 2 +- sco_formsemestre_edit.py | 5 ++- sco_formsemestre_validation.py | 10 ++--- sco_moduleimpl_inscriptions.py | 2 +- sco_saisie_notes.py | 19 ++++----- 11 files changed, 75 insertions(+), 75 deletions(-) diff --git a/ZEntreprises.py b/ZEntreprises.py index 3da1ea12..dd7f5047 100644 --- a/ZEntreprises.py +++ b/ZEntreprises.py @@ -562,7 +562,7 @@ class ZEntreprises( % entreprise_contact_id ) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: etudok = sco_entreprises.do_entreprise_check_etudiant( self, tf[2]["etudiant"] @@ -572,7 +572,7 @@ class ZEntreprises( else: tf[2].update({"etudid": etudok[1]}) sco_entreprises.do_entreprise_contact_edit(self, tf[2]) - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( self.EntreprisesURL() + "/entreprise_contact_list?entreprise_id=" + str(c["entreprise_id"]) @@ -680,13 +680,13 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "%s/entreprise_correspondant_list?entreprise_id=%s" % (self.EntreprisesURL(), c["entreprise_id"]) ) else: sco_entreprises.do_entreprise_correspondant_edit(self, tf[2]) - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "%s/entreprise_correspondant_list?entreprise_id=%s" % (self.EntreprisesURL(), c["entreprise_id"]) ) @@ -789,7 +789,7 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: etudok = sco_entreprises.do_entreprise_check_etudiant( self, tf[2]["etudiant"] @@ -799,7 +799,7 @@ class ZEntreprises( else: tf[2].update({"etudid": etudok[1]}) sco_entreprises.do_entreprise_contact_create(self, tf[2]) - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -828,12 +828,12 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_contact_delete( self, c["entreprise_contact_id"] ) - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -935,10 +935,10 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_correspondant_create(self, tf[2]) - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -967,12 +967,12 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_correspondant_delete( self, c["entreprise_corresp_id"] ) - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) @@ -1025,10 +1025,10 @@ class ZEntreprises( if tf[0] == 0: H.append(tf[1]) elif tf[0] == -1: - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) else: sco_entreprises.do_entreprise_delete(self, E["entreprise_id"]) - REQUEST.RESPONSE.redirect(self.EntreprisesURL()) + return REQUEST.RESPONSE.redirect(self.EntreprisesURL()) H.append(entreprise_footer(self, REQUEST)) return "\n".join(H) diff --git a/ZNotes.py b/ZNotes.py index 553f3538..f78684d9 100644 --- a/ZNotes.py +++ b/ZNotes.py @@ -169,7 +169,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl "Changes the instance values" self.title = title self._p_changed = 1 - RESPONSE.redirect("manage_editForm") + return RESPONSE.redirect("manage_editForm") def _getNotesCache(self): "returns CacheNotesTable instance for us" diff --git a/ZScoDoc.py b/ZScoDoc.py index 3de841af..59a26a6c 100644 --- a/ZScoDoc.py +++ b/ZScoDoc.py @@ -399,7 +399,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp except: admin_password_initialized = "0" if isAdmin and admin_password_initialized != "1": - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "ScoDoc/change_admin_user_form?message=Le%20mot%20de%20passe%20administrateur%20doit%20etre%20change%20!" ) diff --git a/ZScoUsers.py b/ZScoUsers.py index 2550bb4f..efe1eb97 100644 --- a/ZScoUsers.py +++ b/ZScoUsers.py @@ -1072,7 +1072,7 @@ class ZScoUsers( parameters={"user_name": user_name}, ) self._user_delete(user_name) - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( self.UsersURL() + r"?head_message=Utilisateur%20supprimé" ) diff --git a/ZScolar.py b/ZScolar.py index 0537b67e..f61d6a43 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -206,11 +206,11 @@ class ZScolar(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp # The for used to edit this object security.declareProtected(ScoView, "manage_editZScolar") - def manage_editZScolar(self, title, RESPONSE=None): + def manage_editZScolar(self, title, REQUEST=None): "Changes the instance values" self.title = title self._p_changed = 1 - RESPONSE.redirect("manage_editForm") + return REQUEST.RESPONSE.redirect("manage_editForm") def _setup_initial_roles_and_permissions(self): """Initialize roles and permissions @@ -321,43 +321,43 @@ REQUEST.URL0=%s
    # essai: liste des permissions # from AccessControl import getSecurityManager # pylint: disable=import-error - from AccessControl.Permission import Permission # pylint: disable=import-error + # from AccessControl.Permission import Permission # pylint: disable=import-error - permissions = self.ac_inherited_permissions(1) - scoperms = [p for p in permissions if p[0][:3] == "Sco"] - # H.append( str(self.aq_parent.aq_parent.permission_settings()) ) - # H.append('

    perms: %s

    '%str(scoperms)) - # H.append('

    valid_roles: %s

    '%str(self.valid_roles())) - # H.append('

    ac_inherited_permissions=%s

    '%str(self.ac_inherited_permissions(1))) - def collect_roles(context, rd): - for p in scoperms: - name, value = p[:2] - P = Permission(name, value, context) - roles = list(P.getRoles()) - if rd.has_key(name): - rd[name] += roles - else: - rd[name] = roles - if hasattr(context, "aq_parent"): - collect_roles(context.aq_parent, rd) + # permissions = self.ac_inherited_permissions(1) + # scoperms = [p for p in permissions if p[0][:3] == "Sco"] + # # H.append( str(self.aq_parent.aq_parent.permission_settings()) ) + # # H.append('

    perms: %s

    '%str(scoperms)) + # # H.append('

    valid_roles: %s

    '%str(self.valid_roles())) + # # H.append('

    ac_inherited_permissions=%s

    '%str(self.ac_inherited_permissions(1))) + # def collect_roles(context, rd): + # for p in scoperms: + # name, value = p[:2] + # P = Permission(name, value, context) + # roles = list(P.getRoles()) + # if rd.has_key(name): + # rd[name] += roles + # else: + # rd[name] = roles + # if hasattr(context, "aq_parent"): + # collect_roles(context.aq_parent, rd) - b = "" - rd = {} - collect_roles(self, rd) - b = "

    " + str(rd) + "

    " + # b = "" + # rd = {} + # collect_roles(self, rd) + # b = "

    " + str(rd) + "

    " - authuser = REQUEST.AUTHENTICATED_USER - for p in scoperms: - permname, _ = p[:2] - b += "

    " + permname + " : " - if authuser.has_permission(permname, self): - b += "yes" - else: - b += "no" - b += "

    " - b += "

    xxx


    " + str(self.aq_parent.aq_parent) + # authuser = REQUEST.AUTHENTICATED_USER + # for p in scoperms: + # permname, _ = p[:2] + # b += "

    " + permname + " : " + # if authuser.has_permission(permname, self): + # b += "yes" + # else: + # b += "no" + # b += "

    " + # b += "

    xxx


    " + str(self.aq_parent.aq_parent) - return self.sco_header(REQUEST) + str(b) + self.sco_footer(REQUEST) + # return self.sco_header(REQUEST) + str(b) + self.sco_footer(REQUEST) # essais calendriers: security.declareProtected(ScoView, "experimental_calendar") @@ -1122,7 +1122,7 @@ REQUEST.URL0=%s
    }, ) logdb(REQUEST, cnx, method="addAnnotation", etudid=etudid) - REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid) + return REQUEST.RESPONSE.redirect("ficheEtud?etudid=" + etudid) security.declareProtected(ScoView, "canSuppressAnnotation") @@ -1161,7 +1161,7 @@ REQUEST.URL0=%s
    logdb(REQUEST, cnx, method="SuppressAnnotation", etudid=etudid) scolars.etud_annotations_delete(cnx, annotation_id) - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "ficheEtud?etudid=%s&head_message=Annotation%%20supprimée" % (etudid) ) @@ -1231,7 +1231,7 @@ REQUEST.URL0=%s
    else: scolars.adresse_create(cnx, args=tf[2]) logdb(REQUEST, cnx, method="changeCoordonnees", etudid=etudid) - REQUEST.RESPONSE.redirect(dest_url) + return REQUEST.RESPONSE.redirect(dest_url) # --- Gestion des groupes: security.declareProtected(ScoView, "affectGroups") diff --git a/sco_edit_module.py b/sco_edit_module.py index 54ab900b..1b15984e 100644 --- a/sco_edit_module.py +++ b/sco_edit_module.py @@ -452,7 +452,7 @@ def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None) ue_add_malus_module(context, ue["ue_id"], titre=titre, REQUEST=REQUEST) if REQUEST: - REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id) + return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id) def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None): diff --git a/sco_formsemestre_custommenu.py b/sco_formsemestre_custommenu.py index 72e44bd4..ae828c8d 100644 --- a/sco_formsemestre_custommenu.py +++ b/sco_formsemestre_custommenu.py @@ -156,4 +156,4 @@ def formsemestre_custommenu_edit(context, formsemestre_id, REQUEST=None): "url": tf[2]["url_" + custommenu_id], }, ) - REQUEST.RESPONSE.redirect(dest_url) + return REQUEST.RESPONSE.redirect(dest_url) diff --git a/sco_formsemestre_edit.py b/sco_formsemestre_edit.py index 556b5121..09e9f44f 100644 --- a/sco_formsemestre_edit.py +++ b/sco_formsemestre_edit.py @@ -1438,7 +1438,7 @@ def formsemestre_change_lock( args = {"formsemestre_id": formsemestre_id, "etat": etat} context.do_formsemestre_edit(args) if REQUEST: - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=%s" % formsemestre_id ) @@ -1478,9 +1478,10 @@ def formsemestre_change_publication_bul( args = {"formsemestre_id": formsemestre_id, "bul_hide_xml": etat} context.do_formsemestre_edit(args) if REQUEST: - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "formsemestre_status?formsemestre_id=%s" % formsemestre_id ) + return None def formsemestre_edit_uecoefs(context, formsemestre_id, err_ue_id=None, REQUEST=None): diff --git a/sco_formsemestre_validation.py b/sco_formsemestre_validation.py index 5bda7b0e..97b67a6f 100644 --- a/sco_formsemestre_validation.py +++ b/sco_formsemestre_validation.py @@ -346,7 +346,7 @@ def formsemestre_validation_etud( raise ValueError("code choix invalide ! (%s)" % codechoice) # Se.valide_decision(choice, REQUEST) # enregistre - _redirect_valid_choice( + return _redirect_valid_choice( formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST ) @@ -393,7 +393,7 @@ def formsemestre_validation_etud_manu( # Se.valide_decision(choice, REQUEST) # enregistre if redirect: - _redirect_valid_choice( + return _redirect_valid_choice( formsemestre_id, etudid, Se, choice, desturl, sortcol, REQUEST ) @@ -407,9 +407,9 @@ def _redirect_valid_choice( ) if sortcol: adr += "&sortcol=" + sortcol - if desturl: - desturl += "&desturl=" + desturl - REQUEST.RESPONSE.redirect(adr) + # if desturl: + # desturl += "&desturl=" + desturl + return REQUEST.RESPONSE.redirect(adr) # Si le precedent a été modifié, demande relecture du parcours. # sinon renvoie au listing general, diff --git a/sco_moduleimpl_inscriptions.py b/sco_moduleimpl_inscriptions.py index 3a4c535b..43327b24 100644 --- a/sco_moduleimpl_inscriptions.py +++ b/sco_moduleimpl_inscriptions.py @@ -183,7 +183,7 @@ def moduleimpl_inscriptions_edit( sco_moduleimpl.do_moduleimpl_inscrit_etuds( context, moduleimpl_id, formsemestre_id, etuds, reset=True, REQUEST=REQUEST ) - REQUEST.RESPONSE.redirect( + return REQUEST.RESPONSE.redirect( "moduleimpl_status?moduleimpl_id=%s" % (moduleimpl_id) ) # diff --git a/sco_saisie_notes.py b/sco_saisie_notes.py index 9602faea..7decaf79 100644 --- a/sco_saisie_notes.py +++ b/sco_saisie_notes.py @@ -949,9 +949,15 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None): H.append("""""") # Le formulaire de saisie des notes: - form = _form_saisie_notes(context, E, M, groups_infos.group_ids, REQUEST=REQUEST) + destination = "%s/Notes/moduleimpl_status?moduleimpl_id=%s" % ( + context.ScoURL(), + E["moduleimpl_id"], + ) + form = _form_saisie_notes( + context, E, M, groups_infos.group_ids, destination=destination, REQUEST=REQUEST + ) if form is None: - return "" # redirect + return REQUEST.RESPONSE.redirect(destination) H.append(form) # H.append("") # /saisie_notes @@ -1041,7 +1047,7 @@ def _get_sorted_etuds(context, E, etudids, formsemestre_id): return etuds -def _form_saisie_notes(context, E, M, group_ids, REQUEST=None): +def _form_saisie_notes(context, E, M, group_ids, destination="", REQUEST=None): """Formulaire HTML saisie des notes dans l'évaluation E du moduleimpl M pour les groupes indiqués. @@ -1176,11 +1182,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None): ) # H.append('''

    ''') - destination = "%s/Notes/moduleimpl_status?moduleimpl_id=%s" % ( - context.ScoURL(), - M["moduleimpl_id"], - ) - tf = TF( destination, REQUEST.form, @@ -1191,7 +1192,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None): ) H.append(tf.getform()) # check and init if tf.canceled(): - REQUEST.RESPONSE.redirect(destination) return None elif (not tf.submitted()) or not tf.result: # ajout formularie saisie notes manquantes @@ -1213,7 +1213,6 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None): else: # form submission # rien à faire - REQUEST.RESPONSE.redirect(destination) return None From 8f02f16442d94dfaeee13ea03a0220af68ceacf1 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 13 Feb 2021 17:28:55 +0100 Subject: [PATCH 15/18] Handling of neutral genders. Closes #65 --- ImportScolars.py | 10 +-- ZScolar.py | 18 ++-- config/postupgrade-db.py | 15 ++++ html_sidebar.py | 2 +- misc/createtables.sql | 2 +- misc/format_import_etudiants.txt | 2 +- notes_table.py | 12 +-- pe_avislatex.py | 12 +-- pe_jurype.py | 8 +- pe_tools.py | 2 +- sco_bulletins_json.py | 4 +- sco_bulletins_xml.py | 3 +- sco_debouche.py | 6 +- sco_excel.py | 2 +- sco_export_results.py | 6 +- sco_find_etud.py | 6 +- sco_groups.py | 25 +++--- sco_groups_view.py | 5 +- sco_inscr_passage.py | 2 +- sco_lycee.py | 4 +- sco_poursuite_dut.py | 4 +- sco_prepajury.py | 4 +- sco_pvjury.py | 1 - sco_recapcomplet.py | 3 +- sco_report.py | 136 ++++++++++++++++++++----------- sco_synchro_etuds.py | 28 +++---- sco_trombino.py | 16 +--- sco_utils.py | 4 +- scolars.py | 76 ++++++++++------- scotests/demo/demo_reset_noms.py | 12 +-- scotests/demo/gen_nomprenoms.py | 15 ++-- scotests/demo/prenoms-x.txt | 10 +++ scotests/sco_fake_gen.py | 25 +++--- 33 files changed, 281 insertions(+), 199 deletions(-) create mode 100644 scotests/demo/prenoms-x.txt diff --git a/ImportScolars.py b/ImportScolars.py index 8e06e93c..c264e9d4 100644 --- a/ImportScolars.py +++ b/ImportScolars.py @@ -368,16 +368,16 @@ def scolars_import_excel_file( # xxx Ad-hoc checks (should be in format description) if scu.strlower(titleslist[i]) == "sexe": try: - val = scolars.normalize_sexe(val) + val = scolars.input_civilite(val) except: raise ScoValueError( - "valeur invalide pour 'SEXE' (doit etre 'M' ou 'MME' ou 'H' ou 'F', pas '%s') ligne %d, colonne %s" + "valeur invalide pour 'SEXE' (doit etre 'M', 'F', ou 'MME', 'H', 'X' ou vide, mais pas '%s') ligne %d, colonne %s" % (val, linenum, titleslist[i]) ) # Excel date conversion: if scu.strlower(titleslist[i]) == "date_naissance": if val: - if re.match("^[0-9]*\.?[0-9]*$", str(val)): + if re.match(r"^[0-9]*\.?[0-9]*$", str(val)): val = sco_excel.xldate_as_datetime(float(val)) # INE if ( @@ -515,11 +515,11 @@ def _import_one_student( # Admissions args["etudid"] = etudid args["annee"] = annee_courante - adm_id = scolars.admission_create(cnx, args) + _ = scolars.admission_create(cnx, args) # Adresse args["typeadresse"] = "domicile" args["description"] = "(infos admission)" - adresse_id = scolars.adresse_create(cnx, args) + _ = scolars.adresse_create(cnx, args) # Inscription au semestre args["etat"] = "I" # etat insc. semestre if formsemestre_id: diff --git a/ZScolar.py b/ZScolar.py index f61d6a43..6cc176cc 100644 --- a/ZScolar.py +++ b/ZScolar.py @@ -99,7 +99,7 @@ import sco_formations from scolars import ( format_nom, format_prenom, - format_sexe, + format_civilite, format_lycee, format_lycee_from_code, ) @@ -916,7 +916,8 @@ REQUEST.URL0=%s
    "nom": "?", "nom_usuel": "", "prenom": "?", - "sexe": "?", + "civilite": "?", + "sexe": "?", # for backward compat "email": "?", "emailperso": "", "error": "code etudiant inconnu", @@ -935,7 +936,6 @@ REQUEST.URL0=%s
    "nom", "nom_usuel", "prenom", - "sexe", "nomprenom", "email", "emailperso", @@ -956,6 +956,10 @@ REQUEST.URL0=%s
    "date_naissance_iso", ): d[a] = scu.quote_xml_attr(etud[a]) + d["civilite"] = scu.quote_xml_attr( + etud["civilite_str"] + ) # exception: ne sort pas la civilite brute + d["sexe"] = d["civilite"] # backward compat pour anciens clients d["photo_url"] = scu.quote_xml_attr(sco_photos.etud_photo_url(self, etud)) sem = etud["cursem"] @@ -1750,12 +1754,12 @@ REQUEST.URL0=%s
    }, ), ( - "sexe", + "civilite", { "input_type": "menu", - "labels": ["H", "F"], - "allowed_values": ["MR", "MME"], - "title": "Genre", + "labels": ["Homme", "Femme", "Autre/neutre"], + "allowed_values": ["M", "F", "X"], + "title": "Civilité", }, ), ( diff --git a/config/postupgrade-db.py b/config/postupgrade-db.py index 29f2c2ca..e423984c 100755 --- a/config/postupgrade-db.py +++ b/config/postupgrade-db.py @@ -1070,6 +1070,21 @@ for dept in get_depts(): "etape", ["alter table notes_formsemestre_inscription add column etape text"], ) + # Migre identite.sexe vers identite.civilite: normalise valeurs: M, F, X + check_field( + cnx, + "identite", + "civilite", + [ + "UPDATE identite set sexe='M' where upper(sexe) = 'M' or upper(sexe) = 'M.' or upper(sexe) = 'MR' or upper(sexe) = 'H'", + "UPDATE identite set sexe='F' where upper(sexe) = 'F' or upper(sexe) = 'MME' or upper(sexe) = 'MLLE' or upper(sexe) = 'MELLE' or upper(sexe) = 'MLLE.' or upper(sexe) = 'F'", + "UPDATE identite set sexe='X' where sexe is NULL", + "ALTER TABLE identite RENAME COLUMN sexe TO civilite", + "ALTER TABLE identite ALTER COLUMN civilite SET NOT NULL", + "ALTER TABLE identite ADD CONSTRAINT civchk CHECK (civilite IN ('M', 'F', 'X'))", + ], + ) + # Add here actions to performs after upgrades: cnx.commit() cnx.close() diff --git a/html_sidebar.py b/html_sidebar.py index 7c50d5c3..e9e022fc 100644 --- a/html_sidebar.py +++ b/html_sidebar.py @@ -103,7 +103,7 @@ def sidebar(context, REQUEST=None): # compte les absences du semestre en cours H.append( """

    - %(sexe)s %(nom_disp)s + %(civilite_str)s %(nom_disp)s

    Absences""" % params diff --git a/misc/createtables.sql b/misc/createtables.sql index bb809dfe..bc937d0d 100644 --- a/misc/createtables.sql +++ b/misc/createtables.sql @@ -49,7 +49,7 @@ CREATE TABLE identite ( etudid text DEFAULT notes_newid_etud('EID'::text) UNIQUE NOT NULL, nom text, prenom text, - sexe text, + civilite text NOT NULL CHECK (civilite IN ('M', 'F', 'X')), date_naissance date, -- new: date en texte lieu_naissance text, dept_naissance text, diff --git a/misc/format_import_etudiants.txt b/misc/format_import_etudiants.txt index 365a7136..658c6d2c 100644 --- a/misc/format_import_etudiants.txt +++ b/misc/format_import_etudiants.txt @@ -8,7 +8,7 @@ Code_INE; text; identite; 1; code INE;INE nom; text; identite; 0; nom de l'etudiant; nom_usuel; text; identite; 1; nom usuel (si different); prenom; text; identite; 0; prenom de l'etudiant -sexe (H ou F); text; identite; 0; sexe ('H' ou 'F');sexe;genre +civilite; text; identite; 1; sexe ('M', 'F', 'X');sexe;genre date_naissance;text;identite; 1; date de naissance (jj/mm/aaaa) lieu_naissance;text;identite; 1; lieu de naissance nationalite; text; identite; 1; nationalite diff --git a/notes_table.py b/notes_table.py index 1ba2810b..38de3147 100644 --- a/notes_table.py +++ b/notes_table.py @@ -372,7 +372,9 @@ class NotesTable: def get_sexnom(self, etudid): "M. DUPONT" etud = self.identdict[etudid] - return etud["sexe"] + " " + scu.strupper(etud["nom_usuel"] or etud["nom"]) + return ( + etud["civilite_str"] + " " + scu.strupper(etud["nom_usuel"] or etud["nom"]) + ) def get_nom_short(self, etudid): "formatte nom d'un etud (pour table recap)" @@ -391,13 +393,7 @@ class NotesTable: def get_nom_long(self, etudid): "formatte nom d'un etud: M. Pierre DUPONT" etud = self.identdict[etudid] - return " ".join( - [ - scolars.format_sexe(etud["sexe"]), - scolars.format_prenom(etud["prenom"]), - scolars.format_nom(etud["nom_usuel"] or etud["nom"]), - ] - ) + return scolars.format_nomprenom(etud) def get_displayed_etud_code(self, etudid): 'code à afficher sur les listings "anonymes"' diff --git a/pe_avislatex.py b/pe_avislatex.py index fdb2644c..a882a43e 100644 --- a/pe_avislatex.py +++ b/pe_avislatex.py @@ -213,7 +213,7 @@ def get_code_latex_avis_etudiant( elif tag_latex == u"bilanParTag": valeur = get_bilanParTag(donnees_etudiant) - # Les tags "simples": par ex. nom, prenom, sexe, ... + # Les tags "simples": par ex. nom, prenom, civilite, ... else: if tag_latex in donnees_etudiant: valeur = donnees_etudiant[tag_latex].decode(scu.SCO_ENCODING) @@ -410,7 +410,7 @@ def get_avis_poursuite_par_etudiant( if pe_tools.PE_DEBUG: pe_tools.pe_print(jury.syntheseJury[etudid]["nom"] + " " + etudid) - sexe = jury.syntheseJury[etudid]["sexe"].decode(scu.SCO_ENCODING) + civilite_str = jury.syntheseJury[etudid]["civilite_str"].decode(scu.SCO_ENCODING) nom = jury.syntheseJury[etudid]["nom"].replace(" ", "-").decode(scu.SCO_ENCODING) prenom = ( jury.syntheseJury[etudid]["prenom"].replace(" ", "-").decode(scu.SCO_ENCODING) @@ -429,7 +429,9 @@ def get_avis_poursuite_par_etudiant( # Entete (commentaire) - contenu_latex = u"%% ---- Etudiant: " + sexe + " " + nom + " " + prenom + u"\n" + contenu_latex = ( + u"%% ---- Etudiant: " + civilite_str + " " + nom + " " + prenom + u"\n" + ) # les annnotations annotationPE = get_annotation_PE( @@ -502,7 +504,7 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe): [syntheseJury[etudid]["nbSemestres"] for etudid in etudids] ) # le nombre de semestre le + grand - infos = ["sexe", "nom", "prenom", "age", "nbSemestres"] + infos = ["civilite", "nom", "prenom", "age", "nbSemestres"] entete = ["etudid"] entete.extend(infos) entete.extend(["P%d" % i for i in range(1, maxParcours + 1)]) # ajout du parcours @@ -518,7 +520,7 @@ def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe): # Les info générales: row = { "etudid": etudid, - "sexe": e["sexe"], + "civilite": e["civilite"], "nom": e["nom"], "prenom": e["prenom"], "age": e["age"], diff --git a/pe_jurype.py b/pe_jurype.py index fe43e7d1..0b0fad77 100644 --- a/pe_jurype.py +++ b/pe_jurype.py @@ -85,7 +85,7 @@ class JuryPE: - context : le contexte Zope - juryEtudDict : dictionnaire récapitulant les étudiants participant au jury PE (données administratives + celles des semestres valides à prendre en compte permettant le calcul des moyennes ... - {'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }} + {'etudid : { 'nom', 'prenom', 'civilite', 'diplome', '', }} Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif @@ -812,7 +812,7 @@ class JuryPE: self.syntheseJury[etudid] = { "nom": etudinfo["nom"], "prenom": etudinfo["prenom"], - "sexe": etudinfo["sexe"], + "civilite": etudinfo["civilite"], "age": str(pe_tools.calcul_age(etudinfo["date_naissance"])), "lycee": etudinfo["nomlycee"] + ( @@ -985,7 +985,7 @@ class JuryPE: [self.syntheseJury[etudid]["nbSemestres"] for etudid in etudids] ) - infos = ["sexe", "nom", "prenom", "age", "nbSemestres"] + infos = ["civilite", "nom", "prenom", "age", "nbSemestres"] entete = ["etudid"] entete.extend(infos) entete.extend(["P%d" % i for i in range(1, maxParcours + 1)]) @@ -1036,7 +1036,7 @@ class JuryPE: # Les info générales: row = { "etudid": etudid, - "sexe": e["sexe"], + "civilite": e["civilite"], "nom": e["nom"], "prenom": e["prenom"], "age": e["age"], diff --git a/pe_tools.py b/pe_tools.py index ecaebaae..5dad0099 100644 --- a/pe_tools.py +++ b/pe_tools.py @@ -217,7 +217,7 @@ JURY_SYNTHESE_POUR_DEBUG = { "EID1810": { "nom": "ROUX", "entree": "2016", - "sexe": "M.", + "civilite_str": "M.", "promo": 2016, "S2": { "groupe": { diff --git a/sco_bulletins_json.py b/sco_bulletins_json.py index 9a86c583..d21c9586 100644 --- a/sco_bulletins_json.py +++ b/sco_bulletins_json.py @@ -124,14 +124,14 @@ def formsemestre_bulletinetud_published_dict( code_ine=etudinfo["code_ine"], nom=scu.quote_xml_attr(etudinfo["nom"]), prenom=scu.quote_xml_attr(etudinfo["prenom"]), - sexe=scu.quote_xml_attr(etudinfo["sexe"]), + civilite=scu.quote_xml_attr(etudinfo["civilite_str"]), photo_url=scu.quote_xml_attr( sco_photos.etud_photo_url(context, etudinfo, fast=True) ), email=scu.quote_xml_attr(etudinfo["email"]), emailperso=scu.quote_xml_attr(etudinfo["emailperso"]), ) - + d["etudiant"]["sexe"] = d["etudiant"]["civilite"] # backward compat for our clients # Disponible pour publication ? if not published: return d # stop ! diff --git a/sco_bulletins_xml.py b/sco_bulletins_xml.py index 95d9454c..8d9aaecb 100644 --- a/sco_bulletins_xml.py +++ b/sco_bulletins_xml.py @@ -107,7 +107,8 @@ def make_xml_formsemestre_bulletinetud( code_ine=etudinfo["code_ine"], nom=scu.quote_xml_attr(etudinfo["nom"]), prenom=scu.quote_xml_attr(etudinfo["prenom"]), - sexe=scu.quote_xml_attr(etudinfo["sexe"]), + civilite=scu.quote_xml_attr(etudinfo["civilite_str"]), + sexe=scu.quote_xml_attr(etudinfo["civilite_str"]), # compat photo_url=scu.quote_xml_attr(sco_photos.etud_photo_url(context, etudinfo)), email=scu.quote_xml_attr(etudinfo["email"]), emailperso=scu.quote_xml_attr(etudinfo["emailperso"]), diff --git a/sco_debouche.py b/sco_debouche.py index ad3c6530..8641d68d 100644 --- a/sco_debouche.py +++ b/sco_debouche.py @@ -115,7 +115,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True): ) row = { "etudid": etudid, - "sexe": etud["sexe"], + "civilite": etud["civilite"], "nom": etud["nom"], "prenom": etud["prenom"], "_nom_target": "ficheEtud?etudid=" + etud["etudid"], @@ -154,7 +154,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True): L.sort(key=lambda x: x["sem_ident"]) titles = { - "sexe": "", + "civilite": "", "nom": "Nom", "prenom": "Prénom", "semestre": "Dernier semestre", @@ -170,7 +170,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True): "semestre", "semestre_id", "periode", - "sexe", + "civilite", "nom", "prenom", "moy", diff --git a/sco_excel.py b/sco_excel.py index 1e81aa43..d4a2b20b 100644 --- a/sco_excel.py +++ b/sco_excel.py @@ -616,7 +616,7 @@ def Excel_feuille_listeappel( li += 1 ws0.write(li, 0, n, style1b) nomprenom = ( - t["sexe"] + t["civilite_str"] + " " + t["nom"] + " " diff --git a/sco_export_results.py b/sco_export_results.py index 223d3eb2..992c802a 100644 --- a/sco_export_results.py +++ b/sco_export_results.py @@ -122,7 +122,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos): "code_nip": "NIP", "nom": "Nom", "prenom": "Prénom", - "sexe": "Civ.", + "civilite_str": "Civ.", "nom_usuel": "Nom usuel", "bac": "Bac", "parcours": "Parcours", @@ -133,7 +133,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos): "periode", "sid", "code_nip", - "sexe", + "civilite_str", "nom", # 'nom_usuel', # inutile ? "prenom", @@ -171,7 +171,7 @@ def _build_results_list(context, dpv_by_sem, etuds_infos): "nom": etud["nom"], "nom_usuel": etud["nom_usuel"], "prenom": etud["prenom"], - "sexe": etud["sexe"], + "civilite_str": etud["civilite_str"], "_nom_target": "%s/ficheEtud?etudid=%s" % (context.ScoURL(), etudid), "_nom_td_attrs": 'id="%s" class="etudinfo"' % etudid, "bac": bac.abbrev(), diff --git a/sco_find_etud.py b/sco_find_etud.py index 25d76dc0..0af146e2 100644 --- a/sco_find_etud.py +++ b/sco_find_etud.py @@ -384,7 +384,7 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"): Seuls les départements accessibles par l'utilisateur sont cherchés. Renvoie une liste des inscriptions de l'étudiants dans tout ScoDoc: - code_nip, nom, prenom, sexe, dept, formsemestre_id, date_debut_sem, date_fin_sem + code_nip, nom, prenom, civilite_str, dept, formsemestre_id, date_debut_sem, date_fin_sem """ result, _ = search_etud_in_accessible_depts( context, code_nip=code_nip, REQUEST=REQUEST @@ -401,7 +401,7 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"): "dept": DeptId, "etudid": e["etudid"], "code_nip": e["code_nip"], - "sexe": e["sexe"], + "civilite_str": e["civilite_str"], "nom": e["nom"], "prenom": e["prenom"], "formsemestre_id": sem["formsemestre_id"], @@ -414,7 +414,7 @@ def search_inscr_etud_by_nip(context, code_nip, REQUEST=None, format="json"): "dept", "etudid", "code_nip", - "sexe", + "civilite_str", "nom", "prenom", "formsemestre_id", diff --git a/sco_groups.py b/sco_groups.py index c4746f60..aa79d05f 100644 --- a/sco_groups.py +++ b/sco_groups.py @@ -473,7 +473,8 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG doc._push() doc.etud( etudid=e["etudid"], - sexe=scolars.format_sexe(etud["sexe"]), + civilite=etud["civilite_str"], + sexe=etud["civilite_str"], # compat nom=scolars.format_nom(etud["nom"]), prenom=scolars.format_prenom(etud["prenom"]), origin=comp_origin(etud, sem), @@ -497,7 +498,7 @@ def XMLgetGroupsInPartition(context, partition_id, REQUEST=None): # was XMLgetG doc._push() doc.etud( etudid=etud["etudid"], - sexe=scolars.format_sexe(etud["sexe"]), + sexe=etud["civilite_str"], nom=scolars.format_nom(etud["nom"]), prenom=scolars.format_prenom(etud["prenom"]), origin=comp_origin(etud, sem), @@ -1255,26 +1256,26 @@ def groups_auto_repartition(context, partition_id=None, REQUEST=None): context.Notes, formsemestre_id ) # > identdict identdict = nt.identdict - # build: { sexe : liste etudids trie par niveau croissant } - sexes = sets.Set([x["sexe"] for x in identdict.values()]) + # build: { civilite : liste etudids trie par niveau croissant } + civilites = sets.Set([x["civilite"] for x in identdict.values()]) listes = {} - for sexe in sexes: - listes[sexe] = [ + for civilite in civilites: + listes[civilite] = [ (get_prev_moy(context.Notes, x["etudid"], formsemestre_id), x["etudid"]) for x in identdict.values() - if x["sexe"] == sexe + if x["civilite"] == civilite ] - listes[sexe].sort() - log("listes[%s] = %s" % (sexe, listes[sexe])) + listes[civilite].sort() + log("listes[%s] = %s" % (civilite, listes[civilite])) # affect aux groupes: n = len(identdict) igroup = 0 nbgroups = len(group_ids) while n > 0: - for sexe in sexes: - if len(listes[sexe]): + for civilite in civilites: + if len(listes[civilite]): n -= 1 - etudid = listes[sexe].pop()[1] + etudid = listes[civilite].pop()[1] group_id = group_ids[igroup] igroup = (igroup + 1) % nbgroups change_etud_group_in_partition( diff --git a/sco_groups_view.py b/sco_groups_view.py index f3cafcbb..627a7c48 100644 --- a/sco_groups_view.py +++ b/sco_groups_view.py @@ -464,8 +464,9 @@ def groups_table( % (with_paiement, with_archives, with_annotations) ) # - columns_ids = ["nom_disp", "prenom"] # colonnes a inclure + columns_ids = ["civilite_str", "nom_disp", "prenom"] # colonnes a inclure titles = { + "civilite_str": "Civ.", "nom_disp": "Nom", "prenom": "Prénom", "email": "Mail", @@ -733,7 +734,7 @@ def groups_table( "etudid", "code_nip", "etat", - "sexe", + "civilite_str", "nom", "nom_usuel", "prenom", diff --git a/sco_inscr_passage.py b/sco_inscr_passage.py index f746238e..e5bdd1c4 100644 --- a/sco_inscr_passage.py +++ b/sco_inscr_passage.py @@ -611,7 +611,7 @@ def etuds_select_boxes( def etuds_select_box_xls(context, src_cat): "export a box to excel" etuds = src_cat["etuds"] - columns_ids = ["etudid", "sexe", "nom", "prenom", "etape"] + columns_ids = ["etudid", "civilite_str", "nom", "prenom", "etape"] titles = {x: x for x in columns_ids} # Ajoute colonne paiement inscription diff --git a/sco_lycee.py b/sco_lycee.py index 8d25650e..0b3fbf93 100644 --- a/sco_lycee.py +++ b/sco_lycee.py @@ -128,7 +128,7 @@ def _table_etuds_lycees( else: L = etuds columns_ids = ( - "sexe", + "civilite_str", "nom", "prenom", "codelycee", @@ -148,7 +148,7 @@ def _table_etuds_lycees( rows=L, titles={ "nbetuds": "Nb d'étudiants", - "sexe": "", + "civilite_str": "", "nom": "Nom", "prenom": "Prénom", "etudid": "etudid", diff --git a/sco_poursuite_dut.py b/sco_poursuite_dut.py index 97c3a14a..a2fdc2fe 100644 --- a/sco_poursuite_dut.py +++ b/sco_poursuite_dut.py @@ -44,7 +44,7 @@ import VERSION def etud_get_poursuite_info(context, sem, etud): """{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }""" I = {} - I.update(etud) # copie nom, prenom, sexe, ... + I.update(etud) # copie nom, prenom, civilite, ... # Now add each semester, starting from the first one semlist = [] @@ -174,7 +174,7 @@ def formsemestre_poursuite_report( infos.append(info) # column_ids = ( - ("sexe", "nom", "prenom", "annee", "date_naissance") + ("civilite_str", "nom", "prenom", "annee", "date_naissance") + tuple(ids) + ("debouche",) ) diff --git a/sco_prepajury.py b/sco_prepajury.py index 4845defc..82e60819 100644 --- a/sco_prepajury.py +++ b/sco_prepajury.py @@ -37,7 +37,7 @@ import sco_excel import sco_formsemestre import sco_parcours_dut import sco_codes_parcours -from scolars import format_nom, format_prenom, format_sexe, format_lycee +from scolars import format_nom, format_prenom, format_civilite, format_lycee from sco_abs import getAbsSemEtud import VERSION @@ -229,7 +229,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): l.append(etud["code_ine"]) l += [ etudid, - format_sexe(etud["sexe"]), + etud["civilite_str"], format_nom(etud["nom"]), format_prenom(etud["prenom"]), etud["date_naissance"], diff --git a/sco_pvjury.py b/sco_pvjury.py index 148ad1fb..f62a345f 100644 --- a/sco_pvjury.py +++ b/sco_pvjury.py @@ -844,7 +844,6 @@ def formsemestre_lettres_individuelles( else: # submit sf = tf[2]["signature"] - # pdb.set_trace() signature = sf.read() # image of signature try: PDFLOCK.acquire() diff --git a/sco_recapcomplet.py b/sco_recapcomplet.py index 63a8c8d7..8727f74b 100644 --- a/sco_recapcomplet.py +++ b/sco_recapcomplet.py @@ -270,7 +270,7 @@ def make_formsemestre_recapcomplet( )[0] nt = context._getNotesCache().get_NotesTable( context, 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_nom_long, get_etud_decision_sem, + ) # > 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 # @@ -628,7 +628,6 @@ def make_formsemestre_recapcomplet( "formsemestre_id": formsemestre_id, "etudid": etudid, "name": l[1], - "nomprenom": nt.get_nom_long(etudid), } if ir % 2 == 0: cells = '' % etudid diff --git a/sco_report.py b/sco_report.py index ed795c53..246c4f62 100644 --- a/sco_report.py +++ b/sco_report.py @@ -293,7 +293,7 @@ def formsemestre_report_counts( "codedecision", "devenir", "etat", - "sexe", + "civilite", "qualite", "villelycee", "statut", @@ -365,7 +365,7 @@ def table_suivi_cohorte( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite=None, statut="", only_primo=False, ): @@ -404,7 +404,7 @@ def table_suivi_cohorte( bacs = set() bacspecialites = set() annee_bacs = set() - sexes = set() + civilites = set() statuts = set() for etudid in etudids: etud = context.getEtudInfo(etudid=etudid, filled=True)[0] @@ -414,7 +414,7 @@ def table_suivi_cohorte( (not bac or (bac == etud["bac"])) and (not bacspecialite or (bacspecialite == bacspe)) and (not annee_bac or (annee_bac == str(etud["annee_bac"]))) - and (not sexe or (sexe == etud["sexe"])) + and (not civilite or (civilite == etud["civilite"])) and (not statut or (statut == etud["statut"])) and (not only_primo or context.isPrimoEtud(etud, sem)) ): @@ -426,7 +426,7 @@ def table_suivi_cohorte( bacs.add(etud["bac"]) bacspecialites.add(bacspe) annee_bacs.add(etud["annee_bac"]) - sexes.add(etud["sexe"]) + civilites.add(etud["civilite"]) if etud["statut"]: # ne montre pas les statuts non renseignés statuts.add(etud["statut"]) sems = S.values() @@ -617,8 +617,8 @@ def table_suivi_cohorte( dbac += " (spécialité %s)" % bacspecialite if annee_bac: dbac += " (année bac %s)" % annee_bac - if sexe: - dbac += " genre: %s" % sexe + if civilite: + dbac += " civilité: %s" % civilite if statut: dbac += " statut: %s" % statut tab = GenTable( @@ -652,7 +652,15 @@ def table_suivi_cohorte( expl.append(", ".join(ls) + "") expl.append("") logt("Z: table_suivi_cohorte done") - return tab, "\n".join(expl), bacs, bacspecialites, annee_bacs, sexes, statuts + return ( + tab, + "\n".join(expl), + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) def formsemestre_suivi_cohorte( @@ -663,27 +671,35 @@ def formsemestre_suivi_cohorte( bac="", bacspecialite="", annee_bac="", - sexe="", + civilite=None, statut="", only_primo=False, REQUEST=None, ): """Affiche suivi cohortes par numero de semestre""" percent = int(percent) - tab, expl, bacs, bacspecialites, annee_bacs, sexes, statuts = table_suivi_cohorte( + ( + tab, + expl, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = table_suivi_cohorte( context, formsemestre_id, percent=percent, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, only_primo=only_primo, ) tab.base_url = ( - "%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&sexe=%s" - % (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, sexe) + "%s?formsemestre_id=%s&percent=%s&bac=%s&bacspecialite=%s&civilite=%s" + % (REQUEST.URL0, formsemestre_id, percent, bac, bacspecialite, civilite) ) if only_primo: tab.base_url += "&only_primo=on" @@ -693,8 +709,8 @@ def formsemestre_suivi_cohorte( base_url = REQUEST.URL0 burl = ( - "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&sexe=%s&statut=%s" - % (base_url, formsemestre_id, bac, bacspecialite, sexe, statut) + "%s?formsemestre_id=%s&bac=%s&bacspecialite=%s&civilite=%s&statut=%s" + % (base_url, formsemestre_id, bac, bacspecialite, civilite, statut) ) if percent: pplink = ( @@ -724,12 +740,12 @@ def formsemestre_suivi_cohorte( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, bacs=bacs, bacspecialites=bacspecialites, annee_bacs=annee_bacs, - sexes=sexes, + civilites=civilites, statuts=statuts, percent=percent, ), @@ -749,12 +765,12 @@ def _gen_form_selectetuds( bac=None, bacspecialite=None, annee_bac=None, - sexe=None, + civilite=None, statut=None, bacs=None, bacspecialites=None, annee_bacs=None, - sexes=None, + civilites=None, statuts=None, ): """HTML form pour choix criteres selection etudiants""" @@ -764,8 +780,8 @@ def _gen_form_selectetuds( bacspecialites.sort() annee_bacs = list(annee_bacs) annee_bacs.sort() - sexes = list(sexes) - sexes.sort() + civilites = list(civilites) + civilites.sort() statuts = list(statuts) statuts.sort() # @@ -824,13 +840,13 @@ def _gen_form_selectetuds( F.append("") # F.append( - """  Genre: """ % selected ) - for b in sexes: - if sexe == b: + for b in civilites: + if civilite == b: selected = 'selected="selected"' else: selected = "" @@ -984,7 +1000,7 @@ def tsp_etud_list( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", ): """Liste des etuds a considerer dans table suivi parcours @@ -1000,7 +1016,7 @@ def tsp_etud_list( bacs = set() bacspecialites = set() annee_bacs = set() - sexes = set() + civilites = set() statuts = set() for etudid in etudids: etud = context.getEtudInfo(etudid=etudid, filled=True)[0] @@ -1010,7 +1026,7 @@ def tsp_etud_list( (not bac or (bac == etud["bac"])) and (not bacspecialite or (bacspecialite == bacspe)) and (not annee_bac or (annee_bac == str(etud["annee_bac"]))) - and (not sexe or (sexe == etud["sexe"])) + and (not civilite or (civilite == etud["civilite"])) and (not statut or (statut == etud["statut"])) and (not only_primo or context.isPrimoEtud(etud, sem)) ): @@ -1019,11 +1035,11 @@ def tsp_etud_list( bacs.add(etud["bac"]) bacspecialites.add(bacspe) annee_bacs.add(etud["annee_bac"]) - sexes.add(etud["sexe"]) + civilites.add(etud["civilite"]) if etud["statut"]: # ne montre pas les statuts non renseignés statuts.add(etud["statut"]) # log('tsp_etud_list: %s etuds' % len(etuds)) - return etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return etuds, bacs, bacspecialites, annee_bacs, civilites, statuts def tsp_grouped_list(context, codes_etuds): @@ -1049,7 +1065,7 @@ def table_suivi_parcours( ): """Tableau recapitulant tous les parcours""" sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) - etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( + etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list( context, formsemestre_id, only_primo=only_primo ) codes_etuds = scu.DictDefault(defaultvalue=[]) @@ -1065,7 +1081,7 @@ def table_suivi_parcours( titles = { "parcours": "Code parcours", "nb": "Nombre d'étudiants", - "sexe": "", + "civilite": "", "nom": "Nom", "prenom": "Prénom", "etudid": "etudid", @@ -1082,7 +1098,7 @@ def table_suivi_parcours( L = etuds columns_ids = ( "etudid", - "sexe", + "civilite", "nom", "prenom", "bac", @@ -1209,25 +1225,25 @@ def graph_parcours( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", ): """""" if not scu.WITH_PYDOT: raise ScoValueError("pydot module is not installed") - etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = tsp_etud_list( + etuds, bacs, bacspecialites, annee_bacs, civilites, statuts = tsp_etud_list( context, formsemestre_id, only_primo=only_primo, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) # log('graph_parcours: %s etuds (only_primo=%s)' % (len(etuds), only_primo)) if not etuds: - return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return "", etuds, bacs, bacspecialites, annee_bacs, civilites, statuts edges = scu.DictDefault( defaultvalue=set() ) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set} @@ -1417,7 +1433,7 @@ def graph_parcours( # cf http://groups.google.com/group/pydot/browse_thread/thread/b3704c53e331e2ec data = data.replace("font-family:Arial", "font-family:Helvetica") - return data, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts + return data, etuds, bacs, bacspecialites, annee_bacs, civilites, statuts def formsemestre_graph_parcours( @@ -1428,7 +1444,7 @@ def formsemestre_graph_parcours( bac="", # selection sur type de bac bacspecialite="", annee_bac="", - sexe="", + civilite="", statut="", allkeys=False, # unused REQUEST=None, @@ -1437,7 +1453,15 @@ def formsemestre_graph_parcours( # log("formsemestre_graph_parcours") sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) if format == "pdf": - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, format="pdf", @@ -1445,14 +1469,22 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) filename = scu.make_filename("flux " + sem["titreannee"]) return scu.sendPDFFile(REQUEST, doc, filename + ".pdf") elif format == "png": # - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, format="png", @@ -1460,7 +1492,7 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) filename = scu.make_filename("flux " + sem["titreannee"]) @@ -1475,17 +1507,25 @@ def formsemestre_graph_parcours( else: op = "" url = urllib.quote( - "formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&sexe=%s&statut=%s&format=" - % (formsemestre_id, op, bac, bacspecialite, sexe, statut) + "formsemestre_graph_parcours?formsemestre_id=%s&%sbac=%s&bacspecialite=%s&civilite=%s&statut=%s&format=" + % (formsemestre_id, op, bac, bacspecialite, civilite, statut) ) - doc, etuds, bacs, bacspecialites, annee_bacs, sexes, statuts = graph_parcours( + ( + doc, + etuds, + bacs, + bacspecialites, + annee_bacs, + civilites, + statuts, + ) = graph_parcours( context, formsemestre_id, only_primo=only_primo, bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, ) @@ -1505,12 +1545,12 @@ def formsemestre_graph_parcours( bac=bac, bacspecialite=bacspecialite, annee_bac=annee_bac, - sexe=sexe, + civilite=civilite, statut=statut, bacs=bacs, bacspecialites=bacspecialites, annee_bacs=annee_bacs, - sexes=sexes, + civilites=civilites, statuts=statuts, percent=0, ), diff --git a/sco_synchro_etuds.py b/sco_synchro_etuds.py index 14fe953a..ec70f80f 100644 --- a/sco_synchro_etuds.py +++ b/sco_synchro_etuds.py @@ -408,7 +408,7 @@ def list_synch(context, sem, anneeapogee=None): etud = etudsapo_ident[key] etud["etudid"] = "" - etud["sexe"] = etud.get( + etud["civilite"] = etud.get( "sexe", etud.get("gender", "") ) # la cle 'sexe' est prioritaire sur 'gender' etud["inscrit"] = is_inscrit # checkbox state @@ -545,16 +545,14 @@ def formsemestre_synchro_etuds_help(context, sem): ) -def gender2sex(gender): - """Le portail code en 'M', 'F', et ScoDoc en 'MR', 'MME' - Les F sont ici codées en MME - """ - if gender == "M": - return "MR" - elif gender == "F": - return "MME" - log('gender2sex: invalid value "%s", defaulting to "M"' % gender) - return "MR" +def gender2civilite(gender): + """Le portail code en 'M', 'F', et ScoDoc en 'M', 'F', 'X'""" + if gender == "M" or gender == "F" or gender == "X": + return gender + elif not gender: + return "X" + log('gender2civilite: invalid value "%s", defaulting to "X"' % gender) + return "X" # "X" en général n'est pas affiché, donc bon choix si invalide def get_opt_str(etud, k): @@ -598,7 +596,7 @@ def do_import_etuds_from_portal(context, sem, a_importer, etudsapo_ident, REQUES "prenom": etud["prenom"].strip(), # Les champs suivants sont facultatifs (pas toujours renvoyés par le portail) "code_ine": etud.get("ine", "").strip(), - "sexe": gender2sex(etud["gender"].strip()), + "civilite": gender2civilite(etud["gender"].strip()), "etape": etud.get("etape", None), "email": etud.get("mail", "").strip(), "emailperso": etud.get("mailperso", "").strip(), @@ -738,9 +736,9 @@ def do_import_etud_admission( if x: args[sco_field] = x # Champs spécifiques: - sexe = gender2sex(etud["gender"].strip()) - if sexe: - args["sexe"] = sexe + civilite = gender2civilite(etud["gender"].strip()) + if civilite: + args["civilite"] = civilite scolars.identite_edit_nocheck(cnx, args) diff --git a/sco_trombino.py b/sco_trombino.py index b529ea77..ce3ca1b1 100644 --- a/sco_trombino.py +++ b/sco_trombino.py @@ -337,13 +337,7 @@ def _trombino_pdf(context, groups_infos, REQUEST): [img], [ Paragraph( - SU( - scolars.format_sexe(t["sexe"]) - + " " - + scolars.format_prenom(t["prenom"]) - + " " - + scolars.format_nom(t["nom"]) - ), + SU(scolars.format_nomprenom(t)), StyleSheet["Normal"], ) ], @@ -422,13 +416,7 @@ def _listeappel_photos_pdf(context, groups_infos, REQUEST): t = groups_infos.members[i] img = _get_etud_platypus_image(context, t, image_width=PHOTOWIDTH) txt = Paragraph( - SU( - scolars.format_sexe(t["sexe"]) - + " " - + scolars.format_prenom(t["prenom"]) - + " " - + scolars.format_nom(t["nom"]) - ), + SU(scolars.format_nomprenom(t)), StyleSheet["Normal"], ) if currow: diff --git a/sco_utils.py b/sco_utils.py index 88c2a29a..60b26cbc 100644 --- a/sco_utils.py +++ b/sco_utils.py @@ -704,7 +704,7 @@ if WITH_PYDOT: junk_graph = pydot.Dot("junk") junk_graph.add_node(pydot.Node("a")) n = junk_graph.get_node("a") - if type(n) == type([]): + if type(n) == type([]): # "modern" pydot def pydot_get_node(g, name): r = g.get_node(name) @@ -713,7 +713,7 @@ if WITH_PYDOT: else: return r[0] - else: + else: # very old pydot def pydot_get_node(g, name): return g.get_node(name) diff --git a/scolars.py b/scolars.py index 7a17a772..4fb479de 100644 --- a/scolars.py +++ b/scolars.py @@ -101,7 +101,7 @@ def format_etud_ident(etud): else: etud["nom_usuel"] = "" etud["prenom"] = format_prenom(etud["prenom"]) - etud["sexe"] = format_sexe(etud["sexe"]) + etud["civilite_str"] = format_civilite(etud["civilite"]) # Nom à afficher: if etud["nom_usuel"]: etud["nom_disp"] = etud["nom_usuel"] @@ -111,10 +111,12 @@ def format_etud_ident(etud): etud["nom_disp"] = etud["nom"] etud["nomprenom"] = format_nomprenom(etud) # M. Pierre DUPONT - if etud["sexe"] == "M.": + if etud["civilite"] == "M": etud["ne"] = "" - else: + elif etud["civilite"] == "F": etud["ne"] = "e" + else: # 'X' + etud["ne"] = "(e)" # Mail à utiliser pour les envois vers l'étudiant: # choix qui pourrait être controé par une preference # ici priorité au mail institutionnel: @@ -128,14 +130,20 @@ def force_uppercase(s): def format_nomprenom(etud): - "formatte sexe/nom/prenom pour affichages" - return " ".join( - [format_sexe(etud["sexe"]), format_prenom(etud["prenom"]), etud["nom_disp"]] - ) + """Formatte civilité/nom/prenom pour affichages: "M. Pierre Dupont" """ + l = [] + for x in [ + format_civilite(etud["civilite"]), + format_prenom(etud["prenom"]), + etud.get("nom_disp", "") or etud.get("nom_usuel", "") or etud["nom"], + ]: + if x: + l.append(x) + return " ".join(l) def format_prenom(s): - "formatte prenom etudiant pour affichage" + "Formatte prenom etudiant pour affichage" if not s: return "" frags = s.split() @@ -162,22 +170,33 @@ def format_nom(s, uppercase=True): return format_prenom(s) -def format_sexe(sexe): - sexe = scu.strlower(sexe) - if sexe == "mr" or sexe == "m." or sexe == "m": - return "M." - else: - return "Mme" +def input_civilite(s): + """Converts external representation of civilite to internal: + 'M', 'F', or 'X' (and nothing else). + Raises valueError if conversion fails. + """ + s = scu.strupper(s).strip() + if s in ("M", "M.", "MR", "H"): + return "M" + elif s in ("F", "MLLE", "MLLE.", "MELLE", "MME"): + return "F" + elif s == "X" or not s: + return "X" + raise ValueError("valeur invalide pour la civilité: %s" % s) -def normalize_sexe(sexe): - "returns 'MR' ou 'MME'" - sexe = scu.strupper(sexe).strip() - if sexe in ("M.", "M", "MR", "H"): - return "MR" - elif sexe in ("MLLE", "MLLE.", "MELLE", "MME", "F"): - return "MME" - raise ValueError("valeur invalide pour le sexe: %s" % sexe) +def format_civilite(civilite): + """returns 'M.' ou 'Mme' ou '' (pour le genre neutre, + personne ne souhaitant pas d'affichage) + """ + try: + return { + "M": "M.", + "F": "Mme", + "X": "", + }[civilite] + except KeyError: + raise ValueError("valeur invalide pour la civilité: %s" % civilite) def format_lycee(nomlycee): @@ -241,7 +260,7 @@ _identiteEditor = EditableTable( "nom", "nom_usuel", "prenom", - "sexe", + "civilite", # 'M", "F", or "X" "date_naissance", "lieu_naissance", "dept_naissance", @@ -257,10 +276,10 @@ _identiteEditor = EditableTable( input_formators={ "nom": force_uppercase, "prenom": force_uppercase, - "sexe": force_uppercase, + "civilite": input_civilite, "date_naissance": DateDMYtoISO, }, - output_formators={"date_naissance": DateISOtoDMY, "sexe": normalize_sexe}, + output_formators={"date_naissance": DateISOtoDMY}, convert_null_outputs_to_empty=True, allow_set_id=True, # car on specifie le code Apogee a la creation ) @@ -269,13 +288,14 @@ identite_delete = _identiteEditor.delete def identite_list(cnx, *a, **kw): - "list, add 'annee_naissance'" + """List, adding on the fly 'annee_naissance' and 'civilite_str' (M., Mme, "").""" objs = _identiteEditor.list(cnx, *a, **kw) for o in objs: if o["date_naissance"]: o["annee_naissance"] = int(o["date_naissance"].split("/")[2]) else: o["annee_naissance"] = o["date_naissance"] + o["civilite_str"] = format_civilite(o["civilite"]) return objs @@ -372,7 +392,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None): if notify_to: # etat AVANT edition pour envoyer diffs before = identite_list(cnx, {"etudid": args["etudid"]})[0] - before["sexe"] = format_sexe(before["sexe"]) identite_edit_nocheck(cnx, args) @@ -380,7 +399,6 @@ def identite_edit(cnx, args, context=None, REQUEST=None): if notify_to: etud = context.getEtudInfo(etudid=args["etudid"], filled=True)[0] after = identite_list(cnx, {"etudid": args["etudid"]})[0] - after["sexe"] = format_sexe(after["sexe"]) notify_etud_change( context, notify_to, @@ -412,7 +430,7 @@ def notify_etud_change(context, email_addr, etud, before, after, subject): """ txt = [ "Code NIP:" + etud["code_nip"], - "Genre: " + etud["sexe"], + "Civilité: " + etud["civilite_str"], "Nom: " + etud["nom"], "Prénom: " + etud["prenom"], "Etudid: " + etud["etudid"], diff --git a/scotests/demo/demo_reset_noms.py b/scotests/demo/demo_reset_noms.py index 5d569362..d1f00cf3 100755 --- a/scotests/demo/demo_reset_noms.py +++ b/scotests/demo/demo_reset_noms.py @@ -3,12 +3,12 @@ """Outils pour environnements de démo. -Change aléatoirement les identites (nip, sexe, nom, prenom) des étudiants d'un semestre. +Change aléatoirement les identites (nip, civilite, nom, prenom) des étudiants d'un semestre. Le NIP est choisi aléatoirement (nombre entier à 8 chiffres). Les noms et prénoms sont issus des fichiers noms.txt, prenoms-h.txt, prenoms-f.txt (ce sont simlement les plus fréquemment rencontrés en France). -Le sexe est choisi aléatoirement 50-50. +La civilité est choisie aléatoirement 50-50 Homme/Femme. """ import sys @@ -54,17 +54,17 @@ cursor.execute( wcursor = cnx.cursor() n = 0 for (etudid,) in cursor: - sexe = random.choice(("M.", "MME")) - nom, prenom = nomprenom(sexe) + civilite = random.choice(("M", "F")) # pas de neutre, on pourrait ajouter 'X' + nom, prenom = nomprenom(civilite) print(f"{etudid}: {nom}\t{prenom}") args = { "nom": nom, "prenom": prenom, - "sexe": sexe, + "civilite": civilite, "etudid": etudid, "code_nip": random.randrange(10000000, 99999999), } - req = "update identite set nom=%(nom)s, prenom=%(prenom)s, sexe=%(sexe)s where etudid=%(etudid)s" + req = "update identite set nom=%(nom)s, prenom=%(prenom)s, civilite=%(civilite)s where etudid=%(etudid)s" # print( req % args) wcursor.execute(req, args) n += 1 diff --git a/scotests/demo/gen_nomprenoms.py b/scotests/demo/gen_nomprenoms.py index ec36fd75..6ab85188 100644 --- a/scotests/demo/gen_nomprenoms.py +++ b/scotests/demo/gen_nomprenoms.py @@ -10,14 +10,19 @@ cur_dir = Path(os.path.abspath(__file__)).parent NOMS = [x.strip() for x in open(cur_dir / "noms.txt").readlines()] PRENOMS_H = [x.strip() for x in open(cur_dir / "prenoms-h.txt").readlines()] PRENOMS_F = [x.strip() for x in open(cur_dir / "prenoms-f.txt").readlines()] +PRENOMS_X = [x.strip() for x in open(cur_dir / "prenoms-x.txt").readlines()] -def nomprenom(sexe): - """un nom et un prenom au hasard, - toujours en majuscules. +def nomprenom(civilite): + """Un nom et un prenom au hasard, + toujours en majuscules. Pour tests et démos. """ - if "e" in sexe.lower() or "f" in sexe.lower(): + if civilite == "F": prenom = random.choice(PRENOMS_F) - else: + elif civilite == "M": prenom = random.choice(PRENOMS_H) + elif civilite == "X": + prenom = random.choice(PRENOMS_X) + else: + raise ValueError("civilite must be M, F or X") return random.choice(NOMS).upper(), prenom.upper() diff --git a/scotests/demo/prenoms-x.txt b/scotests/demo/prenoms-x.txt new file mode 100644 index 00000000..68ce1abf --- /dev/null +++ b/scotests/demo/prenoms-x.txt @@ -0,0 +1,10 @@ +Camille +Sacha +Eden +Maxime +Morgan +Charlie +Alix +Claude +Ufuk +Lou diff --git a/scotests/sco_fake_gen.py b/scotests/sco_fake_gen.py index 2a066de0..5bf59fe5 100644 --- a/scotests/sco_fake_gen.py +++ b/scotests/sco_fake_gen.py @@ -38,6 +38,7 @@ DEMODIR = sco_utils.SCO_SRCDIR + "/scotests/demo/" NOMS = [x.strip() for x in open(DEMODIR + "/noms.txt").readlines()] PRENOMS_H = [x.strip() for x in open(DEMODIR + "/prenoms-h.txt").readlines()] PRENOMS_F = [x.strip() for x in open(DEMODIR + "/prenoms-f.txt").readlines()] +PRENOMS_X = [x.strip() for x in open(DEMODIR + "/prenoms-x.txt").readlines()] # nb: en python2, les chaines ci-dessus sont en utf8 @@ -66,16 +67,20 @@ class ScoFake: sys.stderr.flush() log("ScoFake: " + str(msg)) - def sexenomprenom(self): + def civilitenomprenom(self): """un nom et un prenom au hasard, toujours en majuscules. """ - sexe = random.choice(("M", "F")) - if "e" in sexe.lower() or "f" in sexe.lower(): + civilite = random.choice(("M", "M", "M", "F", "F", "F", "X")) + if civilite == "F": prenom = random.choice(PRENOMS_F) - else: + elif civilite == "M": prenom = random.choice(PRENOMS_H) - return sexe, random.choice(NOMS).upper(), prenom.upper() + elif civilite == "X": + prenom = random.choice(PRENOMS_X) + else: + raise ValueError("invalid civilite value") + return civilite, random.choice(NOMS).upper(), prenom.upper() @logging_meth def create_etud( @@ -85,7 +90,7 @@ class ScoFake: nom="", prenom="", code_ine="", - sexe="", + civilite="", etape="TST1", email="test@localhost", emailperso="perso@localhost", @@ -106,10 +111,10 @@ class ScoFake: cnx = self.context.GetDBConnexion() if code_nip == "": code_nip = str(random.randint(10000, 99999)) - if not sexe or not nom or not prenom: - r_sexe, r_nom, r_prenom = self.sexenomprenom() - if not sexe: - sexe = r_sexe + if not civilite or not nom or not prenom: + r_civilite, r_nom, r_prenom = self.civilitenomprenom() + if not civilite: + civilite = r_civilite if not nom: nom = r_nom if not prenom: From 2f4edc48dcf7e84d2983fb506a566bb84a695f20 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 13 Feb 2021 19:20:21 +0100 Subject: [PATCH 16/18] 7.23 / pylint pv jury --- VERSION.py | 8 +++++--- sco_pvjury.py | 30 +++++++++++++++++++----------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/VERSION.py b/VERSION.py index 8e8a40a4..3ff1eed4 100644 --- a/VERSION.py +++ b/VERSION.py @@ -1,19 +1,21 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "7.22" +SCOVERSION = "7.23" SCONAME = "ScoDoc" SCONEWS = """

    Année 2021

      -
    • Modernisation du code Python.
    • +
    • Gestion du genre neutre (pas d'affichage de la civilité)
    • +
    • Diverses corrections (PV de jurys, ...)
    • +
    • Modernisation du code Python

    Année 2020

    • Corrections d'erreurs, améliorations saise absences< et affichage bulletins
    • -
    • Nouveau site scodoc.org pour la documentation.
    • +
    • Nouveau site scodoc.org pour la documentation
    • Enregistrement de semestres extérieurs
    • Améliorations PV de Jury
    • Contributions J.-M. Place: aide au diagnostic problèmes export Apogée diff --git a/sco_pvjury.py b/sco_pvjury.py index f62a345f..191247c7 100644 --- a/sco_pvjury.py +++ b/sco_pvjury.py @@ -27,10 +27,13 @@ """Edition des PV de jury """ +import time +from reportlab.platypus import Paragraph +from reportlab.lib import styles import sco_utils as scu import notesdb as ndb - +from notes_log import log import scolars import sco_formsemestre import sco_groups @@ -42,7 +45,8 @@ import sco_excel from TrivialFormulator import TrivialFormulator from gen_tables import GenTable import sco_pvpdf -from sco_pdf import * +import sco_pdf +from sco_pdf import PDFLOCK """PV Jury IUTV 2006: on détaillait 8 cas: Jury de semestre n @@ -75,7 +79,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 ( - CONFIG.CAPITALIZE_ALL_UES + scu.CONFIG.CAPITALIZE_ALL_UES and sco_codes_parcours.code_semestre_validant(decision_sem["code"]) ) ): @@ -414,9 +418,11 @@ def pvjury_table( if context.get_preference("bul_show_ects", formsemestre_id): columns_ids += ["ects"] - # if dpv['semestre_non_terminal']: - # dec 2017: indique toujours le devenir ("diplôme obtenu" ou semestre suivant) - columns_ids += ["validation_parcours_code", "devenir"] + # XXX if not dpv["semestre_non_terminal"]: + # La colonne doit être présente: redoublants validant leur diplome + # en répétant un semestre ancien: exemple: S1 (ADM), S2 (ADM), S3 (AJ), S4 (ADM), S3 (ADM)=> diplôme + columns_ids += ["validation_parcours_code"] + columns_ids += ["devenir"] columns_ids += ["observations"] lines = [] @@ -434,7 +440,7 @@ def pvjury_table( context, e["etat"], e["decision_sem"] ), "ue_cap": e["decisions_ue_descr"], - "validation_parcours_code": "ADM" if e["validation_parcours"] else "AJ", + "validation_parcours_code": "ADM" if e["validation_parcours"] else "", "devenir": e["autorisations_descr"], "observations": ndb.unquote(e["observation"]), "mention": e["mention"], @@ -451,10 +457,10 @@ def pvjury_table( ) # vertical space i = e["identite"] l["nomprenom"] = [ - Paragraph(SU(i["nomprenom"]), cell_style), - Paragraph(SU(i["code_nip"]), cell_style), + Paragraph(sco_pdf.SU(i["nomprenom"]), cell_style), + Paragraph(sco_pdf.SU(i["code_nip"]), cell_style), Paragraph( - SU( + sco_pdf.SU( "Né le %s" % i["date_naissance"] + (" à %s" % i["lieu_naissance"] if i["lieu_naissance"] else "") + (" (%s)" % i["dept_naissance"] if i["dept_naissance"] else "") @@ -516,7 +522,9 @@ def formsemestre_pvjury( titles=titles, columns_ids=columns_ids, filename=scu.make_filename("decisions " + sem["titreannee"]), - origin="Généré par %s le " % VERSION.SCONAME + scu.timedate_human_repr() + "", + origin="Généré par %s le " % scu.VERSION.SCONAME + + scu.timedate_human_repr() + + "", caption="Décisions jury pour " + sem["titreannee"], html_class="table_leftalign", html_sortable=True, From 91bb62587af93b8ab4c993e5e3b1d607ec201853 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 13 Feb 2021 21:28:59 +0100 Subject: [PATCH 17/18] Closes #11 --- sco_recapcomplet.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sco_recapcomplet.py b/sco_recapcomplet.py index 8727f74b..6fb23f74 100644 --- a/sco_recapcomplet.py +++ b/sco_recapcomplet.py @@ -33,6 +33,7 @@ import jaxml import sco_utils as scu from notes_log import log +import scolars import sco_bulletins, sco_excel import sco_groups import sco_evaluations @@ -234,6 +235,7 @@ def make_formsemestre_recapcomplet( pour tous les étudiants, les moyennes par UE et générale, trié par moyenne générale décroissante. """ + civ_nom_prenom = False # 3 colonnes différentes ou une seule avec prénom abrégé ? if format == "xml": return _formsemestre_recapcomplet_xml( context, @@ -251,6 +253,7 @@ def make_formsemestre_recapcomplet( force_publishing=force_publishing, ) if format[:3] == "xls": + civ_nom_prenom = True # 3 cols: civilite, nom, prenom keep_numeric = True # pas de conversion des notes en strings else: keep_numeric = False @@ -292,7 +295,11 @@ def make_formsemestre_recapcomplet( # Construit une liste de listes de chaines: le champs du tableau resultat (HTML ou CSV) F = [] - h = [rank_label, "Nom"] + h = [rank_label] + if civ_nom_prenom: + h += ["Civilité", "Nom", "Prénom"] + else: + h += ["Nom"] if not hidebac: h.append("Bac") @@ -370,7 +377,7 @@ def make_formsemestre_recapcomplet( gr_name = group["group_name"] or "" is_dem[etudid] = False if rank_partition_id: - rang_gr, ninscrits_gr, rank_gr_name = sco_bulletins.get_etud_rangs_groups( + rang_gr, _, rank_gr_name = sco_bulletins.get_etud_rangs_groups( context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt ) if rank_gr_name[rank_partition_id]: @@ -383,8 +390,13 @@ def make_formsemestre_recapcomplet( else: rank = nt.get_etud_rang(etudid) - l = [rank, nt.get_nom_short(etudid)] # rang, nom, e = nt.identdict[etudid] + if civ_nom_prenom: + scolars.format_etud_ident(e) + l = [rank, e["civilite_str"], e["nom_disp"], e["prenom"]] # civ, nom prenom + else: + l = [rank, nt.get_nom_short(etudid)] # rang, nom, + if not hidebac: bac = sco_bac.Baccalaureat(e["bac"], e["specialite"]) l.append(bac.abbrev()) @@ -457,6 +469,8 @@ def make_formsemestre_recapcomplet( def add_bottom_stat(key, title, corner_value=""): l = ["", title] + if civ_nom_prenom: + l += ["", ""] if not hidebac: l.append("") if format[:3] == "xls" or format == "csv": From 54771c8303b018bbaceb4b7b68071b95027f9c32 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sat, 13 Feb 2021 22:06:03 +0100 Subject: [PATCH 18/18] Nom avant prenom sur formulaire saisie notes + deco+ + linted css. --- sco_saisie_notes.py | 8 +++- scolars.py | 23 ++++----- static/css/scodoc.css | 106 +++++++++++------------------------------- 3 files changed, 45 insertions(+), 92 deletions(-) diff --git a/sco_saisie_notes.py b/sco_saisie_notes.py index 7decaf79..5309ee9c 100644 --- a/sco_saisie_notes.py +++ b/sco_saisie_notes.py @@ -1127,7 +1127,13 @@ def _form_saisie_notes(context, E, M, group_ids, destination="", REQUEST=None): for group_info in e["groups"]: etud_classes.append(group_info["group_id"]) - label = '' % classdem + e["nomprenom"] + "" + label = ( + '' % classdem + + e["civilite_str"] + + " " + + scolars.format_nomprenom(e, reverse=True) + + "" + ) # Historique des saisies de notes: if not disabled: diff --git a/scolars.py b/scolars.py index 4fb479de..7b407f1b 100644 --- a/scolars.py +++ b/scolars.py @@ -129,17 +129,18 @@ def force_uppercase(s): return s -def format_nomprenom(etud): - """Formatte civilité/nom/prenom pour affichages: "M. Pierre Dupont" """ - l = [] - for x in [ - format_civilite(etud["civilite"]), - format_prenom(etud["prenom"]), - etud.get("nom_disp", "") or etud.get("nom_usuel", "") or etud["nom"], - ]: - if x: - l.append(x) - return " ".join(l) +def format_nomprenom(etud, reverse=False): + """Formatte civilité/nom/prenom pour affichages: "M. Pierre Dupont" + Si reverse, "Dupont Pierre", sans civilité. + """ + nom = etud.get("nom_disp", "") or etud.get("nom_usuel", "") or etud["nom"] + prenom = format_prenom(etud["prenom"]) + civilite = format_civilite(etud["civilite"]) + if reverse: + fs = [nom, prenom] + else: + fs = [civilite, prenom, nom] + return " ".join([x for x in fs if x]) def format_prenom(s): diff --git a/static/css/scodoc.css b/static/css/scodoc.css index 48dd4df8..deb9cf3c 100644 --- a/static/css/scodoc.css +++ b/static/css/scodoc.css @@ -332,8 +332,7 @@ h2.listesems { margin-bottom: 0px; } -table.semlist tr.gt_firstrow th { -} +/* table.semlist tr.gt_firstrow th {} */ table.semlist tr td { border: none; @@ -690,8 +689,7 @@ a.stdlink:hover { text-decoration: underline; } -a.link_accessible { -} +/* a.link_accessible {} */ a.link_unauthorized, a.link_unauthorized:visited { color: rgb(75,75,75); } @@ -712,8 +710,8 @@ span.spanlink:hover { margin-bottom: 3px; -ms-word-break: break-all; word-break: break-all; - // non std for webkit: - work-break: break-word; + /* non std for webkit: */ + word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; @@ -913,9 +911,10 @@ span.eval_title { font-weight: bold; font-size: 14pt; } -#saisie_notes span.eval_title { - /* border-bottom: 1px solid rgb(100,100,100); */ +/* #saisie_notes span.eval_title { + border-bottom: 1px solid rgb(100,100,100); } +*/ span.jurylink { margin-left: 1.5em; @@ -1012,9 +1011,6 @@ h2.formsemestre, .gtrcontent h2 { border-width: 0; border-collapse: collapse; } -.formsemestre_page_title table.semtitle { - /* width: 100%; */ -} .formsemestre_page_title { width: 100%; @@ -1058,6 +1054,9 @@ h2.formsemestre, .gtrcontent h2 { #formnotes .tf-ro-field.formnote_bareme { font-weight: bold; } +#formnotes td.tf-fieldlabel { + border-bottom: 1px dotted #fdcaca; +} /* .formsemestre_menubar { border-top: 3px solid #67A7E3; @@ -1105,8 +1104,6 @@ h2.formsemestre, .gtrcontent h2 { width : 200px; } -.sco_dropdown_menu { -} .sco_dropdown_menu > li { width : auto; /* 120px !important; */ font-size: 12px; @@ -1133,10 +1130,6 @@ span.inscr_addremove_menu { font-weight: bold; padding-right: 1px; } -.formsemestre_page_title span.lock { - -} - div.formsemestre_status { -moz-border-radius: 8px; -khtml-border-radius: 8px; @@ -1227,10 +1220,6 @@ ul.ue_inscr_list li.etud { border-spacing: 1px; } -#grouplists td { -} - - /* Modules */ div.moduleimpl_tableaubord { padding: 7px; @@ -1264,20 +1253,10 @@ th.moduleimpl_evaluations a:hover { text-decoration: underline; } -tr.moduleimpl_evaluation_row { -} - -td.moduleimpl_evaluation_row { -} - tr.mievr { background-color:#eeeeee; } -tr.mievr_spaced { - /* margin-top: 20px; */ -} - tr.mievr_rattr { background-color:#dddddd; } @@ -1575,8 +1554,6 @@ tr.recap_row_min, tr.recap_row_max { font-weight: normal; font-style: italic; } -tr.recap_row_coef { -} tr.recap_row_moy { font-weight: bold; } @@ -1809,9 +1786,6 @@ div.bulletin_menubar { text-decoration: underline; } -div.bull_appreciations { -} - .bull_appreciations p { margin: 0; font-style: italic; @@ -1867,9 +1841,6 @@ input.note_saved { color: green; } -input.note { -} - span.history { font-style: italic; } @@ -2016,9 +1987,6 @@ td.fvs_val_inf { color: red; } -td.fvs_chk { -} - td.fvs_tit { font-weight: bold; text-align: left; @@ -2274,8 +2242,6 @@ table.recap_hide_details tr.sem_courant td.ue_acro span, table.recap_hide_detail padding-bottom: 5px; } -td.rcp_moy { -} td.sem_ects_tit { text-align: right; } @@ -2308,9 +2274,6 @@ td.ue_cmp { color: green; } -td.ue { -} - td.ue_capitalized { text-decoration: underline; } @@ -2354,9 +2317,6 @@ div.pas_sembox { font-family: arial,verdana,sans-serif; } -div.pas_empty_sems { -} - span.sp_etape { display: inline-block; width: 4em; @@ -2365,10 +2325,6 @@ span.sp_etape { color: black; } -.inscrit { -/* font-weight: bold; */ -} - .inscrailleurs { font-weight: bold; color: red !important; @@ -2534,9 +2490,6 @@ td.calday { vertical-align: top; } -div.cal_evaluations table.monthcalendar td.calcol { -} - div.cal_evaluations table.monthcalendar td.calcell { padding-left: 0.6em; width: 6em; @@ -2585,24 +2538,24 @@ div.update_warning_sub { padding-left: 8ex; } -/* Titres des tabs: */ -.nav-tabs li a { - /* font-variant: small-caps; */ - /*font-size: 13pt;*/ -} +/* + Titres des tabs: + .nav-tabs li a { + font-variant: small-caps; + font-size: 13pt; + } -/* -#group-tabs { - clear: both; -} + #group-tabs { + clear: both; + } -#group-tabs ul { - display: inline; -} + #group-tabs ul { + display: inline; + } -#group-tabs ul li { - display: inline; -} + #group-tabs ul li { + display: inline; + } */ /* Page accueil */ @@ -2758,10 +2711,6 @@ div.apo_csv_list { div.apo_compare_csv_form_but { margin-top: 10px; margin-bottom: 10px; -} -div.apo_compare_csv_form_submit { - - } div.apo_compare_csv_form_submit input { margin-top: 2ex; @@ -2892,12 +2841,9 @@ div#formsemestre_ext_edit_ue_validations { form.tf_ext_edit_ue_validations table { border-collapse: collapse; width: 97%; - margin-left: 1em;ext + margin-left: 1em; margin-right: 1em; } -form.tf_ext_edit_ue_validations table, form.tf_ext_edit_ue_validations table th, form.tf_ext_edit_ue_validations table td { - /* border: 1px solid black; */ -} form.tf_ext_edit_ue_validations table th, form.tf_ext_edit_ue_validations table td { border-bottom: 1px solid rgb(168, 168, 168); }