- Set -> set

- recapcomplet en JSON
- minor code cleaning.
This commit is contained in:
viennet 2020-12-02 01:00:23 +01:00
parent 317252575a
commit 861c3ad6ca
19 changed files with 249 additions and 224 deletions

View File

@ -116,8 +116,7 @@ def sco_import_format(with_codesemestre=True):
def sco_import_format_dict(with_codesemestre=True):
""" Attribut: { 'type': , 'table', 'allow_nulls' , 'description' }
"""
"""Attribut: { 'type': , 'table', 'allow_nulls' , 'description' }"""
fmt = sco_import_format(with_codesemestre=with_codesemestre)
R = collections.OrderedDict()
for l in fmt:
@ -260,7 +259,7 @@ def scolars_import_excel_file(
if not data: # probably a bug
raise ScoException("scolars_import_excel_file: empty file !")
formsemestre_to_invalidate = Set()
formsemestre_to_invalidate = set()
# 1- --- check title line
titles = {}
@ -555,18 +554,18 @@ def scolars_import_admission(
"""Importe données admission depuis un fichier Excel quelconque
par exemple ceux utilisés avec APB
Cherche dans ce fichier les étudiants qui correspondent à des inscrits du
Cherche dans ce fichier les étudiants qui correspondent à des inscrits du
semestre formsemestre_id.
Le fichier n'a pas l'INE ni le NIP ni l'etudid, la correspondance se fait
via les noms/prénoms qui doivent être égaux (la casse, les accents et caractères spéciaux
Le fichier n'a pas l'INE ni le NIP ni l'etudid, la correspondance se fait
via les noms/prénoms qui doivent être égaux (la casse, les accents et caractères spéciaux
étant ignorés).
On tolère plusieurs variantes pour chaque nom de colonne (ici aussi, la casse, les espaces
On tolère plusieurs variantes pour chaque nom de colonne (ici aussi, la casse, les espaces
et les caractères spéciaux sont ignorés. Ainsi, la colonne "Prénom:" sera considéré comme "prenom".
Le parametre type_admission remplace les valeurs vides (dans la base ET dans le fichier importé) du champ type_admission.
Si une valeur existe ou est présente dans le fichier importé, ce paramètre est ignoré.
TODO:
- choix onglet du classeur
"""
@ -611,7 +610,7 @@ def scolars_import_admission(
% formsemestre_id,
)
modifiable_fields = Set(ADMISSION_MODIFIABLE_FIELDS)
modifiable_fields = set(ADMISSION_MODIFIABLE_FIELDS)
nline = 2 # la premiere ligne de donnees du fichier excel est 2
n_import = 0
@ -748,8 +747,7 @@ def adm_convert_real(v):
def adm_table_description_format(context):
"""Table HTML (ou autre format) decrivant les donnees d'admissions importables
"""
"""Table HTML (ou autre format) decrivant les donnees d'admissions importables"""
Fmt = sco_import_format_dict(with_codesemestre=False)
for k in Fmt:
Fmt[k]["attribute"] = k

View File

@ -28,8 +28,6 @@
"""Interface Zope <-> Notes
"""
from sets import Set
from sco_zope import *
# ---------------
@ -2241,7 +2239,7 @@ class ZNotes(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Impl
{"moduleimpl_id": moduleimpl_id},
)
# Inscriptions au module:
inmod_set = Set(
inmod_set = set(
[
x["etudid"]
for x in self.do_moduleimpl_inscription_list(

View File

@ -101,8 +101,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
return self.absolute_url()
def _check_admin_perm(self, REQUEST):
"""Check if user has permission to add/delete departements
"""
"""Check if user has permission to add/delete departements"""
authuser = REQUEST.AUTHENTICATED_USER
if authuser.has_role("manager") or authuser.has_permission(ScoSuperAdmin, self):
return ""
@ -110,8 +109,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
return """<h2>Vous n'avez pas le droit d'accéder à cette page</h2>"""
def _check_users_folder(self, REQUEST=None):
"""Vérifie UserFolder et le crée s'il le faut
"""
"""Vérifie UserFolder et le crée s'il le faut"""
try:
udb = self.UsersDB
return "<!-- uf ok -->"
@ -127,8 +125,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "create_users_folder")
def create_users_folder(self, REQUEST=None):
"""Create Zope user folder
"""
"""Create Zope user folder"""
e = self._check_admin_perm(REQUEST)
if e:
return e
@ -304,8 +301,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "delete_dept")
def delete_dept(self, REQUEST=None, DeptId="", force=False):
"""Supprime un departement (de Zope seulement, ne touche pas la BD)
"""
"""Supprime un departement (de Zope seulement, ne touche pas la BD)"""
e = self._check_admin_perm(REQUEST)
if e:
return e
@ -373,8 +369,7 @@ class ZScoDoc(ObjectManager, PropertyManager, RoleManager, Item, Persistent, Imp
security.declareProtected("View", "index_html")
def index_html(self, REQUEST=None, message=None):
"""Top level page for ScoDoc
"""
"""Top level page for ScoDoc"""
authuser = REQUEST.AUTHENTICATED_USER
deptList = self.list_depts()
self._fix_users_folder() # fix our exUserFolder
@ -825,8 +820,7 @@ subversion: %(svn_version)s
security.declareProtected("View", "scodoc_admin")
def scodoc_admin(self, REQUEST=None):
"""Page Operations d'administration
"""
"""Page Operations d'administration"""
e = self._check_admin_perm(REQUEST)
if e:
return e
@ -847,8 +841,8 @@ subversion: %(svn_version)s
]
deptList = [x.id for x in self.list_depts()] # definis dans Zope
deptIds = Set(self._list_depts_ids()) # definis sur le filesystem
existingDepts = Set(deptList)
deptIds = set(self._list_depts_ids()) # definis sur le filesystem
existingDepts = set(deptList)
addableDepts = deptIds - existingDepts
if not addableDepts:

View File

@ -98,7 +98,7 @@ def formsemestre_bulletinetud_dict(
):
"""Collecte informations pour bulletin de notes
Retourne un dictionnaire (avec valeur par défaut chaine vide).
Le contenu du dictionnaire dépend des options (rangs, ...)
Le contenu du dictionnaire dépend des options (rangs, ...)
et de la version choisie (short, long, selectedevals).
Cette fonction est utilisée pour les bulletins HTML et PDF, mais pas ceux en XML.
@ -131,9 +131,11 @@ def formsemestre_bulletinetud_dict(
I["etud"] = context.getEtudInfo(etudid=etudid, filled=1)[0]
I["descr_situation"] = I["etud"]["inscriptionstr"]
if I["etud"]["inscription_formsemestre_id"]:
I["descr_situation_html"] = (
"""<a href="formsemestre_status?formsemestre_id=%s">%s</a>"""
% (I["etud"]["inscription_formsemestre_id"], I["descr_situation"])
I[
"descr_situation_html"
] = """<a href="formsemestre_status?formsemestre_id=%s">%s</a>""" % (
I["etud"]["inscription_formsemestre_id"],
I["descr_situation"],
)
else:
I["descr_situation_html"] = I["descr_situation"]
@ -314,14 +316,13 @@ def formsemestre_bulletinetud_dict(
u["ue_descr_txt"] = "Capitalisée le %s" % DateISOtoDMY(
ue_status["event_date"]
)
u["ue_descr_html"] = (
'<a href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s" class="bull_link">%s</a>'
% (
sem_origin["formsemestre_id"],
etudid,
sem_origin["titreannee"],
u["ue_descr_txt"],
)
u[
"ue_descr_html"
] = '<a href="formsemestre_bulletinetud?formsemestre_id=%s&amp;etudid=%s" title="%s" class="bull_link">%s</a>' % (
sem_origin["formsemestre_id"],
etudid,
sem_origin["titreannee"],
u["ue_descr_txt"],
)
# log('cap details %s' % ue_status['moy'])
if ue_status["moy"] != "NA" and ue_status["formsemestre_id"]:
@ -539,7 +540,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
# Evaluations incomplètes ou futures:
mod["evaluations_incompletes"] = []
if context.get_preference("bul_show_all_evals", formsemestre_id):
complete_eval_ids = Set([e["evaluation_id"] for e in evals])
complete_eval_ids = set([e["evaluation_id"] for e in evals])
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
)
@ -578,8 +579,7 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
def get_etud_rangs_groups(
context, etudid, formsemestre_id, partitions, partitions_etud_groups, nt
):
"""Ramene rang et nb inscrits dans chaque partition
"""
"""Ramene rang et nb inscrits dans chaque partition"""
rang_gr, ninscrits_gr, gr_name = {}, {}, {}
for partition in partitions:
if partition["partition_name"] != None:
@ -616,7 +616,7 @@ def etud_descr_situation_semestre(
situation : chaine résumant en français la situation de l'étudiant.
Par ex. "Inscrit le 31/12/1999. Décision jury: Validé. ..."
date_inscription : (vide si show_date_inscr est faux)
date_demission : (vide si pas demission ou si show_date_inscr est faux)
descr_inscription : "Inscrit" ou "Pas inscrit[e]"
@ -820,8 +820,7 @@ def formsemestre_bulletinetud(
def can_send_bulletin_by_mail(context, formsemestre_id, REQUEST):
"""True if current user is allowed to send a bulletin by mail
"""
"""True if current user is allowed to send a bulletin by mail"""
authuser = REQUEST.AUTHENTICATED_USER
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
return (
@ -1177,8 +1176,7 @@ def _formsemestre_bulletinetud_header_html(
def formsemestre_bulletins_choice(
context, REQUEST, formsemestre_id, title="", explanation="", choose_mail=False
):
"""Choix d'une version de bulletin
"""
"""Choix d'une version de bulletin"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(REQUEST, title, sem),

View File

@ -273,7 +273,7 @@ def formsemestre_bulletinetud_published_dict(
)
)
# Evaluations incomplètes ou futures:
complete_eval_ids = Set([e["evaluation_id"] for e in evals])
complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id):
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}

View File

@ -265,7 +265,7 @@ def make_xml_formsemestre_bulletinetud(
doc.note(value=val)
doc._pop()
# Evaluations incomplètes ou futures:
complete_eval_ids = Set([e["evaluation_id"] for e in evals])
complete_eval_ids = set([e["evaluation_id"] for e in evals])
if context.get_preference("bul_show_all_evals", formsemestre_id):
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}

View File

@ -28,7 +28,6 @@
"""Calcul des moyennes de module
"""
from sets import Set
import traceback
from sco_utils import *
@ -92,8 +91,7 @@ formsemestre_ue_computation_expr_edit = _formsemestre_ue_computation_exprEditor.
def get_ue_expression(formsemestre_id, ue_id, cnx, html_quote=False):
"""Returns UE expression (formula), or None if no expression has been defined
"""
"""Returns UE expression (formula), or None if no expression has been defined"""
el = formsemestre_ue_computation_expr_list(
cnx, {"formsemestre_id": formsemestre_id, "ue_id": ue_id}
)
@ -196,7 +194,7 @@ def do_moduleimpl_moyennes(context, nt, mod):
moduleimpl_id
) # tous, y compris demissions
# Inscrits au semestre (pour traiter les demissions):
inssem_set = Set(
inssem_set = set(
[
x["etudid"]
for x in context.do_formsemestre_inscription_listinscrits(

View File

@ -27,7 +27,6 @@
"""Evaluations
"""
from sets import Set
from notes_log import log, logCallStack
from sco_utils import *
@ -117,7 +116,7 @@ def do_evaluation_etat(
context, evaluation_id, partition_id=None, select_first_partition=False
):
"""donne infos sur l'etat du evaluation
{ nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att,
{ nb_inscrits, nb_notes, nb_abs, nb_neutre, nb_att,
moyenne, mediane, mini, maxi,
date_last_modif, gr_complets, gr_incomplets, evalcomplete }
evalcomplete est vrai si l'eval est complete (tous les inscrits
@ -176,7 +175,7 @@ def do_evaluation_etat(
# au module (pour gerer les modules optionnels correctement)
insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
insmodset = Set([x["etudid"] for x in insmod])
insmodset = set([x["etudid"] for x in insmod])
# retire de insem ceux qui ne sont pas inscrits au module
ins = [i for i in insem if i["etudid"] in insmodset]
@ -292,50 +291,50 @@ def do_evaluation_etat(
def do_evaluation_list_in_sem(context, formsemestre_id):
"""Liste les evaluations de tous les modules de ce semestre.
Donne pour chaque eval son état (voir do_evaluation_etat)
{ evaluation_id,nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif ... }
Donne pour chaque eval son état (voir do_evaluation_etat)
{ evaluation_id,nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif ... }
Exemple:
[ {
'coefficient': 1.0,
'description': 'QCM et cas pratiques',
'etat': {'evalattente': False,
'evalcomplete': True,
'evaluation_id': 'GEAEVAL82883',
'gr_incomplets': [],
'gr_moyennes': [{'gr_median': '12.00',
'gr_median_num' : 12.,
'gr_moy': '11.88',
'gr_moy_num' : 11.88,
'gr_nb_att': 0,
'gr_nb_notes': 166,
'group_id': 'GEAG266762',
'group_name': None}],
'groups': {'GEAG266762': {'etudid': 'GEAEID80603',
'group_id': 'GEAG266762',
'group_name': None,
'partition_id': 'GEAP266761'}
},
'last_modif': datetime.datetime(2015, 12, 3, 15, 15, 16),
'median': '12.00',
'moy': '11.84',
'nb_abs': 2,
'nb_att': 0,
'nb_inscrits': 166,
'nb_neutre': 0,
'nb_notes': 168,
'nb_notes_total': 169
},
'evaluation_id': 'GEAEVAL82883',
'evaluation_type': 0,
'heure_debut': datetime.time(8, 0),
'heure_fin': datetime.time(9, 30),
'jour': datetime.date(2015, 11, 3), // vide => 1/1/1
'moduleimpl_id': 'GEAMIP80490',
'note_max': 20.0,
'numero': 0,
'publish_incomplete': 0,
'visibulletin': 1} ]
Exemple:
[ {
'coefficient': 1.0,
'description': 'QCM et cas pratiques',
'etat': {'evalattente': False,
'evalcomplete': True,
'evaluation_id': 'GEAEVAL82883',
'gr_incomplets': [],
'gr_moyennes': [{'gr_median': '12.00',
'gr_median_num' : 12.,
'gr_moy': '11.88',
'gr_moy_num' : 11.88,
'gr_nb_att': 0,
'gr_nb_notes': 166,
'group_id': 'GEAG266762',
'group_name': None}],
'groups': {'GEAG266762': {'etudid': 'GEAEID80603',
'group_id': 'GEAG266762',
'group_name': None,
'partition_id': 'GEAP266761'}
},
'last_modif': datetime.datetime(2015, 12, 3, 15, 15, 16),
'median': '12.00',
'moy': '11.84',
'nb_abs': 2,
'nb_att': 0,
'nb_inscrits': 166,
'nb_neutre': 0,
'nb_notes': 168,
'nb_notes_total': 169
},
'evaluation_id': 'GEAEVAL82883',
'evaluation_type': 0,
'heure_debut': datetime.time(8, 0),
'heure_fin': datetime.time(9, 30),
'jour': datetime.date(2015, 11, 3), // vide => 1/1/1
'moduleimpl_id': 'GEAMIP80490',
'note_max': 20.0,
'numero': 0,
'publish_incomplete': 0,
'visibulletin': 1} ]
"""
req = "select E.* from notes_evaluation E, notes_moduleimpl MI where MI.formsemestre_id = %(formsemestre_id)s and MI.moduleimpl_id = E.moduleimpl_id"
@ -410,8 +409,7 @@ def do_evaluation_etat_in_sem(context, formsemestre_id, REQUEST=None):
def do_evaluation_etat_in_mod(context, nt, moduleimpl_id):
"""
"""
""""""
evals = nt.get_mod_evaluation_etat_list(moduleimpl_id)
etat = _eval_etat(evals)
etat["attente"] = moduleimpl_id in [
@ -522,7 +520,7 @@ def evaluation_date_first_completion(context, evaluation_id):
# au module (pour gerer les modules optionnels correctement)
insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
insmod = context.do_moduleimpl_inscription_list(moduleimpl_id=E["moduleimpl_id"])
insmodset = Set([x["etudid"] for x in insmod])
insmodset = set([x["etudid"] for x in insmod])
# retire de insem ceux qui ne sont pas inscrits au module
ins = [i for i in insem if i["etudid"] in insmodset]

View File

@ -28,12 +28,13 @@
"""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
from notesdb import ScoDocCursor, DateISOtoDMY, DateDMYtoISO
from notesdb import *
from sco_utils import *
from notes_log import log
from TrivialFormulator import TrivialFormulator, TF
from notes_table import *
# from notes_table import *
import sco_find_etud
import sco_formsemestre
import sco_groups
@ -283,7 +284,7 @@ def formsemestre_inscription_option(context, etudid, formsemestre_id, REQUEST=No
modimpls_by_ue_ids = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_id ]
modimpls_by_ue_names = DictDefault(defaultvalue=[]) # ue_id : [ moduleimpl_name ]
ues = []
ue_ids = Set()
ue_ids = set()
initvalues = {}
for mod in mods:
ue_id = mod["ue"]["ue_id"]
@ -402,7 +403,7 @@ function chkbx_select(field_id, state) {
if not insdict.has_key(moduleimpl_id):
del a_desinscrire[moduleimpl_id]
a_inscrire = Set()
a_inscrire = set()
for ue in ues:
ue_id = ue["ue_id"]
a_inscrire.update(tf[2]["moduleimpls_%s" % ue_id])
@ -526,7 +527,7 @@ def do_moduleimpl_incription_options(
)
if not inscr:
raise ScoValueError(
"pas inscrit a ce module ! (etudid=%s, moduleimpl_id=%)"
"pas inscrit a ce module ! (etudid=%s, moduleimpl_id=%s)"
% (etudid, moduleimpl_id)
)
oid = inscr[0]["moduleimpl_inscription_id"]

View File

@ -28,7 +28,6 @@
"""Une classe "vecteur" pour les formules utilisateurs de calcul des moyennes
"""
from sets import Set
import operator
import traceback
from types import FloatType, IntType, LongType, StringType
@ -174,8 +173,7 @@ formula_builtins = {
def eval_user_expression(context, expression, variables):
"""Evalue l'expression (formule utilisateur) avec les variables (dict) données.
"""
"""Evalue l'expression (formule utilisateur) avec les variables (dict) données."""
variables["__builtins__"] = formula_builtins
# log('Evaluating %s with %s' % (expression, variables))
# may raise exception if user expression is invalid

View File

@ -28,7 +28,6 @@
"""Form. pour inscription rapide des etudiants d'un semestre dans un autre
Utilise les autorisations d'inscription délivrées en jury.
"""
from sets import Set
from gen_tables import GenTable
@ -117,8 +116,7 @@ def list_inscrits(context, formsemestre_id, with_dems=False):
def list_etuds_from_sem(context, src, dst):
"""Liste des etudiants du semestre src qui sont autorisés à passer dans le semestre dst.
"""
"""Liste des etudiants du semestre src qui sont autorisés à passer dans le semestre dst."""
target = dst["semestre_id"]
dpv = sco_pvjury.dict_pvjury(context, src["formsemestre_id"])
if not dpv:
@ -274,7 +272,7 @@ def formsemestre_inscr_passage(
- on peut choisir les groupes TD, TP, TA
- seuls les etudiants non inscrits changent (de groupe)
- les etudiants inscrit qui se trouvent décochés sont désinscrits
- Confirmation: indiquer les étudiants inscrits et ceux désinscrits, le total courant.
- Confirmation: indiquer les étudiants inscrits et ceux désinscrits, le total courant.
"""
inscrit_groupes = int(inscrit_groupes)
@ -292,11 +290,11 @@ def formsemestre_inscr_passage(
etuds = etuds.split(",") # vient du form de confirmation
auth_etuds_by_sem, inscrits, candidats = list_authorized_etuds_by_sem(context, sem)
etuds_set = Set(etuds)
candidats_set = Set(candidats)
inscrits_set = Set(inscrits)
etuds_set = set(etuds)
candidats_set = set(candidats)
inscrits_set = set(inscrits)
candidats_non_inscrits = candidats_set - inscrits_set
inscrits_ailleurs = Set(list_inscrits_date(context, sem))
inscrits_ailleurs = set(list_inscrits_date(context, sem))
def set_to_sorted_etud_list(etudset):
etuds = [candidats[etudid] for etudid in etudset]
@ -489,7 +487,7 @@ def etuds_select_boxes(
"""Boites pour selection étudiants par catégorie
auth_etuds_by_cat = { category : { 'info' : {}, 'etuds' : ... }
inscrits_ailleurs =
sel_inscrits=
sel_inscrits=
export_cat_xls =
"""
if export_cat_xls:
@ -619,11 +617,8 @@ def etuds_select_box_xls(context, src_cat):
"export a box to excel"
etuds = src_cat["etuds"]
columns_ids = ["etudid", "sexe", "nom", "prenom", "etape"]
titles = {}
map(
lambda x, titles=titles: titles.__setitem__(x[0], x[1]),
zip(columns_ids, columns_ids),
)
titles = {x: x for x in columns_ids}
# Ajoute colonne paiement inscription
columns_ids.append("paiementinscription_str")
titles["paiementinscription_str"] = "paiement inscription"

View File

@ -41,14 +41,12 @@ import sco_excel
from gen_tables import GenTable
from htmlutils import histogram_notes
from sets import Set
def do_evaluation_listenotes(context, REQUEST):
"""
Affichage des notes d'une évaluation
args: evaluation_id
args: evaluation_id
"""
cnx = context.GetDBConnexion()
mode = None
@ -267,8 +265,8 @@ def _make_table_notes(
"prenom": "Prénom",
"nomprenom": "Nom",
"expl_key": "Rem.",
"email" : "e-mail",
"emailperso" : "e-mail perso"
"email": "e-mail",
"emailperso": "e-mail perso",
}
rows = []
@ -323,8 +321,8 @@ def _make_table_notes(
"prenom": strcapitalize(strlower(etud["prenom"])),
"nomprenom": etud["nomprenom"],
"group": grc,
"email" : etud["email"],
"emailperso" : etud["emailperso"],
"email": etud["email"],
"emailperso": etud["emailperso"],
"_css_row_class": css_row_class or "",
}
)
@ -381,7 +379,7 @@ def _make_table_notes(
# Si module, ajoute moyenne du module:
if len(evals) > 1:
notes = _add_moymod_column(
_add_moymod_column(
context,
sem["formsemestre_id"],
e,
@ -397,7 +395,7 @@ def _make_table_notes(
# Ajoute colonnes emails tout à droite:
if with_emails:
columns_ids += [ "email", "emailperso" ]
columns_ids += ["email", "emailperso"]
# Ajoute lignes en tête et moyennes
if len(evals) > 0:
rows = [coefs, note_max] + rows
@ -646,6 +644,7 @@ def _add_moymod_column(
note_sur_20,
keep_numeric,
):
"""Ajoute la colonne moymod à rows"""
col_id = "moymod"
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
@ -701,7 +700,7 @@ def _eval_demijournee(E):
def evaluation_check_absences(context, evaluation_id):
"""Vérifie les absences au moment de cette évaluation.
Cas incohérents que l'on peut rencontrer pour chaque étudiant:
note et absent
note et absent
ABS et pas noté absent
ABS et absent justifié
EXC et pas noté absent
@ -722,13 +721,13 @@ def evaluation_check_absences(context, evaluation_id):
# Liste les absences à ce moment:
A = context.Absences.ListeAbsJour(DateDMYtoISO(E["jour"]), am=am, pm=pm)
As = Set([x["etudid"] for x in A]) # ensemble des etudiants absents
As = set([x["etudid"] for x in A]) # ensemble des etudiants absents
NJ = context.Absences.ListeAbsNonJustJour(DateDMYtoISO(E["jour"]), am=am, pm=pm)
NJs = Set([x["etudid"] for x in NJ]) # ensemble des etudiants absents non justifies
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
)
Justs = Set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif
Justs = set([x["etudid"] for x in Just]) # ensemble des etudiants avec justif
# Les notes:
NotesDB = context._notes_getall(evaluation_id)
@ -860,8 +859,7 @@ def evaluation_check_absences_html(
def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
"""Affiche etat verification absences pour toutes les evaluations du semestre !
"""
"""Affiche etat verification absences pour toutes les evaluations du semestre !"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
H = [
context.html_sem_header(

View File

@ -27,7 +27,6 @@
"""Tableau de bord module
"""
from sets import Set
from notesdb import *
from sco_utils import *

View File

@ -80,8 +80,7 @@ class DecisionSem:
def SituationEtudParcours(context, etud, formsemestre_id):
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)
"""
"""renvoie une instance de SituationEtudParcours (ou sous-classe spécialisée)"""
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
) # > get_etud_decision_sem, get_etud_moy_gen, get_ues, get_etud_ue_status, etud_check_conditions_ues
@ -248,7 +247,7 @@ class SituationEtudParcoursGeneric:
decision = self.nt.get_etud_decision_sem(self.etudid)
return decision and code_semestre_validant(decision["code"])
else:
to_validate = Set(
to_validate = set(
range(1, self.parcours.NB_SEM + 1)
) # ensemble des indices à valider
if exclude_current and self.sem["semestre_id"] in to_validate:
@ -652,8 +651,7 @@ class SituationEtudParcoursGeneric:
class SituationEtudParcoursECTS(SituationEtudParcoursGeneric):
"""Gestion parcours basés sur ECTS
"""
"""Gestion parcours basés sur ECTS"""
def __init__(self, context, etud, formsemestre_id, nt):
SituationEtudParcoursGeneric.__init__(self, context, etud, formsemestre_id, nt)
@ -663,7 +661,7 @@ class SituationEtudParcoursECTS(SituationEtudParcoursGeneric):
def get_possible_choices(self, assiduite=True):
"""Listes de décisions "recommandées" (hors décisions manuelles)
Dans ce type de parcours, on n'utilise que ADM, AJ, et ADJ (?).
"""
etud_moy_infos = self.nt.get_etud_moy_infos(self.etudid)
@ -939,8 +937,7 @@ def do_formsemestre_validate_ue(
semestre_id=None,
is_external=0,
):
"""Ajoute ou change validation UE
"""
"""Ajoute ou change validation UE"""
args = {
"formsemestre_id": formsemestre_id,
"etudid": etudid,
@ -1026,17 +1023,17 @@ def formsemestre_get_autorisation_inscription(context, etudid, origin_formsemest
def formsemestre_get_etud_capitalisation(context, sem, etudid):
"""Liste des UE capitalisées (ADM) correspondant au semestre sem et à l'étudiant.
Recherche dans les semestres de la même formation (code) avec le même
semestre_id et une date de début antérieure à celle du semestre mentionné.
Et aussi les UE externes validées.
Resultat: [ { 'formsemestre_id' :
'ue_id' : ue_id dans le semestre origine
'ue_code' :
'ue_code' :
'moy_ue' :
'event_date' :
'is_external'
'event_date' :
'is_external'
} ]
"""
cnx = context.GetDBConnexion()

View File

@ -28,7 +28,16 @@
"""Liaison avec le portail ENT (qui donne accès aux infos Apogée)
"""
from sco_utils import *
import os, time
import urllib
import xml
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
SCO_CACHE_ETAPE_FILENAME = os.path.join(SCO_TMPDIR, "last_etapes.xml")
@ -153,7 +162,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 = query_portal(req, timeout=actual_timeout)
doc = sco_utils.query_portal(req, timeout=actual_timeout)
if doc:
break
if not doc:
@ -194,7 +203,7 @@ def query_apogee_portal(context, **args):
return []
portal_timeout = context.get_preference("portal_timeout")
req = etud_url + "?" + urllib.urlencode(args.items())
doc = query_portal(req, timeout=portal_timeout) # sco_utils
doc = sco_utils.query_portal(req, timeout=portal_timeout) # sco_utils
return xml_to_list_of_dicts(doc, req=req)
@ -250,7 +259,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(suppression_diacritics(unom))
nom_noaccents = str(sco_utils.suppression_diacritics(unom))
nom_utf8 = unom.encode("utf-8")
else:
nom_noaccents = nom
@ -258,7 +267,7 @@ def get_infos_apogee_allaccents(context, nom, prenom):
if prenom:
uprenom = unicode(prenom, SCO_ENCODING)
prenom_noaccents = str(suppression_diacritics(uprenom))
prenom_noaccents = str(sco_utils.suppression_diacritics(uprenom))
prenom_utf8 = uprenom.encode("utf-8")
else:
prenom_noaccents = prenom
@ -314,7 +323,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 = query_portal(req, timeout=portal_timeout)
doc = sco_utils.query_portal(req, timeout=portal_timeout)
d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
if not d:
return None
@ -378,7 +387,7 @@ def get_etapes_apogee(context):
"get_etapes_apogee: requesting '%s' with timeout=%s"
% (etapes_url, portal_timeout)
)
doc = query_portal(etapes_url, timeout=portal_timeout)
doc = sco_utils.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)
@ -473,7 +482,7 @@ def _normalize_apo_fields(infolist):
for infos in infolist:
if infos.has_key("paiementinscription"):
infos["paiementinscription"] = (
strlower(infos["paiementinscription"]) == "true"
sco_utils.strlower(infos["paiementinscription"]) == "true"
)
if infos["paiementinscription"]:
infos["paiementinscription_str"] = "ok"
@ -508,7 +517,7 @@ def check_paiement_etuds(context, etuds):
Seuls les etudiants avec code NIP sont renseignés.
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud, ainsi que l'étape.
Renseigne l'attribut booleen 'paiementinscription' dans chaque etud.
En sortie: modif les champs de chaque etud
'paiementinscription' : True, False ou None
@ -553,5 +562,5 @@ def get_maquette_apogee(context, etape="", annee_scolaire=""):
+ "?"
+ urllib.urlencode((("etape", etape), ("annee", annee_scolaire)))
)
doc = query_portal(req, timeout=portal_timeout)
doc = sco_utils.query_portal(req, timeout=portal_timeout)
return doc

View File

@ -35,6 +35,7 @@ import sco_evaluations
import sco_formsemestre
import sco_formsemestre_status
import sco_bulletins_xml
import sco_bulletins_json
import sco_codes_parcours
import sco_bac
@ -71,7 +72,7 @@ def formsemestre_recapcomplet(
else:
hidebac = int(hidebac)
xml_with_decisions = int(xml_with_decisions)
isFile = tabformat in ("csv", "xls", "xml", "xlsall")
isFile = tabformat in ("csv", "xls", "xml", "xlsall", "json")
H = []
if not isFile:
H += [
@ -103,6 +104,7 @@ def formsemestre_recapcomplet(
("xlsall", "Fichier tableur avec toutes les évals"),
("csv", "Fichier tableur (CSV)"),
("xml", "Fichier XML"),
("json", "JSON"),
):
if format == tabformat:
selected = " selected"
@ -129,8 +131,7 @@ def formsemestre_recapcomplet(
H.append("checked")
H.append(""" >cacher bac</input>""")
if tabformat == "xml":
REQUEST.RESPONSE.setHeader("content-type", "text/xml")
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
H.append(
do_formsemestre_recapcomplet(
context,
@ -181,7 +182,7 @@ def do_formsemestre_recapcomplet(
context=None,
REQUEST=None,
formsemestre_id=None,
format="html", # html, xml, xls, xlsall
format="html", # html, xml, xls, xlsall, json
hidemodules=False, # ne pas montrer les modules (ignoré en XML)
hidebac=False, # pas de colonne Bac (ignoré en XML)
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
@ -191,8 +192,7 @@ def do_formsemestre_recapcomplet(
disable_etudlink=False,
rank_partition_id=None, # si None, calcul rang global
):
"""Calcule et renvoie le tableau récapitulatif.
"""
"""Calcule et renvoie le tableau récapitulatif."""
data, filename, format = make_formsemestre_recapcomplet(**vars())
if format == "xml" or format == "html":
return data
@ -200,6 +200,8 @@ def do_formsemestre_recapcomplet(
return sendCSVFile(REQUEST, data, filename)
elif format[:3] == "xls":
return sco_excel.sendExcelFile(REQUEST, data, filename)
elif format == "json":
return sendJSON(REQUEST, data)
else:
raise ValueError("unknown format %s" % format)
@ -208,7 +210,7 @@ def make_formsemestre_recapcomplet(
context=None,
REQUEST=None,
formsemestre_id=None,
format="html", # html, xml, xls, xlsall
format="html", # html, xml, xls, xlsall, json
hidemodules=False, # ne pas montrer les modules (ignoré en XML)
hidebac=False, # pas de colonne Bac (ignoré en XML)
xml_nodate=False, # format XML sans dates (sert pour debug cache: comparaison de XML)
@ -226,6 +228,10 @@ def make_formsemestre_recapcomplet(
return _formsemestre_recapcomplet_xml(
context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions
)
elif format == "json":
return _formsemestre_recapcomplet_json(
context, formsemestre_id, xml_nodate, xml_with_decisions=xml_with_decisions
)
if format[:3] == "xls":
keep_numeric = True # pas de conversion des notes en strings
else:
@ -261,7 +267,7 @@ def make_formsemestre_recapcomplet(
else:
rank_partition = sco_groups.get_default_partition(context, formsemestre_id)
rank_label = "Rg"
T = nt.get_table_moyennes_triees()
if not T:
return "", "", format
@ -556,19 +562,18 @@ def make_formsemestre_recapcomplet(
cls = "recap_tit_ue"
else:
cls = "recap_tit"
if i == 0 or F[0][i] == "classement": # Rang: force tri numerique pour sortable
if (
i == 0 or F[0][i] == "classement"
): # Rang: force tri numerique pour sortable
cls = cls + " sortnumeric"
if cod2mod.has_key(F[0][i]): # lien vers etat module
mod = cod2mod[F[0][i]]
cells += (
'<td class="%s"><a href="moduleimpl_status?moduleimpl_id=%s" title="%s (%s)">%s</a></td>'
% (
cls,
mod["moduleimpl_id"],
mod["module"]["titre"],
context.Users.user_info(mod["responsable_id"])["nomcomplet"],
F[0][i],
)
cells += '<td class="%s"><a href="moduleimpl_status?moduleimpl_id=%s" title="%s (%s)">%s</a></td>' % (
cls,
mod["moduleimpl_id"],
mod["module"]["titre"],
context.Users.user_info(mod["responsable_id"])["nomcomplet"],
F[0][i],
)
else:
cells += '<td class="%s">%s</td>' % (cls, F[0][i])
@ -788,8 +793,7 @@ def _list_notes_evals_stats(context, evals, key):
def _formsemestre_recapcomplet_xml(
context, formsemestre_id, xml_nodate, xml_with_decisions=False
):
"XML export: liste tous les bulletins XML"
# REQUEST.RESPONSE.setHeader('content-type', XML_MIMETYPE)
"XML export: liste tous les bulletins XML."
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
@ -827,3 +831,42 @@ def _formsemestre_recapcomplet_xml(
)
doc._pop()
return repr(doc), "", "xml"
def _formsemestre_recapcomplet_json(
context, formsemestre_id, xml_nodate, xml_with_decisions=False
):
"JSON export: liste tous les bulletins JSON"
if xml_nodate:
docdate = ""
else:
docdate = datetime.datetime.now().isoformat()
evals = sco_evaluations.do_evaluation_etat_in_sem(context, formsemestre_id)
J = {
"docdate": docdate,
"formsemestre_id": formsemestre_id,
"evals_info": {
"nb_evals_completes": evals["nb_evals_completes"],
"nb_evals_en_cours": evals["nb_evals_en_cours"],
"nb_evals_vides": evals["nb_evals_vides"],
"date_derniere_note": evals["last_modif"],
},
"bulletins": [],
}
bulletins = J["bulletins"]
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
) # > get_table_moyennes_triees
T = nt.get_table_moyennes_triees()
for t in T:
etudid = t[-1]
bulletins.append(
sco_bulletins_json.formsemestre_bulletinetud_published_dict(
context,
formsemestre_id,
etudid,
force_publishing=True,
xml_with_decisions=xml_with_decisions,
)
)
return J, "", "json"

View File

@ -29,8 +29,8 @@
- statistiques decisions
- suivi cohortes
"""
from mx.DateTime import DateTime as mxDateTime
import mx.DateTime
from mx.DateTime import DateTime as mxDateTime
import tempfile, urllib, re
@ -396,12 +396,12 @@ def table_suivi_cohorte(
logt("A: orig etuds set")
S = {formsemestre_id: sem} # ensemble de formsemestre_id
orig_set = Set() # ensemble d'etudid du semestre d'origine
bacs = Set()
bacspecialites = Set()
annee_bacs = Set()
sexes = Set()
statuts = Set()
orig_set = set() # ensemble d'etudid du semestre d'origine
bacs = set()
bacspecialites = set()
annee_bacs = set()
sexes = set()
statuts = set()
for etudid in etudids:
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
bacspe = etud["bac"] + " / " + etud["specialite"]
@ -429,7 +429,7 @@ 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)
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"]))
# 2-- Pour chaque semestre, trouve l'ensemble des etudiants venant de sem
@ -439,7 +439,7 @@ def table_suivi_cohorte(
ins = context.do_formsemestre_inscription_list(
args={"formsemestre_id": s["formsemestre_id"]}
) # sans dems
inset = Set([i["etudid"] for i in ins])
inset = set([i["etudid"] for i in ins])
s["members"] = orig_set.intersection(inset)
nb_dipl = 0 # combien de diplomes dans ce semestre ?
if s["semestre_id"] == nt.parcours.NB_SEM:
@ -461,7 +461,7 @@ 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)
porigin.datedebut = mxDateTime(y, m, d) # pylint: disable=not-callable
porigin.sems = [sem]
#
@ -480,7 +480,7 @@ def table_suivi_cohorte(
P.append(p)
# 4-- regroupe par indice de semestre S_i
indices_sems = list(Set([s["semestre_id"] for s in sems]))
indices_sems = list(set([s["semestre_id"] for s in sems]))
indices_sems.sort()
for p in P:
p.nb_etuds = 0 # nombre total d'etudiants dans la periode
@ -518,7 +518,7 @@ def table_suivi_cohorte(
d = {"row_title": "Autre semestre"}
for p in P:
etuds_period = Set()
etuds_period = set()
for s in p.sems:
if s["semestre_id"] == idx_sem:
etuds_period = etuds_period.union(s["members"])
@ -533,8 +533,8 @@ def table_suivi_cohorte(
logt("D: cout dems reos")
sem["dems"], sem["reos"] = _count_dem_reo(context, formsemestre_id, sem["members"])
for p in P:
p.dems = Set()
p.reos = Set()
p.dems = set()
p.reos = set()
for s in p.sems:
d, r = _count_dem_reo(context, s["formsemestre_id"], s["members"])
p.dems.update(d)
@ -879,8 +879,8 @@ def _count_dem_reo(context, formsemestre_id, etudids):
nt = context._getNotesCache().get_NotesTable(
context, formsemestre_id
) # > get_etud_etat, get_etud_decision_sem
dems = Set()
reos = Set()
dems = set()
reos = set()
for etudid in etudids:
if nt.get_etud_etat(etudid) == "D":
dems.add(etudid)
@ -994,11 +994,11 @@ def tsp_etud_list(
) # > get_etudids,
etudids = nt.get_etudids()
etuds = []
bacs = Set()
bacspecialites = Set()
annee_bacs = Set()
sexes = Set()
statuts = Set()
bacs = set()
bacspecialites = set()
annee_bacs = set()
sexes = set()
statuts = set()
for etudid in etudids:
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
bacspe = etud["bac"] + " / " + etud["specialite"]
@ -1228,25 +1228,25 @@ def graph_parcours(
if not etuds:
return "", etuds, bacs, bacspecialites, annee_bacs, sexes, statuts
edges = DictDefault(
defaultvalue=Set()
defaultvalue=set()
) # {(formsemestre_id_origin, formsemestre_id_dest) : etud_set}
sems = {}
effectifs = DictDefault(defaultvalue=Set()) # formsemestre_id : etud_set
effectifs = DictDefault(defaultvalue=set()) # formsemestre_id : etud_set
decisions = DictDefault(defaultvalue={}) # formsemestre_id : { code : nb_etud }
isolated_nodes = []
connected_nodes = Set()
connected_nodes = set()
diploma_nodes = []
dem_nodes = {} # formsemestre_id : noeud pour demissionnaires
nar_nodes = {} # formsemestre_id : noeud pour NAR
for etud in etuds:
next = None
nxt = None
etudid = etud["etudid"]
for s in etud["sems"]: # du plus recent au plus ancien
nt = context._getNotesCache().get_NotesTable(
context, s["formsemestre_id"]
) # > get_etud_decision_sem, get_etud_etat
dec = nt.get_etud_decision_sem(etudid)
if next:
if nxt:
if (
s["semestre_id"] == nt.parcours.NB_SEM
and dec
@ -1255,17 +1255,17 @@ def graph_parcours(
):
# cas particulier du diplome puis poursuite etude
edges[
("_dipl_" + s["formsemestre_id"], next["formsemestre_id"])
("_dipl_" + s["formsemestre_id"], nxt["formsemestre_id"])
].add(etudid)
else:
edges[(s["formsemestre_id"], next["formsemestre_id"])].add(etudid)
edges[(s["formsemestre_id"], nxt["formsemestre_id"])].add(etudid)
connected_nodes.add(s["formsemestre_id"])
connected_nodes.add(next["formsemestre_id"])
connected_nodes.add(nxt["formsemestre_id"])
else:
isolated_nodes.append(s["formsemestre_id"])
sems[s["formsemestre_id"]] = s
effectifs[s["formsemestre_id"]].add(etudid)
next = s
nxt = s
# Compte decisions jury de chaque semestres:
dc = decisions[s["formsemestre_id"]]
if dec:

View File

@ -29,8 +29,8 @@
"""
from sco_utils import *
from notesdb import *
from sco_utils import ScoEtudInscrit, annee_scolaire_debut, log, ScoValueError
from notesdb import ScoDocCursor
import sco_portal_apogee
import sco_inscr_passage
@ -698,7 +698,7 @@ def do_import_etud_admission(
log("do_import_etud_admission: etud=%s" % etud)
al = scolars.admission_list(cnx, args={"etudid": etudid})
if not al:
adm_id = scolars.admission_create(cnx, args)
scolars.admission_create(cnx, args) # -> adm_id
else:
# existing data: merge
e = al[0]

View File

@ -61,8 +61,6 @@ except ImportError:
# fallback for very old ScoDoc instances
STRING_TYPES = StringType
from sets import Set
from PIL import Image as PILImage
# XML generation package (apt-get install jaxml)
@ -215,6 +213,7 @@ if SCO_SRCDIR:
SCO_SRCDIR += "/"
else:
SCO_SRCDIR = "/opt/scodoc/Products/ScoDoc/" # debug mode
CONFIG = None
try:
_config_filename = SCO_SRCDIR + "config/scodoc_config.py"
_config_text = open(_config_filename).read()
@ -512,7 +511,7 @@ def make_filename(name):
VALID_CARS = (
"-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.!" # no / !
)
VALID_CARS_SET = Set(VALID_CARS)
VALID_CARS_SET = set(VALID_CARS)
VALID_EXP = re.compile("^[" + VALID_CARS + "]+$")
@ -558,12 +557,14 @@ def sendPDFFile(REQUEST, data, filename):
class ScoDocJSONEncoder(json.JSONEncoder):
def default(self, o):
def default(self, o): # pylint: disable=E0202
import sco_formsemestre
# horrible hack pour encoder les dates
# horrible hack pour encoder les dates mx
if str(type(o)) == "<type 'mx.DateTime.DateTime'>":
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: