blackify and some minor fixes
This commit is contained in:
parent
3c567aeb18
commit
8d74f8feed
@ -1,7 +1,7 @@
|
||||
|
||||
# SCODOC - gestion de la scolarité
|
||||
|
||||
(c) Emmanuel Viennet 1999 - 2020 (voir LICENCE.txt)
|
||||
(c) Emmanuel Viennet 1999 - 2021 (voir LICENCE.txt)
|
||||
|
||||
|
||||
Installation: voir instructions à jour sur <https://scodoc.org>
|
||||
|
@ -277,7 +277,7 @@ class ZScoUsers(
|
||||
|
||||
def user_info(self, user_name=None, user=None):
|
||||
"""Donne infos sur l'utilisateur (qui peut ne pas etre dans notre base).
|
||||
Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict.
|
||||
Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict.
|
||||
"""
|
||||
if user_name:
|
||||
infos = self._user_list(args={"user_name": user_name})
|
||||
@ -919,7 +919,7 @@ class ZScoUsers(
|
||||
self, edit, user_name="", nom="", prenom="", email="", roles=[]
|
||||
):
|
||||
"""Vérifie que et utilisateur peut etre crée (edit=0) ou modifié (edit=1)
|
||||
Cherche homonymes.
|
||||
Cherche homonymes.
|
||||
returns (ok, msg)
|
||||
- ok : si vrai, peut continuer avec ces parametres
|
||||
(si ok est faux, l'utilisateur peut quand même forcer la creation)
|
||||
@ -1252,8 +1252,7 @@ class ZScoUsers(
|
||||
security.declareProtected(ScoView, "get_user_name_from_nomplogin")
|
||||
|
||||
def get_user_name_from_nomplogin(self, nomplogin):
|
||||
"""Returns user_name (login) from nomplogin
|
||||
"""
|
||||
"""Returns user_name (login) from nomplogin"""
|
||||
m = re.match(r".*\((.*)\)", nomplogin.strip())
|
||||
if m:
|
||||
return m.group(1)
|
||||
|
0
csv2rules.py
Normal file → Executable file
0
csv2rules.py
Normal file → Executable file
22
dutrules.py
22
dutrules.py
@ -4,7 +4,27 @@
|
||||
#
|
||||
# Command: ./csv2rules.py misc/parcoursDUT.csv
|
||||
#
|
||||
from sco_codes_parcours import *
|
||||
from sco_codes_parcours import (
|
||||
DUTRule,
|
||||
ADC,
|
||||
ADJ,
|
||||
ADM,
|
||||
AJ,
|
||||
ALL,
|
||||
ATB,
|
||||
ATJ,
|
||||
ATT,
|
||||
CMP,
|
||||
NAR,
|
||||
NEXT,
|
||||
RA_OR_NEXT,
|
||||
RA_OR_RS,
|
||||
RAT,
|
||||
REO,
|
||||
REDOANNEE,
|
||||
REDOSEM,
|
||||
RS_OR_NEXT,
|
||||
)
|
||||
|
||||
rules_source_file = "misc/parcoursDUT.csv"
|
||||
|
||||
|
@ -45,9 +45,20 @@ from collections import OrderedDict
|
||||
|
||||
# XML generation package (apt-get install jaxml)
|
||||
import jaxml
|
||||
import json
|
||||
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
|
||||
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||
from reportlab.lib.colors import Color
|
||||
from reportlab.lib import styles
|
||||
from reportlab.lib.units import inch, cm, mm
|
||||
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
|
||||
|
||||
import sco_utils as scu
|
||||
import sco_excel
|
||||
from sco_pdf import *
|
||||
import sco_pdf
|
||||
from sco_pdf import SU
|
||||
from notes_log import log
|
||||
|
||||
|
||||
def mark_paras(L, tags):
|
||||
@ -280,7 +291,7 @@ class GenTable:
|
||||
if not row:
|
||||
return "<tr></tr>" # empty row
|
||||
|
||||
if self.html_col_width: # XXXX Obsolete ?
|
||||
if self.html_col_width:
|
||||
std = ' style="width:%s;"' % self.html_col_width
|
||||
else:
|
||||
std = ""
|
||||
@ -382,10 +393,6 @@ class GenTable:
|
||||
else:
|
||||
cls = ""
|
||||
|
||||
if self.html_col_width:
|
||||
std = ' style="width:%s;"' % self.html_col_width
|
||||
else:
|
||||
std = ""
|
||||
H = [self.html_before_table, "<table%s%s>" % (hid, cls)]
|
||||
|
||||
line_num = 0
|
||||
@ -438,14 +445,14 @@ class GenTable:
|
||||
if self.xls_link:
|
||||
H.append(
|
||||
' <a href="%s&format=xls">%s</a>'
|
||||
% (self.base_url, ICON_XLS)
|
||||
% (self.base_url, scu.ICON_XLS)
|
||||
)
|
||||
if self.xls_link and self.pdf_link:
|
||||
H.append(" ")
|
||||
if self.pdf_link:
|
||||
H.append(
|
||||
' <a href="%s&format=pdf">%s</a>'
|
||||
% (self.base_url, ICON_PDF)
|
||||
% (self.base_url, scu.ICON_PDF)
|
||||
)
|
||||
H.append("</p>")
|
||||
|
||||
@ -483,10 +490,10 @@ class GenTable:
|
||||
"PDF representation: returns a ReportLab's platypus Table instance"
|
||||
r = []
|
||||
try:
|
||||
PDFLOCK.acquire()
|
||||
sco_pdf.PDFLOCK.acquire()
|
||||
r = self._pdf()
|
||||
finally:
|
||||
PDFLOCK.release()
|
||||
sco_pdf.PDFLOCK.release()
|
||||
return r
|
||||
|
||||
def _pdf(self):
|
||||
@ -513,7 +520,7 @@ class GenTable:
|
||||
CellStyle.leading = 1.0 * self.preferences["SCOLAR_FONT_SIZE"] # vertical space
|
||||
LINEWIDTH = 0.5
|
||||
#
|
||||
titles = ["<para><b>%s</b></para>" % x for x in self.get_titles_list()]
|
||||
# titles = ["<para><b>%s</b></para>" % x for x in self.get_titles_list()]
|
||||
pdf_style_list = []
|
||||
Pt = [
|
||||
[Paragraph(SU(str(x)), CellStyle) for x in line]
|
||||
@ -530,10 +537,10 @@ class GenTable:
|
||||
# log('len(Pt)=%s' % len(Pt))
|
||||
# log( 'line lens=%s' % [ len(x) for x in Pt ] )
|
||||
# log( 'style=\n%s' % pdf_style_list)
|
||||
col_min = min([x[1][0] for x in pdf_style_list])
|
||||
col_max = max([x[2][0] for x in pdf_style_list])
|
||||
lin_min = min([x[1][1] for x in pdf_style_list])
|
||||
lin_max = max([x[2][1] for x in pdf_style_list])
|
||||
# col_min = min([x[1][0] for x in pdf_style_list])
|
||||
# col_max = max([x[2][0] for x in pdf_style_list])
|
||||
# lin_min = min([x[1][1] for x in pdf_style_list])
|
||||
# lin_max = max([x[2][1] for x in pdf_style_list])
|
||||
# log('col_min=%s col_max=%s lin_min=%s lin_max=%s' % (col_min, col_max, lin_min, lin_max))
|
||||
T = Table(Pt, repeatRows=1, colWidths=self.pdf_col_widths, style=pdf_style_list)
|
||||
|
||||
@ -559,7 +566,7 @@ class GenTable:
|
||||
The tag names <table> and <row> can be changed using
|
||||
xml_outer_tag and xml_row_tag
|
||||
"""
|
||||
doc = jaxml.XML_document(encoding=SCO_ENCODING)
|
||||
doc = jaxml.XML_document(encoding=scu.SCO_ENCODING)
|
||||
getattr(doc, self.xml_outer_tag)(
|
||||
id=self.table_id, origin=self.origin or "", caption=self.caption or ""
|
||||
)
|
||||
@ -593,7 +600,7 @@ class GenTable:
|
||||
v = str(v)
|
||||
r[cid] = v
|
||||
d.append(r)
|
||||
return json.dumps(d, encoding=SCO_ENCODING)
|
||||
return json.dumps(d, encoding=scu.SCO_ENCODING)
|
||||
|
||||
def make_page(
|
||||
self,
|
||||
@ -637,11 +644,11 @@ class GenTable:
|
||||
return "\n".join(H)
|
||||
elif format == "pdf":
|
||||
objects = self.pdf()
|
||||
doc = pdf_basic_page(
|
||||
doc = sco_pdf.pdf_basic_page(
|
||||
objects, title=title, preferences=self.preferences, context=context
|
||||
)
|
||||
if publish:
|
||||
return sendPDFFile(REQUEST, doc, filename + ".pdf")
|
||||
return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
|
||||
else:
|
||||
return doc
|
||||
elif format == "xls":
|
||||
@ -653,16 +660,16 @@ class GenTable:
|
||||
elif format == "text":
|
||||
return self.text()
|
||||
elif format == "csv":
|
||||
return sendCSVFile(REQUEST, self.text(), filename + ".csv")
|
||||
return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv")
|
||||
elif format == "xml":
|
||||
xml = self.xml()
|
||||
if REQUEST and publish:
|
||||
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
|
||||
return xml
|
||||
elif format == "json":
|
||||
js = self.json()
|
||||
if REQUEST and publish:
|
||||
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE)
|
||||
REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
|
||||
return js
|
||||
else:
|
||||
log("make_page: format=%s" % format)
|
||||
@ -687,7 +694,7 @@ class SeqGenTable:
|
||||
def excel(self):
|
||||
"""Export des genTables dans un unique fichier excel avec plusieurs feuilles tagguées"""
|
||||
book = sco_excel.Workbook() # Le fichier xls en devenir
|
||||
for (name, gt) in self.genTables.items():
|
||||
for (_, gt) in self.genTables.items():
|
||||
gt.excel(wb=book) # Ecrit dans un fichier excel
|
||||
return book.savetostr()
|
||||
|
||||
|
@ -257,6 +257,5 @@ def sco_header(
|
||||
|
||||
|
||||
def sco_footer(context, REQUEST=None):
|
||||
"""Main HTMl pages footer
|
||||
"""
|
||||
"""Main HTMl pages footer"""
|
||||
return """</div><!-- /gtrcontent -->""" + CUSTOM_HTML_FOOTER + """</body></html>"""
|
||||
|
@ -158,8 +158,7 @@ def sidebar(context, REQUEST=None):
|
||||
|
||||
|
||||
def sidebar_dept(context, REQUEST=None):
|
||||
"""Partie supérieure de la marge de gauche
|
||||
"""
|
||||
"""Partie supérieure de la marge de gauche"""
|
||||
infos = {
|
||||
"BASE0": REQUEST.BASE0,
|
||||
"DeptIntranetTitle": context.get_preference("DeptIntranetTitle"),
|
||||
|
@ -49,7 +49,7 @@ def histogram_notes(notes):
|
||||
"HTML code drawing histogram"
|
||||
if not notes:
|
||||
return ""
|
||||
bins, H = listhistogram.ListHistogram(notes, 21, minmax=(0, 20))
|
||||
_, H = listhistogram.ListHistogram(notes, 21, minmax=(0, 20))
|
||||
D = ['<ul id="vhist-q-graph"><li class="vhist-qtr" id="vhist-q1"><ul>']
|
||||
left = 5
|
||||
colwidth = 16 # must match #q-graph li.bar width in stylesheet
|
||||
|
100
intervals.py
100
intervals.py
@ -10,53 +10,53 @@ from itertools import izip
|
||||
|
||||
class intervalmap(object):
|
||||
"""
|
||||
This class maps a set of intervals to a set of values.
|
||||
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:5] = '0-5'
|
||||
>>> i[8:12] = '8-12'
|
||||
>>> print i[2]
|
||||
0-5
|
||||
>>> print i[10]
|
||||
8-12
|
||||
>>> print repr(i[-1])
|
||||
None
|
||||
>>> print repr(i[17])
|
||||
None
|
||||
>>> i[4:9] = '4-9'
|
||||
>>> print [(j,i[j]) for j in range(6)]
|
||||
[(0, '0-5'), (1, '0-5'), (2, '0-5'), (3, '0-5'), (4, '4-9'), (5, '4-9')]
|
||||
>>> print list(i.items())
|
||||
[((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[:0] = 'less than 0'
|
||||
>>> i[-5]
|
||||
'less than 0'
|
||||
>>> i[0]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[21:] = 'more than twenty'
|
||||
>>> i[42]
|
||||
'more than twenty'
|
||||
>>> i[10.5:15.5] = '10.5-15.5'
|
||||
>>> i[11.5]
|
||||
'10.5-15.5'
|
||||
>>> i[0.5]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),...
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:2] = 1
|
||||
>>> i[2:8] = 2
|
||||
>>> i[4:] = 3
|
||||
>>> i[5:6] = 4
|
||||
>>> i
|
||||
{[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3}
|
||||
This class maps a set of intervals to a set of values.
|
||||
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:5] = '0-5'
|
||||
>>> i[8:12] = '8-12'
|
||||
>>> print i[2]
|
||||
0-5
|
||||
>>> print i[10]
|
||||
8-12
|
||||
>>> print repr(i[-1])
|
||||
None
|
||||
>>> print repr(i[17])
|
||||
None
|
||||
>>> i[4:9] = '4-9'
|
||||
>>> print [(j,i[j]) for j in range(6)]
|
||||
[(0, '0-5'), (1, '0-5'), (2, '0-5'), (3, '0-5'), (4, '4-9'), (5, '4-9')]
|
||||
>>> print list(i.items())
|
||||
[((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[:0] = 'less than 0'
|
||||
>>> i[-5]
|
||||
'less than 0'
|
||||
>>> i[0]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
|
||||
>>> i[21:] = 'more than twenty'
|
||||
>>> i[42]
|
||||
'more than twenty'
|
||||
>>> i[10.5:15.5] = '10.5-15.5'
|
||||
>>> i[11.5]
|
||||
'10.5-15.5'
|
||||
>>> i[0.5]
|
||||
'0-5'
|
||||
>>> print list(i.items())
|
||||
[((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),...
|
||||
>>> i = intervalmap()
|
||||
>>> i[0:2] = 1
|
||||
>>> i[2:8] = 2
|
||||
>>> i[4:] = 3
|
||||
>>> i[5:6] = 4
|
||||
>>> i
|
||||
{[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3}
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initializes an empty intervalmap.
|
||||
Initializes an empty intervalmap.
|
||||
"""
|
||||
self._bounds = []
|
||||
self._items = []
|
||||
@ -64,7 +64,7 @@ class intervalmap(object):
|
||||
|
||||
def __setitem__(self, _slice, _value):
|
||||
"""
|
||||
Sets an interval mapping.
|
||||
Sets an interval mapping.
|
||||
"""
|
||||
assert isinstance(_slice, slice), "The key must be a slice object"
|
||||
|
||||
@ -112,7 +112,7 @@ class intervalmap(object):
|
||||
|
||||
def __getitem__(self, _point):
|
||||
"""
|
||||
Gets a value from the mapping.
|
||||
Gets a value from the mapping.
|
||||
"""
|
||||
assert not isinstance(_point, slice), "The key cannot be a slice object"
|
||||
|
||||
@ -124,9 +124,9 @@ class intervalmap(object):
|
||||
|
||||
def items(self):
|
||||
"""
|
||||
Returns an iterator with each item being
|
||||
((low_bound,high_bound), value). The items are returned
|
||||
in order.
|
||||
Returns an iterator with each item being
|
||||
((low_bound,high_bound), value). The items are returned
|
||||
in order.
|
||||
"""
|
||||
previous_bound = None
|
||||
for b, v in izip(self._bounds, self._items):
|
||||
@ -138,8 +138,8 @@ class intervalmap(object):
|
||||
|
||||
def values(self):
|
||||
"""
|
||||
Returns an iterator with each item being a stored value. The items
|
||||
are returned in order.
|
||||
Returns an iterator with each item being a stored value. The items
|
||||
are returned in order.
|
||||
"""
|
||||
for v in self._items:
|
||||
if v is not None:
|
||||
|
@ -61,5 +61,5 @@ class CacheFunc:
|
||||
|
||||
def inval_cache(self): # >
|
||||
"clear whole cache"
|
||||
log("inval_cache %s(%s)" % (str(self.func), str(args))) # >
|
||||
log("inval_cache %s" % (str(self.func))) # >
|
||||
self.cache = {}
|
||||
|
@ -88,7 +88,7 @@ def retreive_dept():
|
||||
return ""
|
||||
try:
|
||||
url = REQUEST.URL
|
||||
m = re.match("^.*ScoDoc/(\w+).*$", url)
|
||||
m = re.match(r"^.*ScoDoc/(\w+).*$", url)
|
||||
return m.group(1)
|
||||
except:
|
||||
return ""
|
||||
|
@ -51,7 +51,7 @@ BONUS_TWO_ARGS = len(inspect.getargspec(CONFIG.compute_bonus)[0]) == 2
|
||||
|
||||
|
||||
def comp_ranks(T):
|
||||
"""Calcul rangs à partir d'une liste ordonnée de tuples [ (valeur, ..., etudid) ]
|
||||
"""Calcul rangs à partir d'une liste ordonnée de tuples [ (valeur, ..., etudid) ]
|
||||
(valeur est une note numérique), en tenant compte des ex-aequos
|
||||
Le resultat est: { etudid : rang } où rang est une chaine decrivant le rang
|
||||
"""
|
||||
@ -135,8 +135,8 @@ class NotesTable:
|
||||
- inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions)
|
||||
- identdict: { etudid : ident }
|
||||
- sem : le formsemestre
|
||||
get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ]
|
||||
(où toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'),
|
||||
get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ]
|
||||
(où toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'),
|
||||
incluant les UE de sport
|
||||
|
||||
- bonus[etudid] : valeur du bonus "sport".
|
||||
@ -145,7 +145,7 @@ class NotesTable:
|
||||
- _modmoys : { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
|
||||
- _ues : liste des UE de ce semestre (hors capitalisees)
|
||||
- _matmoys : { matiere_id : { etudid: note moyenne dans cette matiere } }
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, context, formsemestre_id):
|
||||
@ -408,7 +408,7 @@ class NotesTable:
|
||||
|
||||
def get_ues(self, filter_sport=False, filter_non_inscrit=False, etudid=None):
|
||||
"""liste des ue, ordonnée par numero.
|
||||
Si filter_non_inscrit, retire les UE dans lesquelles l'etudiant n'est
|
||||
Si filter_non_inscrit, retire les UE dans lesquelles l'etudiant n'est
|
||||
inscrit à aucun module.
|
||||
Si filter_sport, retire les UE de type SPORT
|
||||
"""
|
||||
@ -580,11 +580,11 @@ class NotesTable:
|
||||
return matmoy.get(etudid, "NA")
|
||||
|
||||
def comp_etud_moy_ue(self, etudid, ue_id=None, cnx=None):
|
||||
"""Calcule moyenne gen. pour un etudiant dans une UE
|
||||
"""Calcule moyenne gen. pour un etudiant dans une UE
|
||||
Ne prend en compte que les evaluations où toutes les notes sont entrées
|
||||
Return a dict(moy, nb_notes, nb_missing, sum_coefs)
|
||||
Si pas de notes, moy == 'NA' et sum_coefs==0
|
||||
Si non inscrit, moy == 'NI' et sum_coefs==0
|
||||
Si non inscrit, moy == 'NI' et sum_coefs==0
|
||||
"""
|
||||
assert ue_id
|
||||
modimpls = self.get_modimpls(ue_id)
|
||||
@ -608,7 +608,6 @@ class NotesTable:
|
||||
est_inscrit = False # inscrit à l'un des modules de cette UE ?
|
||||
|
||||
for modimpl in modimpls:
|
||||
mod_ue_id = modimpl["ue"]["ue_id"]
|
||||
# module ne faisant pas partie d'une UE capitalisee
|
||||
val = self._modmoys[modimpl["moduleimpl_id"]].get(etudid, "NI")
|
||||
# si 'NI', etudiant non inscrit a ce module
|
||||
@ -711,7 +710,7 @@ class NotesTable:
|
||||
def comp_etud_moy_gen(self, etudid, cnx):
|
||||
"""Calcule moyenne gen. pour un etudiant
|
||||
Return a dict:
|
||||
moy : moyenne générale
|
||||
moy : moyenne générale
|
||||
nb_notes, nb_missing, sum_coefs
|
||||
ects_pot : (float) nb de crédits ECTS qui seraient validés (sous réserve de validation par le jury),
|
||||
ects_pot_fond: (float) nb d'ECTS issus d'UE fondamentales (non électives)
|
||||
@ -721,14 +720,14 @@ class NotesTable:
|
||||
'est_inscrit' : True si étudiant inscrit à au moins un module de cette UE
|
||||
'moy' : moyenne, avec capitalisation eventuelle
|
||||
'coef_ue' : coef de l'UE utilisé pour le calcul de la moyenne générale
|
||||
(la somme des coefs des modules, ou le coef d'UE capitalisée,
|
||||
(la somme des coefs des modules, ou le coef d'UE capitalisée,
|
||||
ou encore le coef d'UE si l'option use_ue_coefs est active)
|
||||
'cur_moy_ue' : moyenne de l'UE en cours (sans considérer de capitalisation)
|
||||
'cur_coef_ue': coefficient de l'UE courante
|
||||
'is_capitalized' : True|False,
|
||||
'ects_pot' : (float) nb de crédits ECTS qui seraient validés (sous réserve de validation par le jury),
|
||||
'ects_pot_fond': 0. si UE non fondamentale, = ects_pot sinon,
|
||||
'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon,
|
||||
'ects_pot_fond': 0. si UE non fondamentale, = ects_pot sinon,
|
||||
'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon,
|
||||
'formsemestre_id' : (si capitalisee),
|
||||
'event_date' : (si capitalisee)
|
||||
}
|
||||
@ -760,7 +759,6 @@ class NotesTable:
|
||||
sem_ects_pot_pro = 0.0
|
||||
|
||||
for ue in self.get_ues():
|
||||
ue_id = ue["ue_id"]
|
||||
# - On calcule la moyenne d'UE courante:
|
||||
if not block_computation:
|
||||
mu = self.comp_etud_moy_ue(etudid, ue_id=ue["ue_id"], cnx=cnx)
|
||||
@ -956,10 +954,10 @@ class NotesTable:
|
||||
Ne considère que les UE ayant des notes (moyenne calculée).
|
||||
(les UE sans notes ne sont pas comptées comme sous la barre)
|
||||
Prend en compte les éventuelles UE capitalisées.
|
||||
|
||||
|
||||
Pour les parcours habituels, cela revient à vérifier que
|
||||
les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes)
|
||||
|
||||
|
||||
Pour les parcours non standards (LP2014), cela peut être plus compliqué.
|
||||
|
||||
Return: True|False, message explicatif
|
||||
@ -1000,8 +998,7 @@ class NotesTable:
|
||||
)
|
||||
|
||||
def get_table_moyennes_dict(self):
|
||||
"""{ etudid : (liste des moyennes) } comme get_table_moyennes_triees
|
||||
"""
|
||||
"""{ etudid : (liste des moyennes) } comme get_table_moyennes_triees"""
|
||||
D = {}
|
||||
for t in self.T:
|
||||
D[t[-1]] = t
|
||||
@ -1209,13 +1206,13 @@ class NotesTable:
|
||||
# return sum(c_list)
|
||||
|
||||
def get_etud_ue_cap_coef(self, etudid, ue, ue_cap, cnx=None):
|
||||
"""Calcule le coefficient d'une UE capitalisée, pour cet étudiant,
|
||||
"""Calcule le coefficient d'une UE capitalisée, pour cet étudiant,
|
||||
injectée dans le semestre courant.
|
||||
|
||||
ue : ue du semestre courant
|
||||
|
||||
|
||||
ue_cap = resultat de formsemestre_get_etud_capitalisation
|
||||
{ 'ue_id' (dans le semestre source),
|
||||
{ 'ue_id' (dans le semestre source),
|
||||
'ue_code', 'moy', 'event_date','formsemestre_id' }
|
||||
"""
|
||||
# log("get_etud_ue_cap_coef\nformsemestre_id='%s'\netudid='%s'\nue=%s\nue_cap=%s\n" % (self.formsemestre_id, etudid, ue, ue_cap))
|
||||
@ -1291,8 +1288,7 @@ class NotesTable:
|
||||
return len(cursor.fetchall()) > 0
|
||||
|
||||
def get_evaluations_etats(self): # evaluation_list_in_sem
|
||||
"""[ {...evaluation et son etat...} ]
|
||||
"""
|
||||
"""[ {...evaluation et son etat...} ]"""
|
||||
if self._evaluations_etats is None:
|
||||
self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem(
|
||||
self.context, self.formsemestre_id
|
||||
@ -1301,13 +1297,11 @@ class NotesTable:
|
||||
return self._evaluations_etats
|
||||
|
||||
def get_sem_evaluation_etat_list(self):
|
||||
"""Liste des evaluations de ce semestre, avec leur etat
|
||||
"""
|
||||
"""Liste des evaluations de ce semestre, avec leur etat"""
|
||||
return self.get_evaluations_etats()
|
||||
|
||||
def get_mod_evaluation_etat_list(self, moduleimpl_id):
|
||||
"""Liste des évaluations de ce module
|
||||
"""
|
||||
"""Liste des évaluations de ce module"""
|
||||
return [
|
||||
e
|
||||
for e in self.get_evaluations_etats()
|
||||
|
@ -50,7 +50,7 @@ DONNEE_MANQUANTE = (
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_code_latex_from_modele(fichier):
|
||||
"""Lit le code latex à partir d'un modèle. Renvoie une chaine unicode.
|
||||
|
||||
|
||||
Le fichier doit contenir le chemin relatif
|
||||
vers le modele : attention pas de vérification du format d'encodage
|
||||
Le fichier doit donc etre enregistré avec le même codage que ScoDoc (utf-8)
|
||||
@ -85,7 +85,7 @@ def get_tags_latex(code_latex):
|
||||
à la lecture d'un modèle d'avis pe).
|
||||
Ces tags sont répérés par les balises **, débutant et finissant le tag
|
||||
et sont renvoyés sous la forme d'une liste.
|
||||
|
||||
|
||||
result: liste de chaines unicode
|
||||
"""
|
||||
if code_latex:
|
||||
@ -144,7 +144,7 @@ def comp_latex_parcourstimeline(etudiant, promo, taille=17):
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def interprete_tag_latex(tag):
|
||||
"""Découpe les tags latex de la forme S1:groupe:dut:min et renvoie si possible
|
||||
"""Découpe les tags latex de la forme S1:groupe:dut:min et renvoie si possible
|
||||
le résultat sous la forme d'un quadruplet.
|
||||
"""
|
||||
infotag = tag.split(":")
|
||||
@ -164,7 +164,7 @@ def get_code_latex_avis_etudiant(
|
||||
donnees_etudiant, un_avis_latex, annotationPE, footer_latex, prefs
|
||||
):
|
||||
"""
|
||||
Renvoie le code latex permettant de générer l'avis d'un étudiant en utilisant ses
|
||||
Renvoie le code latex permettant de générer l'avis d'un étudiant en utilisant ses
|
||||
donnees_etudiant contenu dans le dictionnaire de synthèse du jury PE et en suivant un
|
||||
fichier modele donné
|
||||
|
||||
@ -228,8 +228,8 @@ def get_code_latex_avis_etudiant(
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_annotation_PE(context, etudid, tag_annotation_pe):
|
||||
"""Renvoie l'annotation PE dans la liste de ces annotations ;
|
||||
Cette annotation est reconnue par la présence d'un tag **PE**
|
||||
"""Renvoie l'annotation PE dans la liste de ces annotations ;
|
||||
Cette annotation est reconnue par la présence d'un tag **PE**
|
||||
(cf. context.get_preferences -> pe_tag_annotation_avis_latex).
|
||||
|
||||
Result: chaine unicode
|
||||
@ -269,8 +269,8 @@ def get_annotation_PE(context, etudid, tag_annotation_pe):
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def str_from_syntheseJury(donnees_etudiant, aggregat, groupe, tag_scodoc, champ):
|
||||
"""Extrait du dictionnaire de synthèse du juryPE pour un étudiant donnée,
|
||||
une valeur indiquée par un champ ;
|
||||
"""Extrait du dictionnaire de synthèse du juryPE pour un étudiant donnée,
|
||||
une valeur indiquée par un champ ;
|
||||
si champ est une liste, renvoie la liste des valeurs extraites.
|
||||
|
||||
Result: chaine unicode ou liste de chaines unicode
|
||||
@ -322,7 +322,7 @@ def str_from_syntheseJury(donnees_etudiant, aggregat, groupe, tag_scodoc, champ)
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_bilanParTag(donnees_etudiant, groupe="groupe"):
|
||||
"""Renvoie le code latex d'un tableau récapitulant, pour tous les tags trouvés dans
|
||||
"""Renvoie le code latex d'un tableau récapitulant, pour tous les tags trouvés dans
|
||||
les données étudiants, ses résultats.
|
||||
result: chaine unicode
|
||||
"""
|
||||
@ -474,8 +474,7 @@ def get_templates_from_distrib(template="avis"):
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe):
|
||||
"""Génère un fichier excel synthétisant les annotations PE telles qu'inscrites dans les fiches de chaque étudiant
|
||||
"""
|
||||
"""Génère un fichier excel synthétisant les annotations PE telles qu'inscrites dans les fiches de chaque étudiant"""
|
||||
sT = SeqGenTable() # le fichier excel à générer
|
||||
|
||||
# Les etudids des étudiants à afficher, triés par ordre alphabétiques de nom+prénom
|
||||
|
34
pe_jurype.py
34
pe_jurype.py
@ -88,7 +88,7 @@ class JuryPE:
|
||||
{'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }}
|
||||
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue
|
||||
et ceux qui sont éliminés (abandon, redoublement, ...) pour affichage alternatif
|
||||
|
||||
|
||||
|
||||
Note (EV:): les attributs sont des chaines encodées (utf8), comme dans ScoDoc (pas des unicodes)
|
||||
"""
|
||||
@ -210,8 +210,7 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def get_zipped_data(self):
|
||||
"""returns zipped data with all generated (CSV) files
|
||||
"""
|
||||
"""returns zipped data with all generated (CSV) files"""
|
||||
if self.zipfile:
|
||||
self.zipfile.close()
|
||||
self.zipfile = None
|
||||
@ -366,7 +365,7 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def add_etudiants(self, etudid):
|
||||
""" Ajoute un étudiant (via son etudid) au dictionnaire de synthèse jurydict.
|
||||
"""Ajoute un étudiant (via son etudid) au dictionnaire de synthèse jurydict.
|
||||
L'ajout consiste à :
|
||||
> insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo),
|
||||
avec son nom, prénom, etc...
|
||||
@ -479,7 +478,7 @@ class JuryPE:
|
||||
pour autant avoir été indiqué NAR ou DEM ; recherche son dernier semestre validé et regarde s'il
|
||||
n'existe pas parmi les semestres existants dans scodoc un semestre postérieur (en terme de date de
|
||||
début) de n° au moins égal à celui de son dernier semestre valide dans lequel il aurait pu
|
||||
s'inscrire mais ne l'a pas fait. """
|
||||
s'inscrire mais ne l'a pas fait."""
|
||||
sessems = self.get_semestresDUT_d_un_etudiant(
|
||||
etudid
|
||||
) # les semestres de l'étudiant
|
||||
@ -868,9 +867,7 @@ class JuryPE:
|
||||
return semDeb["annee_debut"]
|
||||
|
||||
def get_parcoursIUT(self, etudid):
|
||||
"""Renvoie une liste d'infos sur les semestres du parcours d'un étudiant
|
||||
|
||||
"""
|
||||
"""Renvoie une liste d'infos sur les semestres du parcours d'un étudiant"""
|
||||
etudinfo = self.ETUDINFO_DICT[etudid]
|
||||
sems = self.get_semestresDUT_d_un_etudiant(etudid)
|
||||
|
||||
@ -934,7 +931,7 @@ class JuryPE:
|
||||
|
||||
def get_allTagForAggregat(self, nom_aggregat):
|
||||
"""Extrait du dictionnaire syntheseJury la liste des tags d'un semestre ou
|
||||
d'un aggrégat donné par son nom (S1, S2, S3 ou S4, 1A, ...). Renvoie [] si aucun tag."""
|
||||
d'un aggrégat donné par son nom (S1, S2, S3 ou S4, 1A, ...). Renvoie [] si aucun tag."""
|
||||
taglist = set()
|
||||
for etudid in self.get_etudids_du_jury():
|
||||
taglist = taglist.union(
|
||||
@ -1127,10 +1124,9 @@ class JuryPE:
|
||||
|
||||
# ------------------------------------------------------------------------------------------------------------------
|
||||
def get_cache_notes_d_un_semestre(
|
||||
cls, context, formsemestre_id
|
||||
self, context, formsemestre_id
|
||||
): # inutile en realité !
|
||||
"""Charge la table des notes d'un formsemestre
|
||||
"""
|
||||
"""Charge la table des notes d'un formsemestre"""
|
||||
return context.Notes._getNotesCache().get_NotesTable(
|
||||
context.Notes, formsemestre_id
|
||||
)
|
||||
@ -1196,7 +1192,7 @@ class JuryPE:
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def get_annee_diplome_semestre(sem):
|
||||
""" Pour un semestre donne, décrit par le biais du dictionnaire sem usuel :
|
||||
"""Pour un semestre donne, décrit par le biais du dictionnaire sem usuel :
|
||||
sem = {'formestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
à condition qu'il soit un semestre de formation DUT,
|
||||
predit l'annee à laquelle sera remis le diplome DUT des etudiants scolarisés dans le semestre
|
||||
@ -1230,12 +1226,12 @@ def get_annee_diplome_semestre(sem):
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
def get_cosemestres_diplomants(context, semBase, avec_meme_formation=False):
|
||||
""" Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
renvoie la liste de tous ses co-semestres (lui-meme inclus)
|
||||
Par co-semestre, s'entend les semestres :
|
||||
> dont l'annee predite pour la remise du diplome DUT est la meme
|
||||
> dont la formation est la même (optionnel)
|
||||
> ne prenant en compte que les etudiants sans redoublement
|
||||
"""Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
|
||||
renvoie la liste de tous ses co-semestres (lui-meme inclus)
|
||||
Par co-semestre, s'entend les semestres :
|
||||
> dont l'annee predite pour la remise du diplome DUT est la meme
|
||||
> dont la formation est la même (optionnel)
|
||||
> ne prenant en compte que les etudiants sans redoublement
|
||||
"""
|
||||
tousLesSems = (
|
||||
context.Notes.formsemestre_list()
|
||||
|
@ -144,8 +144,7 @@ class SetTag(pe_tagtable.TableTag):
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
def do_tagdict(self):
|
||||
"""Synthétise la liste des modules pris en compte dans le calcul d'un tag (pour analyse des résultats)
|
||||
"""
|
||||
"""Synthétise la liste des modules pris en compte dans le calcul d'un tag (pour analyse des résultats)"""
|
||||
self.tagdict = {}
|
||||
for semtag in self.SemTagDict.values():
|
||||
for tag in semtag.get_all_tags():
|
||||
@ -208,8 +207,8 @@ class SetTag(pe_tagtable.TableTag):
|
||||
|
||||
class SetTagInterClasse(pe_tagtable.TableTag):
|
||||
"""Récupère les moyennes de SetTag aggrégant un même parcours (par ex un ['S1', 'S2'] n'ayant pas fini au même S2
|
||||
pour fournir un interclassement sur un groupe d'étudiant => seul compte alors la promo
|
||||
nom_combinaison = 'S1' ou '1A'
|
||||
pour fournir un interclassement sur un groupe d'étudiant => seul compte alors la promo
|
||||
nom_combinaison = 'S1' ou '1A'
|
||||
"""
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -95,7 +95,7 @@ class TableTag:
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
def get_coeff_from_resultats(self, tag, etudid):
|
||||
"""Renvoie la somme des coeffs de pondération normalisée utilisés dans le calcul de la moyenne à un tag d'un étudiant
|
||||
"""Renvoie la somme des coeffs de pondération normalisée utilisés dans le calcul de la moyenne à un tag d'un étudiant
|
||||
au regard du format de self.resultats.
|
||||
"""
|
||||
return (
|
||||
@ -329,7 +329,7 @@ def moyenne_ponderee_terme_a_terme(notes, coeffs=None, force=False):
|
||||
|
||||
# -------------------------------------------------------------------------------------------
|
||||
def conversionDate_StrToDate(date_fin):
|
||||
""" Conversion d'une date fournie sous la forme d'une chaine de caractère de
|
||||
"""Conversion d'une date fournie sous la forme d'une chaine de caractère de
|
||||
type 'jj/mm/aaaa' en un objet date du package datetime.
|
||||
Fonction servant au tri des semestres par date
|
||||
"""
|
||||
|
@ -97,7 +97,7 @@ def print_semestres_description(sems, avec_affichage_debug=False):
|
||||
|
||||
# ----------------------------------------------------------------------------------------
|
||||
def calcul_age(born):
|
||||
"""Calcule l'age à partir de la date de naissance sous forme d'une chaine de caractère 'jj/mm/aaaa'.
|
||||
"""Calcule l'age à partir de la date de naissance sous forme d'une chaine de caractère 'jj/mm/aaaa'.
|
||||
Aucun test de validité sur le format de la date n'est fait.
|
||||
"""
|
||||
if not isinstance(born, str) or born == "":
|
||||
@ -122,8 +122,7 @@ def remove_accents(input_unicode_str):
|
||||
|
||||
|
||||
def escape_for_latex(s):
|
||||
"""Protège les caractères pour inclusion dans du source LaTeX
|
||||
"""
|
||||
"""Protège les caractères pour inclusion dans du source LaTeX"""
|
||||
if not s:
|
||||
return ""
|
||||
conv = {
|
||||
@ -162,8 +161,7 @@ def list_directory_filenames(path):
|
||||
|
||||
|
||||
def add_local_file_to_zip(zipfile, ziproot, pathname, path_in_zip):
|
||||
"""Read pathname server file and add content to zip under path_in_zip
|
||||
"""
|
||||
"""Read pathname server file and add content to zip under path_in_zip"""
|
||||
rooted_path_in_zip = os.path.join(ziproot, path_in_zip)
|
||||
data = open(pathname).read()
|
||||
zipfile.writestr(rooted_path_in_zip, data)
|
||||
|
@ -89,7 +89,7 @@ def pe_view_sem_recap(
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Génération des avis de poursuite d'étude
|
||||
|
||||
|
||||
mode_debug = Pour "squeezer" le calcul du jury pe (long)
|
||||
et debugger uniquement la partie avis latex
|
||||
"""
|
||||
|
@ -47,7 +47,7 @@ import sco_formsemestre
|
||||
|
||||
def abs_notify(context, etudid, date):
|
||||
"""Check if notifications are requested and send them
|
||||
Considère le nombre d'absence dans le semestre courant
|
||||
Considère le nombre d'absence dans le semestre courant
|
||||
(s'il n'y a pas de semestre courant, ne fait rien,
|
||||
car l'etudiant n'est pas inscrit au moment de l'absence!).
|
||||
"""
|
||||
@ -64,8 +64,7 @@ def abs_notify(context, etudid, date):
|
||||
|
||||
|
||||
def do_abs_notify(context, sem, etudid, date, nbabs, nbabsjust):
|
||||
"""Given new counts of absences, check if notifications are requested and send them.
|
||||
"""
|
||||
"""Given new counts of absences, check if notifications are requested and send them."""
|
||||
# prefs fallback to global pref if sem is None:
|
||||
if sem:
|
||||
formsemestre_id = sem["formsemestre_id"]
|
||||
@ -131,8 +130,7 @@ def abs_notify_send(
|
||||
|
||||
|
||||
def abs_notify_get_destinations(context, sem, prefs, etudid, date, nbabs, nbabsjust):
|
||||
"""Returns set of destination emails to be notified
|
||||
"""
|
||||
"""Returns set of destination emails to be notified"""
|
||||
formsemestre_id = sem["formsemestre_id"]
|
||||
|
||||
destinations = [] # list of email address to notify
|
||||
@ -176,8 +174,8 @@ def abs_notify_is_above_threshold(context, etudid, nbabs, nbabsjust, formsemestr
|
||||
|
||||
nbabs: nombre d'absence (de tous types, unité de compte = demi-journée)
|
||||
nbabsjust: nombre d'absences justifiées
|
||||
|
||||
(nbabs > abs_notify_abs_threshold)
|
||||
|
||||
(nbabs > abs_notify_abs_threshold)
|
||||
(nbabs - nbabs_last_notified) > abs_notify_abs_increment
|
||||
"""
|
||||
abs_notify_abs_threshold = context.get_preference(
|
||||
@ -282,8 +280,7 @@ def retreive_current_formsemestre(context, etudid, cur_date):
|
||||
|
||||
|
||||
def mod_with_evals_at_date(context, date_abs, etudid):
|
||||
"""Liste des moduleimpls avec des evaluations a la date indiquée
|
||||
"""
|
||||
"""Liste des moduleimpls avec des evaluations a la date indiquée"""
|
||||
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"""
|
||||
|
@ -62,8 +62,7 @@ _help_txt = """
|
||||
|
||||
|
||||
def apo_compare_csv_form(context, REQUEST=None):
|
||||
"""Form: submit 2 CSV files to compare them.
|
||||
"""
|
||||
"""Form: submit 2 CSV files to compare them."""
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"),
|
||||
"""<h2>Comparaison de fichiers Apogée</h2>
|
||||
@ -90,8 +89,7 @@ def apo_compare_csv_form(context, REQUEST=None):
|
||||
|
||||
|
||||
def apo_compare_csv(context, A_file, B_file, autodetect=True, REQUEST=None):
|
||||
"""Page comparing 2 Apogee CSV files
|
||||
"""
|
||||
"""Page comparing 2 Apogee CSV files"""
|
||||
A = _load_apo_data(A_file, autodetect=autodetect)
|
||||
B = _load_apo_data(B_file, autodetect=autodetect)
|
||||
|
||||
@ -182,7 +180,11 @@ def _apo_compare_csv(context, A, B, REQUEST=None):
|
||||
elts_only_B = B_elts - A_elts.intersection(B_elts)
|
||||
L.append(
|
||||
'<span class="val_dif">différents (%d en commun, %d seulement dans A, %d seulement dans B)</span>'
|
||||
% (len(elts_communs), len(elts_only_A), len(elts_only_B),)
|
||||
% (
|
||||
len(elts_communs),
|
||||
len(elts_only_A),
|
||||
len(elts_only_B),
|
||||
)
|
||||
)
|
||||
if elts_only_A:
|
||||
L.append(
|
||||
@ -244,8 +246,7 @@ def _apo_compare_csv(context, A, B, REQUEST=None):
|
||||
|
||||
|
||||
def apo_table_compare_etud_results(context, A, B, REQUEST=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
D = compare_etuds_res(A, B)
|
||||
T = GenTable(
|
||||
rows=D,
|
||||
|
@ -112,8 +112,7 @@ APO_NEWLINE = "\r\n"
|
||||
|
||||
|
||||
def code_scodoc_to_apo(code):
|
||||
"""Conversion code jury ScoDoc en code Apogée
|
||||
"""
|
||||
"""Conversion code jury ScoDoc en code Apogée"""
|
||||
return {
|
||||
ATT: "AJAC",
|
||||
ATB: "AJAC",
|
||||
@ -159,7 +158,7 @@ def fix_data_encoding(
|
||||
text, default_source_encoding=APO_INPUT_ENCODING, dest_encoding=APO_INPUT_ENCODING
|
||||
):
|
||||
"""Try to ensure that text is using dest_encoding
|
||||
returns converted text, and a message describing the conversion.
|
||||
returns converted text, and a message describing the conversion.
|
||||
"""
|
||||
message = ""
|
||||
detected_encoding = guess_data_encoding(text)
|
||||
@ -241,8 +240,7 @@ VOID_APO_RES = dict(N="", B="", J="", R="", M="")
|
||||
|
||||
|
||||
class ApoEtud(dict):
|
||||
"""Etudiant Apogee:
|
||||
"""
|
||||
"""Etudiant Apogee:"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -361,7 +359,7 @@ class ApoEtud(dict):
|
||||
Autres éléments: résultats du semestre ou de l'année scolaire:
|
||||
=> VRTW1: code additionnel au semestre ("code élement semestre", elt_sem_apo)
|
||||
=> VRT1A: le même que le VET: ("code élement annuel", elt_annee_apo)
|
||||
Attention, si le semestre couvre plusieurs étapes, indiquer les codes des éléments,
|
||||
Attention, si le semestre couvre plusieurs étapes, indiquer les codes des éléments,
|
||||
séparés par des virgules.
|
||||
|
||||
Args:
|
||||
@ -369,7 +367,7 @@ class ApoEtud(dict):
|
||||
sem (dict): semestre dans lequel on cherche l'élément
|
||||
cur_sem (dict): semestre "courant" pour résultats annuels (VET)
|
||||
autre_sem (dict): autre semestre utilisé pour calculé les résultats annuels (VET)
|
||||
|
||||
|
||||
Returns:
|
||||
dict: with N, B, J, R keys, ou None si elt non trouvé
|
||||
"""
|
||||
@ -701,8 +699,7 @@ class ApoData:
|
||||
self.periode = periode
|
||||
|
||||
def setup(self, context):
|
||||
"""Recherche semestres ScoDoc concernés
|
||||
"""
|
||||
"""Recherche semestres ScoDoc concernés"""
|
||||
self.context = context
|
||||
self.sems_etape = comp_apo_sems(context, self.etape_apogee, self.annee_scolaire)
|
||||
self.etape_formsemestre_ids = {s["formsemestre_id"] for s in self.sems_etape}
|
||||
@ -803,7 +800,7 @@ class ApoData:
|
||||
Clé: id apogée, eg 'V1RT', 'V1GE2201', ...
|
||||
Valeur: ApoElt, avec les attributs code, type_objet
|
||||
|
||||
Si les id Apogée ne sont pas uniques (ce n'est pas garanti), garde le premier
|
||||
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):
|
||||
@ -849,8 +846,7 @@ class ApoData:
|
||||
return L
|
||||
|
||||
def get_etape_apogee(self):
|
||||
"""Le code etape: 'V1RT', donné par le code de l'élément VET
|
||||
"""
|
||||
"""Le code etape: 'V1RT', donné par le code de l'élément VET"""
|
||||
for elt in self.apo_elts.values():
|
||||
if elt.type_objet == "VET":
|
||||
return elt.code
|
||||
@ -893,8 +889,7 @@ class ApoData:
|
||||
f.write(self.column_titles)
|
||||
|
||||
def write_etuds(self, f):
|
||||
"""write apo CSV etuds on f
|
||||
"""
|
||||
"""write apo CSV etuds on f"""
|
||||
for e in self.etuds:
|
||||
fs = [] # e['nip'], e['nom'], e['prenom'], e['naissance'] ]
|
||||
for col_id in self.col_ids:
|
||||
@ -983,8 +978,7 @@ class ApoData:
|
||||
return codes_by_sem
|
||||
|
||||
def build_cr_table(self):
|
||||
"""Table compte rendu des décisions
|
||||
"""
|
||||
"""Table compte rendu des décisions"""
|
||||
CR = [] # tableau compte rendu des decisions
|
||||
for e in self.etuds:
|
||||
cr = {
|
||||
@ -1015,14 +1009,14 @@ class ApoData:
|
||||
|
||||
|
||||
def _apo_read_cols(f):
|
||||
"""Lecture colonnes apo :
|
||||
"""Lecture colonnes apo :
|
||||
Démarre après la balise XX-APO_COLONNES-XX
|
||||
et s'arrête après la balise APO_COL_VAL_FIN
|
||||
|
||||
Colonne Apogee: les champs sont données par la ligne
|
||||
apoL_a01_code de la section XX-APO_COLONNES-XX
|
||||
apoL_a01_code de la section XX-APO_COLONNES-XX
|
||||
col_id est apoL_c0001, apoL_c0002, ...
|
||||
|
||||
|
||||
:return: { col_id : { title : value } }
|
||||
Example: { 'apoL_c0001' : { 'Type Objet' : 'VET', 'Code' : 'V1IN', ... }, ... }
|
||||
"""
|
||||
@ -1116,8 +1110,7 @@ def comp_apo_sems(context, etape_apogee, annee_scolaire):
|
||||
|
||||
|
||||
def nar_etuds_table(context, apo_data, NAR_Etuds):
|
||||
"""Liste les NAR -> excel table
|
||||
"""
|
||||
"""Liste les NAR -> excel table"""
|
||||
code_etape = apo_data.etape_apogee
|
||||
today = datetime.datetime.today().strftime("%d/%m/%y")
|
||||
L = []
|
||||
@ -1186,7 +1179,7 @@ def export_csv_to_apogee(
|
||||
export_res_rat=True,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Genere un fichier CSV Apogée
|
||||
"""Genere un fichier CSV Apogée
|
||||
à partir d'un fichier CSV Apogée vide (ou partiellement rempli)
|
||||
et des résultats ScoDoc.
|
||||
Si dest_zip, ajoute les fichiers générés à ce zip
|
||||
|
@ -49,14 +49,12 @@ EtudsArchive = EtudsArchiver()
|
||||
|
||||
|
||||
def can_edit_etud_archive(context, authuser):
|
||||
"""True si l'utilisateur peut modifier les archives etudiantes
|
||||
"""
|
||||
"""True si l'utilisateur peut modifier les archives etudiantes"""
|
||||
return authuser.has_permission(ScoEtudAddAnnotations, context)
|
||||
|
||||
|
||||
def etud_list_archives_html(context, REQUEST, etudid):
|
||||
"""HTML snippet listing archives
|
||||
"""
|
||||
"""HTML snippet listing archives"""
|
||||
can_edit = can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER)
|
||||
L = []
|
||||
for archive_id in EtudsArchive.list_obj_archives(context, etudid):
|
||||
@ -122,8 +120,7 @@ def add_archives_info_to_etud_list(context, etuds):
|
||||
|
||||
|
||||
def etud_upload_file_form(context, REQUEST, etudid):
|
||||
"""Page with a form to choose and upload a file, with a description.
|
||||
"""
|
||||
"""Page with a form to choose and upload a file, with a description."""
|
||||
# check permission
|
||||
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
|
||||
raise AccessDenied(
|
||||
@ -178,8 +175,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
|
||||
def _store_etud_file_to_new_archive(
|
||||
context, REQUEST, etudid, data, filename, description=""
|
||||
):
|
||||
"""Store data to new archive.
|
||||
"""
|
||||
"""Store data to new archive."""
|
||||
filesize = len(data)
|
||||
if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE:
|
||||
return 0, "Fichier image de taille invalide ! (%d)" % filesize
|
||||
@ -188,8 +184,7 @@ def _store_etud_file_to_new_archive(
|
||||
|
||||
|
||||
def etud_delete_archive(context, REQUEST, etudid, archive_name, dialog_confirmed=False):
|
||||
"""Delete an archive
|
||||
"""
|
||||
"""Delete an archive"""
|
||||
# check permission
|
||||
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
|
||||
raise AccessDenied(
|
||||
@ -218,8 +213,7 @@ def etud_delete_archive(context, REQUEST, etudid, archive_name, dialog_confirmed
|
||||
|
||||
|
||||
def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
|
||||
"""Send file to client.
|
||||
"""
|
||||
"""Send file to client."""
|
||||
return EtudsArchive.get_archived_file(
|
||||
context, REQUEST, etudid, archive_name, filename
|
||||
)
|
||||
@ -227,8 +221,7 @@ def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
|
||||
|
||||
# --- Upload d'un ensemble de fichiers (pour un groupe d'étudiants)
|
||||
def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
|
||||
"""Feuille excel pour import fichiers etudiants (utilisé pour admissions)
|
||||
"""
|
||||
"""Feuille excel pour import fichiers etudiants (utilisé pour admissions)"""
|
||||
fmt = ImportScolars.sco_import_format()
|
||||
data = ImportScolars.sco_import_generate_excel_sample(
|
||||
fmt,
|
||||
@ -249,8 +242,7 @@ def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None):
|
||||
|
||||
|
||||
def etudarchive_import_files_form(context, group_id, REQUEST=None):
|
||||
"""Formualaire pour importation fichiers d'un groupe
|
||||
"""
|
||||
"""Formualaire pour importation fichiers d'un groupe"""
|
||||
H = [
|
||||
context.sco_header(
|
||||
REQUEST, page_title="Import de fichiers associés aux étudiants"
|
||||
|
@ -162,4 +162,4 @@ class Baccalaureat:
|
||||
return self.type() == "G"
|
||||
|
||||
def is_techno(self):
|
||||
return selt.type() == "T"
|
||||
return self.type() == "T"
|
||||
|
@ -80,8 +80,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
||||
return [self.buildTableObject(P, pdfTableStyle, colWidths)]
|
||||
|
||||
def bul_table_html(self):
|
||||
"""Génère la table centrale du bulletin de notes: chaine HTML
|
||||
"""
|
||||
"""Génère la table centrale du bulletin de notes: chaine HTML"""
|
||||
format = "html"
|
||||
I = self.infos
|
||||
authuser = self.authuser
|
||||
@ -130,13 +129,10 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
|
||||
continue # saute les modules où on n'est pas inscrit
|
||||
H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle)
|
||||
if context.get_preference("bul_show_minmax_mod", formsemestre_id):
|
||||
rang_minmax = (
|
||||
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
|
||||
% (
|
||||
mod["mod_rang_txt"],
|
||||
fmt_note(mod["stats"]["min"]),
|
||||
fmt_note(mod["stats"]["max"]),
|
||||
)
|
||||
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
|
||||
mod["mod_rang_txt"],
|
||||
fmt_note(mod["stats"]["min"]),
|
||||
fmt_note(mod["stats"]["max"]),
|
||||
)
|
||||
else:
|
||||
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
|
||||
@ -386,8 +382,7 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorLegacy)
|
||||
|
||||
|
||||
class BulTableStyle:
|
||||
"""Construction du style de tables reportlab platypus pour les bulletins "classiques"
|
||||
"""
|
||||
"""Construction du style de tables reportlab platypus pour les bulletins "classiques" """
|
||||
|
||||
LINEWIDTH = 0.5
|
||||
LINECOLOR = Color(0, 0, 0)
|
||||
|
@ -57,8 +57,7 @@ import os
|
||||
|
||||
|
||||
def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
|
||||
"""Change pdf signature
|
||||
"""
|
||||
"""Change pdf signature"""
|
||||
filename = _get_sig_existing_filename(
|
||||
context, side, formsemestre_id=formsemestre_id
|
||||
)
|
||||
|
@ -305,5 +305,4 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorUCAC)
|
||||
|
||||
|
||||
def bulletin_table_ucac(context, I, version=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
|
@ -35,6 +35,7 @@ import thread, time
|
||||
# Cache data
|
||||
class simpleCache:
|
||||
def __init__(self):
|
||||
self.cache = {}
|
||||
self.inval_cache() # >
|
||||
|
||||
def inval_cache(self, key=None): # >
|
||||
@ -56,7 +57,7 @@ class simpleCache:
|
||||
class expiringCache(simpleCache):
|
||||
"""A simple cache wich cache data for a most "duration" seconds.
|
||||
|
||||
This is used for users (which may be updated from external
|
||||
This is used for users (which may be updated from external
|
||||
information systems)
|
||||
"""
|
||||
|
||||
|
@ -64,8 +64,7 @@ SCO_DUMP_LOCK = "/tmp/scodump.lock"
|
||||
|
||||
|
||||
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
|
||||
"""
|
||||
"""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()", {})
|
||||
@ -150,8 +149,7 @@ def _duplicate_db(db_name, ano_db_name):
|
||||
|
||||
|
||||
def _anonymize_db(ano_db_name):
|
||||
"""Anonymize a departement database
|
||||
"""
|
||||
"""Anonymize a departement database"""
|
||||
cmd = os.path.join(SCO_CONFIG_DIR, "anonymize_db.py")
|
||||
log("_anonymize_db: {}".format(cmd))
|
||||
try:
|
||||
@ -171,8 +169,7 @@ def _get_scodoc_serial(context):
|
||||
|
||||
|
||||
def _send_db(context, REQUEST, ano_db_name):
|
||||
"""Dump this (anonymized) database and send it to tech support
|
||||
"""
|
||||
"""Dump this (anonymized) database and send it to tech support"""
|
||||
log("dumping anonymized database {}".format(ano_db_name))
|
||||
try:
|
||||
data = subprocess.check_output("pg_dump {} | gzip".format(ano_db_name), shell=1)
|
||||
|
@ -37,8 +37,7 @@ import sco_formsemestre
|
||||
|
||||
|
||||
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None):
|
||||
"""Delete a formation
|
||||
"""
|
||||
"""Delete a formation"""
|
||||
F = context.formation_list(args={"formation_id": formation_id})
|
||||
if not F:
|
||||
raise ScoValueError("formation inexistante !")
|
||||
@ -89,14 +88,12 @@ def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST
|
||||
|
||||
|
||||
def formation_create(context, REQUEST=None):
|
||||
"""Creation d'une formation
|
||||
"""
|
||||
"""Creation d'une formation"""
|
||||
return formation_edit(context, create=True, REQUEST=REQUEST)
|
||||
|
||||
|
||||
def formation_edit(context, formation_id=None, create=False, REQUEST=None):
|
||||
"""Edit or create a formation
|
||||
"""
|
||||
"""Edit or create a formation"""
|
||||
if create:
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Création d'une formation"),
|
||||
|
@ -36,8 +36,7 @@ import sco_formsemestre
|
||||
|
||||
|
||||
def matiere_create(context, ue_id=None, REQUEST=None):
|
||||
"""Creation d'une matiere
|
||||
"""
|
||||
"""Creation d'une matiere"""
|
||||
UE = context.do_ue_list(args={"ue_id": ue_id})[0]
|
||||
H = [
|
||||
context.sco_header(REQUEST, page_title="Création d'une matière"),
|
||||
|
@ -55,8 +55,7 @@ saisir et modifier les notes de ce module.
|
||||
|
||||
|
||||
def module_create(context, matiere_id=None, REQUEST=None):
|
||||
"""Creation d'un module
|
||||
"""
|
||||
"""Creation d'un module"""
|
||||
if not matiere_id:
|
||||
raise ScoValueError("invalid matiere !")
|
||||
M = context.do_matiere_list(args={"matiere_id": matiere_id})[0]
|
||||
@ -436,8 +435,7 @@ def module_list(context, formation_id, REQUEST=None):
|
||||
|
||||
|
||||
def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None):
|
||||
"""Création d'un module de "malus" dans chaque UE d'une formation
|
||||
"""
|
||||
"""Création d'un module de "malus" dans chaque UE d'une formation"""
|
||||
ue_list = context.do_ue_list(args={"formation_id": formation_id})
|
||||
|
||||
for ue in ue_list:
|
||||
@ -457,8 +455,7 @@ def formation_add_malus_modules(context, formation_id, titre=None, REQUEST=None)
|
||||
|
||||
|
||||
def ue_add_malus_module(context, ue_id, titre=None, code=None, REQUEST=None):
|
||||
"""Add a malus module in this ue
|
||||
"""
|
||||
"""Add a malus module in this ue"""
|
||||
ue = context.do_ue_list(args={"ue_id": ue_id})[0]
|
||||
|
||||
if titre is None:
|
||||
|
@ -41,14 +41,12 @@ import sco_tag_module
|
||||
|
||||
|
||||
def ue_create(context, formation_id=None, REQUEST=None):
|
||||
"""Creation d'une UE
|
||||
"""
|
||||
"""Creation d'une UE"""
|
||||
return ue_edit(context, create=True, formation_id=formation_id, REQUEST=REQUEST)
|
||||
|
||||
|
||||
def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
||||
"""Modification ou creation d'une UE
|
||||
"""
|
||||
"""Modification ou creation d'une UE"""
|
||||
create = int(create)
|
||||
if not create:
|
||||
U = context.do_ue_list(args={"ue_id": ue_id})
|
||||
@ -227,7 +225,7 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
|
||||
|
||||
def _add_ue_semestre_id(context, ue_list):
|
||||
"""ajoute semestre_id dans les ue, en regardant le premier module de chacune.
|
||||
Les UE sans modules se voient attribuer le numero UE_SEM_DEFAULT (1000000),
|
||||
Les UE sans modules se voient attribuer le numero UE_SEM_DEFAULT (1000000),
|
||||
qui les place à la fin de la liste.
|
||||
"""
|
||||
for ue in ue_list:
|
||||
@ -281,7 +279,7 @@ def ue_delete(
|
||||
|
||||
|
||||
def ue_list(context, formation_id=None, msg="", REQUEST=None):
|
||||
"""Liste des matières et modules d'une formation, avec liens pour
|
||||
"""Liste des matières et modules d'une formation, avec liens pour
|
||||
editer (si non verrouillée).
|
||||
"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
@ -781,8 +779,7 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
|
||||
|
||||
# ---- Table recap formation
|
||||
def formation_table_recap(context, formation_id, format="html", REQUEST=None):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
F = context.formation_list(args={"formation_id": formation_id})
|
||||
if not F:
|
||||
raise ScoValueError("invalid formation_id")
|
||||
|
@ -67,8 +67,7 @@ def formsemestre_get_ics_url(context, sem):
|
||||
|
||||
|
||||
def formsemestre_load_ics(context, sem):
|
||||
"""Load ics data, from our cache or, when necessary, from external provider
|
||||
"""
|
||||
"""Load ics data, from our cache or, when necessary, from external provider"""
|
||||
# TODO: cacher le résultat
|
||||
ics_url = formsemestre_get_ics_url(context, sem)
|
||||
if not ics_url:
|
||||
@ -86,15 +85,13 @@ def formsemestre_load_ics(context, sem):
|
||||
|
||||
|
||||
def formsemestre_edt_groups_used(context, sem):
|
||||
"""L'ensemble des groupes EDT utilisés dans l'emplois du temps publié
|
||||
"""
|
||||
"""L'ensemble des groupes EDT utilisés dans l'emplois du temps publié"""
|
||||
cal = formsemestre_load_ics(context, sem)
|
||||
return {e["X-GROUP-ID"].decode("utf8") for e in events}
|
||||
|
||||
|
||||
def get_edt_transcodage_groups(context, formsemestre_id):
|
||||
""" -> { nom_groupe_edt : nom_groupe_scodoc }
|
||||
"""
|
||||
"""-> { nom_groupe_edt : nom_groupe_scodoc }"""
|
||||
# TODO: valider ces données au moment où on enregistre les préférences
|
||||
edt2sco = {}
|
||||
sco2edt = {}
|
||||
@ -161,8 +158,7 @@ for e in events:
|
||||
|
||||
|
||||
def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=None):
|
||||
"""experimental page
|
||||
"""
|
||||
"""experimental page"""
|
||||
return "\n".join(
|
||||
[
|
||||
context.sco_header(
|
||||
|
@ -190,8 +190,7 @@ def apo_csv_list_stored_etapes(context, annee_scolaire, sem_id=None, etapes=None
|
||||
|
||||
|
||||
def apo_csv_delete(context, archive_id):
|
||||
"""Delete archived CSV
|
||||
"""
|
||||
"""Delete archived CSV"""
|
||||
ApoCSVArchive.delete_archive(archive_id)
|
||||
|
||||
|
||||
@ -224,19 +223,18 @@ def apo_csv_get(context, etape_apo="", annee_scolaire="", sem_id=""):
|
||||
|
||||
|
||||
def apo_get_sem_etapes(context, sem):
|
||||
"""Etapes de ce semestre: pour l'instant, celles déclarées
|
||||
Dans une future version, on pourrait aussi utiliser les étapes
|
||||
d'inscription des étudiants, recupérées via le portail,
|
||||
"""Etapes de ce semestre: pour l'instant, celles déclarées
|
||||
Dans une future version, on pourrait aussi utiliser les étapes
|
||||
d'inscription des étudiants, recupérées via le portail,
|
||||
voir check_paiement_etuds().
|
||||
|
||||
|
||||
:return: list of etape_apo (ApoEtapeVDI instances)
|
||||
"""
|
||||
return sem["etapes"]
|
||||
|
||||
|
||||
def apo_csv_check_etape(context, semset, set_nips, etape_apo):
|
||||
"""Check etape vs set of sems
|
||||
"""
|
||||
"""Check etape vs set of sems"""
|
||||
# Etudiants dans la maquette CSV:
|
||||
csv_data = apo_csv_get(
|
||||
context, etape_apo, semset["annee_scolaire"], semset["sem_id"]
|
||||
@ -254,7 +252,10 @@ def apo_csv_check_etape(context, semset, set_nips, etape_apo):
|
||||
|
||||
return nips_ok, apo_nips, nips_no_apo, nips_no_sco, maq_elems, sem_elems
|
||||
|
||||
def apo_csv_semset_check(context, semset, allow_missing_apo=False, allow_missing_csv=False): # was apo_csv_check
|
||||
|
||||
def apo_csv_semset_check(
|
||||
context, semset, allow_missing_apo=False, allow_missing_csv=False
|
||||
): # was apo_csv_check
|
||||
"""
|
||||
check students in stored maqs vs students in semset
|
||||
Cas à détecter:
|
||||
|
@ -58,9 +58,7 @@ def apo_semset_maq_status(
|
||||
block_export_res_sdj=True,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Page statut / tableau de bord
|
||||
|
||||
"""
|
||||
"""Page statut / tableau de bord"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -91,7 +89,9 @@ def apo_semset_maq_status(
|
||||
apo_dups,
|
||||
maq_elems,
|
||||
sem_elems,
|
||||
) = sco_etape_apogee.apo_csv_semset_check(context, semset, allow_missing_apo, allow_missing_csv)
|
||||
) = sco_etape_apogee.apo_csv_semset_check(
|
||||
context, semset, allow_missing_apo, allow_missing_csv
|
||||
)
|
||||
|
||||
if not allow_missing_decisions:
|
||||
ok_for_export &= semset["jury_ok"]
|
||||
@ -265,9 +265,7 @@ def apo_semset_maq_status(
|
||||
)
|
||||
if allow_missing_csv:
|
||||
H.append("checked")
|
||||
H.append(
|
||||
""" >autoriser export même si étapes sans maquettes</input></div>"""
|
||||
)
|
||||
H.append(""" >autoriser export même si étapes sans maquettes</input></div>""")
|
||||
H.append("""</form>""")
|
||||
|
||||
if semset and ok_for_export:
|
||||
@ -295,7 +293,9 @@ def apo_semset_maq_status(
|
||||
H.append(
|
||||
"""<div><label><input type="checkbox" name="block_export_res_etape" value="1" %s %s>%s</input></label></div>"""
|
||||
% checked(
|
||||
block_export_res_etape, "export_res_etape", "résultat de l'étape (VET), sauf si diplôme"
|
||||
block_export_res_etape,
|
||||
"export_res_etape",
|
||||
"résultat de l'étape (VET), sauf si diplôme",
|
||||
)
|
||||
)
|
||||
H.append(
|
||||
@ -424,8 +424,7 @@ def apo_semset_maq_status(
|
||||
|
||||
|
||||
def table_apo_csv_list(context, semset, REQUEST=None):
|
||||
"""Table des archives (triée par date d'archivage)
|
||||
"""
|
||||
"""Table des archives (triée par date d'archivage)"""
|
||||
annee_scolaire = semset["annee_scolaire"]
|
||||
sem_id = semset["sem_id"]
|
||||
|
||||
@ -481,8 +480,7 @@ def table_apo_csv_list(context, semset, REQUEST=None):
|
||||
|
||||
|
||||
def view_apo_etuds(context, semset_id, title="", nips=[], format="html", REQUEST=None):
|
||||
"""Table des étudiants Apogée par nips
|
||||
"""
|
||||
"""Table des étudiants Apogée par nips"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -520,8 +518,7 @@ def view_apo_etuds(context, semset_id, title="", nips=[], format="html", REQUEST
|
||||
def view_scodoc_etuds(
|
||||
context, semset_id, title="", etudids=None, nips=None, format="html", REQUEST=None
|
||||
):
|
||||
"""Table des étudiants ScoDoc par nips ou etudids
|
||||
"""
|
||||
"""Table des étudiants ScoDoc par nips ou etudids"""
|
||||
if etudids is not None:
|
||||
if type(etudids) != type([]):
|
||||
etudids = [etudids]
|
||||
@ -636,8 +633,7 @@ def view_apo_csv_store(
|
||||
|
||||
|
||||
def view_apo_csv_download_and_store(context, etape_apo="", semset_id="", REQUEST=None):
|
||||
"""Download maquette and store it
|
||||
"""
|
||||
"""Download maquette and store it"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
@ -656,8 +652,7 @@ def view_apo_csv_download_and_store(context, etape_apo="", semset_id="", REQUEST
|
||||
def view_apo_csv_delete(
|
||||
context, etape_apo="", semset_id="", dialog_confirmed=False, REQUEST=None
|
||||
):
|
||||
"""Delete CSV file
|
||||
"""
|
||||
"""Delete CSV file"""
|
||||
if not semset_id:
|
||||
raise ValueError("invalid null semset_id")
|
||||
semset = sco_semset.SemSet(context, semset_id=semset_id)
|
||||
|
@ -237,8 +237,7 @@ class ScoExcelSheet:
|
||||
|
||||
|
||||
def Excel_SimpleTable(titles=[], lines=[[]], SheetName="feuille", titlesStyles=[]):
|
||||
"""Export simple type 'CSV': 1ere ligne en gras, le reste tel quel
|
||||
"""
|
||||
"""Export simple type 'CSV': 1ere ligne en gras, le reste tel quel"""
|
||||
# XXX devrait maintenant utiliser ScoExcelSheet
|
||||
wb = Workbook()
|
||||
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))
|
||||
|
@ -201,8 +201,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
|
||||
"""
|
||||
"""Ensemble des formsemestre_id entre ces dates"""
|
||||
s = SimpleDictFetch(
|
||||
context,
|
||||
"SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s",
|
||||
@ -216,7 +215,7 @@ def scodoc_table_results(
|
||||
):
|
||||
"""Page affichant la table des résultats
|
||||
Les dates sont en dd/mm/yyyy (datepicker javascript)
|
||||
types_parcours est la liste des types de parcours à afficher
|
||||
types_parcours est la liste des types de parcours à afficher
|
||||
(liste de chaines, eg ['100', '210'] )
|
||||
"""
|
||||
log("scodoc_table_results: start_date=%s" % (start_date,)) # XXX
|
||||
|
@ -216,7 +216,7 @@ def search_etud_in_dept(
|
||||
# Was chercheEtudsInfo()
|
||||
def search_etuds_infos(context, expnom=None, code_nip=None, REQUEST=None):
|
||||
"""recherche les étudiants correspondants à expnom ou au code_nip
|
||||
et ramene liste de mappings utilisables en DTML.
|
||||
et ramene liste de mappings utilisables en DTML.
|
||||
"""
|
||||
may_be_nip = is_valid_code_nip(expnom)
|
||||
cnx = context.GetDBConnexion()
|
||||
@ -286,8 +286,7 @@ def search_etud_by_name(context, term, REQUEST=None):
|
||||
|
||||
|
||||
def form_search_etud_in_accessible_depts(context, REQUEST):
|
||||
"""Form recherche etudiants pour page accueil ScoDoc
|
||||
"""
|
||||
"""Form recherche etudiants pour page accueil ScoDoc"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
# present form only to authenticated users
|
||||
if not authuser.has_role("Authenticated"):
|
||||
|
@ -480,7 +480,7 @@ def formsemestre_recap_parcours_table(
|
||||
show_details=False,
|
||||
):
|
||||
"""Tableau HTML recap parcours
|
||||
Si with_links, ajoute liens pour modifier decisions (colonne de droite)
|
||||
Si with_links, ajoute liens pour modifier decisions (colonne de droite)
|
||||
sem_info = { formsemestre_id : txt } permet d'ajouter des informations associées à chaque semestre
|
||||
with_all_columns: si faux, pas de colonne "assiduité".
|
||||
"""
|
||||
@ -690,8 +690,7 @@ def formsemestre_recap_parcours_table(
|
||||
def form_decision_manuelle(
|
||||
context, Se, formsemestre_id, etudid, desturl="", sortcol=None
|
||||
):
|
||||
"""Formulaire pour saisie décision manuelle
|
||||
"""
|
||||
"""Formulaire pour saisie décision manuelle"""
|
||||
H = [
|
||||
"""
|
||||
<script type="text/javascript">
|
||||
@ -1033,8 +1032,7 @@ def formsemestre_fix_validation_ues(context, formsemestre_id, REQUEST=None):
|
||||
|
||||
|
||||
def formsemestre_validation_suppress_etud(context, formsemestre_id, etudid):
|
||||
"""Suppression des decisions de jury pour un etudiant.
|
||||
"""
|
||||
"""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)
|
||||
@ -1064,7 +1062,7 @@ def formsemestre_validation_suppress_etud(context, formsemestre_id, etudid):
|
||||
|
||||
|
||||
def formsemestre_validate_previous_ue(context, formsemestre_id, etudid, REQUEST=None):
|
||||
"""Form. saisie UE validée hors ScoDoc
|
||||
"""Form. saisie UE validée hors ScoDoc
|
||||
(pour étudiants arrivant avec un UE antérieurement validée).
|
||||
"""
|
||||
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
||||
@ -1205,7 +1203,7 @@ def do_formsemestre_validate_previous_ue(
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Enregistre (ou modifie) validation d'UE (obtenue hors ScoDoc).
|
||||
Si le coefficient est spécifié, modifie le coefficient de
|
||||
Si le coefficient est spécifié, modifie le coefficient de
|
||||
cette UE (utile seulement pour les semestres extérieurs).
|
||||
"""
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
@ -1265,8 +1263,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
|
||||
"""
|
||||
"""Ramene bout de HTML pour pouvoir supprimer une validation de cette UE"""
|
||||
valids = SimpleDictFetch(
|
||||
context,
|
||||
"""SELECT SFV.* FROM scolar_formsemestre_validation SFV
|
||||
|
@ -39,8 +39,7 @@ TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept")
|
||||
|
||||
|
||||
def generate_excel_sample():
|
||||
"""generates an excel document suitable to import users
|
||||
"""
|
||||
"""generates an excel document suitable to import users"""
|
||||
style = sco_excel.Excel_MakeStyle(bold=True)
|
||||
titles = TITLES
|
||||
titlesStyles = [style] * len(titles)
|
||||
@ -105,7 +104,7 @@ def import_users(U, auth_dept="", context=None):
|
||||
- créer utilisateur et mettre le mot de passe
|
||||
- envoyer mot de passe par mail
|
||||
|
||||
En cas d'erreur: supprimer tous les utilisateurs que l'on vient de créer.
|
||||
En cas d'erreur: supprimer tous les utilisateurs que l'on vient de créer.
|
||||
"""
|
||||
created = [] # liste de uid créés
|
||||
try:
|
||||
|
@ -45,8 +45,7 @@ import sco_formsemestre
|
||||
def formsemestre_table_etuds_lycees(
|
||||
context, formsemestre_id, group_lycees=True, only_primo=False
|
||||
):
|
||||
"""Récupère liste d'etudiants avec etat et decision.
|
||||
"""
|
||||
"""Récupère liste d'etudiants avec etat et decision."""
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
etuds = sco_report.tsp_etud_list(context, formsemestre_id, only_primo=only_primo)[0]
|
||||
if only_primo:
|
||||
@ -60,8 +59,7 @@ def formsemestre_table_etuds_lycees(
|
||||
|
||||
|
||||
def scodoc_table_etuds_lycees(context, format="html", REQUEST=None):
|
||||
"""Table avec _tous_ les étudiants des semestres non verrouillés de _tous_ les départements.
|
||||
"""
|
||||
"""Table avec _tous_ les étudiants des semestres non verrouillés de _tous_ les départements."""
|
||||
semdepts = sco_formsemestre.scodoc_get_all_unlocked_sems(context)
|
||||
etuds = []
|
||||
for (sem, deptcontext) in semdepts:
|
||||
|
@ -41,8 +41,7 @@ import sco_codes_parcours
|
||||
|
||||
|
||||
def list_formsemestres_modalites(context, sems):
|
||||
"""Liste ordonnée des modalités présentes dans ces formsemestres
|
||||
"""
|
||||
"""Liste ordonnée des modalités présentes dans ces formsemestres"""
|
||||
modalites = {}
|
||||
for sem in sems:
|
||||
if sem["modalite"] not in modalites:
|
||||
@ -86,8 +85,7 @@ _modaliteEditor = EditableTable(
|
||||
|
||||
|
||||
def do_modalite_list(context, *args, **kw):
|
||||
"""Liste des modalites
|
||||
"""
|
||||
"""Liste des modalites"""
|
||||
cnx = context.GetDBConnexion()
|
||||
return _modaliteEditor.list(cnx, *args, **kw)
|
||||
|
||||
|
@ -273,18 +273,17 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
||||
if not context.canSuppressAnnotation(a["id"], REQUEST):
|
||||
a["dellink"] = ""
|
||||
else:
|
||||
a["dellink"] = (
|
||||
'<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>'
|
||||
% (
|
||||
etudid,
|
||||
a["id"],
|
||||
icontag(
|
||||
"delete_img",
|
||||
border="0",
|
||||
alt="suppress",
|
||||
title="Supprimer cette annotation",
|
||||
),
|
||||
)
|
||||
a[
|
||||
"dellink"
|
||||
] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&annotation_id=%s">%s</a></td>' % (
|
||||
etudid,
|
||||
a["id"],
|
||||
icontag(
|
||||
"delete_img",
|
||||
border="0",
|
||||
alt="suppress",
|
||||
title="Supprimer cette annotation",
|
||||
),
|
||||
)
|
||||
alist.append(
|
||||
'<tr><td><span class="annodate">Le %(date)s par %(zope_authenticated_user)s : </span><span class="annoc">%(comment)s</span></td>%(dellink)s</tr>'
|
||||
@ -486,8 +485,7 @@ def ficheEtud(context, etudid=None, REQUEST=None):
|
||||
|
||||
|
||||
def menus_etud(context, REQUEST=None):
|
||||
"""Menu etudiant (operations sur l'etudiant)
|
||||
"""
|
||||
"""Menu etudiant (operations sur l'etudiant)"""
|
||||
if not REQUEST.form.has_key("etudid"):
|
||||
return ""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
|
@ -41,7 +41,7 @@ from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
|
||||
from reportlab.platypus.flowables import Flowable
|
||||
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
from reportlab.rl_config import defaultPageSize
|
||||
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
|
||||
from reportlab.lib.units import inch, cm, mm
|
||||
from reportlab.lib.colors import pink, black, red, blue, green, magenta, red
|
||||
from reportlab.lib.colors import Color
|
||||
|
@ -197,16 +197,18 @@ def do_placement_selectetuds(context, REQUEST):
|
||||
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]
|
||||
query = "evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&" % (
|
||||
evaluation_id,
|
||||
placement_method,
|
||||
teachers,
|
||||
building,
|
||||
room,
|
||||
columns,
|
||||
numbering,
|
||||
) + "&".join(
|
||||
gs
|
||||
query = (
|
||||
"evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&"
|
||||
% (
|
||||
evaluation_id,
|
||||
placement_method,
|
||||
teachers,
|
||||
building,
|
||||
room,
|
||||
columns,
|
||||
numbering,
|
||||
)
|
||||
+ "&".join(gs)
|
||||
)
|
||||
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query)
|
||||
else:
|
||||
@ -385,8 +387,7 @@ def do_placement(context, REQUEST):
|
||||
|
||||
|
||||
def placement_eval_selectetuds(context, evaluation_id, REQUEST=None):
|
||||
"""Dialogue placement etudiants: choix methode et localisation
|
||||
"""
|
||||
"""Dialogue placement etudiants: choix methode et localisation"""
|
||||
evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
|
||||
if not evals:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
|
@ -41,8 +41,7 @@ from sco_codes_parcours import code_semestre_validant, code_semestre_attente
|
||||
|
||||
|
||||
def etud_get_poursuite_info(context, sem, etud):
|
||||
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }
|
||||
"""
|
||||
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
|
||||
I = {}
|
||||
I.update(etud) # copie nom, prenom, sexe, ...
|
||||
|
||||
@ -153,8 +152,7 @@ def _flatten_info(info):
|
||||
def formsemestre_poursuite_report(
|
||||
context, formsemestre_id, format="html", REQUEST=None
|
||||
):
|
||||
"""Table avec informations "poursuite"
|
||||
"""
|
||||
"""Table avec informations "poursuite" """
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
|
||||
etuds = context.getEtudInfoGroupes(
|
||||
|
@ -270,8 +270,7 @@ def do_evaluation_upload_xls(context, REQUEST):
|
||||
def do_evaluation_set_missing(
|
||||
context, evaluation_id, value, REQUEST=None, dialog_confirmed=False
|
||||
):
|
||||
"""Initialisation des notes manquantes
|
||||
"""
|
||||
"""Initialisation des notes manquantes"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
evaluation_id = REQUEST.form["evaluation_id"]
|
||||
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0]
|
||||
@ -547,9 +546,9 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
|
||||
|
||||
|
||||
def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
|
||||
"""Saisie des notes via un fichier Excel
|
||||
"""
|
||||
"""Saisie des notes via un fichier Excel"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
authusername = str(authuser)
|
||||
evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
|
||||
if not evals:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
@ -724,8 +723,7 @@ def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
|
||||
|
||||
|
||||
def feuille_saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
|
||||
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués
|
||||
"""
|
||||
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
||||
evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
|
||||
if not evals:
|
||||
raise ScoValueError("invalid evaluation_id")
|
||||
@ -825,8 +823,7 @@ def has_existing_decision(context, M, E, etudid):
|
||||
|
||||
|
||||
def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
|
||||
"""Formulaire saisie notes d'une évaluation pour un groupe
|
||||
"""
|
||||
"""Formulaire saisie notes d'une évaluation pour un groupe"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
authusername = str(authuser)
|
||||
|
||||
@ -1182,8 +1179,7 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
|
||||
def save_note(
|
||||
context, etudid=None, evaluation_id=None, value=None, comment="", REQUEST=None
|
||||
):
|
||||
"""Enregistre une note (ajax)
|
||||
"""
|
||||
"""Enregistre une note (ajax)"""
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
log(
|
||||
"save_note: evaluation_id=%s etudid=%s uid=%s value=%s"
|
||||
|
@ -63,8 +63,7 @@ semset_delete = _semset_editor.delete
|
||||
|
||||
class SemSet(dict):
|
||||
def __init__(self, context, semset_id=None, title="", annee_scolaire="", sem_id=""):
|
||||
"""Load and init, or, if semset_id is not specified, create
|
||||
"""
|
||||
"""Load and init, or, if semset_id is not specified, create"""
|
||||
if not annee_scolaire and not semset_id:
|
||||
# on autorise annee_scolaire null si sem_id pour pouvoir lire les anciens semsets
|
||||
# mal construits...
|
||||
@ -201,8 +200,7 @@ class SemSet(dict):
|
||||
return etapes
|
||||
|
||||
def list_possible_sems(self):
|
||||
"""List sems that can be added to this set
|
||||
"""
|
||||
"""List sems that can be added to this set"""
|
||||
sems = sco_formsemestre.do_formsemestre_list(self.context)
|
||||
# remove sems already here:
|
||||
sems = [
|
||||
@ -243,8 +241,7 @@ class SemSet(dict):
|
||||
self["jury_ok"] &= sem["jury_ok"]
|
||||
|
||||
def html_descr(self):
|
||||
"""Short HTML description
|
||||
"""
|
||||
"""Short HTML description"""
|
||||
H = [
|
||||
"""<span class="box_title">Ensemble de semestres %(title)s</span>""" % self
|
||||
]
|
||||
@ -354,7 +351,7 @@ def do_semset_create(context, title="", annee_scolaire=None, sem_id=None, REQUES
|
||||
"do_semset_create(title=%s, annee_scolaire=%s, sem_id=%s)"
|
||||
% (title, annee_scolaire, sem_id)
|
||||
)
|
||||
s = SemSet(context, title=title, annee_scolaire=annee_scolaire, sem_id=sem_id)
|
||||
SemSet(context, title=title, annee_scolaire=annee_scolaire, sem_id=sem_id)
|
||||
return REQUEST.RESPONSE.redirect("semset_page")
|
||||
|
||||
|
||||
@ -376,12 +373,11 @@ def do_semset_delete(context, semset_id, dialog_confirmed=False, REQUEST=None):
|
||||
|
||||
|
||||
def edit_semset_set_title(context, id=None, value=None, REQUEST=None):
|
||||
"""Change title of semset
|
||||
"""
|
||||
"""Change title of semset"""
|
||||
title = value.strip()
|
||||
if not id:
|
||||
raise ScoValueError("empty semset_id")
|
||||
s = SemSet(context, semset_id=id)
|
||||
SemSet(context, semset_id=id)
|
||||
cnx = context.GetDBConnexion()
|
||||
semset_edit(cnx, {"semset_id": id, "title": title})
|
||||
return title
|
||||
@ -393,7 +389,7 @@ def do_semset_add_sem(context, semset_id, formsemestre_id, REQUEST=None):
|
||||
raise ScoValueError("empty semset_id")
|
||||
s = SemSet(context, semset_id=semset_id)
|
||||
# check for valid formsemestre_id
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # raise exc
|
||||
_ = sco_formsemestre.get_formsemestre(context, formsemestre_id) # raise exc
|
||||
|
||||
s.add(formsemestre_id)
|
||||
|
||||
@ -431,9 +427,10 @@ def semset_page(context, format="html", REQUEST=None):
|
||||
# (remplacé par n liens vers chacun des semestres)
|
||||
# s['_semtitles_str_target'] = s['_export_link_target']
|
||||
# Experimental:
|
||||
s["_title_td_attrs"] = (
|
||||
'class="inplace_edit" data-url="edit_semset_set_title" id="%s"'
|
||||
% (s["semset_id"])
|
||||
s[
|
||||
"_title_td_attrs"
|
||||
] = 'class="inplace_edit" data-url="edit_semset_set_title" id="%s"' % (
|
||||
s["semset_id"]
|
||||
)
|
||||
|
||||
tab = GenTable(
|
||||
|
@ -53,8 +53,7 @@ from notes_log import log
|
||||
|
||||
|
||||
class ScoTag:
|
||||
"""Generic tags for ScoDoc
|
||||
"""
|
||||
"""Generic tags for ScoDoc"""
|
||||
|
||||
# must be overloaded:
|
||||
tag_table = None # table (tag_id, title)
|
||||
@ -62,8 +61,7 @@ class ScoTag:
|
||||
obj_colname = None # column name for object_id in assoc_table
|
||||
|
||||
def __init__(self, context, title, object_id=""):
|
||||
"""Load tag, or create if does not exist
|
||||
"""
|
||||
"""Load tag, or create if does not exist"""
|
||||
self.context = context
|
||||
self.title = title.strip()
|
||||
if not self.title:
|
||||
@ -153,16 +151,14 @@ class ScoTag:
|
||||
|
||||
|
||||
class ModuleTag(ScoTag):
|
||||
"""Tags sur les modules dans les programmes pédagogiques
|
||||
"""
|
||||
"""Tags sur les modules dans les programmes pédagogiques"""
|
||||
|
||||
tag_table = "notes_tags" # table (tag_id, title)
|
||||
assoc_table = "notes_modules_tags" # table (tag_id, object_id)
|
||||
obj_colname = "module_id" # column name for object_id in assoc_table
|
||||
|
||||
def list_modules(self, formation_code=""):
|
||||
"""Liste des modules des formations de code donné (formation_code) avec ce tag
|
||||
"""
|
||||
"""Liste des modules des formations de code donné (formation_code) avec ce tag"""
|
||||
args = {"tag_id": self.tag_id}
|
||||
if not formation_code:
|
||||
# tous les modules de toutes les formations !
|
||||
@ -212,8 +208,7 @@ def module_tag_search(context, term, REQUEST=None):
|
||||
|
||||
|
||||
def module_tag_list(context, module_id=""):
|
||||
"""les noms de tags associés à ce module
|
||||
"""
|
||||
"""les noms de tags associés à ce module"""
|
||||
r = SimpleDictFetch(
|
||||
context,
|
||||
"""SELECT t.title
|
||||
@ -267,7 +262,7 @@ def module_tag_set(context, module_id="", taglist=[], REQUEST=None):
|
||||
def get_etud_tagged_modules(context, etudid, tagname):
|
||||
"""Liste d'infos sur les modules de ce semestre avec ce tag.
|
||||
Cherche dans tous les semestres dans lesquel l'étudiant est ou a été inscrit.
|
||||
Construit la liste des modules avec le tag donné par tagname
|
||||
Construit la liste des modules avec le tag donné par tagname
|
||||
"""
|
||||
etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
|
||||
R = []
|
||||
@ -292,7 +287,7 @@ def get_etud_tagged_modules(context, etudid, tagname):
|
||||
|
||||
|
||||
def split_tagname_coeff(tag, separateur=":"):
|
||||
"""Découpe un tag saisi par un utilisateur pour en extraire un tagname
|
||||
"""Découpe un tag saisi par un utilisateur pour en extraire un tagname
|
||||
(chaine de caractère correspondant au tag)
|
||||
et un éventuel coefficient de pondération, avec le séparateur fourni (par défaut ":").
|
||||
Renvoie le résultat sous la forme d'une liste [tagname, pond] où pond est un float
|
||||
|
@ -66,8 +66,7 @@ def pdf_trombino_tours(
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Generation du trombinoscope en fichier PDF
|
||||
"""
|
||||
"""Generation du trombinoscope en fichier PDF"""
|
||||
# Informations sur les groupes à afficher:
|
||||
groups_infos = sco_groups_view.DisplayedGroupsInfos(
|
||||
context, group_ids, formsemestre_id=formsemestre_id, REQUEST=REQUEST
|
||||
@ -294,8 +293,7 @@ def pdf_feuille_releve_absences(
|
||||
formsemestre_id=None, # utilisé si pas de groupes selectionné
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Generation de la feuille d'absence en fichier PDF, avec photos
|
||||
"""
|
||||
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
|
||||
|
||||
NB_CELL_AM = context.get_preference("feuille_releve_abs_AM")
|
||||
NB_CELL_PM = context.get_preference("feuille_releve_abs_PM")
|
||||
|
@ -72,8 +72,7 @@ def external_ue_create(
|
||||
ects=0.0,
|
||||
REQUEST=None,
|
||||
):
|
||||
"""Crée UE/matiere/module/evaluation puis saisie les notes
|
||||
"""
|
||||
"""Crée UE/matiere/module/evaluation puis saisie les notes"""
|
||||
log("external_ue_create( formsemestre_id=%s, titre=%s )" % (formsemestre_id, titre))
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
# Contrôle d'accès:
|
||||
@ -196,13 +195,14 @@ def get_external_moduleimpl_id(context, formsemestre_id, ue_id):
|
||||
# Web function
|
||||
def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
|
||||
"""Formulaire création UE externe + inscription étudiant et saisie note
|
||||
- Demande UE: peut-être existante (liste les UE externes de cette formation),
|
||||
- Demande UE: peut-être existante (liste les UE externes de cette formation),
|
||||
ou sinon spécifier titre, acronyme, type, ECTS
|
||||
- Demande note à enregistrer.
|
||||
|
||||
Note: pour l'édition éventuelle de ces informations, on utilisera les
|
||||
Note: pour l'édition éventuelle de ces informations, on utilisera les
|
||||
fonctions standards sur les UE/modules/notes
|
||||
"""
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
# Contrôle d'accès:
|
||||
authuser = REQUEST.AUTHENTICATED_USER
|
||||
if not authuser.has_permission(ScoImplement, context):
|
||||
@ -210,9 +210,7 @@ def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
|
||||
raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
|
||||
|
||||
etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
|
||||
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
|
||||
formation_id = sem["formation_id"]
|
||||
F = context.formation_list(args={"formation_id": formation_id})[0]
|
||||
existing_external_ue = get_existing_external_ue(context, formation_id)
|
||||
|
||||
H = [
|
||||
|
@ -123,8 +123,7 @@ def is_up_to_date(context):
|
||||
|
||||
|
||||
def html_up_to_date_box(context):
|
||||
"""
|
||||
"""
|
||||
""""""
|
||||
status, msg = is_up_to_date(context)
|
||||
if status:
|
||||
return ""
|
||||
|
@ -57,8 +57,7 @@ def logdb(REQUEST=None, cnx=None, method=None, etudid=None, msg=None, commit=Tru
|
||||
|
||||
|
||||
def loglist(cnx, method=None, authenticated_user=None):
|
||||
"""List of events logged for these method and user
|
||||
"""
|
||||
"""List of events logged for these method and user"""
|
||||
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
|
||||
cursor.execute(
|
||||
"select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s",
|
||||
|
Loading…
Reference in New Issue
Block a user