diff --git a/app/scodoc/SuppressAccents.py b/app/scodoc/SuppressAccents.py index f0b4d34fe..18332fbb6 100644 --- a/app/scodoc/SuppressAccents.py +++ b/app/scodoc/SuppressAccents.py @@ -5,6 +5,7 @@ Source: http://wikipython.flibuste.net/moin.py/JouerAvecUnicode#head-1213938516c633958921591439c33d202244e2f4 """ +import six _reptable = {} @@ -202,5 +203,5 @@ def suppression_diacritics(s): @rtype: unicode """ if isinstance(s, str): - s = unicode(s, "utf8", "replace") + s = six.text_type(s, "utf8", "replace") return s.translate(_reptable) diff --git a/app/scodoc/TrivialFormulator.py b/app/scodoc/TrivialFormulator.py index 3934d5760..06b0f60ee 100644 --- a/app/scodoc/TrivialFormulator.py +++ b/app/scodoc/TrivialFormulator.py @@ -196,12 +196,12 @@ class TF: for (field, descr) in self.formdescription: # special case for boolcheckbox if descr.get("input_type", None) == "boolcheckbox" and self.submitted(): - if not self.values.has_key(field): + if field not in self.values: self.values[field] = 0 else: self.values[field] = 1 - if not self.values.has_key(field): - if descr.has_key("default"): # first: default in form description + if field not in self.values: + if "default" in descr: # first: default in form description self.values[field] = descr["default"] else: # then: use initvalues dict self.values[field] = self.initvalues.get(field, "") @@ -214,7 +214,7 @@ class TF: ): self.values[field] = str(self.values[field]) # - if not self.values.has_key("tf-checked"): + if "tf-checked" not in self.values: if self.submitted(): # si rien n'est coché, tf-checked n'existe plus dans la reponse self.values["tf-checked"] = [] @@ -264,14 +264,14 @@ class TF: ) ok = 0 if typ[:3] == "int" or typ == "float" or typ == "real": - if descr.has_key("min_value") and val < descr["min_value"]: + if "min_value" in descr and val < descr["min_value"]: msg.append( "La valeur (%d) du champ '%s' est trop petite (min=%s)" % (val, field, descr["min_value"]) ) ok = 0 - if descr.has_key("max_value") and val > descr["max_value"]: + if "max_value" in descr and val > descr["max_value"]: msg.append( "La valeur (%s) du champ '%s' est trop grande (max=%s)" % (val, field, descr["max_value"]) @@ -279,7 +279,7 @@ class TF: ok = 0 # allowed values - if descr.has_key("allowed_values"): + if "allowed_values" in descr: if descr.get("input_type", None) == "checkbox": # for checkboxes, val is a list for v in val: @@ -293,7 +293,7 @@ class TF: elif not val in descr["allowed_values"]: msg.append("valeur invalide (%s) pour le champ '%s'" % (val, field)) ok = 0 - if descr.has_key("validator"): + if "validator" in descr: if not descr["validator"](val, field): msg.append("valeur invalide (%s) pour le champ '%s'" % (val, field)) ok = 0 diff --git a/app/scodoc/notesdb.py b/app/scodoc/notesdb.py index b46b2c9b6..3df2fd466 100644 --- a/app/scodoc/notesdb.py +++ b/app/scodoc/notesdb.py @@ -1,8 +1,8 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -from __future__ import absolute_import -import pdb, os, sys, string + +import string import traceback import psycopg2 import psycopg2.pool diff --git a/app/scodoc/pe_avislatex.py b/app/scodoc/pe_avislatex.py index fbf356f8f..ba8654d57 100644 --- a/app/scodoc/pe_avislatex.py +++ b/app/scodoc/pe_avislatex.py @@ -224,9 +224,9 @@ def get_code_latex_avis_etudiant( scu.SCO_ENCODING ) - # Gestion des pb d'encodage XXX debug - assert isinstance(tag_latex, unicode) - assert isinstance(valeur, unicode) + # Vérification des pb d'encodage (debug) + # assert isinstance(tag_latex, unicode) + # assert isinstance(valeur, unicode) # Substitution code = code.replace("**" + tag_latex + "**", valeur) diff --git a/app/scodoc/pe_jurype.py b/app/scodoc/pe_jurype.py index 4c9fd4be3..55bf2601f 100644 --- a/app/scodoc/pe_jurype.py +++ b/app/scodoc/pe_jurype.py @@ -46,10 +46,10 @@ import os try: from cStringIO import StringIO -except: +except ImportError: try: from StringIO import StringIO - except: + except ImportError: from io import StringIO from zipfile import ZipFile, BadZipfile import pprint @@ -382,7 +382,7 @@ class JuryPE: c'est à dire ceux pour lesquels il faudra prendre en compte ses notes dans les calculs de moyenne (type 1A=S1+S2/2) """ - if not self.PARCOURSINFO_DICT.has_key(etudid): + if etudid not in self.PARCOURSINFO_DICT: etud = self.get_cache_etudInfo_d_un_etudiant( self.context, etudid ) # On charge les données de l'étudiant @@ -476,7 +476,7 @@ class JuryPE: reponse = True if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: pe_tools.pe_print(" -> à éliminer car réorienté (NAR)") - if "DEM" in parcours.values(): # Eliminé car DEM + if "DEM" in list(parcours.values()): # Eliminé car DEM reponse = True if pe_tools.PE_DEBUG and pe_tools.PE_DEBUG >= 2: pe_tools.pe_print(" -> à éliminer car DEM") @@ -567,8 +567,8 @@ class JuryPE: dec = nt.get_etud_decision_sem( etudid ) # quelle est la décision du jury ? - if ( - dec and dec["code"] in sco_codes_parcours.CODES_SEM_VALIDES.keys() + if dec and dec["code"] in list( + sco_codes_parcours.CODES_SEM_VALIDES.keys() ): # isinstance( sesMoyennes[i+1], float) and # mT = sesMoyennes[i+1] # substitue la moyenne si le semestre suivant est "valide" leFid = sem["formsemestre_id"] @@ -603,7 +603,7 @@ class JuryPE: charge également les données des nouveaux étudiants qui en font partis. """ # Semestre taggué avec classement dans le groupe - if not self.semTagDict.has_key(fid): + if fid not in self.semTagDict: nt = self.get_cache_notes_d_un_semestre(self.context, fid) # Création du semestres @@ -656,7 +656,7 @@ class JuryPE: * '3S', '4S' => fusion des semestres * [ 'Si', 'iA' , ... ] => une liste combinant les formats précédents """ - champs_possibles = JuryPE.PARCOURS.keys() + champs_possibles = list(JuryPE.PARCOURS.keys()) if ( not isinstance(liste_semestres, list) and not isinstance(liste_semestres, str) @@ -962,7 +962,7 @@ class JuryPE: allTags = allTags.union(set(self.get_allTagForAggregat(nom))) return sorted(list(allTags)) if len(allTags) > 0 else [] - def table_syntheseJury(self, mode="singlesheet"): # XXX was str_syntheseJury + def table_syntheseJury(self, mode="singlesheet"): # was str_syntheseJury """Table(s) du jury mode: singlesheet ou multiplesheet pour export excel """ @@ -1011,7 +1011,7 @@ class JuryPE: ] # Les aggrégats à afficher par ordre tel que indiqué dans le dictionnaire parcours - aggregats = JuryPE.PARCOURS.keys() # ['S1', 'S2', ..., '1A', '4S'] + aggregats = list(JuryPE.PARCOURS.keys()) # ['S1', 'S2', ..., '1A', '4S'] aggregats = sorted( aggregats, key=lambda t: JuryPE.PARCOURS[t]["ordre"] ) # Tri des aggrégats diff --git a/app/scodoc/pe_semestretag.py b/app/scodoc/pe_semestretag.py index 13c36d216..18e5ba7c4 100644 --- a/app/scodoc/pe_semestretag.py +++ b/app/scodoc/pe_semestretag.py @@ -130,7 +130,7 @@ class SemestreTag(pe_tagtable.TableTag): self.add_moyennesTag(tag, self.comp_MoyennesTag(tag, force=True)) self.add_moyennesTag("dut", self.get_moyennes_DUT()) self.taglist = sorted( - self.tagdict.keys() + ["dut"] + list(self.tagdict.keys()) + ["dut"] ) # actualise la liste des tags # ----------------------------------------------------------------------------- @@ -170,7 +170,7 @@ class SemestreTag(pe_tagtable.TableTag): tag ) # extrait un tagname et un éventuel coefficient de pondération (par defaut: 1) # tagname = tagname - if not tagdict.has_key(tagname): # Ajout d'une clé pour le tag + if tagname not in tagdict: # Ajout d'une clé pour le tag tagdict[tagname] = {} # Ajout du modimpl au tagname considéré diff --git a/app/scodoc/pe_settag.py b/app/scodoc/pe_settag.py index 2db2b4a14..05eba20f2 100644 --- a/app/scodoc/pe_settag.py +++ b/app/scodoc/pe_settag.py @@ -126,7 +126,7 @@ class SetTag(pe_tagtable.TableTag): # ------------------------------------------------------------------------------------------------------------------- def get_etudids(self): - return self.identdict.keys() + return list(self.identdict.keys()) # ------------------------------------------------------------------------------------------------------------------- def do_taglist(self): @@ -272,7 +272,7 @@ class SetTagInterClasse(pe_tagtable.TableTag): # ------------------------------------------------------------------------------------------------------------------- def get_etudids(self): - return self.identdict.keys() + return list(self.identdict.keys()) # ------------------------------------------------------------------------------------------------------------------- def do_taglist(self): diff --git a/app/scodoc/pe_tools.py b/app/scodoc/pe_tools.py index 16b394fea..966799c89 100644 --- a/app/scodoc/pe_tools.py +++ b/app/scodoc/pe_tools.py @@ -44,6 +44,7 @@ import unicodedata import app.scodoc.sco_utils as scu from app.scodoc.notes_log import log +import six PE_DEBUG = 0 @@ -141,8 +142,8 @@ def escape_for_latex(s): } exp = re.compile( "|".join( - re.escape(unicode(key)) - for key in sorted(conv.keys(), key=lambda item: -len(item)) + re.escape(six.text_type(key)) + for key in sorted(list(conv.keys()), key=lambda item: -len(item)) ) ) return exp.sub(lambda match: conv[match.group()], s) diff --git a/app/scodoc/pe_view.py b/app/scodoc/pe_view.py index 7f9899575..b1eeba62e 100644 --- a/app/scodoc/pe_view.py +++ b/app/scodoc/pe_view.py @@ -98,7 +98,7 @@ def pe_view_sem_recap( jury = pe_jurype.JuryPE(context, semBase) # Ajout avis LaTeX au même zip: - etudids = jury.syntheseJury.keys() + etudids = list(jury.syntheseJury.keys()) # Récupération du template latex, du footer latex et du tag identifiant les annotations relatives aux PE # (chaines unicodes, html non quoté) diff --git a/app/scodoc/sco_abs.py b/app/scodoc/sco_abs.py index 74043f9bb..c05924a66 100644 --- a/app/scodoc/sco_abs.py +++ b/app/scodoc/sco_abs.py @@ -215,7 +215,7 @@ def DateRangeISO(context, date_beg, date_end, workable=1): r.append(cur) cur = cur.next_day() - return map(lambda x: x.ISO(), r) + return [x.ISO() for x in r] def day_names(context): @@ -413,7 +413,7 @@ def ListeAbsDate(context, etudid, beg_date, end_date): A[(jour, matin)]["begin"] = dat + " 12:00:00" A[(jour, matin)]["end"] = dat + " 17:59:59" # sort - R = A.values() + R = list(A.values()) R.sort(key=lambda x: (x["begin"])) return R diff --git a/app/scodoc/sco_abs_views.py b/app/scodoc/sco_abs_views.py index 41f5ec444..fc3408d77 100644 --- a/app/scodoc/sco_abs_views.py +++ b/app/scodoc/sco_abs_views.py @@ -961,7 +961,7 @@ def _TablesAbsEtud( return "après-midi" def descr_exams(a): - if not a.has_key("evals"): + if "evals" not in a: return "" ex = [] for ev in a["evals"]: diff --git a/app/scodoc/sco_apogee_csv.py b/app/scodoc/sco_apogee_csv.py index 633cfbebd..e75b6324c 100644 --- a/app/scodoc/sco_apogee_csv.py +++ b/app/scodoc/sco_apogee_csv.py @@ -89,6 +89,7 @@ import os from cStringIO import StringIO from zipfile import ZipFile import pprint +from functools import reduce # Pour la détection auto de l'encodage des fichiers Apogée: try: @@ -832,7 +833,7 @@ class ApoData: Si les id Apogée ne sont pas uniques (ce n'est pas garanti), garde le premier """ elts = collections.OrderedDict() - for col_id in sorted(cols.keys(), reverse=True): + for col_id in sorted(list(cols.keys()), reverse=True): col = cols[col_id] if col["Code"] in elts: elts[col["Code"]].append(col) @@ -967,7 +968,7 @@ class ApoData: % (declared, present) ) # l'ensemble de tous les codes des elements apo des semestres: - sem_elems = reduce(set.union, self.get_codes_by_sem().values(), set()) + sem_elems = reduce(set.union, list(self.get_codes_by_sem().values()), set()) return maq_elems, sem_elems @@ -1081,7 +1082,7 @@ def _apo_read_cols(f): if int(m.group(1)) != i: raise FormatError("invalid column id: %s for index %s" % (col_id, i)) - cols[col_id] = DictCol(zip(col_keys, fs)) + cols[col_id] = DictCol(list(zip(col_keys, fs))) cols[col_id].lineno = f.lineno # for debuging purpose return cols diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py index 46a56a142..693b4e52e 100644 --- a/app/scodoc/sco_bulletins.py +++ b/app/scodoc/sco_bulletins.py @@ -31,7 +31,7 @@ import time from types import StringType import pprint -import urllib +import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error from app.scodoc import htmlutils import email from email.mime.multipart import MIMEMultipart @@ -1111,7 +1111,7 @@ def _formsemestre_bulletinetud_header_html( # Menu endpoint = "notes.formsemestre_bulletinetud" url = REQUEST.URL0 - qurl = urllib.quote_plus(url + "?" + REQUEST.QUERY_STRING) + qurl = six.moves.urllib.parse.quote_plus(url + "?" + REQUEST.QUERY_STRING) menuBul = [ { diff --git a/app/scodoc/sco_bulletins_generator.py b/app/scodoc/sco_bulletins_generator.py index 411822966..8f0d2707c 100644 --- a/app/scodoc/sco_bulletins_generator.py +++ b/app/scodoc/sco_bulletins_generator.py @@ -72,7 +72,7 @@ def bulletin_class_descriptions(): def bulletin_class_names(): - return BULLETIN_CLASSES.keys() + return list(BULLETIN_CLASSES.keys()) def bulletin_default_class_name(): diff --git a/app/scodoc/sco_codes_parcours.py b/app/scodoc/sco_codes_parcours.py index c1f0da022..da948d0a8 100644 --- a/app/scodoc/sco_codes_parcours.py +++ b/app/scodoc/sco_codes_parcours.py @@ -29,6 +29,7 @@ """ from types import ListType, TupleType, FloatType import collections +from six.moves import range NOTES_TOLERANCE = 0.00499999999999 # si note >= (BARRE-TOLERANCE), considere ok # (permet d'eviter d'afficher 10.00 sous barre alors que la moyenne vaut 9.999) @@ -212,7 +213,7 @@ class TypeParcours: UNUSED_CODES = set() # Ensemble des codes jury non autorisés dans ce parcours UE_IS_MODULE = False # 1 seul module par UE (si plusieurs modules, etudiants censéments inscrits à un seul d'entre eux) ECTS_ONLY = False # Parcours avec progression basée uniquement sur les ECTS - ALLOWED_UE_TYPES = UE_TYPE_NAME.keys() # par defaut, autorise tous les types d'UE + ALLOWED_UE_TYPES = list(UE_TYPE_NAME.keys()) # par defaut, autorise tous les types d'UE def check(self, formation=None): return True, "" # status, diagnostic_message @@ -664,7 +665,7 @@ register_parcours(ParcoursMasterIG()) # ------------------------- -_tp = TYPES_PARCOURS.items() +_tp = list(TYPES_PARCOURS.items()) _tp.sort(key=lambda x: x[1].__doc__) # sort by intitulé FORMATION_PARCOURS_DESCRS = [p[1].__doc__ for p in _tp] # intitulés (eg pour menu) FORMATION_PARCOURS_TYPES = [p[0] for p in _tp] # codes numeriques (TYPE_PARCOURS) diff --git a/app/scodoc/sco_compute_moy.py b/app/scodoc/sco_compute_moy.py index f0d0e3ae0..d9012c4bc 100644 --- a/app/scodoc/sco_compute_moy.py +++ b/app/scodoc/sco_compute_moy.py @@ -284,7 +284,7 @@ def do_moduleimpl_moyennes(context, nt, mod): for e in valid_evals: if e["evaluation_type"] != EVALUATION_NORMALE: continue - if e["notes"].has_key(etudid): + if etudid in e["notes"]: note = e["notes"][etudid]["value"] if note is None: # ABSENT note = 0 @@ -315,7 +315,7 @@ def do_moduleimpl_moyennes(context, nt, mod): for e in evals: if ( (e["etat"]["evalcomplete"] or e["etat"]["evalattente"]) - and e["notes"].has_key(etudid) + and etudid in e["notes"] ) and (e["note_max"] > 0): note = e["notes"][etudid]["value"] if note is None: @@ -352,7 +352,7 @@ def do_moduleimpl_moyennes(context, nt, mod): R[etudid] = user_moy # Note de rattrapage ou deuxième session ? if eval_rattr: - if eval_rattr["notes"].has_key(etudid): + if etudid in eval_rattr["notes"]: note = eval_rattr["notes"][etudid]["value"] if note != None and note != NOTES_NEUTRALISE and note != NOTES_ATTENTE: if type(R[etudid]) != FloatType: @@ -397,7 +397,7 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id): )[0] modimpl["module"] = mod # add module dict to moduleimpl (used by nt) moduleimpl_id = modimpl["moduleimpl_id"] - assert not D.has_key(moduleimpl_id) + assert moduleimpl_id not in D D[moduleimpl_id], valid_evals_mod, attente, expr_diag = do_moduleimpl_moyennes( context, nt, modimpl ) diff --git a/app/scodoc/sco_core.py b/app/scodoc/sco_core.py index 571283c08..97c848a3d 100644 --- a/app/scodoc/sco_core.py +++ b/app/scodoc/sco_core.py @@ -5,7 +5,7 @@ """ import time -import thread +import six.moves._thread from scodoc_manager import sco_mgr import app.scodoc.sco_utils as scu @@ -27,7 +27,7 @@ CACHE_evaluations = {} def get_evaluations_cache(context): """returns cache for evaluations""" u = sco_mgr.get_db_uri() - if CACHE_evaluations.has_key(u): + if u in CACHE_evaluations: return CACHE_evaluations[u] else: log("get_evaluations_cache: new simpleCache") @@ -41,7 +41,7 @@ class CacheNotesTable: def __init__(self): log("new CacheTable (id=%s)" % id(self)) # - self.lock = thread.allocate_lock() + self.lock = six.moves._thread.allocate_lock() self.owner_thread = None # thread owning this cache self.nref = 0 # Cache des NotesTables @@ -55,13 +55,13 @@ class CacheNotesTable: def acquire(self): "If this thread does not own the cache, acquire the lock" - if thread.get_ident() != self.owner_thread: + if six.moves._thread.get_ident() != self.owner_thread: if self.lock.locked(): log( - "acquire: ident=%s waiting for lock" % thread.get_ident() + "acquire: ident=%s waiting for lock" % six.moves._thread.get_ident() ) # XXX debug self.lock.acquire() - self.owner_thread = thread.get_ident() + self.owner_thread = six.moves._thread.get_ident() if self.owner_thread is None: # bug catching log("WARNING: None thread id !") self.nref += 1 @@ -76,10 +76,10 @@ class CacheNotesTable: self.lock.release() self.owner_thread = None # Debug: - if thread.get_ident() != cur_owner_thread: + if six.moves._thread.get_ident() != cur_owner_thread: log( "WARNING: release: ident=%s != owner=%s nref=%d" - % (thread.get_ident(), cur_owner_thread, self.nref) + % (six.moves._thread.get_ident(), cur_owner_thread, self.nref) ) raise NoteProcessError("problem with notes cache") @@ -88,7 +88,7 @@ class CacheNotesTable: try: self.acquire() - if self.cache.has_key(formsemestre_id): + if formsemestre_id in self.cache: # log('cache hit %s (id=%s, thread=%s)' # % (formsemestre_id, id(self), thread.get_ident())) return self.cache[formsemestre_id] @@ -107,7 +107,7 @@ class CacheNotesTable: def get_cached_formsemestre_ids(self): "List of currently cached formsemestre_id" - return self.cache.keys() + return list(self.cache.keys()) def inval_cache(self, context, formsemestre_id=None, pdfonly=False): # > "expire cache pour un semestre (ou tous si pas d'argument)" @@ -144,7 +144,7 @@ class CacheNotesTable: ) if not pdfonly: for formsemestre_id in to_trash: - if self.cache.has_key(formsemestre_id): + if formsemestre_id in self.cache: log( "delete %s from cache (id=%s)" % (formsemestre_id, id(self)) @@ -191,7 +191,7 @@ class CacheNotesTable: if r: log( "get_bulletins_pdf(%s): cache hit %s (id=%s, thread=%s)" - % (version, formsemestre_id, id(self), thread.get_ident()) + % (version, formsemestre_id, id(self), six.moves._thread.get_ident()) ) return r finally: @@ -219,7 +219,7 @@ class CacheNotesTable: def get_notes_cache(context): "returns CacheNotesTable instance for us" u = sco_mgr.get_db_uri() # identifie le dept de facon unique - if not NOTES_CACHE_INST.has_key(u): + if u not in NOTES_CACHE_INST: log("getNotesCache: creating cache for %s" % u) NOTES_CACHE_INST[u] = CacheNotesTable() return NOTES_CACHE_INST[u] @@ -247,7 +247,7 @@ def inval_cache( # Cache inscriptions semestres def get_formsemestre_inscription_cache(context, format=None): u = sco_mgr.get_db_uri() - if CACHE_formsemestre_inscription.has_key(u): + if u in CACHE_formsemestre_inscription: return CACHE_formsemestre_inscription[u] else: log("get_formsemestre_inscription_cache: new simpleCache") diff --git a/app/scodoc/sco_debouche.py b/app/scodoc/sco_debouche.py index 4e9d52b97..0355ca790 100644 --- a/app/scodoc/sco_debouche.py +++ b/app/scodoc/sco_debouche.py @@ -110,7 +110,7 @@ def table_debouche_etudids(context, etudids, keep_numeric=True): etud = sco_etud.get_etud_info(filled=1, etudid=etudid)[0] # retrouve le "dernier" semestre (au sens de la date de fin) sems = etud["sems"] - es = [(sems[i]["date_fin_iso"], i) for i in range(len(sems))] + es = [(s["date_fin-iso"], i) for i, s in enumerate(sems)] imax = max(es)[1] last_sem = sems[imax] nt = sco_core.get_notes_cache( diff --git a/app/scodoc/sco_edit_formation.py b/app/scodoc/sco_edit_formation.py index 2231a14cb..078ef4254 100644 --- a/app/scodoc/sco_edit_formation.py +++ b/app/scodoc/sco_edit_formation.py @@ -265,14 +265,14 @@ def do_formation_create(context, args, REQUEST): cnx = ndb.GetDBConnexion() # check unique acronyme/titre/version a = args.copy() - if a.has_key("formation_id"): + if "formation_id" in a: del a["formation_id"] F = sco_formations.formation_list(context, args=a) if len(F) > 0: log("do_formation_create: error: %d formations matching args=%s" % (len(F), a)) raise ScoValueError("Formation non unique (%s) !" % str(a)) # Si pas de formation_code, l'enleve (default SQL) - if args.has_key("formation_code") and not args["formation_code"]: + if "formation_code" in args and not args["formation_code"]: del args["formation_code"] # r = sco_formations._formationEditor.create(cnx, args) @@ -294,10 +294,10 @@ def do_formation_edit(context, args): # car cela ne change que du cosmetique, (sauf eventuellement le code formation ?) # mais si verrouillée on ne peut changer le type de parcours if sco_formations.formation_has_locked_sems(context, args["formation_id"]): - if args.has_key("type_parcours"): + if "type_parcours" in args: del args["type_parcours"] # On ne peut jamais supprimer le code formation: - if args.has_key("formation_code") and not args["formation_code"]: + if "formation_code" in args and not args["formation_code"]: del args["formation_code"] cnx = ndb.GetDBConnexion() diff --git a/app/scodoc/sco_edit_module.py b/app/scodoc/sco_edit_module.py index b9c80e2df..fdec4467d 100644 --- a/app/scodoc/sco_edit_module.py +++ b/app/scodoc/sco_edit_module.py @@ -133,7 +133,7 @@ def module_create(context, matiere_id=None, REQUEST=None): context, args={"formation_id": UE["formation_id"]} )[0] parcours = sco_codes_parcours.get_parcours_from_code(Fo["type_parcours"]) - semestres_indices = range(1, parcours.NB_SEM + 1) + semestres_indices = list(range(1, parcours.NB_SEM + 1)) H = [ html_sco_header.sco_header(context, REQUEST, page_title="Création d'un module"), """
Coefficient dans le module: %s, notes sur %g ' @@ -1249,8 +1257,9 @@ def evaluation_create_form( initvalues["visibulletinlist"] = ["X"] else: initvalues["visibulletinlist"] = [] - if REQUEST.form.get("tf-submitted", False) and not REQUEST.form.has_key( - "visibulletinlist" + if ( + REQUEST.form.get("tf-submitted", False) + and "visibulletinlist" not in REQUEST.form ): REQUEST.form["visibulletinlist"] = [] # diff --git a/app/scodoc/sco_excel.py b/app/scodoc/sco_excel.py index a2fb9cc66..3556efce9 100644 --- a/app/scodoc/sco_excel.py +++ b/app/scodoc/sco_excel.py @@ -39,6 +39,7 @@ from app.scodoc.notes_log import log from app.scodoc.scolog import logdb from app.scodoc.sco_exceptions import ScoValueError from app.scodoc import sco_preferences +import six # colors, voir exemple format.py @@ -454,7 +455,7 @@ def Excel_to_list(data, convert_to_string=str): # we may need 'encoding' argume if not values: diag.append("Aucune valeur trouvée dans le classeur !") return diag, None - indexes = values.keys() + indexes = list(values.keys()) # search numbers of rows and cols rows = [x[0] for x in indexes] cols = [x[1] for x in indexes] @@ -466,7 +467,7 @@ def Excel_to_list(data, convert_to_string=str): # we may need 'encoding' argume for row_idx, col_idx in indexes: v = values[(row_idx, col_idx)] - if isinstance(v, unicode): + if isinstance(v, six.text_type): v = v.encode(scu.SCO_ENCODING, "backslashreplace") elif convert_to_string: v = convert_to_string(v) diff --git a/app/scodoc/sco_formsemestre.py b/app/scodoc/sco_formsemestre.py index 51dd9759b..8fbe9c221 100644 --- a/app/scodoc/sco_formsemestre.py +++ b/app/scodoc/sco_formsemestre.py @@ -243,7 +243,7 @@ def do_formsemestre_create(context, args, REQUEST, silent=False): ) # news - if not args.has_key("titre"): + if "titre" not in args: args["titre"] = "sans titre" args["formsemestre_id"] = formsemestre_id args["url"] = "Notes/formsemestre_status?formsemestre_id=%(formsemestre_id)s" % args @@ -622,7 +622,7 @@ def list_formsemestre_by_etape( context, sem, year=int(annee_scolaire), REQUEST=REQUEST ): ds[sem["formsemestre_id"]] = sem - sems = ds.values() + sems = list(ds.values()) else: sems = do_formsemestre_list(context) if annee_scolaire: diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py index 6ac094f79..511ab7bbb 100644 --- a/app/scodoc/sco_formsemestre_edit.py +++ b/app/scodoc/sco_formsemestre_edit.py @@ -56,6 +56,7 @@ from app.scodoc import sco_permissions_check from app.scodoc import sco_portal_apogee from app.scodoc import sco_preferences from app.scodoc import sco_users +import six def _default_sem_title(F): @@ -77,7 +78,7 @@ def formsemestre_createwithmodules(context, REQUEST=None): """
', ] - commentkeys = K.items() # [ (comment, key), ... ] + commentkeys = list(K.items()) # [ (comment, key), ... ] commentkeys.sort(lambda x, y: cmp(int(x[1]), int(y[1]))) for (comment, key) in commentkeys: C.append( @@ -554,7 +554,7 @@ def _add_eval_columns( NotesDB = sco_evaluations.do_evaluation_get_all_notes(context, evaluation_id) for row in rows: etudid = row["etudid"] - if NotesDB.has_key(etudid): + if etudid in NotesDB: val = NotesDB[etudid]["value"] if val is None: nb_abs += 1 @@ -591,7 +591,7 @@ def _add_eval_columns( row["_css_row_class"] = "etudabs" # regroupe les commentaires if explanation: - if K.has_key(explanation): + if explanation in K: expl_key = "(%s)" % K[explanation] else: K[explanation] = K.nextkey() @@ -745,7 +745,7 @@ def evaluation_check_absences(context, evaluation_id): ExcNonJust = [] # note EXC mais absent non justifie AbsButExc = [] # note ABS mais justifié for etudid in etudids: - if NotesDB.has_key(etudid): + if etudid in NotesDB: val = NotesDB[etudid]["value"] if ( val != None and val != scu.NOTES_NEUTRALISE and val != scu.NOTES_ATTENTE @@ -824,8 +824,8 @@ def evaluation_check_absences_html( 'signaler cette absence' % ( etud["etudid"], - urllib.quote(E["jour"]), - urllib.quote(E["jour"]), + six.moves.urllib.parse.quote(E["jour"]), + six.moves.urllib.parse.quote(E["jour"]), demijournee, E["moduleimpl_id"], ) diff --git a/app/scodoc/sco_modalites.py b/app/scodoc/sco_modalites.py index 5b70d66cd..b17892368 100644 --- a/app/scodoc/sco_modalites.py +++ b/app/scodoc/sco_modalites.py @@ -45,7 +45,7 @@ def list_formsemestres_modalites(context, sems): if sem["modalite"] not in modalites: m = do_modalite_list(context, args={"modalite": sem["modalite"]})[0] modalites[m["modalite"]] = m - modalites = modalites.values() + modalites = list(modalites.values()) modalites.sort(key=lambda x: x["numero"]) return modalites diff --git a/app/scodoc/sco_moduleimpl_status.py b/app/scodoc/sco_moduleimpl_status.py index 51c478349..478820448 100644 --- a/app/scodoc/sco_moduleimpl_status.py +++ b/app/scodoc/sco_moduleimpl_status.py @@ -28,7 +28,7 @@ """Tableau de bord module """ import time -import urllib +import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error import app.scodoc.sco_utils as scu from app.scodoc.sco_permissions import Permission @@ -136,7 +136,7 @@ def moduleimpl_evaluation_menu(context, evaluation_id, nbnotes=0, REQUEST=None): "title": "Absences ce jour", "endpoint": "absences.EtatAbsencesDate", "args": { - "date": urllib.quote(E["jour"], safe=""), + "date": six.moves.urllib.parse.quote(E["jour"], safe=""), "group_ids": group_id, }, "enabled": E["jour"], diff --git a/app/scodoc/sco_news.py b/app/scodoc/sco_news.py index c9ffe606d..dcbecf770 100644 --- a/app/scodoc/sco_news.py +++ b/app/scodoc/sco_news.py @@ -46,6 +46,7 @@ from app.scodoc import sco_formsemestre from app.scodoc import sco_moduleimpl from app.scodoc import sco_preferences from app.scodoc import sco_users +import six _scolar_news_editor = ndb.EditableTable( "scolar_news", @@ -69,7 +70,7 @@ NEWS_MAP = { NEWS_SEM: "création semestre", NEWS_MISC: "opération", # unused } -NEWS_TYPES = NEWS_MAP.keys() +NEWS_TYPES = list(NEWS_MAP.keys()) scolar_news_create = _scolar_news_editor.create scolar_news_list = _scolar_news_editor.list @@ -126,7 +127,7 @@ def scolar_news_summary(context, n=5): key = (r["type"], r["object"], dmy) selected_news[key] = r - news = selected_news.values() + news = list(selected_news.values()) # sort by date, descending news.sort(lambda x, y: cmp(y["date"], x["date"])) news = news[:n] @@ -139,7 +140,7 @@ def scolar_news_summary(context, n=5): for k in n.keys(): if n[k] is None: n[k] = "" - if _scolar_news_editor.output_formators.has_key(k): + if k in _scolar_news_editor.output_formators: n[k] = _scolar_news_editor.output_formators[k](n[k]) # date resumee j, m = n["date"].split("/")[:2] @@ -233,15 +234,15 @@ def scolar_news_summary_rss(context, title, sco_url, n=5): text = html2text(n["text"]) items.append( PyRSS2Gen.RSSItem( - title=unicode("%s %s" % (n["rssdate"], text), SCO_ENCODING), + title=six.text_type("%s %s" % (n["rssdate"], text), SCO_ENCODING), link=sco_url + "/" + n["url"], pubDate=n["date822"], ) ) rss = PyRSS2Gen.RSS2( - title=unicode(title, SCO_ENCODING), + title=six.text_type(title, SCO_ENCODING), link=sco_url, - description=unicode(title, SCO_ENCODING), + description=six.text_type(title, SCO_ENCODING), lastBuildDate=datetime.datetime.now(), items=items, ) diff --git a/app/scodoc/sco_page_etud.py b/app/scodoc/sco_page_etud.py index f38813108..9bc9974ec 100644 --- a/app/scodoc/sco_page_etud.py +++ b/app/scodoc/sco_page_etud.py @@ -494,7 +494,7 @@ def ficheEtud(context, etudid=None, REQUEST=None): def menus_etud(context, REQUEST=None): """Menu etudiant (operations sur l'etudiant)""" - if not REQUEST.form.has_key("etudid"): + if "etudid" not in REQUEST.form: return "" authuser = REQUEST.AUTHENTICATED_USER diff --git a/app/scodoc/sco_parcours_dut.py b/app/scodoc/sco_parcours_dut.py index 49b1d9ddf..ce7a48b17 100644 --- a/app/scodoc/sco_parcours_dut.py +++ b/app/scodoc/sco_parcours_dut.py @@ -349,7 +349,7 @@ class SituationEtudParcoursGeneric: self.etudid, self.sem, self.nt, sem, nt ) - self.ue_acros = ue_acros.keys() + self.ue_acros = list(ue_acros.keys()) self.ue_acros.sort() self.nb_max_ue = nb_max_ue self.sems = sems @@ -389,7 +389,7 @@ class SituationEtudParcoursGeneric: if self.sem["semestre_id"] == NO_SEMESTRE_ID: indices = [NO_SEMESTRE_ID] else: - indices = range(1, self.parcours.NB_SEM + 1) + indices = list(range(1, self.parcours.NB_SEM + 1)) for i in indices: # cherche dans les semestres de l'étudiant, en partant du plus récent sem = None diff --git a/app/scodoc/sco_pdf.py b/app/scodoc/sco_pdf.py index 4ae9118d6..7ebc7d28b 100644 --- a/app/scodoc/sco_pdf.py +++ b/app/scodoc/sco_pdf.py @@ -64,6 +64,7 @@ from app.scodoc.sco_exceptions import ScoGenError from SuppressAccents import suppression_diacritics from app.scodoc import VERSION from VERSION import SCOVERSION, SCONAME +import six PAGE_HEIGHT = defaultPageSize[1] PAGE_WIDTH = defaultPageSize[0] @@ -81,7 +82,7 @@ def SU(s): # eg 'e\xcc\x81' COMBINING ACUTE ACCENT par '\xc3\xa9' LATIN SMALL LETTER E WITH ACUTE # car les "combining accents" ne sont pas traités par ReportLab mais peuvent # nous être envoyés par certains navigateurs ou imports - u = unicodedata.normalize("NFC", unicode(s, SCO_ENCODING, "replace")) + u = unicodedata.normalize("NFC", six.text_type(s, SCO_ENCODING, "replace")) return u.encode("utf8") @@ -330,19 +331,19 @@ def pdf_basic_page( # Gestion du lock pdf -import threading, time, Queue, thread +import threading, time, six.moves.queue, six.moves._thread class PDFLock: def __init__(self, timeout=15): - self.Q = Queue.Queue(1) + self.Q = six.moves.queue.Queue(1) self.timeout = timeout self.current_thread = None self.nref = 0 def release(self): "Release lock. Raise Empty if not acquired first" - if self.current_thread == thread.get_ident(): + if self.current_thread == six.moves._thread.get_ident(): self.nref -= 1 if self.nref == 0: log("PDFLock: release from %s" % self.current_thread) @@ -354,14 +355,14 @@ class PDFLock: def acquire(self): "Acquire lock. Raise ScoGenError if can't lock after timeout." - if self.current_thread == thread.get_ident(): + if self.current_thread == six.moves._thread.get_ident(): self.nref += 1 return # deja lock pour ce thread try: self.Q.put(1, True, self.timeout) - except Queue.Full: + except six.moves.queue.Full: raise ScoGenError(msg="Traitement PDF occupé: ré-essayez") - self.current_thread = thread.get_ident() + self.current_thread = six.moves._thread.get_ident() self.nref = 1 log("PDFLock: granted to %s" % self.current_thread) diff --git a/app/scodoc/sco_photos.py b/app/scodoc/sco_photos.py index 5e20a8e80..0b2a7ae92 100644 --- a/app/scodoc/sco_photos.py +++ b/app/scodoc/sco_photos.py @@ -47,7 +47,7 @@ import os import time import datetime import random -import urllib2 +import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse import traceback from PIL import Image as PILImage from cStringIO import StringIO @@ -355,7 +355,7 @@ def copy_portal_photo_to_fs(context, etud, REQUEST=None): f = None try: log("copy_portal_photo_to_fs: getting %s" % url) - f = urllib2.urlopen(url, timeout=portal_timeout) # python >= 2.7 + f = six.moves.urllib.request.urlopen(url, timeout=portal_timeout) # python >= 2.7 except: log("download failed: exception:\n%s" % traceback.format_exc()) log("called from:\n" + "".join(traceback.format_stack())) diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index 344aed158..21e928624 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -30,7 +30,7 @@ Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016 """ -import urllib +import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error import random import app.scodoc.sco_utils as scu @@ -155,7 +155,7 @@ def do_placement_selectetuds(context, REQUEST): ) ] - if not (REQUEST.form.has_key("group_ids") and REQUEST.form["group_ids"]): + if not ("group_ids" in REQUEST.form and REQUEST.form["group_ids"]): submitbuttonattributes = ['disabled="1"'] else: submitbuttonattributes = [] # groupe(s) preselectionnés @@ -208,7 +208,10 @@ def do_placement_selectetuds(context, REQUEST): columns = tf[2]["columns"] numbering = tf[2]["numbering"] if columns in ("3", "4", "5", "6", "7", "8"): - gs = [("group_ids%3Alist=" + urllib.quote_plus(x)) for x in group_ids] + gs = [ + ("group_ids%3Alist=" + six.moves.urllib.parse.quote_plus(x)) + for x in group_ids + ] query = ( "evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&" % ( diff --git a/app/scodoc/sco_portal_apogee.py b/app/scodoc/sco_portal_apogee.py index 8b7afb370..fd8ac01a4 100644 --- a/app/scodoc/sco_portal_apogee.py +++ b/app/scodoc/sco_portal_apogee.py @@ -29,7 +29,7 @@ """ import os, time -import urllib +import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error import xml import xml.sax.saxutils import xml.dom.minidom @@ -39,6 +39,8 @@ import app.scodoc.sco_utils as scu from app.scodoc.notes_log import log from app.scodoc.sco_exceptions import ScoValueError from app.scodoc import sco_preferences +import six +from six.moves import range SCO_CACHE_ETAPE_FILENAME = os.path.join(scu.SCO_TMP_DIR, "last_etapes.xml") @@ -155,10 +157,10 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2): req = ( etud_url + "?" - + urllib.urlencode((("etape", code_etape), ("annee", anneeapogee))) + + six.moves.urllib.parse.urlencode((("etape", code_etape), ("annee", anneeapogee))) ) else: - req = etud_url + "?" + urllib.urlencode((("etape", code_etape),)) + req = etud_url + "?" + six.moves.urllib.parse.urlencode((("etape", code_etape),)) actual_timeout = float(portal_timeout) / ntrials if portal_timeout > 0: actual_timeout = max(1, actual_timeout) @@ -172,7 +174,7 @@ def get_inscrits_etape(context, code_etape, anneeapogee=None, ntrials=2): # Filtre sur annee inscription Apogee: def check_inscription(e): - if e.has_key("inscription"): + if "inscription" in e: if e["inscription"] == anneeapogee: return True else: @@ -203,7 +205,7 @@ def query_apogee_portal(context, **args): # XXX TODO : va poser problème pour la page modif données étudiants : A VOIR return [] portal_timeout = sco_preferences.get_preference(context, "portal_timeout") - req = etud_url + "?" + urllib.urlencode(args.items()) + req = etud_url + "?" + six.moves.urllib.parse.urlencode(list(args.items())) doc = scu.query_portal(req, timeout=portal_timeout) # sco_utils return xml_to_list_of_dicts(doc, req=req) @@ -261,7 +263,7 @@ def xml_to_list_of_dicts(doc, req=None): def get_infos_apogee_allaccents(context, nom, prenom): "essai recup infos avec differents codages des accents" if nom: - unom = unicode(nom, scu.SCO_ENCODING) + unom = six.text_type(nom, scu.SCO_ENCODING) nom_noaccents = str(scu.suppression_diacritics(unom)) nom_utf8 = unom.encode("utf-8") else: @@ -269,7 +271,7 @@ def get_infos_apogee_allaccents(context, nom, prenom): nom_utf8 = nom if prenom: - uprenom = unicode(prenom, scu.SCO_ENCODING) + uprenom = six.text_type(prenom, scu.SCO_ENCODING) prenom_noaccents = str(scu.suppression_diacritics(uprenom)) prenom_utf8 = uprenom.encode("utf-8") else: @@ -325,7 +327,7 @@ def get_etud_apogee(context, code_nip): if not etud_url: return {} portal_timeout = sco_preferences.get_preference(context, "portal_timeout") - req = etud_url + "?" + urllib.urlencode((("nip", code_nip),)) + req = etud_url + "?" + six.moves.urllib.parse.urlencode((("nip", code_nip),)) doc = scu.query_portal(req, timeout=portal_timeout) d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req)) if not d: @@ -346,7 +348,7 @@ def get_default_etapes(context): if line and line[0] != "#": dept, code, intitule = [x.strip() for x in line.split(":")] if dept and code: - if etapes.has_key(dept): + if dept in etapes: etapes[dept][code] = intitule else: etapes[dept] = {code: intitule} @@ -418,7 +420,7 @@ def _xml_list_codes(target_dict, dept, nodes): if e.nodeType == e.ELEMENT_NODE: intitule = e.childNodes[0].nodeValue.encode(scu.SCO_ENCODING) code = e.attributes["code"].value.encode(scu.SCO_ENCODING) - if target_dict.has_key(dept): + if dept in target_dict: target_dict[dept][code] = intitule else: target_dict[dept] = {code: intitule} @@ -442,19 +444,19 @@ def get_etapes_apogee_dept(context): log("get_etapes_apogee_dept: pas de sections par departement") infos = get_etapes_apogee(context) - if portal_dept_name and not infos.has_key(portal_dept_name): + if portal_dept_name and portal_dept_name not in infos: log( "get_etapes_apogee_dept: pas de section '%s' dans la reponse portail" % portal_dept_name ) return [] if portal_dept_name: - etapes = infos[portal_dept_name].items() + etapes = list(infos[portal_dept_name].items()) else: # prend toutes les etapes etapes = [] for k in infos.keys(): - etapes += infos[k].items() + etapes += list(infos[k].items()) etapes.sort() # tri sur le code etape return etapes @@ -483,7 +485,7 @@ def _normalize_apo_fields(infolist): ajoute les champs 'etape' (= None) et 'prenom' ('') s'ils ne sont pas présents. """ for infos in infolist: - if infos.has_key("paiementinscription"): + if "paiementinscription" in infos: infos["paiementinscription"] = ( scu.strlower(infos["paiementinscription"]) == "true" ) @@ -495,7 +497,7 @@ def _normalize_apo_fields(infolist): infos["paiementinscription"] = None infos["paiementinscription_str"] = "?" - if infos.has_key("datefinalisationinscription"): + if "datefinalisationinscription" in infos: infos["datefinalisationinscription"] = _portal_date_dmy2date( infos["datefinalisationinscription"] ) @@ -506,10 +508,10 @@ def _normalize_apo_fields(infolist): infos["datefinalisationinscription"] = None infos["datefinalisationinscription_str"] = "" - if not infos.has_key("etape"): + if "etape" not in infos: infos["etape"] = None - if not infos.has_key("prenom"): + if "prenom" not in infos: infos["prenom"] = "" return infolist @@ -529,7 +531,7 @@ def check_paiement_etuds(context, etuds): """ # interrogation séquentielle longue... for etud in etuds: - if not etud.has_key("code_nip"): + if "code_nip" not in etud: etud["paiementinscription"] = None etud["paiementinscription_str"] = "(pas de code)" etud["datefinalisationinscription"] = None @@ -563,7 +565,7 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""): req = ( maquette_url + "?" - + urllib.urlencode((("etape", etape), ("annee", annee_scolaire))) + + six.moves.urllib.parse.urlencode((("etape", etape), ("annee", annee_scolaire))) ) doc = scu.query_portal(req, timeout=portal_timeout) return doc diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py index b526b8344..4d60b8dbe 100644 --- a/app/scodoc/sco_preferences.py +++ b/app/scodoc/sco_preferences.py @@ -1797,9 +1797,7 @@ class BasePreferences(object): self.prefs[p["formsemestre_id"]] = {} # Convert types: - if p["name"] in self.prefs_dict and self.prefs_dict[p["name"]].has_key( - "type" - ): + if p["name"] in self.prefs_dict and "type" in self.prefs_dict[p["name"]]: typ = self.prefs_dict[p["name"]]["type"] if typ == "float": # special case for float values (where NULL means 0) @@ -1879,7 +1877,7 @@ class BasePreferences(object): modif = False cnx = ndb.GetDBConnexion() if name is None: - names = self.prefs[formsemestre_id].keys() + names = list(self.prefs[formsemestre_id].keys()) else: names = [name] for name in names: diff --git a/app/scodoc/sco_prepajury.py b/app/scodoc/sco_prepajury.py index 5104af001..74de7ad46 100644 --- a/app/scodoc/sco_prepajury.py +++ b/app/scodoc/sco_prepajury.py @@ -135,14 +135,14 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): nbabsjust[etudid] = AbsEtudSem.CountAbs() - AbsEtudSem.CountAbsJust() # Codes des UE "semestre précédent": - ue_prev_codes = prev_moy_ue.keys() + ue_prev_codes = list(prev_moy_ue.keys()) ue_prev_codes.sort( 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 = list(moy_ue.keys()) ue_codes.sort( lambda x, y, ue_acro=ue_acro: cmp( # pylint: disable=undefined-variable ue_acro[x], ue_acro[y] @@ -280,7 +280,7 @@ def feuille_preparation_jury(context, formsemestre_id, REQUEST): # L.append([""]) # Explications des codes - codes = sco_codes_parcours.CODES_EXPL.keys() + codes = list(sco_codes_parcours.CODES_EXPL.keys()) codes.sort() L.append(["Explication des codes"]) for code in codes: diff --git a/app/scodoc/sco_pvjury.py b/app/scodoc/sco_pvjury.py index f68c6fb25..727a12ae4 100644 --- a/app/scodoc/sco_pvjury.py +++ b/app/scodoc/sco_pvjury.py @@ -572,10 +572,10 @@ def formsemestre_pvjury( for row in rows: counts[row["decision"]] += 1 # add codes for previous (for explanation, without count) - if row.has_key("prev_decision") and row["prev_decision"]: + if "prev_decision" in row and row["prev_decision"]: counts[row["prev_decision"]] += 0 # Légende des codes - codes = counts.keys() # sco_codes_parcours.CODES_EXPL.keys() + codes = list(counts.keys()) # sco_codes_parcours.CODES_EXPL.keys() codes.sort() H.append("
%s | %d |