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 = '

' 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 = '' 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: