blackify and some minor fixes

This commit is contained in:
viennet 2021-01-01 18:40:47 +01:00
parent 3c567aeb18
commit 8d74f8feed
53 changed files with 331 additions and 397 deletions

View File

@ -1,7 +1,7 @@
# SCODOC - gestion de la scolarité # 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> Installation: voir instructions à jour sur <https://scodoc.org>

View File

@ -277,7 +277,7 @@ class ZScoUsers(
def user_info(self, user_name=None, user=None): def user_info(self, user_name=None, user=None):
"""Donne infos sur l'utilisateur (qui peut ne pas etre dans notre base). """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: if user_name:
infos = self._user_list(args={"user_name": 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=[] self, edit, user_name="", nom="", prenom="", email="", roles=[]
): ):
"""Vérifie que et utilisateur peut etre crée (edit=0) ou modifié (edit=1) """Vérifie que et utilisateur peut etre crée (edit=0) ou modifié (edit=1)
Cherche homonymes. Cherche homonymes.
returns (ok, msg) returns (ok, msg)
- ok : si vrai, peut continuer avec ces parametres - ok : si vrai, peut continuer avec ces parametres
(si ok est faux, l'utilisateur peut quand même forcer la creation) (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") security.declareProtected(ScoView, "get_user_name_from_nomplogin")
def get_user_name_from_nomplogin(self, 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()) m = re.match(r".*\((.*)\)", nomplogin.strip())
if m: if m:
return m.group(1) return m.group(1)

0
csv2rules.py Normal file → Executable file
View File

View File

@ -4,7 +4,27 @@
# #
# Command: ./csv2rules.py misc/parcoursDUT.csv # 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" rules_source_file = "misc/parcoursDUT.csv"

View File

@ -45,9 +45,20 @@ from collections import OrderedDict
# XML generation package (apt-get install jaxml) # XML generation package (apt-get install jaxml)
import 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 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): def mark_paras(L, tags):
@ -280,7 +291,7 @@ class GenTable:
if not row: if not row:
return "<tr></tr>" # empty 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 std = ' style="width:%s;"' % self.html_col_width
else: else:
std = "" std = ""
@ -382,10 +393,6 @@ class GenTable:
else: else:
cls = "" 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)] H = [self.html_before_table, "<table%s%s>" % (hid, cls)]
line_num = 0 line_num = 0
@ -438,14 +445,14 @@ class GenTable:
if self.xls_link: if self.xls_link:
H.append( H.append(
' <a href="%s&amp;format=xls">%s</a>' ' <a href="%s&amp;format=xls">%s</a>'
% (self.base_url, ICON_XLS) % (self.base_url, scu.ICON_XLS)
) )
if self.xls_link and self.pdf_link: if self.xls_link and self.pdf_link:
H.append("&nbsp;&nbsp;") H.append("&nbsp;&nbsp;")
if self.pdf_link: if self.pdf_link:
H.append( H.append(
' <a href="%s&amp;format=pdf">%s</a>' ' <a href="%s&amp;format=pdf">%s</a>'
% (self.base_url, ICON_PDF) % (self.base_url, scu.ICON_PDF)
) )
H.append("</p>") H.append("</p>")
@ -483,10 +490,10 @@ class GenTable:
"PDF representation: returns a ReportLab's platypus Table instance" "PDF representation: returns a ReportLab's platypus Table instance"
r = [] r = []
try: try:
PDFLOCK.acquire() sco_pdf.PDFLOCK.acquire()
r = self._pdf() r = self._pdf()
finally: finally:
PDFLOCK.release() sco_pdf.PDFLOCK.release()
return r return r
def _pdf(self): def _pdf(self):
@ -513,7 +520,7 @@ class GenTable:
CellStyle.leading = 1.0 * self.preferences["SCOLAR_FONT_SIZE"] # vertical space CellStyle.leading = 1.0 * self.preferences["SCOLAR_FONT_SIZE"] # vertical space
LINEWIDTH = 0.5 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 = [] pdf_style_list = []
Pt = [ Pt = [
[Paragraph(SU(str(x)), CellStyle) for x in line] [Paragraph(SU(str(x)), CellStyle) for x in line]
@ -530,10 +537,10 @@ class GenTable:
# log('len(Pt)=%s' % len(Pt)) # log('len(Pt)=%s' % len(Pt))
# log( 'line lens=%s' % [ len(x) for x in Pt ] ) # log( 'line lens=%s' % [ len(x) for x in Pt ] )
# log( 'style=\n%s' % pdf_style_list) # log( 'style=\n%s' % pdf_style_list)
col_min = min([x[1][0] 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]) # 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_min = min([x[1][1] for x in pdf_style_list])
lin_max = max([x[2][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)) # 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) 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 The tag names <table> and <row> can be changed using
xml_outer_tag and xml_row_tag 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)( getattr(doc, self.xml_outer_tag)(
id=self.table_id, origin=self.origin or "", caption=self.caption or "" id=self.table_id, origin=self.origin or "", caption=self.caption or ""
) )
@ -593,7 +600,7 @@ class GenTable:
v = str(v) v = str(v)
r[cid] = v r[cid] = v
d.append(r) d.append(r)
return json.dumps(d, encoding=SCO_ENCODING) return json.dumps(d, encoding=scu.SCO_ENCODING)
def make_page( def make_page(
self, self,
@ -637,11 +644,11 @@ class GenTable:
return "\n".join(H) return "\n".join(H)
elif format == "pdf": elif format == "pdf":
objects = self.pdf() objects = self.pdf()
doc = pdf_basic_page( doc = sco_pdf.pdf_basic_page(
objects, title=title, preferences=self.preferences, context=context objects, title=title, preferences=self.preferences, context=context
) )
if publish: if publish:
return sendPDFFile(REQUEST, doc, filename + ".pdf") return scu.sendPDFFile(REQUEST, doc, filename + ".pdf")
else: else:
return doc return doc
elif format == "xls": elif format == "xls":
@ -653,16 +660,16 @@ class GenTable:
elif format == "text": elif format == "text":
return self.text() return self.text()
elif format == "csv": elif format == "csv":
return sendCSVFile(REQUEST, self.text(), filename + ".csv") return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv")
elif format == "xml": elif format == "xml":
xml = self.xml() xml = self.xml()
if REQUEST and publish: if REQUEST and publish:
REQUEST.RESPONSE.setHeader("content-type", XML_MIMETYPE) REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE)
return xml return xml
elif format == "json": elif format == "json":
js = self.json() js = self.json()
if REQUEST and publish: if REQUEST and publish:
REQUEST.RESPONSE.setHeader("content-type", JSON_MIMETYPE) REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE)
return js return js
else: else:
log("make_page: format=%s" % format) log("make_page: format=%s" % format)
@ -687,7 +694,7 @@ class SeqGenTable:
def excel(self): def excel(self):
"""Export des genTables dans un unique fichier excel avec plusieurs feuilles tagguées""" """Export des genTables dans un unique fichier excel avec plusieurs feuilles tagguées"""
book = sco_excel.Workbook() # Le fichier xls en devenir 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 gt.excel(wb=book) # Ecrit dans un fichier excel
return book.savetostr() return book.savetostr()

View File

@ -257,6 +257,5 @@ def sco_header(
def sco_footer(context, REQUEST=None): def sco_footer(context, REQUEST=None):
"""Main HTMl pages footer """Main HTMl pages footer"""
"""
return """</div><!-- /gtrcontent -->""" + CUSTOM_HTML_FOOTER + """</body></html>""" return """</div><!-- /gtrcontent -->""" + CUSTOM_HTML_FOOTER + """</body></html>"""

View File

@ -158,8 +158,7 @@ def sidebar(context, REQUEST=None):
def sidebar_dept(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 = { infos = {
"BASE0": REQUEST.BASE0, "BASE0": REQUEST.BASE0,
"DeptIntranetTitle": context.get_preference("DeptIntranetTitle"), "DeptIntranetTitle": context.get_preference("DeptIntranetTitle"),

View File

@ -49,7 +49,7 @@ def histogram_notes(notes):
"HTML code drawing histogram" "HTML code drawing histogram"
if not notes: if not notes:
return "" 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>'] D = ['<ul id="vhist-q-graph"><li class="vhist-qtr" id="vhist-q1"><ul>']
left = 5 left = 5
colwidth = 16 # must match #q-graph li.bar width in stylesheet colwidth = 16 # must match #q-graph li.bar width in stylesheet

View File

@ -10,53 +10,53 @@ from itertools import izip
class intervalmap(object): class intervalmap(object):
""" """
This class maps a set of intervals to a set of values. This class maps a set of intervals to a set of values.
>>> i = intervalmap() >>> i = intervalmap()
>>> i[0:5] = '0-5' >>> i[0:5] = '0-5'
>>> i[8:12] = '8-12' >>> i[8:12] = '8-12'
>>> print i[2] >>> print i[2]
0-5 0-5
>>> print i[10] >>> print i[10]
8-12 8-12
>>> print repr(i[-1]) >>> print repr(i[-1])
None None
>>> print repr(i[17]) >>> print repr(i[17])
None None
>>> i[4:9] = '4-9' >>> i[4:9] = '4-9'
>>> print [(j,i[j]) for j in range(6)] >>> 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')] [(0, '0-5'), (1, '0-5'), (2, '0-5'), (3, '0-5'), (4, '4-9'), (5, '4-9')]
>>> print list(i.items()) >>> print list(i.items())
[((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')] [((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
>>> i[:0] = 'less than 0' >>> i[:0] = 'less than 0'
>>> i[-5] >>> i[-5]
'less than 0' 'less than 0'
>>> i[0] >>> i[0]
'0-5' '0-5'
>>> print list(i.items()) >>> print list(i.items())
[((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')] [((None, 0), 'less than 0'), ((0, 4), '0-5'), ((4, 9), '4-9'), ((9, 12), '8-12')]
>>> i[21:] = 'more than twenty' >>> i[21:] = 'more than twenty'
>>> i[42] >>> i[42]
'more than twenty' 'more than twenty'
>>> i[10.5:15.5] = '10.5-15.5' >>> i[10.5:15.5] = '10.5-15.5'
>>> i[11.5] >>> i[11.5]
'10.5-15.5' '10.5-15.5'
>>> i[0.5] >>> i[0.5]
'0-5' '0-5'
>>> print list(i.items()) >>> print list(i.items())
[((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),... [((None, 0),... ((9, 10.5), '8-12'), ((10.5, 15.5), '10.5-15.5'), ((21, None),...
>>> i = intervalmap() >>> i = intervalmap()
>>> i[0:2] = 1 >>> i[0:2] = 1
>>> i[2:8] = 2 >>> i[2:8] = 2
>>> i[4:] = 3 >>> i[4:] = 3
>>> i[5:6] = 4 >>> i[5:6] = 4
>>> i >>> i
{[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3} {[0, 2] => 1, [2, 4] => 2, [4, 5] => 3, [5, 6] => 4, [6, None] => 3}
""" """
def __init__(self): def __init__(self):
""" """
Initializes an empty intervalmap. Initializes an empty intervalmap.
""" """
self._bounds = [] self._bounds = []
self._items = [] self._items = []
@ -64,7 +64,7 @@ class intervalmap(object):
def __setitem__(self, _slice, _value): def __setitem__(self, _slice, _value):
""" """
Sets an interval mapping. Sets an interval mapping.
""" """
assert isinstance(_slice, slice), "The key must be a slice object" assert isinstance(_slice, slice), "The key must be a slice object"
@ -112,7 +112,7 @@ class intervalmap(object):
def __getitem__(self, _point): 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" assert not isinstance(_point, slice), "The key cannot be a slice object"
@ -124,9 +124,9 @@ class intervalmap(object):
def items(self): def items(self):
""" """
Returns an iterator with each item being Returns an iterator with each item being
((low_bound,high_bound), value). The items are returned ((low_bound,high_bound), value). The items are returned
in order. in order.
""" """
previous_bound = None previous_bound = None
for b, v in izip(self._bounds, self._items): for b, v in izip(self._bounds, self._items):
@ -138,8 +138,8 @@ class intervalmap(object):
def values(self): def values(self):
""" """
Returns an iterator with each item being a stored value. The items Returns an iterator with each item being a stored value. The items
are returned in order. are returned in order.
""" """
for v in self._items: for v in self._items:
if v is not None: if v is not None:

View File

@ -61,5 +61,5 @@ class CacheFunc:
def inval_cache(self): # > def inval_cache(self): # >
"clear whole cache" "clear whole cache"
log("inval_cache %s(%s)" % (str(self.func), str(args))) # > log("inval_cache %s" % (str(self.func))) # >
self.cache = {} self.cache = {}

View File

@ -88,7 +88,7 @@ def retreive_dept():
return "" return ""
try: try:
url = REQUEST.URL url = REQUEST.URL
m = re.match("^.*ScoDoc/(\w+).*$", url) m = re.match(r"^.*ScoDoc/(\w+).*$", url)
return m.group(1) return m.group(1)
except: except:
return "" return ""

View File

@ -51,7 +51,7 @@ BONUS_TWO_ARGS = len(inspect.getargspec(CONFIG.compute_bonus)[0]) == 2
def comp_ranks(T): 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 (valeur est une note numérique), en tenant compte des ex-aequos
Le resultat est: { etudid : rang } rang est une chaine decrivant le rang Le resultat est: { etudid : rang } rang est une chaine decrivant le rang
""" """
@ -135,8 +135,8 @@ class NotesTable:
- inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions) - inscrlist: étudiants inscrits à ce semestre, par ordre alphabétique (avec demissions)
- identdict: { etudid : ident } - identdict: { etudid : ident }
- sem : le formsemestre - sem : le formsemestre
get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ] get_table_moyennes_triees: [ (moy_gen, moy_ue1, moy_ue2, ... moy_ues, moy_mod1, ..., moy_modn, etudid) ]
( toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'), ( toutes les valeurs sont soit des nombrs soit des chaines spéciales comme 'NA', 'NI'),
incluant les UE de sport incluant les UE de sport
- bonus[etudid] : valeur du bonus "sport". - bonus[etudid] : valeur du bonus "sport".
@ -145,7 +145,7 @@ class NotesTable:
- _modmoys : { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } } - _modmoys : { moduleimpl_id : { etudid: note_moyenne_dans_ce_module } }
- _ues : liste des UE de ce semestre (hors capitalisees) - _ues : liste des UE de ce semestre (hors capitalisees)
- _matmoys : { matiere_id : { etudid: note moyenne dans cette matiere } } - _matmoys : { matiere_id : { etudid: note moyenne dans cette matiere } }
""" """
def __init__(self, context, formsemestre_id): 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): def get_ues(self, filter_sport=False, filter_non_inscrit=False, etudid=None):
"""liste des ue, ordonnée par numero. """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. inscrit à aucun module.
Si filter_sport, retire les UE de type SPORT Si filter_sport, retire les UE de type SPORT
""" """
@ -580,11 +580,11 @@ class NotesTable:
return matmoy.get(etudid, "NA") return matmoy.get(etudid, "NA")
def comp_etud_moy_ue(self, etudid, ue_id=None, cnx=None): 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 toutes les notes sont entrées Ne prend en compte que les evaluations toutes les notes sont entrées
Return a dict(moy, nb_notes, nb_missing, sum_coefs) Return a dict(moy, nb_notes, nb_missing, sum_coefs)
Si pas de notes, moy == 'NA' et sum_coefs==0 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 assert ue_id
modimpls = self.get_modimpls(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 ? est_inscrit = False # inscrit à l'un des modules de cette UE ?
for modimpl in modimpls: for modimpl in modimpls:
mod_ue_id = modimpl["ue"]["ue_id"]
# module ne faisant pas partie d'une UE capitalisee # module ne faisant pas partie d'une UE capitalisee
val = self._modmoys[modimpl["moduleimpl_id"]].get(etudid, "NI") val = self._modmoys[modimpl["moduleimpl_id"]].get(etudid, "NI")
# si 'NI', etudiant non inscrit a ce module # si 'NI', etudiant non inscrit a ce module
@ -711,7 +710,7 @@ class NotesTable:
def comp_etud_moy_gen(self, etudid, cnx): def comp_etud_moy_gen(self, etudid, cnx):
"""Calcule moyenne gen. pour un etudiant """Calcule moyenne gen. pour un etudiant
Return a dict: Return a dict:
moy : moyenne générale moy : moyenne générale
nb_notes, nb_missing, sum_coefs 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 : (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) 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 'est_inscrit' : True si étudiant inscrit à au moins un module de cette UE
'moy' : moyenne, avec capitalisation eventuelle 'moy' : moyenne, avec capitalisation eventuelle
'coef_ue' : coef de l'UE utilisé pour le calcul de la moyenne générale '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) 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_moy_ue' : moyenne de l'UE en cours (sans considérer de capitalisation)
'cur_coef_ue': coefficient de l'UE courante 'cur_coef_ue': coefficient de l'UE courante
'is_capitalized' : True|False, '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' : (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_fond': 0. si UE non fondamentale, = ects_pot sinon,
'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon, 'ects_pot_pro' : 0 si UE non pro, = ects_pot sinon,
'formsemestre_id' : (si capitalisee), 'formsemestre_id' : (si capitalisee),
'event_date' : (si capitalisee) 'event_date' : (si capitalisee)
} }
@ -760,7 +759,6 @@ class NotesTable:
sem_ects_pot_pro = 0.0 sem_ects_pot_pro = 0.0
for ue in self.get_ues(): for ue in self.get_ues():
ue_id = ue["ue_id"]
# - On calcule la moyenne d'UE courante: # - On calcule la moyenne d'UE courante:
if not block_computation: if not block_computation:
mu = self.comp_etud_moy_ue(etudid, ue_id=ue["ue_id"], cnx=cnx) 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). 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) (les UE sans notes ne sont pas comptées comme sous la barre)
Prend en compte les éventuelles UE capitalisées. Prend en compte les éventuelles UE capitalisées.
Pour les parcours habituels, cela revient à vérifier que Pour les parcours habituels, cela revient à vérifier que
les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes) les moyennes d'UE sont toutes > à leur barre (sauf celles sans notes)
Pour les parcours non standards (LP2014), cela peut être plus compliqué. Pour les parcours non standards (LP2014), cela peut être plus compliqué.
Return: True|False, message explicatif Return: True|False, message explicatif
@ -1000,8 +998,7 @@ class NotesTable:
) )
def get_table_moyennes_dict(self): 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 = {} D = {}
for t in self.T: for t in self.T:
D[t[-1]] = t D[t[-1]] = t
@ -1209,13 +1206,13 @@ class NotesTable:
# return sum(c_list) # return sum(c_list)
def get_etud_ue_cap_coef(self, etudid, ue, ue_cap, cnx=None): 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. injectée dans le semestre courant.
ue : ue du semestre courant ue : ue du semestre courant
ue_cap = resultat de formsemestre_get_etud_capitalisation 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' } '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)) # 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 return len(cursor.fetchall()) > 0
def get_evaluations_etats(self): # evaluation_list_in_sem def get_evaluations_etats(self): # evaluation_list_in_sem
"""[ {...evaluation et son etat...} ] """[ {...evaluation et son etat...} ]"""
"""
if self._evaluations_etats is None: if self._evaluations_etats is None:
self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem( self._evaluations_etats = sco_evaluations.do_evaluation_list_in_sem(
self.context, self.formsemestre_id self.context, self.formsemestre_id
@ -1301,13 +1297,11 @@ class NotesTable:
return self._evaluations_etats return self._evaluations_etats
def get_sem_evaluation_etat_list(self): 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() return self.get_evaluations_etats()
def get_mod_evaluation_etat_list(self, moduleimpl_id): def get_mod_evaluation_etat_list(self, moduleimpl_id):
"""Liste des évaluations de ce module """Liste des évaluations de ce module"""
"""
return [ return [
e e
for e in self.get_evaluations_etats() for e in self.get_evaluations_etats()

View File

@ -50,7 +50,7 @@ DONNEE_MANQUANTE = (
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def get_code_latex_from_modele(fichier): def get_code_latex_from_modele(fichier):
"""Lit le code latex à partir d'un modèle. Renvoie une chaine unicode. """Lit le code latex à partir d'un modèle. Renvoie une chaine unicode.
Le fichier doit contenir le chemin relatif Le fichier doit contenir le chemin relatif
vers le modele : attention pas de vérification du format d'encodage 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) 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). à 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 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. et sont renvoyés sous la forme d'une liste.
result: liste de chaines unicode result: liste de chaines unicode
""" """
if code_latex: if code_latex:
@ -144,7 +144,7 @@ def comp_latex_parcourstimeline(etudiant, promo, taille=17):
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def interprete_tag_latex(tag): 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. le résultat sous la forme d'un quadruplet.
""" """
infotag = tag.split(":") infotag = tag.split(":")
@ -164,7 +164,7 @@ def get_code_latex_avis_etudiant(
donnees_etudiant, un_avis_latex, annotationPE, footer_latex, prefs 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 donnees_etudiant contenu dans le dictionnaire de synthèse du jury PE et en suivant un
fichier modele donné fichier modele donné
@ -228,8 +228,8 @@ def get_code_latex_avis_etudiant(
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def get_annotation_PE(context, etudid, tag_annotation_pe): def get_annotation_PE(context, etudid, tag_annotation_pe):
"""Renvoie l'annotation PE dans la liste de ces annotations ; """Renvoie l'annotation PE dans la liste de ces annotations ;
Cette annotation est reconnue par la présence d'un tag **PE** Cette annotation est reconnue par la présence d'un tag **PE**
(cf. context.get_preferences -> pe_tag_annotation_avis_latex). (cf. context.get_preferences -> pe_tag_annotation_avis_latex).
Result: chaine unicode 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): def str_from_syntheseJury(donnees_etudiant, aggregat, groupe, tag_scodoc, champ):
"""Extrait du dictionnaire de synthèse du juryPE pour un étudiant donnée, """Extrait du dictionnaire de synthèse du juryPE pour un étudiant donnée,
une valeur indiquée par un champ ; une valeur indiquée par un champ ;
si champ est une liste, renvoie la liste des valeurs extraites. si champ est une liste, renvoie la liste des valeurs extraites.
Result: chaine unicode ou liste de chaines unicode 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"): 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. les données étudiants, ses résultats.
result: chaine unicode result: chaine unicode
""" """
@ -474,8 +474,7 @@ def get_templates_from_distrib(template="avis"):
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def table_syntheseAnnotationPE(context, syntheseJury, tag_annotation_pe): 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 sT = SeqGenTable() # le fichier excel à générer
# Les etudids des étudiants à afficher, triés par ordre alphabétiques de nom+prénom # Les etudids des étudiants à afficher, triés par ordre alphabétiques de nom+prénom

View File

@ -88,7 +88,7 @@ class JuryPE:
{'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }} {'etudid : { 'nom', 'prenom', 'sexe', 'diplome', '', }}
Rq: il contient à la fois les étudiants qui vont être diplomés à la date prévue 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 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) 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): def get_zipped_data(self):
"""returns zipped data with all generated (CSV) files """returns zipped data with all generated (CSV) files"""
"""
if self.zipfile: if self.zipfile:
self.zipfile.close() self.zipfile.close()
self.zipfile = None self.zipfile = None
@ -366,7 +365,7 @@ class JuryPE:
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
def add_etudiants(self, etudid): 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 à : L'ajout consiste à :
> insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo), > insérer une entrée pour l'étudiant en mémorisant ses infos (get_etudInfo),
avec son nom, prénom, etc... 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 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 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 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( sessems = self.get_semestresDUT_d_un_etudiant(
etudid etudid
) # les semestres de l'étudiant ) # les semestres de l'étudiant
@ -868,9 +867,7 @@ class JuryPE:
return semDeb["annee_debut"] return semDeb["annee_debut"]
def get_parcoursIUT(self, etudid): 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] etudinfo = self.ETUDINFO_DICT[etudid]
sems = self.get_semestresDUT_d_un_etudiant(etudid) sems = self.get_semestresDUT_d_un_etudiant(etudid)
@ -934,7 +931,7 @@ class JuryPE:
def get_allTagForAggregat(self, nom_aggregat): def get_allTagForAggregat(self, nom_aggregat):
"""Extrait du dictionnaire syntheseJury la liste des tags d'un semestre ou """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() taglist = set()
for etudid in self.get_etudids_du_jury(): for etudid in self.get_etudids_du_jury():
taglist = taglist.union( taglist = taglist.union(
@ -1127,10 +1124,9 @@ class JuryPE:
# ------------------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------------------
def get_cache_notes_d_un_semestre( def get_cache_notes_d_un_semestre(
cls, context, formsemestre_id self, context, formsemestre_id
): # inutile en realité ! ): # 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( return context.Notes._getNotesCache().get_NotesTable(
context.Notes, formsemestre_id context.Notes, formsemestre_id
) )
@ -1196,7 +1192,7 @@ class JuryPE:
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def get_annee_diplome_semestre(sem): 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': ...}, sem = {'formestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
à condition qu'il soit un semestre de formation DUT, à 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 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): def get_cosemestres_diplomants(context, semBase, avec_meme_formation=False):
""" Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...}, """Partant d'un semestre de Base = {'formsemestre_id': ..., 'semestre_id': ..., 'annee_debut': ...},
renvoie la liste de tous ses co-semestres (lui-meme inclus) renvoie la liste de tous ses co-semestres (lui-meme inclus)
Par co-semestre, s'entend les semestres : Par co-semestre, s'entend les semestres :
> dont l'annee predite pour la remise du diplome DUT est la meme > dont l'annee predite pour la remise du diplome DUT est la meme
> dont la formation est la même (optionnel) > dont la formation est la même (optionnel)
> ne prenant en compte que les etudiants sans redoublement > ne prenant en compte que les etudiants sans redoublement
""" """
tousLesSems = ( tousLesSems = (
context.Notes.formsemestre_list() context.Notes.formsemestre_list()

View File

@ -144,8 +144,7 @@ class SetTag(pe_tagtable.TableTag):
# ------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------
def do_tagdict(self): 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 = {} self.tagdict = {}
for semtag in self.SemTagDict.values(): for semtag in self.SemTagDict.values():
for tag in semtag.get_all_tags(): for tag in semtag.get_all_tags():
@ -208,8 +207,8 @@ class SetTag(pe_tagtable.TableTag):
class SetTagInterClasse(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 """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 pour fournir un interclassement sur un groupe d'étudiant => seul compte alors la promo
nom_combinaison = 'S1' ou '1A' nom_combinaison = 'S1' ou '1A'
""" """
# ------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------

View File

@ -95,7 +95,7 @@ class TableTag:
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
def get_coeff_from_resultats(self, tag, etudid): 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. au regard du format de self.resultats.
""" """
return ( return (
@ -329,7 +329,7 @@ def moyenne_ponderee_terme_a_terme(notes, coeffs=None, force=False):
# ------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------
def conversionDate_StrToDate(date_fin): 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. type 'jj/mm/aaaa' en un objet date du package datetime.
Fonction servant au tri des semestres par date Fonction servant au tri des semestres par date
""" """

View File

@ -97,7 +97,7 @@ def print_semestres_description(sems, avec_affichage_debug=False):
# ---------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------
def calcul_age(born): 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. Aucun test de validité sur le format de la date n'est fait.
""" """
if not isinstance(born, str) or born == "": if not isinstance(born, str) or born == "":
@ -122,8 +122,7 @@ def remove_accents(input_unicode_str):
def escape_for_latex(s): 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: if not s:
return "" return ""
conv = { conv = {
@ -162,8 +161,7 @@ def list_directory_filenames(path):
def add_local_file_to_zip(zipfile, ziproot, pathname, path_in_zip): 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) rooted_path_in_zip = os.path.join(ziproot, path_in_zip)
data = open(pathname).read() data = open(pathname).read()
zipfile.writestr(rooted_path_in_zip, data) zipfile.writestr(rooted_path_in_zip, data)

View File

@ -89,7 +89,7 @@ def pe_view_sem_recap(
REQUEST=None, REQUEST=None,
): ):
"""Génération des avis de poursuite d'étude """Génération des avis de poursuite d'étude
mode_debug = Pour "squeezer" le calcul du jury pe (long) mode_debug = Pour "squeezer" le calcul du jury pe (long)
et debugger uniquement la partie avis latex et debugger uniquement la partie avis latex
""" """

View File

@ -47,7 +47,7 @@ import sco_formsemestre
def abs_notify(context, etudid, date): def abs_notify(context, etudid, date):
"""Check if notifications are requested and send them """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, (s'il n'y a pas de semestre courant, ne fait rien,
car l'etudiant n'est pas inscrit au moment de l'absence!). 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): 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: # prefs fallback to global pref if sem is None:
if sem: if sem:
formsemestre_id = sem["formsemestre_id"] 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): 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"] formsemestre_id = sem["formsemestre_id"]
destinations = [] # list of email address to notify 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) nbabs: nombre d'absence (de tous types, unité de compte = demi-journée)
nbabsjust: nombre d'absences justifiées nbabsjust: nombre d'absences justifiées
(nbabs > abs_notify_abs_threshold) (nbabs > abs_notify_abs_threshold)
(nbabs - nbabs_last_notified) > abs_notify_abs_increment (nbabs - nbabs_last_notified) > abs_notify_abs_increment
""" """
abs_notify_abs_threshold = context.get_preference( 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): 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 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 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""" AND i.etudid = %(etudid)s AND e.jour = %(date_abs)s"""

View File

@ -62,8 +62,7 @@ _help_txt = """
def apo_compare_csv_form(context, REQUEST=None): 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 = [ H = [
context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"), context.sco_header(REQUEST, page_title="Comparaison de fichiers Apogée"),
"""<h2>Comparaison de fichiers Apogée</h2> """<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): 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) A = _load_apo_data(A_file, autodetect=autodetect)
B = _load_apo_data(B_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) elts_only_B = B_elts - A_elts.intersection(B_elts)
L.append( L.append(
'<span class="val_dif">différents (%d en commun, %d seulement dans A, %d seulement dans B)</span>' '<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: if elts_only_A:
L.append( 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): def apo_table_compare_etud_results(context, A, B, REQUEST=None):
""" """"""
"""
D = compare_etuds_res(A, B) D = compare_etuds_res(A, B)
T = GenTable( T = GenTable(
rows=D, rows=D,

View File

@ -112,8 +112,7 @@ APO_NEWLINE = "\r\n"
def code_scodoc_to_apo(code): def code_scodoc_to_apo(code):
"""Conversion code jury ScoDoc en code Apogée """Conversion code jury ScoDoc en code Apogée"""
"""
return { return {
ATT: "AJAC", ATT: "AJAC",
ATB: "AJAC", ATB: "AJAC",
@ -159,7 +158,7 @@ def fix_data_encoding(
text, default_source_encoding=APO_INPUT_ENCODING, dest_encoding=APO_INPUT_ENCODING text, default_source_encoding=APO_INPUT_ENCODING, dest_encoding=APO_INPUT_ENCODING
): ):
"""Try to ensure that text is using dest_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 = "" message = ""
detected_encoding = guess_data_encoding(text) detected_encoding = guess_data_encoding(text)
@ -241,8 +240,7 @@ VOID_APO_RES = dict(N="", B="", J="", R="", M="")
class ApoEtud(dict): class ApoEtud(dict):
"""Etudiant Apogee: """Etudiant Apogee:"""
"""
def __init__( def __init__(
self, self,
@ -361,7 +359,7 @@ class ApoEtud(dict):
Autres éléments: résultats du semestre ou de l'année scolaire: Autres éléments: résultats du semestre ou de l'année scolaire:
=> VRTW1: code additionnel au semestre ("code élement semestre", elt_sem_apo) => VRTW1: code additionnel au semestre ("code élement semestre", elt_sem_apo)
=> VRT1A: le même que le VET: ("code élement annuel", elt_annee_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. séparés par des virgules.
Args: Args:
@ -369,7 +367,7 @@ class ApoEtud(dict):
sem (dict): semestre dans lequel on cherche l'élément sem (dict): semestre dans lequel on cherche l'élément
cur_sem (dict): semestre "courant" pour résultats annuels (VET) cur_sem (dict): semestre "courant" pour résultats annuels (VET)
autre_sem (dict): autre semestre utilisé pour calculé les résultats annuels (VET) autre_sem (dict): autre semestre utilisé pour calculé les résultats annuels (VET)
Returns: Returns:
dict: with N, B, J, R keys, ou None si elt non trouvé dict: with N, B, J, R keys, ou None si elt non trouvé
""" """
@ -701,8 +699,7 @@ class ApoData:
self.periode = periode self.periode = periode
def setup(self, context): def setup(self, context):
"""Recherche semestres ScoDoc concernés """Recherche semestres ScoDoc concernés"""
"""
self.context = context self.context = context
self.sems_etape = comp_apo_sems(context, self.etape_apogee, self.annee_scolaire) 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} 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', ... Clé: id apogée, eg 'V1RT', 'V1GE2201', ...
Valeur: ApoElt, avec les attributs code, type_objet 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() elts = collections.OrderedDict()
for col_id in sorted(cols.keys(), reverse=True): for col_id in sorted(cols.keys(), reverse=True):
@ -849,8 +846,7 @@ class ApoData:
return L return L
def get_etape_apogee(self): 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(): for elt in self.apo_elts.values():
if elt.type_objet == "VET": if elt.type_objet == "VET":
return elt.code return elt.code
@ -893,8 +889,7 @@ class ApoData:
f.write(self.column_titles) f.write(self.column_titles)
def write_etuds(self, f): def write_etuds(self, f):
"""write apo CSV etuds on f """write apo CSV etuds on f"""
"""
for e in self.etuds: for e in self.etuds:
fs = [] # e['nip'], e['nom'], e['prenom'], e['naissance'] ] fs = [] # e['nip'], e['nom'], e['prenom'], e['naissance'] ]
for col_id in self.col_ids: for col_id in self.col_ids:
@ -983,8 +978,7 @@ class ApoData:
return codes_by_sem return codes_by_sem
def build_cr_table(self): def build_cr_table(self):
"""Table compte rendu des décisions """Table compte rendu des décisions"""
"""
CR = [] # tableau compte rendu des decisions CR = [] # tableau compte rendu des decisions
for e in self.etuds: for e in self.etuds:
cr = { cr = {
@ -1015,14 +1009,14 @@ class ApoData:
def _apo_read_cols(f): def _apo_read_cols(f):
"""Lecture colonnes apo : """Lecture colonnes apo :
Démarre après la balise XX-APO_COLONNES-XX Démarre après la balise XX-APO_COLONNES-XX
et s'arrête après la balise APO_COL_VAL_FIN et s'arrête après la balise APO_COL_VAL_FIN
Colonne Apogee: les champs sont données par la ligne 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, ... col_id est apoL_c0001, apoL_c0002, ...
:return: { col_id : { title : value } } :return: { col_id : { title : value } }
Example: { 'apoL_c0001' : { 'Type Objet' : 'VET', 'Code' : 'V1IN', ... }, ... } 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): 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 code_etape = apo_data.etape_apogee
today = datetime.datetime.today().strftime("%d/%m/%y") today = datetime.datetime.today().strftime("%d/%m/%y")
L = [] L = []
@ -1186,7 +1179,7 @@ def export_csv_to_apogee(
export_res_rat=True, export_res_rat=True,
REQUEST=None, 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) à partir d'un fichier CSV Apogée vide (ou partiellement rempli)
et des résultats ScoDoc. et des résultats ScoDoc.
Si dest_zip, ajoute les fichiers générés à ce zip Si dest_zip, ajoute les fichiers générés à ce zip

View File

@ -49,14 +49,12 @@ EtudsArchive = EtudsArchiver()
def can_edit_etud_archive(context, authuser): 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) return authuser.has_permission(ScoEtudAddAnnotations, context)
def etud_list_archives_html(context, REQUEST, etudid): 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) can_edit = can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER)
L = [] L = []
for archive_id in EtudsArchive.list_obj_archives(context, etudid): 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): 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 # check permission
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER): if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
raise AccessDenied( raise AccessDenied(
@ -178,8 +175,7 @@ def etud_upload_file_form(context, REQUEST, etudid):
def _store_etud_file_to_new_archive( def _store_etud_file_to_new_archive(
context, REQUEST, etudid, data, filename, description="" context, REQUEST, etudid, data, filename, description=""
): ):
"""Store data to new archive. """Store data to new archive."""
"""
filesize = len(data) filesize = len(data)
if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE: if filesize < 10 or filesize > CONFIG.ETUD_MAX_FILE_SIZE:
return 0, "Fichier image de taille invalide ! (%d)" % filesize 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): def etud_delete_archive(context, REQUEST, etudid, archive_name, dialog_confirmed=False):
"""Delete an archive """Delete an archive"""
"""
# check permission # check permission
if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER): if not can_edit_etud_archive(context, REQUEST.AUTHENTICATED_USER):
raise AccessDenied( 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): def etud_get_archived_file(context, REQUEST, etudid, archive_name, filename):
"""Send file to client. """Send file to client."""
"""
return EtudsArchive.get_archived_file( return EtudsArchive.get_archived_file(
context, REQUEST, etudid, archive_name, filename 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) # --- Upload d'un ensemble de fichiers (pour un groupe d'étudiants)
def etudarchive_generate_excel_sample(context, group_id=None, REQUEST=None): 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() fmt = ImportScolars.sco_import_format()
data = ImportScolars.sco_import_generate_excel_sample( data = ImportScolars.sco_import_generate_excel_sample(
fmt, 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): 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 = [ H = [
context.sco_header( context.sco_header(
REQUEST, page_title="Import de fichiers associés aux étudiants" REQUEST, page_title="Import de fichiers associés aux étudiants"

View File

@ -162,4 +162,4 @@ class Baccalaureat:
return self.type() == "G" return self.type() == "G"
def is_techno(self): def is_techno(self):
return selt.type() == "T" return self.type() == "T"

View File

@ -80,8 +80,7 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
return [self.buildTableObject(P, pdfTableStyle, colWidths)] return [self.buildTableObject(P, pdfTableStyle, colWidths)]
def bul_table_html(self): 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" format = "html"
I = self.infos I = self.infos
authuser = self.authuser authuser = self.authuser
@ -130,13 +129,10 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
continue # saute les modules où on n'est pas inscrit continue # saute les modules où on n'est pas inscrit
H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle) H.append('<tr class="notes_bulletin_row_mod%s">' % rowstyle)
if context.get_preference("bul_show_minmax_mod", formsemestre_id): if context.get_preference("bul_show_minmax_mod", formsemestre_id):
rang_minmax = ( rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' mod["mod_rang_txt"],
% ( fmt_note(mod["stats"]["min"]),
mod["mod_rang_txt"], fmt_note(mod["stats"]["max"]),
fmt_note(mod["stats"]["min"]),
fmt_note(mod["stats"]["max"]),
)
) )
else: else:
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang rang_minmax = mod["mod_rang_txt"] # vide si pas option rang
@ -386,8 +382,7 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorLegacy)
class BulTableStyle: 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 LINEWIDTH = 0.5
LINECOLOR = Color(0, 0, 0) LINECOLOR = Color(0, 0, 0)

View File

@ -57,8 +57,7 @@ import os
def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None): def form_change_bul_sig(context, side, formsemestre_id=None, REQUEST=None):
"""Change pdf signature """Change pdf signature"""
"""
filename = _get_sig_existing_filename( filename = _get_sig_existing_filename(
context, side, formsemestre_id=formsemestre_id context, side, formsemestre_id=formsemestre_id
) )

View File

@ -305,5 +305,4 @@ sco_bulletins_generator.register_bulletin_class(BulletinGeneratorUCAC)
def bulletin_table_ucac(context, I, version=None): def bulletin_table_ucac(context, I, version=None):
""" """"""
"""

View File

@ -35,6 +35,7 @@ import thread, time
# Cache data # Cache data
class simpleCache: class simpleCache:
def __init__(self): def __init__(self):
self.cache = {}
self.inval_cache() # > self.inval_cache() # >
def inval_cache(self, key=None): # > def inval_cache(self, key=None): # >
@ -56,7 +57,7 @@ class simpleCache:
class expiringCache(simpleCache): class expiringCache(simpleCache):
"""A simple cache wich cache data for a most "duration" seconds. """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) information systems)
""" """

View File

@ -64,8 +64,7 @@ SCO_DUMP_LOCK = "/tmp/scodump.lock"
def sco_dump_and_send_db(context, REQUEST=None): 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")] H = [context.sco_header(REQUEST, page_title="Assistance technique")]
# get currect (dept) DB name: # get currect (dept) DB name:
cursor = SimpleQuery(context, "SELECT current_database()", {}) cursor = SimpleQuery(context, "SELECT current_database()", {})
@ -150,8 +149,7 @@ def _duplicate_db(db_name, ano_db_name):
def _anonymize_db(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") cmd = os.path.join(SCO_CONFIG_DIR, "anonymize_db.py")
log("_anonymize_db: {}".format(cmd)) log("_anonymize_db: {}".format(cmd))
try: try:
@ -171,8 +169,7 @@ def _get_scodoc_serial(context):
def _send_db(context, REQUEST, ano_db_name): 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)) log("dumping anonymized database {}".format(ano_db_name))
try: try:
data = subprocess.check_output("pg_dump {} | gzip".format(ano_db_name), shell=1) data = subprocess.check_output("pg_dump {} | gzip".format(ano_db_name), shell=1)

View File

@ -37,8 +37,7 @@ import sco_formsemestre
def formation_delete(context, formation_id=None, dialog_confirmed=False, REQUEST=None): 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}) F = context.formation_list(args={"formation_id": formation_id})
if not F: if not F:
raise ScoValueError("formation inexistante !") 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): def formation_create(context, REQUEST=None):
"""Creation d'une formation """Creation d'une formation"""
"""
return formation_edit(context, create=True, REQUEST=REQUEST) return formation_edit(context, create=True, REQUEST=REQUEST)
def formation_edit(context, formation_id=None, create=False, REQUEST=None): def formation_edit(context, formation_id=None, create=False, REQUEST=None):
"""Edit or create a formation """Edit or create a formation"""
"""
if create: if create:
H = [ H = [
context.sco_header(REQUEST, page_title="Création d'une formation"), context.sco_header(REQUEST, page_title="Création d'une formation"),

View File

@ -36,8 +36,7 @@ import sco_formsemestre
def matiere_create(context, ue_id=None, REQUEST=None): 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] UE = context.do_ue_list(args={"ue_id": ue_id})[0]
H = [ H = [
context.sco_header(REQUEST, page_title="Création d'une matière"), context.sco_header(REQUEST, page_title="Création d'une matière"),

View File

@ -55,8 +55,7 @@ saisir et modifier les notes de ce module.
def module_create(context, matiere_id=None, REQUEST=None): def module_create(context, matiere_id=None, REQUEST=None):
"""Creation d'un module """Creation d'un module"""
"""
if not matiere_id: if not matiere_id:
raise ScoValueError("invalid matiere !") raise ScoValueError("invalid matiere !")
M = context.do_matiere_list(args={"matiere_id": matiere_id})[0] 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): 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}) ue_list = context.do_ue_list(args={"formation_id": formation_id})
for ue in ue_list: 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): 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] ue = context.do_ue_list(args={"ue_id": ue_id})[0]
if titre is None: if titre is None:

View File

@ -41,14 +41,12 @@ import sco_tag_module
def ue_create(context, formation_id=None, REQUEST=None): 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) 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): 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) create = int(create)
if not create: if not create:
U = context.do_ue_list(args={"ue_id": ue_id}) 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): def _add_ue_semestre_id(context, ue_list):
"""ajoute semestre_id dans les ue, en regardant le premier module de chacune. """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. qui les place à la fin de la liste.
""" """
for ue in ue_list: for ue in ue_list:
@ -281,7 +279,7 @@ def ue_delete(
def ue_list(context, formation_id=None, msg="", REQUEST=None): 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). editer (si non verrouillée).
""" """
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
@ -781,8 +779,7 @@ def edit_ue_set_code_apogee(context, id=None, value=None, REQUEST=None):
# ---- Table recap formation # ---- Table recap formation
def formation_table_recap(context, formation_id, format="html", REQUEST=None): def formation_table_recap(context, formation_id, format="html", REQUEST=None):
""" """"""
"""
F = context.formation_list(args={"formation_id": formation_id}) F = context.formation_list(args={"formation_id": formation_id})
if not F: if not F:
raise ScoValueError("invalid formation_id") raise ScoValueError("invalid formation_id")

View File

@ -67,8 +67,7 @@ def formsemestre_get_ics_url(context, sem):
def formsemestre_load_ics(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 # TODO: cacher le résultat
ics_url = formsemestre_get_ics_url(context, sem) ics_url = formsemestre_get_ics_url(context, sem)
if not ics_url: if not ics_url:
@ -86,15 +85,13 @@ def formsemestre_load_ics(context, sem):
def formsemestre_edt_groups_used(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) cal = formsemestre_load_ics(context, sem)
return {e["X-GROUP-ID"].decode("utf8") for e in events} return {e["X-GROUP-ID"].decode("utf8") for e in events}
def get_edt_transcodage_groups(context, formsemestre_id): 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 # TODO: valider ces données au moment où on enregistre les préférences
edt2sco = {} edt2sco = {}
sco2edt = {} sco2edt = {}
@ -161,8 +158,7 @@ for e in events:
def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=None): def experimental_calendar(context, group_id=None, formsemestre_id=None, REQUEST=None):
"""experimental page """experimental page"""
"""
return "\n".join( return "\n".join(
[ [
context.sco_header( context.sco_header(

View File

@ -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): def apo_csv_delete(context, archive_id):
"""Delete archived CSV """Delete archived CSV"""
"""
ApoCSVArchive.delete_archive(archive_id) 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): def apo_get_sem_etapes(context, sem):
"""Etapes de ce semestre: pour l'instant, celles déclarées """Etapes de ce semestre: pour l'instant, celles déclarées
Dans une future version, on pourrait aussi utiliser les étapes Dans une future version, on pourrait aussi utiliser les étapes
d'inscription des étudiants, recupérées via le portail, d'inscription des étudiants, recupérées via le portail,
voir check_paiement_etuds(). voir check_paiement_etuds().
:return: list of etape_apo (ApoEtapeVDI instances) :return: list of etape_apo (ApoEtapeVDI instances)
""" """
return sem["etapes"] return sem["etapes"]
def apo_csv_check_etape(context, semset, set_nips, etape_apo): 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: # Etudiants dans la maquette CSV:
csv_data = apo_csv_get( csv_data = apo_csv_get(
context, etape_apo, semset["annee_scolaire"], semset["sem_id"] 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 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 check students in stored maqs vs students in semset
Cas à détecter: Cas à détecter:

View File

@ -58,9 +58,7 @@ def apo_semset_maq_status(
block_export_res_sdj=True, block_export_res_sdj=True,
REQUEST=None, REQUEST=None,
): ):
"""Page statut / tableau de bord """Page statut / tableau de bord"""
"""
if not semset_id: if not semset_id:
raise ValueError("invalid null semset_id") raise ValueError("invalid null semset_id")
semset = sco_semset.SemSet(context, semset_id=semset_id) semset = sco_semset.SemSet(context, semset_id=semset_id)
@ -91,7 +89,9 @@ def apo_semset_maq_status(
apo_dups, apo_dups,
maq_elems, maq_elems,
sem_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: if not allow_missing_decisions:
ok_for_export &= semset["jury_ok"] ok_for_export &= semset["jury_ok"]
@ -265,9 +265,7 @@ def apo_semset_maq_status(
) )
if allow_missing_csv: if allow_missing_csv:
H.append("checked") H.append("checked")
H.append( H.append(""" >autoriser export même si étapes sans maquettes</input></div>""")
""" >autoriser export même si étapes sans maquettes</input></div>"""
)
H.append("""</form>""") H.append("""</form>""")
if semset and ok_for_export: if semset and ok_for_export:
@ -295,7 +293,9 @@ def apo_semset_maq_status(
H.append( H.append(
"""<div><label><input type="checkbox" name="block_export_res_etape" value="1" %s %s>%s</input></label></div>""" """<div><label><input type="checkbox" name="block_export_res_etape" value="1" %s %s>%s</input></label></div>"""
% checked( % 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( H.append(
@ -424,8 +424,7 @@ def apo_semset_maq_status(
def table_apo_csv_list(context, semset, REQUEST=None): 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"] annee_scolaire = semset["annee_scolaire"]
sem_id = semset["sem_id"] 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): 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: if not semset_id:
raise ValueError("invalid null semset_id") raise ValueError("invalid null semset_id")
semset = sco_semset.SemSet(context, semset_id=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( def view_scodoc_etuds(
context, semset_id, title="", etudids=None, nips=None, format="html", REQUEST=None 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 etudids is not None:
if type(etudids) != type([]): if type(etudids) != type([]):
etudids = [etudids] 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): 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: if not semset_id:
raise ValueError("invalid null semset_id") raise ValueError("invalid null semset_id")
semset = sco_semset.SemSet(context, semset_id=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( def view_apo_csv_delete(
context, etape_apo="", semset_id="", dialog_confirmed=False, REQUEST=None context, etape_apo="", semset_id="", dialog_confirmed=False, REQUEST=None
): ):
"""Delete CSV file """Delete CSV file"""
"""
if not semset_id: if not semset_id:
raise ValueError("invalid null semset_id") raise ValueError("invalid null semset_id")
semset = sco_semset.SemSet(context, semset_id=semset_id) semset = sco_semset.SemSet(context, semset_id=semset_id)

View File

@ -237,8 +237,7 @@ class ScoExcelSheet:
def Excel_SimpleTable(titles=[], lines=[[]], SheetName="feuille", titlesStyles=[]): 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 # XXX devrait maintenant utiliser ScoExcelSheet
wb = Workbook() wb = Workbook()
ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING)) ws0 = wb.add_sheet(SheetName.decode(SCO_ENCODING))

View File

@ -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): 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( s = SimpleDictFetch(
context, context,
"SELECT formsemestre_id FROM notes_formsemestre WHERE date_debut >= %(start_date)s AND date_fin <= %(end_date)s", "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 """Page affichant la table des résultats
Les dates sont en dd/mm/yyyy (datepicker javascript) 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'] ) (liste de chaines, eg ['100', '210'] )
""" """
log("scodoc_table_results: start_date=%s" % (start_date,)) # XXX log("scodoc_table_results: start_date=%s" % (start_date,)) # XXX

View File

@ -216,7 +216,7 @@ def search_etud_in_dept(
# Was chercheEtudsInfo() # Was chercheEtudsInfo()
def search_etuds_infos(context, expnom=None, code_nip=None, REQUEST=None): def search_etuds_infos(context, expnom=None, code_nip=None, REQUEST=None):
"""recherche les étudiants correspondants à expnom ou au code_nip """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) may_be_nip = is_valid_code_nip(expnom)
cnx = context.GetDBConnexion() 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): 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 authuser = REQUEST.AUTHENTICATED_USER
# present form only to authenticated users # present form only to authenticated users
if not authuser.has_role("Authenticated"): if not authuser.has_role("Authenticated"):

View File

@ -480,7 +480,7 @@ def formsemestre_recap_parcours_table(
show_details=False, show_details=False,
): ):
"""Tableau HTML recap parcours """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 sem_info = { formsemestre_id : txt } permet d'ajouter des informations associées à chaque semestre
with_all_columns: si faux, pas de colonne "assiduité". with_all_columns: si faux, pas de colonne "assiduité".
""" """
@ -690,8 +690,7 @@ def formsemestre_recap_parcours_table(
def form_decision_manuelle( def form_decision_manuelle(
context, Se, formsemestre_id, etudid, desturl="", sortcol=None context, Se, formsemestre_id, etudid, desturl="", sortcol=None
): ):
"""Formulaire pour saisie décision manuelle """Formulaire pour saisie décision manuelle"""
"""
H = [ H = [
""" """
<script type="text/javascript"> <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): 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)) log("formsemestre_validation_suppress_etud( %s, %s)" % (formsemestre_id, etudid))
cnx = context.GetDBConnexion(autocommit=False) cnx = context.GetDBConnexion(autocommit=False)
cursor = cnx.cursor(cursor_factory=ScoDocCursor) 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): 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). (pour étudiants arrivant avec un UE antérieurement validée).
""" """
etud = context.getEtudInfo(etudid=etudid, filled=True)[0] etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
@ -1205,7 +1203,7 @@ def do_formsemestre_validate_previous_ue(
REQUEST=None, REQUEST=None,
): ):
"""Enregistre (ou modifie) validation d'UE (obtenue hors ScoDoc). """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). cette UE (utile seulement pour les semestres extérieurs).
""" """
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) 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): 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( valids = SimpleDictFetch(
context, context,
"""SELECT SFV.* FROM scolar_formsemestre_validation SFV """SELECT SFV.* FROM scolar_formsemestre_validation SFV

View File

@ -39,8 +39,7 @@ TITLES = ("user_name", "nom", "prenom", "email", "roles", "dept")
def generate_excel_sample(): 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) style = sco_excel.Excel_MakeStyle(bold=True)
titles = TITLES titles = TITLES
titlesStyles = [style] * len(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 - créer utilisateur et mettre le mot de passe
- envoyer mot de passe par mail - 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 created = [] # liste de uid créés
try: try:

View File

@ -45,8 +45,7 @@ import sco_formsemestre
def formsemestre_table_etuds_lycees( def formsemestre_table_etuds_lycees(
context, formsemestre_id, group_lycees=True, only_primo=False 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) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
etuds = sco_report.tsp_etud_list(context, formsemestre_id, only_primo=only_primo)[0] etuds = sco_report.tsp_etud_list(context, formsemestre_id, only_primo=only_primo)[0]
if only_primo: if only_primo:
@ -60,8 +59,7 @@ def formsemestre_table_etuds_lycees(
def scodoc_table_etuds_lycees(context, format="html", REQUEST=None): 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) semdepts = sco_formsemestre.scodoc_get_all_unlocked_sems(context)
etuds = [] etuds = []
for (sem, deptcontext) in semdepts: for (sem, deptcontext) in semdepts:

View File

@ -41,8 +41,7 @@ import sco_codes_parcours
def list_formsemestres_modalites(context, sems): 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 = {} modalites = {}
for sem in sems: for sem in sems:
if sem["modalite"] not in modalites: if sem["modalite"] not in modalites:
@ -86,8 +85,7 @@ _modaliteEditor = EditableTable(
def do_modalite_list(context, *args, **kw): def do_modalite_list(context, *args, **kw):
"""Liste des modalites """Liste des modalites"""
"""
cnx = context.GetDBConnexion() cnx = context.GetDBConnexion()
return _modaliteEditor.list(cnx, *args, **kw) return _modaliteEditor.list(cnx, *args, **kw)

View File

@ -273,18 +273,17 @@ def ficheEtud(context, etudid=None, REQUEST=None):
if not context.canSuppressAnnotation(a["id"], REQUEST): if not context.canSuppressAnnotation(a["id"], REQUEST):
a["dellink"] = "" a["dellink"] = ""
else: else:
a["dellink"] = ( a[
'<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&amp;annotation_id=%s">%s</a></td>' "dellink"
% ( ] = '<td class="annodel"><a href="doSuppressAnnotation?etudid=%s&amp;annotation_id=%s">%s</a></td>' % (
etudid, etudid,
a["id"], a["id"],
icontag( icontag(
"delete_img", "delete_img",
border="0", border="0",
alt="suppress", alt="suppress",
title="Supprimer cette annotation", title="Supprimer cette annotation",
), ),
)
) )
alist.append( 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>' '<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): 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"): if not REQUEST.form.has_key("etudid"):
return "" return ""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER

View File

@ -41,7 +41,7 @@ from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
from reportlab.platypus.flowables import Flowable from reportlab.platypus.flowables import Flowable
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from reportlab.lib.styles import getSampleStyleSheet 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.units import inch, cm, mm
from reportlab.lib.colors import pink, black, red, blue, green, magenta, red from reportlab.lib.colors import pink, black, red, blue, green, magenta, red
from reportlab.lib.colors import Color from reportlab.lib.colors import Color

View File

@ -197,16 +197,18 @@ def do_placement_selectetuds(context, REQUEST):
numbering = tf[2]["numbering"] numbering = tf[2]["numbering"]
if columns in ("3", "4", "5", "6", "7", "8"): if columns in ("3", "4", "5", "6", "7", "8"):
gs = [("group_ids%3Alist=" + urllib.quote_plus(x)) for x in group_ids] gs = [("group_ids%3Alist=" + urllib.quote_plus(x)) for x in group_ids]
query = "evaluation_id=%s&amp;placement_method=%s&amp;teachers=%s&amp;building=%s&amp;room=%s&amp;columns=%s&amp;numbering=%s&amp;" % ( query = (
evaluation_id, "evaluation_id=%s&amp;placement_method=%s&amp;teachers=%s&amp;building=%s&amp;room=%s&amp;columns=%s&amp;numbering=%s&amp;"
placement_method, % (
teachers, evaluation_id,
building, placement_method,
room, teachers,
columns, building,
numbering, room,
) + "&amp;".join( columns,
gs numbering,
)
+ "&amp;".join(gs)
) )
return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query) return REQUEST.RESPONSE.redirect(REQUEST.URL1 + "/do_placement?" + query)
else: else:
@ -385,8 +387,7 @@ def do_placement(context, REQUEST):
def placement_eval_selectetuds(context, evaluation_id, REQUEST=None): 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}) evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")

View File

@ -41,8 +41,7 @@ from sco_codes_parcours import code_semestre_validant, code_semestre_attente
def etud_get_poursuite_info(context, sem, etud): def etud_get_poursuite_info(context, sem, etud):
"""{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] } """{ 'nom' : ..., 'semlist' : [ { 'semestre_id': , 'moy' : ... }, {}, ...] }"""
"""
I = {} I = {}
I.update(etud) # copie nom, prenom, sexe, ... I.update(etud) # copie nom, prenom, sexe, ...
@ -153,8 +152,7 @@ def _flatten_info(info):
def formsemestre_poursuite_report( def formsemestre_poursuite_report(
context, formsemestre_id, format="html", REQUEST=None context, formsemestre_id, format="html", REQUEST=None
): ):
"""Table avec informations "poursuite" """Table avec informations "poursuite" """
"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
nt = context._getNotesCache().get_NotesTable(context, formsemestre_id) nt = context._getNotesCache().get_NotesTable(context, formsemestre_id)
etuds = context.getEtudInfoGroupes( etuds = context.getEtudInfoGroupes(

View File

@ -270,8 +270,7 @@ def do_evaluation_upload_xls(context, REQUEST):
def do_evaluation_set_missing( def do_evaluation_set_missing(
context, evaluation_id, value, REQUEST=None, dialog_confirmed=False context, evaluation_id, value, REQUEST=None, dialog_confirmed=False
): ):
"""Initialisation des notes manquantes """Initialisation des notes manquantes"""
"""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
evaluation_id = REQUEST.form["evaluation_id"] evaluation_id = REQUEST.form["evaluation_id"]
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] 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): 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 authuser = REQUEST.AUTHENTICATED_USER
authusername = str(authuser)
evals = context.do_evaluation_list({"evaluation_id": evaluation_id}) evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") 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): 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}) evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") 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): 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 authuser = REQUEST.AUTHENTICATED_USER
authusername = str(authuser) authusername = str(authuser)
@ -1182,8 +1179,7 @@ def _form_saisie_notes(context, E, M, group_ids, REQUEST=None):
def save_note( def save_note(
context, etudid=None, evaluation_id=None, value=None, comment="", REQUEST=None context, etudid=None, evaluation_id=None, value=None, comment="", REQUEST=None
): ):
"""Enregistre une note (ajax) """Enregistre une note (ajax)"""
"""
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
log( log(
"save_note: evaluation_id=%s etudid=%s uid=%s value=%s" "save_note: evaluation_id=%s etudid=%s uid=%s value=%s"

View File

@ -63,8 +63,7 @@ semset_delete = _semset_editor.delete
class SemSet(dict): class SemSet(dict):
def __init__(self, context, semset_id=None, title="", annee_scolaire="", sem_id=""): 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: if not annee_scolaire and not semset_id:
# on autorise annee_scolaire null si sem_id pour pouvoir lire les anciens semsets # on autorise annee_scolaire null si sem_id pour pouvoir lire les anciens semsets
# mal construits... # mal construits...
@ -201,8 +200,7 @@ class SemSet(dict):
return etapes return etapes
def list_possible_sems(self): 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) sems = sco_formsemestre.do_formsemestre_list(self.context)
# remove sems already here: # remove sems already here:
sems = [ sems = [
@ -243,8 +241,7 @@ class SemSet(dict):
self["jury_ok"] &= sem["jury_ok"] self["jury_ok"] &= sem["jury_ok"]
def html_descr(self): def html_descr(self):
"""Short HTML description """Short HTML description"""
"""
H = [ H = [
"""<span class="box_title">Ensemble de semestres %(title)s</span>""" % self """<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)" "do_semset_create(title=%s, annee_scolaire=%s, sem_id=%s)"
% (title, annee_scolaire, sem_id) % (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") 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): def edit_semset_set_title(context, id=None, value=None, REQUEST=None):
"""Change title of semset """Change title of semset"""
"""
title = value.strip() title = value.strip()
if not id: if not id:
raise ScoValueError("empty semset_id") raise ScoValueError("empty semset_id")
s = SemSet(context, semset_id=id) SemSet(context, semset_id=id)
cnx = context.GetDBConnexion() cnx = context.GetDBConnexion()
semset_edit(cnx, {"semset_id": id, "title": title}) semset_edit(cnx, {"semset_id": id, "title": title})
return title return title
@ -393,7 +389,7 @@ def do_semset_add_sem(context, semset_id, formsemestre_id, REQUEST=None):
raise ScoValueError("empty semset_id") raise ScoValueError("empty semset_id")
s = SemSet(context, semset_id=semset_id) s = SemSet(context, semset_id=semset_id)
# check for valid formsemestre_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) s.add(formsemestre_id)
@ -431,9 +427,10 @@ def semset_page(context, format="html", REQUEST=None):
# (remplacé par n liens vers chacun des semestres) # (remplacé par n liens vers chacun des semestres)
# s['_semtitles_str_target'] = s['_export_link_target'] # s['_semtitles_str_target'] = s['_export_link_target']
# Experimental: # Experimental:
s["_title_td_attrs"] = ( s[
'class="inplace_edit" data-url="edit_semset_set_title" id="%s"' "_title_td_attrs"
% (s["semset_id"]) ] = 'class="inplace_edit" data-url="edit_semset_set_title" id="%s"' % (
s["semset_id"]
) )
tab = GenTable( tab = GenTable(

View File

@ -53,8 +53,7 @@ from notes_log import log
class ScoTag: class ScoTag:
"""Generic tags for ScoDoc """Generic tags for ScoDoc"""
"""
# must be overloaded: # must be overloaded:
tag_table = None # table (tag_id, title) tag_table = None # table (tag_id, title)
@ -62,8 +61,7 @@ class ScoTag:
obj_colname = None # column name for object_id in assoc_table obj_colname = None # column name for object_id in assoc_table
def __init__(self, context, title, object_id=""): 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.context = context
self.title = title.strip() self.title = title.strip()
if not self.title: if not self.title:
@ -153,16 +151,14 @@ class ScoTag:
class ModuleTag(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) tag_table = "notes_tags" # table (tag_id, title)
assoc_table = "notes_modules_tags" # table (tag_id, object_id) assoc_table = "notes_modules_tags" # table (tag_id, object_id)
obj_colname = "module_id" # column name for object_id in assoc_table obj_colname = "module_id" # column name for object_id in assoc_table
def list_modules(self, formation_code=""): 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} args = {"tag_id": self.tag_id}
if not formation_code: if not formation_code:
# tous les modules de toutes les formations ! # 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=""): 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( r = SimpleDictFetch(
context, context,
"""SELECT t.title """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): def get_etud_tagged_modules(context, etudid, tagname):
"""Liste d'infos sur les modules de ce semestre avec ce tag. """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. 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] etud = context.getEtudInfo(etudid=etudid, filled=True)[0]
R = [] R = []
@ -292,7 +287,7 @@ def get_etud_tagged_modules(context, etudid, tagname):
def split_tagname_coeff(tag, separateur=":"): 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) (chaine de caractère correspondant au tag)
et un éventuel coefficient de pondération, avec le séparateur fourni (par défaut ":"). 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 Renvoie le résultat sous la forme d'une liste [tagname, pond] où pond est un float

View File

@ -66,8 +66,7 @@ def pdf_trombino_tours(
formsemestre_id=None, # utilisé si pas de groupes selectionné formsemestre_id=None, # utilisé si pas de groupes selectionné
REQUEST=None, REQUEST=None,
): ):
"""Generation du trombinoscope en fichier PDF """Generation du trombinoscope en fichier PDF"""
"""
# Informations sur les groupes à afficher: # Informations sur les groupes à afficher:
groups_infos = sco_groups_view.DisplayedGroupsInfos( groups_infos = sco_groups_view.DisplayedGroupsInfos(
context, group_ids, formsemestre_id=formsemestre_id, REQUEST=REQUEST 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é formsemestre_id=None, # utilisé si pas de groupes selectionné
REQUEST=None, 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_AM = context.get_preference("feuille_releve_abs_AM")
NB_CELL_PM = context.get_preference("feuille_releve_abs_PM") NB_CELL_PM = context.get_preference("feuille_releve_abs_PM")

View File

@ -72,8 +72,7 @@ def external_ue_create(
ects=0.0, ects=0.0,
REQUEST=None, 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)) log("external_ue_create( formsemestre_id=%s, titre=%s )" % (formsemestre_id, titre))
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès: # Contrôle d'accès:
@ -196,13 +195,14 @@ def get_external_moduleimpl_id(context, formsemestre_id, ue_id):
# Web function # Web function
def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None): def external_ue_create_form(context, formsemestre_id, etudid, REQUEST=None):
"""Formulaire création UE externe + inscription étudiant et saisie note """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 ou sinon spécifier titre, acronyme, type, ECTS
- Demande note à enregistrer. - 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 fonctions standards sur les UE/modules/notes
""" """
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# Contrôle d'accès: # Contrôle d'accès:
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
if not authuser.has_permission(ScoImplement, context): 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") raise AccessDenied("vous n'avez pas le droit d'effectuer cette opération")
etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0] etud = context.getEtudInfo(etudid=etudid, filled=1, REQUEST=REQUEST)[0]
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
formation_id = sem["formation_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) existing_external_ue = get_existing_external_ue(context, formation_id)
H = [ H = [

View File

@ -123,8 +123,7 @@ def is_up_to_date(context):
def html_up_to_date_box(context): def html_up_to_date_box(context):
""" """"""
"""
status, msg = is_up_to_date(context) status, msg = is_up_to_date(context)
if status: if status:
return "" return ""

View File

@ -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): 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 = cnx.cursor(cursor_factory=ScoDocCursor)
cursor.execute( cursor.execute(
"select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s", "select * from scolog where method=%(method)s and authenticated_user=%(authenticated_user)s",