1
0
forked from ScoDoc/ScoDoc

WIP fixing imports (still broken!)

This commit is contained in:
Emmanuel Viennet 2021-06-17 00:08:37 +02:00
parent c2798be033
commit 3e225c9fda
44 changed files with 724 additions and 610 deletions

2
.pylintrc Normal file
View File

@ -0,0 +1,2 @@
[TYPECHECK]
ignored-classes=Permission

View File

@ -39,13 +39,6 @@ import re
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
import scolars
import sco_formsemestre
import sco_groups
import sco_excel
import sco_groups_view
import sco_news
from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules from sco_formsemestre_inscriptions import do_formsemestre_inscription_with_modules
from gen_tables import GenTable from gen_tables import GenTable
from sco_exceptions import ( from sco_exceptions import (
@ -57,6 +50,14 @@ from sco_exceptions import (
ScoLockedFormError, ScoLockedFormError,
ScoGenError, ScoGenError,
) )
import html_sco_header
import scolars
import sco_formsemestre
import sco_groups
import sco_excel
import sco_groups_view
import sco_news
import sco_preferences
# format description (relative to Product directory)) # format description (relative to Product directory))
FORMAT_FILE = "misc/format_import_etudiants.txt" FORMAT_FILE = "misc/format_import_etudiants.txt"
@ -476,7 +477,7 @@ def scolars_import_excel_file(
sco_news.add( sco_news.add(
context, context,
REQUEST, REQUEST,
typ=NEWS_INSCR, typ=sco_news.NEWS_INSCR,
text="Inscription de %d étudiants" # peuvent avoir ete inscrits a des semestres differents text="Inscription de %d étudiants" # peuvent avoir ete inscrits a des semestres differents
% len(created_etudids), % len(created_etudids),
object=formsemestre_id, object=formsemestre_id,

View File

@ -5,13 +5,13 @@
Lancer ScoDoc ainsi: (comme root) Lancer ScoDoc ainsi: (comme root)
/opt/scodoc/bin/zopectl debug /opt/scodoc/bin/zopectl debug
Puis Puis
from debug import * from debug import *
context = go(app) context = go(app)
# ou # ou
context = go_dept(app, 'CJ') context = go_dept(app, 'CJ')
authuser = app.acl_users.getUserById('admin') authuser = app.acl_users.getUserById('admin')
@ -31,14 +31,14 @@ nt = context.Notes._getNotesCache().get_NotesTable(context.Notes, formsemestre_i
""" """
import pdb import pdb # pylint: disable=unused-import
import pprint import pprint
import notesdb as ndb import app.scodoc.notesdb as ndb
from notesdb import * # pylint: disable=unused-wildcard-import from app.scodoc.notesdb import * # pylint: disable=unused-wildcard-import
from notes_log import log from app.scodoc.notes_log import log
import sco_utils as scu import app.scodoc.sco_utils as scu
from sco_utils import * # pylint: disable=unused-wildcard-import from app.scodoc.sco_utils import * # pylint: disable=unused-wildcard-import
from gen_tables import GenTable from gen_tables import GenTable
import sco_archives import sco_archives

View File

@ -626,7 +626,8 @@ class GenTable:
if with_html_headers: if with_html_headers:
H.append( H.append(
self.html_header self.html_header
or html_sco_header.sco_header(context, or html_sco_header.sco_header(
context,
REQUEST, REQUEST,
page_title=page_title, page_title=page_title,
javascripts=javascripts, javascripts=javascripts,

View File

@ -125,8 +125,8 @@ _HTML_BEGIN = """<?xml version="1.0" encoding="%(encoding)s"?>
def scodoc_top_html_header(context, REQUEST, page_title="ScoDoc"): def scodoc_top_html_header(context, REQUEST, page_title="ScoDoc"):
H = [ H = [
HTML_BEGIN % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING}, _HTML_BEGIN % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING},
TOP_LEVEL_CSS, _TOP_LEVEL_CSS,
"""</head><body class="gtrcontent" id="gtrcontent">""", """</head><body class="gtrcontent" id="gtrcontent">""",
scu.CUSTOM_HTML_HEADER_CNX, scu.CUSTOM_HTML_HEADER_CNX,
] ]

View File

@ -29,7 +29,7 @@ import sco_utils as scu
import sco_preferences import sco_preferences
from sco_abs import getAbsSemEtud from sco_abs import getAbsSemEtud
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
import scolars
""" """
Génération de la "sidebar" (marge gauche des pages HTML) Génération de la "sidebar" (marge gauche des pages HTML)

View File

@ -98,9 +98,11 @@ def make_menu(title, items, css_class="", alone=False):
li_id = 'id="%s" ' % the_id li_id = 'id="%s" ' % the_id
else: else:
li_id = "" li_id = ""
if "endpoint" in items: if "endpoint" in item:
args = item.get("args", {}) args = item.get("args", {})
item["urlq"] = url_for(endpoint, scodoc_dept=g.scodoc_dept, **args) item["urlq"] = url_for(
item["endpoint"], scodoc_dept=g.scodoc_dept, **args
)
else: else:
item["urlq"] = "#" item["urlq"] = "#"
item["attr"] = item.get("attr", "") item["attr"] = item.get("attr", "")

View File

@ -30,6 +30,7 @@
# XXX WIP: à ré-écrire pour ScoDoc 8 (étaient des méthodes de ZScoDoc) # XXX WIP: à ré-écrire pour ScoDoc 8 (étaient des méthodes de ZScoDoc)
import os import os
import time
from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error from email.MIMEMultipart import ( # pylint: disable=no-name-in-module,import-error
MIMEMultipart, MIMEMultipart,
) )

View File

@ -113,6 +113,7 @@ def retreive_dept():
def sendAlarm(context, subj, txt): def sendAlarm(context, subj, txt):
import sco_utils import sco_utils
import mails import mails
import sco_preferences
msg = MIMEMultipart() msg = MIMEMultipart()
subj = Header(subj, sco_utils.SCO_ENCODING) subj = Header(subj, sco_utils.SCO_ENCODING)

View File

@ -32,22 +32,9 @@ import time
import pdb import pdb
import inspect import inspect
import sco_core
import scolars
import sco_groups
from notes_log import log, logCallStack
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
import sco_codes_parcours from notes_log import log, logCallStack
from sco_codes_parcours import DEF, UE_SPORT, UE_is_fondamentale, UE_is_professionnelle
from sco_parcours_dut import formsemestre_get_etud_capitalisation
from sco_parcours_dut import list_formsemestre_utilisateurs_uecap
import sco_parcours_dut
import sco_formsemestre
from sco_formsemestre import formsemestre_uecoef_list, formsemestre_uecoef_create
import sco_moduleimpl
import sco_evaluations
import sco_compute_moy
from sco_formulas import NoteVector from sco_formulas import NoteVector
from sco_exceptions import ( from sco_exceptions import (
AccessDenied, AccessDenied,
@ -55,6 +42,25 @@ from sco_exceptions import (
ScoException, ScoException,
ScoValueError, ScoValueError,
) )
from sco_formsemestre import formsemestre_uecoef_list, formsemestre_uecoef_create
from sco_codes_parcours import DEF, UE_SPORT, UE_is_fondamentale, UE_is_professionnelle
from sco_parcours_dut import formsemestre_get_etud_capitalisation
import sco_codes_parcours
import sco_compute_moy
import sco_core
import sco_edit_matiere
import sco_edit_module
import sco_edit_ue
import sco_evaluations
import sco_formations
import sco_formsemestre
import sco_formsemestre_inscriptions
import sco_groups
import sco_moduleimpl
import sco_parcours_dut
import sco_preferences
import scolars
# Support for old user-written "bonus" functions with 2 args: # Support for old user-written "bonus" functions with 2 args:
BONUS_TWO_ARGS = len(inspect.getargspec(scu.CONFIG.compute_bonus)[0]) == 2 BONUS_TWO_ARGS = len(inspect.getargspec(scu.CONFIG.compute_bonus)[0]) == 2
@ -100,7 +106,9 @@ def get_sem_ues_modimpls(context, formsemestre_id, modimpls=None):
) )
uedict = {} uedict = {}
for modimpl in modimpls: for modimpl in modimpls:
mod = sco_edit_module.do_module_list(context, args={"module_id": modimpl["module_id"]})[0] mod = sco_edit_module.do_module_list(
context, args={"module_id": modimpl["module_id"]}
)[0]
modimpl["module"] = mod modimpl["module"] = mod
if not mod["ue_id"] in uedict: if not mod["ue_id"] in uedict:
ue = sco_edit_ue.do_ue_list(context, args={"ue_id": mod["ue_id"]})[0] ue = sco_edit_ue.do_ue_list(context, args={"ue_id": mod["ue_id"]})[0]
@ -177,8 +185,8 @@ class NotesTable:
context, "use_ue_coefs", formsemestre_id context, "use_ue_coefs", formsemestre_id
) )
# Infos sur les etudiants # Infos sur les etudiants
self.inscrlist = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, self.inscrlist = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
args={"formsemestre_id": formsemestre_id} context, args={"formsemestre_id": formsemestre_id}
) )
# infos identite etudiant # infos identite etudiant
# xxx sous-optimal: 1/select par etudiant -> 0.17" pour identdict sur GTR1 ! # xxx sous-optimal: 1/select par etudiant -> 0.17" pour identdict sur GTR1 !
@ -224,13 +232,15 @@ class NotesTable:
ue = uedict[mod["ue_id"]] ue = uedict[mod["ue_id"]]
modimpl["ue"] = ue # add ue dict to moduleimpl modimpl["ue"] = ue # add ue dict to moduleimpl
self._matmoys[mod["matiere_id"]] = {} self._matmoys[mod["matiere_id"]] = {}
mat = sco_edit_matiere.do_matiere_list(context, args={"matiere_id": mod["matiere_id"]})[0] mat = sco_edit_matiere.do_matiere_list(
context, args={"matiere_id": mod["matiere_id"]}
)[0]
modimpl["mat"] = mat # add matiere dict to moduleimpl modimpl["mat"] = mat # add matiere dict to moduleimpl
# calcul moyennes du module et stocke dans le module # calcul moyennes du module et stocke dans le module
# nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif= # nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif=
self.formation = sco_formations.formation_list(context, self.formation = sco_formations.formation_list(
args={"formation_id": self.sem["formation_id"]} context, args={"formation_id": self.sem["formation_id"]}
)[0] )[0]
self.parcours = sco_codes_parcours.get_parcours_from_code( self.parcours = sco_codes_parcours.get_parcours_from_code(
self.formation["type_parcours"] self.formation["type_parcours"]
@ -1175,7 +1185,7 @@ class NotesTable:
"comp_ue_capitalisees: recomputing UE moy (etudid=%s, ue_id=%s formsemestre_id=%s)" "comp_ue_capitalisees: recomputing UE moy (etudid=%s, ue_id=%s formsemestre_id=%s)"
% (etudid, ue_cap["ue_id"], ue_cap["formsemestre_id"]) % (etudid, ue_cap["ue_id"], ue_cap["formsemestre_id"])
) )
nt_cap = self.sco_core.get_notes_cache(context).get_NotesTable( nt_cap = sco_core.get_notes_cache(context).get_NotesTable(
self.context, ue_cap["formsemestre_id"] self.context, ue_cap["formsemestre_id"]
) # > UE capitalisees par un etud ) # > UE capitalisees par un etud
moy_ue_cap = nt_cap.get_etud_ue_status(etudid, ue_cap["ue_id"])[ moy_ue_cap = nt_cap.get_etud_ue_status(etudid, ue_cap["ue_id"])[
@ -1327,188 +1337,3 @@ class NotesTable:
for e in self.get_evaluations_etats() for e in self.get_evaluations_etats()
if e["moduleimpl_id"] == moduleimpl_id if e["moduleimpl_id"] == moduleimpl_id
] ]
import thread
class CacheNotesTable:
"""gestion rudimentaire de cache pour les NotesTables"""
def __init__(self):
log("new CacheTable (id=%s)" % id(self))
#
self.lock = thread.allocate_lock()
self.owner_thread = None # thread owning this cache
self.nref = 0
# Cache des NotesTables
self.cache = {} # { formsemestre_id : NoteTable instance }
# Cache des classeur PDF (bulletins)
self.pdfcache = {} # { formsemestre_id : (filename, pdfdoc) }
# Listeners:
self.listeners = scu.DictDefault(
defaultvalue={}
) # {formsemestre_id : {listener_id : callback }}
def acquire(self):
"If this thread does not own the cache, acquire the lock"
if thread.get_ident() != self.owner_thread:
if self.lock.locked():
log(
"acquire: ident=%s waiting for lock" % thread.get_ident()
) # XXX debug
self.lock.acquire()
self.owner_thread = thread.get_ident()
if self.owner_thread is None: # bug catching
log("WARNING: None thread id !")
self.nref += 1
# log('nref=%d' % self.nref)
def release(self):
"Release the lock"
cur_owner_thread = self.owner_thread
# log('release: ident=%s (nref=%d)' % (thread.get_ident(), self.nref))
self.nref -= 1
if self.nref == 0:
self.lock.release()
self.owner_thread = None
# Debug:
if thread.get_ident() != cur_owner_thread:
log(
"WARNING: release: ident=%s != owner=%s nref=%d"
% (thread.get_ident(), cur_owner_thread, self.nref)
)
raise NoteProcessError("problem with notes cache")
def get_NotesTable(self, context, formsemestre_id): # >
try:
self.acquire()
if self.cache.has_key(formsemestre_id):
# log('cache hit %s (id=%s, thread=%s)'
# % (formsemestre_id, id(self), thread.get_ident()))
return self.cache[formsemestre_id]
else:
t0 = time.time()
nt = NotesTable(context, formsemestre_id)
dt = time.time() - t0
self.cache[formsemestre_id] = nt
log(
"caching formsemestre_id=%s (id=%s) (%gs)"
% (formsemestre_id, id(self), dt)
)
return nt
finally:
self.release()
def get_cached_formsemestre_ids(self):
"List of currently cached formsemestre_id"
return self.cache.keys()
def inval_cache(self, context, formsemestre_id=None, pdfonly=False): # >
"expire cache pour un semestre (ou tous si pas d'argument)"
log(
"inval_cache, formsemestre_id=%s pdfonly=%s (id=%s)"
% (formsemestre_id, pdfonly, id(self)) # >
)
try:
self.acquire()
if not hasattr(self, "pdfcache"):
self.pdfcache = {} # fix for old zope instances...
if formsemestre_id is None:
# clear all caches
log("----- inval_cache: clearing all caches -----")
# log('cache was containing ' + str(self.cache.keys()))
# logCallStack() # >>> DEBUG <<<
if not pdfonly:
self.cache = {}
self.pdfcache = {}
self._call_all_listeners()
sco_core.get_evaluations_cache(
context,
).inval_cache()
else:
# formsemestre_id modifié:
# on doit virer formsemestre_id et tous les semestres
# susceptibles d'utiliser des UE capitalisées de ce semestre.
to_trash = [formsemestre_id] + list_formsemestre_utilisateurs_uecap(
context, formsemestre_id
)
if not pdfonly:
for formsemestre_id in to_trash:
if self.cache.has_key(formsemestre_id):
log(
"delete %s from cache (id=%s)"
% (formsemestre_id, id(self))
)
del self.cache[formsemestre_id]
self._call_listeners(formsemestre_id)
sco_core.get_evaluations_cache(
context,
).inval_cache()
for formsemestre_id in to_trash:
for (
cached_formsemestre_id,
cached_version,
) in self.pdfcache.keys():
if cached_formsemestre_id == formsemestre_id:
log(
"delete pdfcache[(%s,%s)]"
% (formsemestre_id, cached_version)
)
del self.pdfcache[(formsemestre_id, cached_version)]
finally:
self.release()
def store_bulletins_pdf(self, formsemestre_id, version, filename, pdfdoc):
"cache pdf data"
log(
"caching PDF formsemestre_id=%s version=%s (id=%s)"
% (formsemestre_id, version, id(self))
)
try:
self.acquire()
self.pdfcache[(formsemestre_id, version)] = (filename, pdfdoc)
finally:
self.release()
def get_bulletins_pdf(self, formsemestre_id, version):
"returns cached PDF, or None if not in the cache"
try:
self.acquire()
if not hasattr(self, "pdfcache"):
self.pdfcache = {} # fix for old zope instances...
r = self.pdfcache.get((formsemestre_id, version), None)
if r:
log(
"get_bulletins_pdf(%s): cache hit %s (id=%s, thread=%s)"
% (version, formsemestre_id, id(self), thread.get_ident())
)
return r
finally:
self.release()
def add_listener(self, callback, formsemestre_id, listener_id):
"""Add a "listener": a function called each time a formsemestre is modified"""
self.listeners[formsemestre_id][listener_id] = callback
def remove_listener(self, formsemestre_id, listener_id):
"""Remove a listener.
May raise exception if does not exists.
"""
del self.listeners[formsemestre_id][listener_id]
def _call_listeners(self, formsemestre_id):
for listener_id, callback in self.listeners[formsemestre_id].items():
callback(listener_id)
def _call_all_listeners(self):
for formsemestre_id in self.listeners:
self._call_listeners(formsemestre_id)
#
# Cache global: chaque instance, repérée par sa connexion a la DB, a un cache
# qui est recréé à la demande (voir ZNotes._getNotesCache() )
#
NOTES_CACHE_INST = {} # { db_cnx_string : CacheNotesTable instance }

View File

@ -40,6 +40,7 @@ import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
import scolars import scolars
import sco_preferences
import pe_jurype, pe_tagtable, pe_tools import pe_jurype, pe_tagtable, pe_tools
from gen_tables import GenTable, SeqGenTable from gen_tables import GenTable, SeqGenTable

View File

@ -41,7 +41,9 @@ import sco_formsemestre
import sco_formsemestre_status import sco_formsemestre_status
import notes_table import notes_table
from gen_tables import GenTable from gen_tables import GenTable
import html_sco_header
import sco_codes_parcours import sco_codes_parcours
import sco_preferences
import pe_tools import pe_tools
from pe_tools import PE_LATEX_ENCODING from pe_tools import PE_LATEX_ENCODING

View File

@ -38,9 +38,12 @@ import calendar
import cgi import cgi
import notesdb import notesdb
from scodoc_manager import sco_mgr
from sco_exceptions import ScoValueError, ScoInvalidDateError from sco_exceptions import ScoValueError, ScoInvalidDateError
import sco_formsemestre import sco_formsemestre
import sco_compute_moy import sco_compute_moy
import sco_preferences
import scolars
def is_work_saturday(context): def is_work_saturday(context):
@ -589,7 +592,7 @@ def getAbsSemEtud(context, sem, etudid):
def getAbsSemEtuds(context, sem): def getAbsSemEtuds(context, sem):
u = context.GetDBConnexionString() # identifie le dept de facon fiable u = sco_mgr.get_db_uri() # identifie le dept de facon fiable
if not u in ABS_CACHE_INST: if not u in ABS_CACHE_INST:
ABS_CACHE_INST[u] = {} ABS_CACHE_INST[u] = {}
C = ABS_CACHE_INST[u] C = ABS_CACHE_INST[u]

View File

@ -44,6 +44,8 @@ from notes_log import log
from scolog import logdb from scolog import logdb
import sco_bulletins import sco_bulletins
import sco_formsemestre import sco_formsemestre
import sco_preferences
import scolars
def abs_notify(context, etudid, date): def abs_notify(context, etudid, date):

View File

@ -37,15 +37,17 @@ from gen_tables import GenTable
from notesdb import DateISOtoDMY from notesdb import DateISOtoDMY
import sco_utils as scu import sco_utils as scu
from sco_exceptions import ScoValueError from sco_exceptions import ScoValueError
from sco_permissions import ScoAbsChange from sco_permissions import Permission
from notes_log import log from notes_log import log
import sco_groups import html_sco_header
import sco_abs
import sco_find_etud import sco_find_etud
import sco_formsemestre import sco_formsemestre
import sco_groups
import sco_moduleimpl import sco_moduleimpl
import sco_photos import sco_photos
import sco_preferences
import sco_abs import scolars
def doSignaleAbsence( def doSignaleAbsence(

View File

@ -51,6 +51,8 @@ from notes_log import log
import sco_apogee_csv import sco_apogee_csv
from gen_tables import GenTable from gen_tables import GenTable
from sco_exceptions import ScoValueError from sco_exceptions import ScoValueError
import html_sco_header
import sco_preferences
_help_txt = """ _help_txt = """
<div class="help"> <div class="help">

View File

@ -99,14 +99,15 @@ import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
from sco_exceptions import ScoValueError, FormatError from sco_exceptions import ScoValueError, FormatError
import sco_formsemestre from gen_tables import GenTable
from sco_formsemestre import ApoEtapeVDI from sco_formsemestre import ApoEtapeVDI
import sco_formsemestre_status
import sco_parcours_dut
import sco_codes_parcours
from sco_codes_parcours import code_semestre_validant from sco_codes_parcours import code_semestre_validant
from sco_codes_parcours import ATT, ATB, ADM, ADC, ADJ, ATJ, ATB, AJ, CMP, NAR, RAT, DEF from sco_codes_parcours import ATT, ATB, ADM, ADC, ADJ, ATJ, ATB, AJ, CMP, NAR, RAT, DEF
from gen_tables import GenTable import sco_codes_parcours
import sco_formsemestre
import sco_formsemestre_status
import sco_parcours_dut
import scolars
APO_PORTAL_ENCODING = ( APO_PORTAL_ENCODING = (
"utf8" # encodage du fichier CSV Apogée (était 'ISO-8859-1' avant jul. 2016) "utf8" # encodage du fichier CSV Apogée (était 'ISO-8859-1' avant jul. 2016)

View File

@ -56,18 +56,20 @@ import sco_utils as scu
from config import Config from config import Config
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
import sco_formsemestre
import sco_pvjury
import sco_excel
import sco_pvpdf
import sco_groups
import sco_groups_view
from sco_recapcomplet import make_formsemestre_recapcomplet from sco_recapcomplet import make_formsemestre_recapcomplet
import sco_bulletins_pdf
from TrivialFormulator import TrivialFormulator from TrivialFormulator import TrivialFormulator
from sco_exceptions import ( from sco_exceptions import (
AccessDenied, AccessDenied,
) )
import html_sco_header
import sco_bulletins_pdf
import sco_excel
import sco_formsemestre
import sco_groups
import sco_groups_view
import sco_permissions
import sco_pvjury
import sco_pvpdf
class BaseArchiver: class BaseArchiver:

View File

@ -38,9 +38,11 @@ import sco_groups
import sco_trombino import sco_trombino
import sco_excel import sco_excel
import sco_archives import sco_archives
from sco_permissions import ScoEtudAddAnnotations from sco_permissions import Permission
from sco_exceptions import AccessDenied from sco_exceptions import AccessDenied
from TrivialFormulator import TrivialFormulator from TrivialFormulator import TrivialFormulator
import html_sco_header
import scolars
class EtudsArchiver(sco_archives.BaseArchiver): class EtudsArchiver(sco_archives.BaseArchiver):

View File

@ -45,22 +45,23 @@ import mails
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
import scolars from sco_permissions import Permission
from sco_permissions import ScoImplement, ScoEtudInscrit
from sco_exceptions import AccessDenied from sco_exceptions import AccessDenied
import sco_codes_parcours
import sco_formsemestre
import sco_groups
import sco_pvjury
import sco_formsemestre_status
import sco_photos
import sco_abs import sco_abs
import sco_abs_views import sco_abs_views
import sco_preferences
import sco_codes_parcours
import sco_bulletins_generator import sco_bulletins_generator
import sco_bulletins_xml
import sco_bulletins_json import sco_bulletins_json
import sco_bulletins_xml
import sco_codes_parcours
import sco_core
import sco_formations
import sco_formsemestre
import sco_formsemestre_status
import sco_groups
import sco_photos
import sco_preferences
import sco_pvjury
import scolars
def make_context_dict(context, sem, etud): def make_context_dict(context, sem, etud):
@ -131,8 +132,8 @@ def formsemestre_bulletinetud_dict(
I["server_name"] = "" I["server_name"] = ""
# Formation et parcours # Formation et parcours
I["formation"] = sco_formations.formation_list(context, I["formation"] = sco_formations.formation_list(
args={"formation_id": I["sem"]["formation_id"]} context, args={"formation_id": I["sem"]["formation_id"]}
)[0] )[0]
I["parcours"] = sco_codes_parcours.get_parcours_from_code( I["parcours"] = sco_codes_parcours.get_parcours_from_code(
I["formation"]["type_parcours"] I["formation"]["type_parcours"]
@ -568,8 +569,8 @@ def _ue_mod_bulletin(context, etudid, formsemestre_id, ue_id, modimpls, nt, vers
context, "bul_show_all_evals", formsemestre_id context, "bul_show_all_evals", formsemestre_id
): ):
complete_eval_ids = set([e["evaluation_id"] for e in evals]) complete_eval_ids = set([e["evaluation_id"] for e in evals])
all_evals = context.do_evaluation_list( all_evals = sco_evaluations.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} context, args={"moduleimpl_id": modimpl["moduleimpl_id"]}
) )
all_evals.reverse() # plus ancienne d'abord all_evals.reverse() # plus ancienne d'abord
for e in all_evals: for e in all_evals:

View File

@ -87,7 +87,9 @@ def bulletin_get_class(class_name):
def bulletin_get_class_name_displayed(context, formsemestre_id): def bulletin_get_class_name_displayed(context, formsemestre_id):
"""Le nom du générateur utilisé, en clair""" """Le nom du générateur utilisé, en clair"""
bul_class_name = sco_preferences.get_preference(context, "bul_class_name", formsemestre_id) bul_class_name = sco_preferences.get_preference(
context, "bul_class_name", formsemestre_id
)
try: try:
gen_class = bulletin_get_class(bul_class_name) gen_class = bulletin_get_class(bul_class_name)
return gen_class.description return gen_class.description
@ -223,8 +225,8 @@ class BulletinGenerator:
margins=self.margins, margins=self.margins,
server_name=self.server_name, server_name=self.server_name,
filigranne=self.filigranne, filigranne=self.filigranne,
preferences=self.sco_preferences.SemPreferences( preferences=sco_preferences.SemPreferences(
context, formsemestre_id self.context, formsemestre_id
), ),
) )
) )
@ -275,7 +277,9 @@ def make_formsemestre_bulletinetud(
raise ValueError("invalid version code !") raise ValueError("invalid version code !")
formsemestre_id = infos["formsemestre_id"] formsemestre_id = infos["formsemestre_id"]
bul_class_name = sco_preferences.get_preference(context, "bul_class_name", formsemestre_id) bul_class_name = sco_preferences.get_preference(
context, "bul_class_name", formsemestre_id
)
try: try:
gen_class = bulletin_get_class(bul_class_name) gen_class = bulletin_get_class(bul_class_name)
except: except:

View File

@ -33,12 +33,16 @@ import json
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
import scolars import sco_abs
import sco_bulletins
import sco_core
import sco_edit_ue
import sco_evaluations
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
import sco_photos import sco_photos
import sco_abs import sco_preferences
import sco_bulletins import scolars
# -------- Bulletin en JSON # -------- Bulletin en JSON
@ -293,8 +297,8 @@ def formsemestre_bulletinetud_published_dict(
if sco_preferences.get_preference( if sco_preferences.get_preference(
context, "bul_show_all_evals", formsemestre_id context, "bul_show_all_evals", formsemestre_id
): ):
all_evals = context.do_evaluation_list( all_evals = sco_evaluations.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} context, args={"moduleimpl_id": modimpl["moduleimpl_id"]}
) )
all_evals.reverse() # plus ancienne d'abord all_evals.reverse() # plus ancienne d'abord
for e in all_evals: for e in all_evals:

View File

@ -35,10 +35,8 @@
""" """
import traceback, re
import sco_utils as scu import sco_utils as scu
from sco_permissions import ScoEtudInscrit from sco_permissions import Permission
import sco_formsemestre import sco_formsemestre
import sco_pdf import sco_pdf
from sco_pdf import Color, Paragraph, Spacer, Table from sco_pdf import Color, Paragraph, Spacer, Table
@ -90,8 +88,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
formsemestre_id = self.infos["formsemestre_id"] formsemestre_id = self.infos["formsemestre_id"]
context = self.context context = self.context
bul_show_abs_modules = sco_preferences.get_preference(context, bul_show_abs_modules = sco_preferences.get_preference(
"bul_show_abs_modules", formsemestre_id context, "bul_show_abs_modules", formsemestre_id
) )
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
@ -131,7 +129,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if mod["mod_moy_txt"] == "NI": if mod["mod_moy_txt"] == "NI":
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 sco_preferences.get_preference(context, "bul_show_minmax_mod", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_minmax_mod", formsemestre_id
):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % ( rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % (
mod["mod_rang_txt"], mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]), scu.fmt_note(mod["stats"]["min"]),
@ -178,7 +178,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
rowstyle = "" rowstyle = ""
plusminus = minuslink # plusminus = minuslink #
if ue["ue_status"]["is_capitalized"]: if ue["ue_status"]["is_capitalized"]:
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_ue_cap_details", formsemestre_id
):
plusminus = minuslink plusminus = minuslink
hide = "" hide = ""
else: else:
@ -208,7 +210,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
) )
H.append('<tr class="notes_bulletin_row_ue">') H.append('<tr class="notes_bulletin_row_ue">')
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_minmax", formsemestre_id
):
moy_txt = ( moy_txt = (
'%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
% ( % (
@ -444,8 +448,8 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
S = BulTableStyle() S = BulTableStyle()
P = [] # elems pour gen. pdf P = [] # elems pour gen. pdf
formsemestre_id = I["formsemestre_id"] formsemestre_id = I["formsemestre_id"]
bul_show_abs_modules = sco_preferences.get_preference(context, bul_show_abs_modules = sco_preferences.get_preference(
"bul_show_abs_modules", formsemestre_id context, "bul_show_abs_modules", formsemestre_id
) )
if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id): if sco_preferences.get_preference(context, "bul_show_minmax", formsemestre_id):
@ -470,7 +474,9 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
if mod["mod_moy_txt"] == "NI": if mod["mod_moy_txt"] == "NI":
continue # saute les modules où on n'est pas inscrit continue # saute les modules où on n'est pas inscrit
S.modline(ue_type=ue_type) S.modline(ue_type=ue_type)
if sco_preferences.get_preference(context, "bul_show_minmax_mod", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_minmax_mod", formsemestre_id
):
rang_minmax = '%s <font size="8">[%s, %s]</font>' % ( rang_minmax = '%s <font size="8">[%s, %s]</font>' % (
mod["mod_rang_txt"], mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]), scu.fmt_note(mod["stats"]["min"]),
@ -510,7 +516,9 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
coef_ue = "" coef_ue = ""
ue_descr = "(en cours, non prise en compte)" ue_descr = "(en cours, non prise en compte)"
S.ueline() S.ueline()
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_ue_cap_details", formsemestre_id
):
list_modules(ue["modules_capitalized"]) list_modules(ue["modules_capitalized"])
ue_type = "cur" ue_type = "cur"

View File

@ -55,17 +55,19 @@ import time
import pprint import pprint
import traceback import traceback
import re import re
import os
import cStringIO import cStringIO
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
import VERSION import VERSION
import sco_utils as scu import sco_utils as scu
from notes_log import log from notes_log import log
import sco_formsemestre
import sco_bulletins import sco_bulletins
import sco_core
import sco_formsemestre
import sco_pdf import sco_pdf
import os import sco_preferences
import scolars
def pdfassemblebulletins( def pdfassemblebulletins(

View File

@ -31,7 +31,7 @@
XXX en projet, non finalisé: on peut utiliser en attendant les paramétrages des bulletins (malcommodes). XXX en projet, non finalisé: on peut utiliser en attendant les paramétrages des bulletins (malcommodes).
Il ne s'agit pas d'une "signature" électronique, mais simplement d'une image Il ne s'agit pas d'une "signature" électronique, mais simplement d'une image
que l'on intègre dans les documents pdf générés (bulletins, classeur des bulletins, que l'on intègre dans les documents pdf générés (bulletins, classeur des bulletins,
envois par mail). envois par mail).

View File

@ -59,7 +59,7 @@ from sco_pdf import blue, cm, mm
from sco_pdf import SU from sco_pdf import SU
import sco_preferences import sco_preferences
from notes_log import log from notes_log import log
from sco_permissions import ScoEtudInscrit from sco_permissions import Permission
from sco_codes_parcours import ( from sco_codes_parcours import (
UE_COLORS, UE_COLORS,
UE_DEFAULT_COLOR, UE_DEFAULT_COLOR,
@ -105,7 +105,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
columns_ids=colkeys, columns_ids=colkeys,
pdf_table_style=pdf_style, pdf_table_style=pdf_style,
pdf_col_widths=[colWidths[k] for k in colkeys], pdf_col_widths=[colWidths[k] for k in colkeys],
preferences=self.sco_preferences.SemPreferences(context, formsemestre_id), preferences=sco_preferences.SemPreferences(self.context, formsemestre_id),
html_class="notes_bulletin", html_class="notes_bulletin",
html_class_ignore_default=True, html_class_ignore_default=True,
html_with_td_classes=True, html_with_td_classes=True,

View File

@ -32,7 +32,6 @@ On redéfini la table centrale du bulletin de note et hérite de tout le reste d
E. Viennet, juillet 2011 E. Viennet, juillet 2011
""" """
import traceback
import sco_utils as scu import sco_utils as scu
import sco_formsemestre import sco_formsemestre
@ -195,7 +194,9 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
ue_type = None ue_type = None
# --- UE capitalisée: # --- UE capitalisée:
if ue["ue_status"]["is_capitalized"]: if ue["ue_status"]["is_capitalized"]:
if sco_preferences.get_preference(context, "bul_show_ue_cap_details", formsemestre_id): if sco_preferences.get_preference(
context, "bul_show_ue_cap_details", formsemestre_id
):
nb_modules = len(ue["modules_capitalized"]) nb_modules = len(ue["modules_capitalized"])
hidden = False hidden = False
cssstyle = "" cssstyle = ""

View File

@ -43,13 +43,16 @@ import jaxml
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from notes_log import log from notes_log import log
import scolars import sco_abs
import sco_bulletins
import sco_codes_parcours import sco_codes_parcours
import sco_core
import sco_evaluations
import sco_formsemestre import sco_formsemestre
import sco_groups import sco_groups
import sco_photos import sco_photos
import sco_abs import sco_preferences
import sco_bulletins import scolars
# -------- Bulletin en XML # -------- Bulletin en XML
# (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict() # (fonction séparée: n'utilise pas formsemestre_bulletinetud_dict()
@ -289,8 +292,8 @@ def make_xml_formsemestre_bulletinetud(
if sco_preferences.get_preference( if sco_preferences.get_preference(
context, "bul_show_all_evals", formsemestre_id context, "bul_show_all_evals", formsemestre_id
): ):
all_evals = context.do_evaluation_list( all_evals = sco_evaluations.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]} context, args={"moduleimpl_id": modimpl["moduleimpl_id"]}
) )
all_evals.reverse() # plus ancienne d'abord all_evals.reverse() # plus ancienne d'abord
for e in all_evals: for e in all_evals:

View File

@ -33,6 +33,7 @@ import pprint
from types import FloatType from types import FloatType
import sco_utils as scu import sco_utils as scu
import notesdb as ndb
from sco_utils import ( from sco_utils import (
NOTES_ATTENTE, NOTES_ATTENTE,
NOTES_NEUTRALISE, NOTES_NEUTRALISE,
@ -43,12 +44,14 @@ from sco_utils import (
from sco_exceptions import ScoException from sco_exceptions import ScoException
from notesdb import EditableTable, quote_html from notesdb import EditableTable, quote_html
from notes_log import log, sendAlarm from notes_log import log, sendAlarm
import sco_formsemestre
import sco_moduleimpl
import sco_groups
import sco_evaluations
import sco_formulas
import sco_abs import sco_abs
import sco_edit_module
import sco_evaluations
import sco_formsemestre
import sco_formulas
import sco_groups
import sco_moduleimpl
import scolars
def moduleimpl_has_expression(context, mod): def moduleimpl_has_expression(context, mod):
@ -376,7 +379,7 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id):
liste des moduleimpls avec notes en attente. liste des moduleimpls avec notes en attente.
""" """
# sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
# inscr = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, # inscr = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context,
# args={"formsemestre_id": formsemestre_id} # args={"formsemestre_id": formsemestre_id}
# ) # )
# etudids = [x["etudid"] for x in inscr] # etudids = [x["etudid"] for x in inscr]
@ -390,7 +393,9 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id):
mods_att = [] mods_att = []
expr_diags = [] expr_diags = []
for modimpl in modimpls: for modimpl in modimpls:
mod = sco_edit_module.do_module_list(context, args={"module_id": modimpl["module_id"]})[0] mod = sco_edit_module.do_module_list(
context, args={"module_id": modimpl["module_id"]}
)[0]
modimpl["module"] = mod # add module dict to moduleimpl (used by nt) modimpl["module"] = mod # add module dict to moduleimpl (used by nt)
moduleimpl_id = modimpl["moduleimpl_id"] moduleimpl_id = modimpl["moduleimpl_id"]
assert not D.has_key(moduleimpl_id) assert not D.has_key(moduleimpl_id)

View File

@ -4,14 +4,19 @@
"""essai: ceci serait un module scodoc/sco_xxx.py """essai: ceci serait un module scodoc/sco_xxx.py
""" """
import time
import thread
import types import types
from flask import url_for from flask import url_for
import sco_utils as scu import sco_utils as scu
from notes_table import NOTES_CACHE_INST, CacheNotesTable from notes_log import log
from scodoc_manager import sco_mgr from scodoc_manager import sco_mgr
from sco_exceptions import ScoInvalidDept from sco_exceptions import ScoInvalidDept, NoteProcessError
from sco_parcours_dut import list_formsemestre_utilisateurs_uecap
import sco_cache
import sco_core
def sco_get_version(context, REQUEST=None): def sco_get_version(context, REQUEST=None):
@ -19,30 +24,32 @@ def sco_get_version(context, REQUEST=None):
return """<html><body><p>%s</p></body></html>""" % scu.SCOVERSION return """<html><body><p>%s</p></body></html>""" % scu.SCOVERSION
def test_refactor(context, x=1): # def test_refactor(context, x=1):
x = context.toto() # x = context.toto()
y = ("context=" + sco_edit_module.module_is_locked(context, "alpha")) + "23" # y = ("context=" + sco_edit_module.module_is_locked(context, "alpha")) + "23"
z = html_sco_header.sco_header( # z = html_sco_header.sco_header(
context, # context,
a_long_argument_hahahahaha=1, # a_long_argument_hahahahaha=1,
another_very_long_arggggggggggggg=2, # another_very_long_arggggggggggggg=2,
z=6, # z=6,
u=99, # u=99,
kkkkkk=1, # kkkkkk=1,
) # )
# #
# Cache global: chaque instance, repérée par sa connexion db, a un cache # Cache global: chaque instance, repérée par sa connexion db, a un cache
# qui est recréé à la demande # qui est recréé à la demande
# #
NOTES_CACHE_INST = {} # { db_cnx_string : CacheNotesTable instance }
CACHE_formsemestre_inscription = {} CACHE_formsemestre_inscription = {}
CACHE_evaluations = {} CACHE_evaluations = {}
# cache notes evaluations # cache notes evaluations
def get_evaluations_cache(context): def get_evaluations_cache(context):
"""returns cache for evaluations""" """returns cache for evaluations"""
u = context.GetDBConnexionString() u = sco_mgr.get_db_uri()
if CACHE_evaluations.has_key(u): if CACHE_evaluations.has_key(u):
return CACHE_evaluations[u] return CACHE_evaluations[u]
else: else:
@ -51,6 +58,183 @@ def get_evaluations_cache(context):
return CACHE_evaluations[u] return CACHE_evaluations[u]
class CacheNotesTable:
"""gestion rudimentaire de cache pour les NotesTables"""
def __init__(self):
log("new CacheTable (id=%s)" % id(self))
#
self.lock = thread.allocate_lock()
self.owner_thread = None # thread owning this cache
self.nref = 0
# Cache des NotesTables
self.cache = {} # { formsemestre_id : NoteTable instance }
# Cache des classeur PDF (bulletins)
self.pdfcache = {} # { formsemestre_id : (filename, pdfdoc) }
# Listeners:
self.listeners = scu.DictDefault(
defaultvalue={}
) # {formsemestre_id : {listener_id : callback }}
def acquire(self):
"If this thread does not own the cache, acquire the lock"
if thread.get_ident() != self.owner_thread:
if self.lock.locked():
log(
"acquire: ident=%s waiting for lock" % thread.get_ident()
) # XXX debug
self.lock.acquire()
self.owner_thread = thread.get_ident()
if self.owner_thread is None: # bug catching
log("WARNING: None thread id !")
self.nref += 1
# log('nref=%d' % self.nref)
def release(self):
"Release the lock"
cur_owner_thread = self.owner_thread
# log('release: ident=%s (nref=%d)' % (thread.get_ident(), self.nref))
self.nref -= 1
if self.nref == 0:
self.lock.release()
self.owner_thread = None
# Debug:
if thread.get_ident() != cur_owner_thread:
log(
"WARNING: release: ident=%s != owner=%s nref=%d"
% (thread.get_ident(), cur_owner_thread, self.nref)
)
raise NoteProcessError("problem with notes cache")
def get_NotesTable(self, context, formsemestre_id): # >
import notes_table
try:
self.acquire()
if self.cache.has_key(formsemestre_id):
# log('cache hit %s (id=%s, thread=%s)'
# % (formsemestre_id, id(self), thread.get_ident()))
return self.cache[formsemestre_id]
else:
t0 = time.time()
nt = notes_table.NotesTable(context, formsemestre_id)
dt = time.time() - t0
self.cache[formsemestre_id] = nt
log(
"caching formsemestre_id=%s (id=%s) (%gs)"
% (formsemestre_id, id(self), dt)
)
return nt
finally:
self.release()
def get_cached_formsemestre_ids(self):
"List of currently cached formsemestre_id"
return self.cache.keys()
def inval_cache(self, context, formsemestre_id=None, pdfonly=False): # >
"expire cache pour un semestre (ou tous si pas d'argument)"
log(
"inval_cache, formsemestre_id=%s pdfonly=%s (id=%s)"
% (formsemestre_id, pdfonly, id(self)) # >
)
try:
self.acquire()
if not hasattr(self, "pdfcache"):
self.pdfcache = {} # fix for old zope instances...
if formsemestre_id is None:
# clear all caches
log("----- inval_cache: clearing all caches -----")
# log('cache was containing ' + str(self.cache.keys()))
# logCallStack() # >>> DEBUG <<<
if not pdfonly:
self.cache = {}
self.pdfcache = {}
self._call_all_listeners()
sco_core.get_evaluations_cache(
context,
).inval_cache()
else:
# formsemestre_id modifié:
# on doit virer formsemestre_id et tous les semestres
# susceptibles d'utiliser des UE capitalisées de ce semestre.
to_trash = [formsemestre_id] + list_formsemestre_utilisateurs_uecap(
context, formsemestre_id
)
if not pdfonly:
for formsemestre_id in to_trash:
if self.cache.has_key(formsemestre_id):
log(
"delete %s from cache (id=%s)"
% (formsemestre_id, id(self))
)
del self.cache[formsemestre_id]
self._call_listeners(formsemestre_id)
sco_core.get_evaluations_cache(
context,
).inval_cache()
for formsemestre_id in to_trash:
for (
cached_formsemestre_id,
cached_version,
) in self.pdfcache.keys():
if cached_formsemestre_id == formsemestre_id:
log(
"delete pdfcache[(%s,%s)]"
% (formsemestre_id, cached_version)
)
del self.pdfcache[(formsemestre_id, cached_version)]
finally:
self.release()
def store_bulletins_pdf(self, formsemestre_id, version, filename, pdfdoc):
"cache pdf data"
log(
"caching PDF formsemestre_id=%s version=%s (id=%s)"
% (formsemestre_id, version, id(self))
)
try:
self.acquire()
self.pdfcache[(formsemestre_id, version)] = (filename, pdfdoc)
finally:
self.release()
def get_bulletins_pdf(self, formsemestre_id, version):
"returns cached PDF, or None if not in the cache"
try:
self.acquire()
if not hasattr(self, "pdfcache"):
self.pdfcache = {} # fix for old zope instances...
r = self.pdfcache.get((formsemestre_id, version), None)
if r:
log(
"get_bulletins_pdf(%s): cache hit %s (id=%s, thread=%s)"
% (version, formsemestre_id, id(self), thread.get_ident())
)
return r
finally:
self.release()
def add_listener(self, callback, formsemestre_id, listener_id):
"""Add a "listener": a function called each time a formsemestre is modified"""
self.listeners[formsemestre_id][listener_id] = callback
def remove_listener(self, formsemestre_id, listener_id):
"""Remove a listener.
May raise exception if does not exists.
"""
del self.listeners[formsemestre_id][listener_id]
def _call_listeners(self, formsemestre_id):
for listener_id, callback in self.listeners[formsemestre_id].items():
callback(listener_id)
def _call_all_listeners(self):
for formsemestre_id in self.listeners:
self._call_listeners(formsemestre_id)
def get_notes_cache(context): def get_notes_cache(context):
"returns CacheNotesTable instance for us" "returns CacheNotesTable instance for us"
u = sco_mgr.get_db_uri() # identifie le dept de facon unique u = sco_mgr.get_db_uri() # identifie le dept de facon unique
@ -81,7 +265,7 @@ def inval_cache(
# Cache inscriptions semestres # Cache inscriptions semestres
def get_formsemestre_inscription_cache(context, format=None): def get_formsemestre_inscription_cache(context, format=None):
u = context.GetDBConnexionString() u = sco_mgr.get_db_uri()
if CACHE_formsemestre_inscription.has_key(u): if CACHE_formsemestre_inscription.has_key(u):
return CACHE_formsemestre_inscription[u] return CACHE_formsemestre_inscription[u]
else: else:

View File

@ -33,6 +33,8 @@ import sco_utils as scu
from notes_log import log from notes_log import log
from TrivialFormulator import TrivialFormulator, TF, tf_error_message from TrivialFormulator import TrivialFormulator, TF, tf_error_message
import sco_codes_parcours import sco_codes_parcours
import sco_edit_module
import sco_edit_ue
import sco_formsemestre import sco_formsemestre
from sco_exceptions import ScoValueError from sco_exceptions import ScoValueError
import sco_formations import sco_formations
@ -305,3 +307,69 @@ def do_formation_edit(context, args):
sco_core.inval_cache( sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"] context, formsemestre_id=sem["formsemestre_id"]
) # > formation modif. ) # > formation modif.
def module_move(context, module_id, after=0, REQUEST=None, redirect=1):
"""Move before/after previous one (decrement/increment numero)"""
module = sco_edit_module.do_module_list(context, {"module_id": module_id})[0]
redirect = int(redirect)
after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1):
raise ValueError('invalid value for "after"')
formation_id = module["formation_id"]
others = sco_edit_module.do_module_list(
context, {"matiere_id": module["matiere_id"]}
)
# log('others=%s' % others)
if len(others) > 1:
idx = [p["module_id"] for p in others].index(module_id)
# log('module_move: after=%s idx=%s' % (after, idx))
neigh = None # object to swap with
if after == 0 and idx > 0:
neigh = others[idx - 1]
elif after == 1 and idx < len(others) - 1:
neigh = others[idx + 1]
if neigh: #
# swap numero between partition and its neighbor
# log('moving module %s' % module_id)
cnx = ndb.GetDBConnexion()
module["numero"], neigh["numero"] = neigh["numero"], module["numero"]
if module["numero"] == neigh["numero"]:
neigh["numero"] -= 2 * after - 1
sco_edit_module._moduleEditor.edit(cnx, module)
sco_edit_module._moduleEditor.edit(cnx, neigh)
# redirect to ue_list page:
if redirect:
return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id)
def ue_move(context, ue_id, after=0, REQUEST=None, redirect=1):
"""Move UE before/after previous one (decrement/increment numero)"""
o = sco_edit_ue.do_ue_list(context, {"ue_id": ue_id})[0]
# log('ue_move %s (#%s) after=%s' % (ue_id, o['numero'], after))
redirect = int(redirect)
after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1):
raise ValueError('invalid value for "after"')
formation_id = o["formation_id"]
others = sco_edit_ue.do_ue_list(context, {"formation_id": formation_id})
if len(others) > 1:
idx = [p["ue_id"] for p in others].index(ue_id)
neigh = None # object to swap with
if after == 0 and idx > 0:
neigh = others[idx - 1]
elif after == 1 and idx < len(others) - 1:
neigh = others[idx + 1]
if neigh: #
# swap numero between partition and its neighbor
# log('moving ue %s (neigh #%s)' % (ue_id, neigh['numero']))
cnx = ndb.GetDBConnexion()
o["numero"], neigh["numero"] = neigh["numero"], o["numero"]
if o["numero"] == neigh["numero"]:
neigh["numero"] -= 2 * after - 1
sco_edit_ue._ueEditor.edit(cnx, o)
sco_edit_ue._ueEditor.edit(cnx, neigh)
# redirect to ue_list page
if redirect:
return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + o["formation_id"])

View File

@ -77,13 +77,13 @@ def do_ue_create(context, args, REQUEST):
"create an ue" "create an ue"
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
# check duplicates # check duplicates
ues = do_ue_list(context, ues = do_ue_list(
{"formation_id": args["formation_id"], "acronyme": args["acronyme"]} context, {"formation_id": args["formation_id"], "acronyme": args["acronyme"]}
) )
if ues: if ues:
raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"]) raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"])
# create # create
r = context._ueEditor.create(cnx, args) r = _ueEditor.create(cnx, args)
# news # news
F = sco_formations.formation_list( F = sco_formations.formation_list(
@ -148,7 +148,7 @@ def do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=F
context, "DELETE FROM scolar_events WHERE ue_id=%(ue_id)s", {"ue_id": ue_id} context, "DELETE FROM scolar_events WHERE ue_id=%(ue_id)s", {"ue_id": ue_id}
) )
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
context._ueEditor.delete(cnx, ue_id) _ueEditor.delete(cnx, ue_id)
# > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?): # > UE delete + supr. validations associées etudiants (cas compliqué, mais rarement utilisé: acceptable de tout invalider ?):
sco_core.inval_cache(context) sco_core.inval_cache(context)
# news # news
@ -332,12 +332,15 @@ def ue_edit(context, ue_id=None, create=False, formation_id=None, REQUEST=None):
ue_id = do_ue_create(context, tf[2], REQUEST) ue_id = do_ue_create(context, tf[2], REQUEST)
if parcours.UE_IS_MODULE or tf[2]["create_matiere"]: if parcours.UE_IS_MODULE or tf[2]["create_matiere"]:
matiere_id = sco_edit_matiere.do_matiere_create(context, matiere_id = sco_edit_matiere.do_matiere_create(
{"ue_id": ue_id, "titre": tf[2]["titre"], "numero": 1}, REQUEST context,
{"ue_id": ue_id, "titre": tf[2]["titre"], "numero": 1},
REQUEST,
) )
if parcours.UE_IS_MODULE: if parcours.UE_IS_MODULE:
# dans ce mode, crée un (unique) module dans l'UE: # dans ce mode, crée un (unique) module dans l'UE:
_ = sco_edit_module.do_module_create(context, _ = sco_edit_module.do_module_create(
context,
{ {
"titre": tf[2]["titre"], "titre": tf[2]["titre"],
"code": tf[2]["acronyme"], "code": tf[2]["acronyme"],
@ -625,7 +628,9 @@ Si vous souhaitez modifier cette formation (par exemple pour y ajouter un module
H.append("</a>") H.append("</a>")
H.append('<ul class="notes_module_list">') H.append('<ul class="notes_module_list">')
Modlist = sco_edit_module.do_module_list(context, args={"matiere_id": Mat["matiere_id"]}) Modlist = sco_edit_module.do_module_list(
context, args={"matiere_id": Mat["matiere_id"]}
)
im = 0 im = 0
for Mod in Modlist: for Mod in Modlist:
Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls( Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls(
@ -877,8 +882,8 @@ def do_ue_edit(context, args, bypass_lock=False, dont_invalidate_cache=False):
# check: acronyme unique dans cette formation # check: acronyme unique dans cette formation
if args.has_key("acronyme"): if args.has_key("acronyme"):
new_acro = args["acronyme"] new_acro = args["acronyme"]
ues = do_ue_list(context, ues = do_ue_list(
{"formation_id": ue["formation_id"], "acronyme": new_acro} context, {"formation_id": ue["formation_id"], "acronyme": new_acro}
) )
if ues and ues[0]["ue_id"] != ue_id: if ues and ues[0]["ue_id"] != ue_id:
raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"]) raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"])
@ -888,7 +893,7 @@ def do_ue_edit(context, args, bypass_lock=False, dont_invalidate_cache=False):
del args["ue_code"] del args["ue_code"]
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
context._ueEditor.edit(cnx, args) _ueEditor.edit(cnx, args)
if not dont_invalidate_cache: if not dont_invalidate_cache:
# Invalide les semestres utilisant cette formation: # Invalide les semestres utilisant cette formation:
@ -950,7 +955,9 @@ def formation_table_recap(context, formation_id, format="html", REQUEST=None):
for UE in ue_list: for UE in ue_list:
Matlist = sco_edit_matiere.do_matiere_list(context, args={"ue_id": UE["ue_id"]}) Matlist = sco_edit_matiere.do_matiere_list(context, args={"ue_id": UE["ue_id"]})
for Mat in Matlist: for Mat in Matlist:
Modlist = sco_edit_module.do_module_list(context, args={"matiere_id": Mat["matiere_id"]}) Modlist = sco_edit_module.do_module_list(
context, args={"matiere_id": Mat["matiere_id"]}
)
for Mod in Modlist: for Mod in Modlist:
Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls( Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls(
context, Mod["module_id"] context, Mod["module_id"]

View File

@ -83,11 +83,121 @@ def ListMedian(L):
# -------------------------------------------------------------------- # --------------------------------------------------------------------
_evaluationEditor = ndb.EditableTable(
"notes_evaluation",
"evaluation_id",
(
"evaluation_id",
"moduleimpl_id",
"jour",
"heure_debut",
"heure_fin",
"description",
"note_max",
"coefficient",
"visibulletin",
"publish_incomplete",
"evaluation_type",
"numero",
),
sortkey="numero desc, jour desc, heure_debut desc", # plus recente d'abord
output_formators={
"jour": ndb.DateISOtoDMY,
"visibulletin": str,
"publish_incomplete": str,
"numero": ndb.int_null_is_zero,
},
input_formators={
"jour": ndb.DateDMYtoISO,
"heure_debut": ndb.TimetoISO8601, # converti par do_evaluation_list
"heure_fin": ndb.TimetoISO8601, # converti par do_evaluation_list
"visibulletin": int,
"publish_incomplete": int,
},
)
def do_evaluation_list(context, args, sortkey=None):
"""List evaluations, sorted by numero (or most recent date first).
Ajoute les champs:
'duree' : '2h30'
'matin' : 1 (commence avant 12:00) ou 0
'apresmidi' : 1 (termine après 12:00) ou 0
'descrheure' : ' de 15h00 à 16h30'
"""
cnx = ndb.GetDBConnexion()
evals = _evaluationEditor.list(cnx, args, sortkey=sortkey)
# calcule duree (chaine de car.) de chaque evaluation et ajoute jouriso, matin, apresmidi
for e in evals:
heure_debut_dt = e["heure_debut"] or datetime.time(
8, 00
) # au cas ou pas d'heure (note externe?)
heure_fin_dt = e["heure_fin"] or datetime.time(8, 00)
e["heure_debut"] = ndb.TimefromISO8601(e["heure_debut"])
e["heure_fin"] = ndb.TimefromISO8601(e["heure_fin"])
e["jouriso"] = ndb.DateDMYtoISO(e["jour"])
heure_debut, heure_fin = e["heure_debut"], e["heure_fin"]
d = ndb.TimeDuration(heure_debut, heure_fin)
if d is not None:
m = d % 60
e["duree"] = "%dh" % (d / 60)
if m != 0:
e["duree"] += "%02d" % m
else:
e["duree"] = ""
if heure_debut and (not heure_fin or heure_fin == heure_debut):
e["descrheure"] = " à " + heure_debut
elif heure_debut and heure_fin:
e["descrheure"] = " de %s à %s" % (heure_debut, heure_fin)
else:
e["descrheure"] = ""
# matin, apresmidi: utile pour se referer aux absences:
if heure_debut_dt < datetime.time(12, 00):
e["matin"] = 1
else:
e["matin"] = 0
if heure_fin_dt > datetime.time(12, 00):
e["apresmidi"] = 1
else:
e["apresmidi"] = 0
return evals
def do_evaluation_list_in_formsemestre(context, formsemestre_id):
"list evaluations in this formsemestre"
mods = sco_moduleimpl.do_moduleimpl_list(context, formsemestre_id=formsemestre_id)
evals = []
for mod in mods:
evals += sco_evaluations.do_evaluation_list(
context, args={"moduleimpl_id": mod["moduleimpl_id"]}
)
return evals
def do_evaluation_edit(context, REQUEST, args):
"edit an evaluation"
evaluation_id = args["evaluation_id"]
the_evals = do_evaluation_list(context, {"evaluation_id": evaluation_id})
if not the_evals:
raise ValueError("evaluation inexistante !")
moduleimpl_id = the_evals[0]["moduleimpl_id"]
args["moduleimpl_id"] = moduleimpl_id
context._check_evaluation_args(args)
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
cnx = ndb.GetDBConnexion()
context._evaluationEditor.edit(cnx, args)
# inval cache pour ce semestre
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
sco_core.inval_cache(
context, formsemestre_id=M["formsemestre_id"]
) # > evaluation_edit (coef, ...)
def do_evaluation_delete(context, REQUEST, evaluation_id): def do_evaluation_delete(context, REQUEST, evaluation_id):
"delete evaluation" "delete evaluation"
the_evals = context.do_evaluation_list({"evaluation_id": evaluation_id}) the_evals = do_evaluation_list(context, {"evaluation_id": evaluation_id})
if not the_evals: if not the_evals:
raise ValueError("evaluation inexistante !") raise ValueError("evaluation inexistante !")
@ -164,7 +274,7 @@ def do_evaluation_etat(
else: else:
last_modif = None last_modif = None
# ---- Liste des groupes complets et incomplets # ---- Liste des groupes complets et incomplets
E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] E = do_evaluation_list(context, args={"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0]
is_malus = Mod["module_type"] == scu.MODULE_MALUS # True si module de malus is_malus = Mod["module_type"] == scu.MODULE_MALUS # True si module de malus
@ -530,7 +640,7 @@ def evaluation_date_first_completion(context, evaluation_id):
# Il faut considerer les inscriptions au semestre # Il faut considerer les inscriptions au semestre
# (pour avoir l'etat et le groupe) et aussi les inscriptions # (pour avoir l'etat et le groupe) et aussi les inscriptions
# au module (pour gerer les modules optionnels correctement) # au module (pour gerer les modules optionnels correctement)
# E = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] # E = do_evaluation_list(context, args={"evaluation_id": evaluation_id})[0]
# M = sco_moduleimpl.do_moduleimpl_list(context,moduleimpl_id=E["moduleimpl_id"])[0] # M = sco_moduleimpl.do_moduleimpl_list(context,moduleimpl_id=E["moduleimpl_id"])[0]
# formsemestre_id = M["formsemestre_id"] # formsemestre_id = M["formsemestre_id"]
# insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id) # insem = context.do_formsemestre_inscription_listinscrits(formsemestre_id)
@ -576,7 +686,9 @@ def formsemestre_evaluations_delai_correction(
M = sco_moduleimpl.do_moduleimpl_list( M = sco_moduleimpl.do_moduleimpl_list(
context, moduleimpl_id=e["moduleimpl_id"] context, moduleimpl_id=e["moduleimpl_id"]
)[0] )[0]
Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.do_module_list(
context, args={"module_id": M["module_id"]}
)[0]
if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or ( if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or (
Mod["module_type"] == scu.MODULE_MALUS Mod["module_type"] == scu.MODULE_MALUS
): ):
@ -644,8 +756,8 @@ def module_evaluation_insert_before(context, ModEvals, next_eval, REQUEST):
if not n: if not n:
log("renumbering old evals") log("renumbering old evals")
module_evaluation_renumber(context, next_eval["moduleimpl_id"], REQUEST) module_evaluation_renumber(context, next_eval["moduleimpl_id"], REQUEST)
next_eval = context.do_evaluation_list( next_eval = do_evaluation_list(
args={"evaluation_id": next_eval["evaluation_id"]} context, args={"evaluation_id": next_eval["evaluation_id"]}
)[0] )[0]
n = next_eval["numero"] n = next_eval["numero"]
else: else:
@ -656,7 +768,7 @@ def module_evaluation_insert_before(context, ModEvals, next_eval, REQUEST):
if e["numero"] >= n: if e["numero"] >= n:
e["numero"] += 1 e["numero"] += 1
# log('incrementing %s to %s' % (e['evaluation_id'], e['numero'])) # log('incrementing %s to %s' % (e['evaluation_id'], e['numero']))
context.do_evaluation_edit(REQUEST, e) do_evaluation_edit(context, REQUEST, e)
return n return n
@ -665,7 +777,7 @@ def module_evaluation_move(context, evaluation_id, after=0, REQUEST=None, redire
"""Move before/after previous one (decrement/increment numero) """Move before/after previous one (decrement/increment numero)
(published) (published)
""" """
e = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] e = do_evaluation_list(context, args={"evaluation_id": evaluation_id})[0]
redirect = int(redirect) redirect = int(redirect)
# access: can change eval ? (raises exception) # access: can change eval ? (raises exception)
@ -674,12 +786,12 @@ def module_evaluation_move(context, evaluation_id, after=0, REQUEST=None, redire
module_evaluation_renumber( module_evaluation_renumber(
context, e["moduleimpl_id"], REQUEST=REQUEST, only_if_unumbered=True context, e["moduleimpl_id"], REQUEST=REQUEST, only_if_unumbered=True
) )
e = context.do_evaluation_list(args={"evaluation_id": evaluation_id})[0] e = do_evaluation_list(context, args={"evaluation_id": evaluation_id})[0]
after = int(after) # 0: deplace avant, 1 deplace apres after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1): if after not in (0, 1):
raise ValueError('invalid value for "after"') raise ValueError('invalid value for "after"')
ModEvals = context.do_evaluation_list({"moduleimpl_id": e["moduleimpl_id"]}) ModEvals = do_evaluation_list(context, {"moduleimpl_id": e["moduleimpl_id"]})
# log('ModEvals=%s' % [ x['evaluation_id'] for x in ModEvals] ) # log('ModEvals=%s' % [ x['evaluation_id'] for x in ModEvals] )
if len(ModEvals) > 1: if len(ModEvals) > 1:
idx = [p["evaluation_id"] for p in ModEvals].index(evaluation_id) idx = [p["evaluation_id"] for p in ModEvals].index(evaluation_id)
@ -691,8 +803,8 @@ def module_evaluation_move(context, evaluation_id, after=0, REQUEST=None, redire
if neigh: # if neigh: #
# swap numero with neighbor # swap numero with neighbor
e["numero"], neigh["numero"] = neigh["numero"], e["numero"] e["numero"], neigh["numero"] = neigh["numero"], e["numero"]
context.do_evaluation_edit(REQUEST, e) do_evaluation_edit(context, REQUEST, e)
context.do_evaluation_edit(REQUEST, neigh) do_evaluation_edit(context, REQUEST, neigh)
# redirect to moduleimpl page: # redirect to moduleimpl page:
if redirect: if redirect:
return REQUEST.RESPONSE.redirect( return REQUEST.RESPONSE.redirect(
@ -711,8 +823,10 @@ def module_evaluation_renumber(
# log('module_evaluation_renumber( moduleimpl_id=%s )' % moduleimpl_id ) # log('module_evaluation_renumber( moduleimpl_id=%s )' % moduleimpl_id )
# List sorted according to date/heure, ignoring numeros: # List sorted according to date/heure, ignoring numeros:
# (note that we place evaluations with NULL date at the end) # (note that we place evaluations with NULL date at the end)
ModEvals = context.do_evaluation_list( ModEvals = do_evaluation_list(
args={"moduleimpl_id": moduleimpl_id}, sortkey="jour asc, heure_debut asc" context,
args={"moduleimpl_id": moduleimpl_id},
sortkey="jour asc, heure_debut asc",
) )
all_numbered = False not in [x["numero"] > 0 for x in ModEvals] all_numbered = False not in [x["numero"] > 0 for x in ModEvals]
@ -724,7 +838,7 @@ def module_evaluation_renumber(
i = 1 i = 1
for e in ModEvals: for e in ModEvals:
e["numero"] = i e["numero"] = i
context.do_evaluation_edit(REQUEST, e) do_evaluation_edit(context, REQUEST, e)
i += 1 i += 1
# If requested, redirect to moduleimpl page: # If requested, redirect to moduleimpl page:
@ -739,7 +853,7 @@ def evaluation_describe(context, evaluation_id="", edit_in_place=True, REQUEST=N
"""HTML description of evaluation, for page headers """HTML description of evaluation, for page headers
edit_in_place: allow in-place editing when permitted (not implemented) edit_in_place: allow in-place editing when permitted (not implemented)
""" """
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
moduleimpl_id = E["moduleimpl_id"] moduleimpl_id = E["moduleimpl_id"]
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0]
@ -816,7 +930,7 @@ def evaluation_create_form(
): ):
"formulaire creation/edition des evaluations (pas des notes)" "formulaire creation/edition des evaluations (pas des notes)"
if evaluation_id != None: if evaluation_id != None:
the_eval = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] the_eval = do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
moduleimpl_id = the_eval["moduleimpl_id"] moduleimpl_id = the_eval["moduleimpl_id"]
# #
M = sco_moduleimpl.do_moduleimpl_withmodule_list( M = sco_moduleimpl.do_moduleimpl_withmodule_list(
@ -1081,5 +1195,5 @@ def evaluation_create_form(
evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **tf[2]) evaluation_id = context.do_evaluation_create(REQUEST=REQUEST, **tf[2])
return REQUEST.RESPONSE.redirect(dest_url) return REQUEST.RESPONSE.redirect(dest_url)
else: else:
context.do_evaluation_edit(REQUEST, tf[2]) do_evaluation_edit(context, REQUEST, tf[2])
return REQUEST.RESPONSE.redirect(dest_url) return REQUEST.RESPONSE.redirect(dest_url)

View File

@ -37,7 +37,7 @@ from TrivialFormulator import TrivialFormulator, TF
import notes_table import notes_table
from sco_exceptions import AccessDenied, ScoValueError from sco_exceptions import AccessDenied, ScoValueError
from sco_formsemestre import ApoEtapeVDI from sco_formsemestre import ApoEtapeVDI
from sco_permissions import ScoImplement from sco_permissions import Permission
import sco_codes_parcours import sco_codes_parcours
import sco_compute_moy import sco_compute_moy
import sco_formsemestre import sco_formsemestre
@ -197,7 +197,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
for ue in uelist: for ue in uelist:
matlist = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue["ue_id"]}) matlist = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue["ue_id"]})
for mat in matlist: for mat in matlist:
modsmat = sco_edit_module.do_module_list(context, {"matiere_id": mat["matiere_id"]}) modsmat = sco_edit_module.do_module_list(
context, {"matiere_id": mat["matiere_id"]}
)
# XXX debug checks # XXX debug checks
for m in modsmat: for m in modsmat:
if m["ue_id"] != ue["ue_id"]: if m["ue_id"] != ue["ue_id"]:
@ -747,7 +749,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
"responsable_id": tf[2][module_id], "responsable_id": tf[2][module_id],
} }
moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs) moduleimpl_id = sco_moduleimpl.do_moduleimpl_create(context, modargs)
mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[
0
]
msg += ["création de %s (%s)" % (mod["code"], mod["titre"])] msg += ["création de %s (%s)" % (mod["code"], mod["titre"])]
# INSCRIPTIONS DES ETUDIANTS # INSCRIPTIONS DES ETUDIANTS
log( log(
@ -798,7 +802,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
sco_moduleimpl.do_moduleimpl_edit( sco_moduleimpl.do_moduleimpl_edit(
context, modargs, formsemestre_id=formsemestre_id context, modargs, formsemestre_id=formsemestre_id
) )
mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[
0
]
if msg: if msg:
msg_html = ( msg_html = (
@ -836,7 +842,9 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del)
)[0]["moduleimpl_id"] )[0]["moduleimpl_id"]
mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0] mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0]
# Evaluations dans ce module ? # Evaluations dans ce module ?
evals = context.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) evals = sco_evaluations.do_evaluation_list(
context, {"moduleimpl_id": moduleimpl_id}
)
if evals: if evals:
msg += [ msg += [
'<b>impossible de supprimer %s (%s) car il y a %d évaluations définies (<a href="moduleimpl_status?moduleimpl_id=%s" class="stdlink">supprimer les d\'abord</a>)</b>' '<b>impossible de supprimer %s (%s) car il y a %d évaluations définies (<a href="moduleimpl_status?moduleimpl_id=%s" class="stdlink">supprimer les d\'abord</a>)</b>'
@ -1020,8 +1028,8 @@ def do_formsemestre_clone(
sco_moduleimpl.do_ens_create(context, args) sco_moduleimpl.do_ens_create(context, args)
# optionally, copy evaluations # optionally, copy evaluations
if clone_evaluations: if clone_evaluations:
evals = context.do_evaluation_list( evals = sco_evaluations.do_evaluation_list(
args={"moduleimpl_id": mod_orig["moduleimpl_id"]} context, args={"moduleimpl_id": mod_orig["moduleimpl_id"]}
) )
for e in evals: for e in evals:
args = e.copy() args = e.copy()
@ -1109,7 +1117,9 @@ def formsemestre_associate_new_version(
if not dialog_confirmed: if not dialog_confirmed:
# dresse le liste des semestres de la meme formation et version # dresse le liste des semestres de la meme formation et version
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
othersems = sco_formsemestre.do_formsemestre_list( othersems = sco_formsemestre.do_formsemestre_list(
context, context,
args={ args={
@ -1227,7 +1237,9 @@ def _reassociate_moduleimpls(
def formsemestre_delete(context, formsemestre_id, REQUEST=None): def formsemestre_delete(context, formsemestre_id, REQUEST=None):
"""Delete a formsemestre (affiche avertissements)""" """Delete a formsemestre (affiche avertissements)"""
sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id)
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
H = [ H = [
html_sco_header.html_sem_header( html_sco_header.html_sem_header(
context, REQUEST, "Suppression du semestre", sem context, REQUEST, "Suppression du semestre", sem
@ -1244,7 +1256,7 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
</ol></div>""", </ol></div>""",
] ]
evals = context.do_evaluation_list_in_formsemestre(formsemestre_id) evals = sco_evaluations.do_evaluation_list_in_formsemestre(context, formsemestre_id)
if evals: if evals:
H.append( H.append(
"""<p class="warning">Attention: il y a %d évaluations dans ce semestre (sa suppression entrainera l'effacement définif des notes) !</p>""" """<p class="warning">Attention: il y a %d évaluations dans ce semestre (sa suppression entrainera l'effacement définif des notes) !</p>"""
@ -1324,7 +1336,9 @@ def do_formsemestre_delete(context, formsemestre_id, REQUEST):
mods = context.do_moduleimpl_list(formsemestre_id=formsemestre_id) mods = context.do_moduleimpl_list(formsemestre_id=formsemestre_id)
for mod in mods: for mod in mods:
# evaluations # evaluations
evals = context.do_evaluation_list(args={"moduleimpl_id": mod["moduleimpl_id"]}) evals = sco_evaluations.do_evaluation_list(
context, args={"moduleimpl_id": mod["moduleimpl_id"]}
)
for e in evals: for e in evals:
ndb.SimpleQuery( ndb.SimpleQuery(
context, context,

View File

@ -29,31 +29,32 @@
""" """
# Rewritten from ancient DTML code # Rewritten from ancient DTML code
from flask import current_app
from notes_log import log from notes_log import log
import sco_utils as scu import sco_utils as scu
import notesdb as ndb import notesdb as ndb
from sco_permissions import ( from sco_permissions import Permission
ScoImplement,
ScoChangeFormation,
ScoEtudInscrit,
ScoView,
ScoEtudChangeAdr,
)
from sco_exceptions import ScoValueError from sco_exceptions import ScoValueError
import VERSION import VERSION
import htmlutils import htmlutils
from sco_formsemestre_custommenu import formsemestre_custommenu_html from sco_formsemestre_custommenu import formsemestre_custommenu_html
from gen_tables import GenTable from gen_tables import GenTable
import html_sco_header
import sco_archives import sco_archives
import sco_groups import sco_bulletins
import sco_codes_parcours
import sco_core
import sco_compute_moy
import sco_evaluations import sco_evaluations
import sco_formations
import sco_formsemestre import sco_formsemestre
import sco_formsemestre_edit import sco_formsemestre_edit
import sco_groups
import sco_moduleimpl import sco_moduleimpl
import sco_compute_moy import sco_formsemestre_inscriptions
import sco_codes_parcours import sco_permissions
import sco_bulletins import sco_preferences
# H = [ """<span class="barrenav"><ul class="nav"> # H = [ """<span class="barrenav"><ul class="nav">
@ -140,7 +141,9 @@ def formsemestre_status_menubar(context, sem, REQUEST):
else: else:
change_lock_msg = "Déverrouiller" change_lock_msg = "Déverrouiller"
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
menuSemestre = [ menuSemestre = [
{ {
@ -247,7 +250,7 @@ def formsemestre_status_menubar(context, sem, REQUEST):
}, },
] ]
# debug : # debug :
if app.config["ENV"] == "development": if current_app.config["ENV"] == "development":
menuSemestre.append( menuSemestre.append(
{ {
"title": "Check integrity", "title": "Check integrity",
@ -311,7 +314,7 @@ def formsemestre_status_menubar(context, sem, REQUEST):
"title": "Exporter table des étudiants", "title": "Exporter table des étudiants",
"endpoint": "notes.groups_view", "endpoint": "notes.groups_view",
"args": { "args": {
"format": allxls, "format": "allxls",
"group_ids": sco_groups.get_default_group( "group_ids": sco_groups.get_default_group(
context, formsemestre_id, fix_if_missing=True, REQUEST=REQUEST context, formsemestre_id, fix_if_missing=True, REQUEST=REQUEST
), ),
@ -474,7 +477,9 @@ def retreive_formsemestre_from_request(context, REQUEST):
modimpl = modimpl[0] modimpl = modimpl[0]
formsemestre_id = modimpl["formsemestre_id"] formsemestre_id = modimpl["formsemestre_id"]
elif REQUEST.form.has_key("evaluation_id"): elif REQUEST.form.has_key("evaluation_id"):
E = context.do_evaluation_list({"evaluation_id": REQUEST.form["evaluation_id"]}) E = sco_evaluations.do_evaluation_list(
context, {"evaluation_id": REQUEST.form["evaluation_id"]}
)
if not E: if not E:
return None # evaluation suppressed ? return None # evaluation suppressed ?
E = E[0] E = E[0]
@ -563,7 +568,9 @@ def fill_formsemestre(context, sem, REQUEST=None):
) )
else: else:
sem["eyelink"] = "" sem["eyelink"] = ""
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
sem["formation"] = F sem["formation"] = F
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
if sem["semestre_id"] != -1: if sem["semestre_id"] != -1:
@ -579,8 +586,8 @@ def fill_formsemestre(context, sem, REQUEST=None):
sco_formsemestre.formsemestre_etape_apo_str(sem) or "Pas de code étape" sco_formsemestre.formsemestre_etape_apo_str(sem) or "Pas de code étape"
) )
inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
args={"formsemestre_id": formsemestre_id} context, args={"formsemestre_id": formsemestre_id}
) )
sem["nbinscrits"] = len(inscrits) sem["nbinscrits"] = len(inscrits)
uresps = [ uresps = [
@ -605,7 +612,9 @@ def formsemestre_description_table(
use_ue_coefs = sco_preferences.get_preference( use_ue_coefs = sco_preferences.get_preference(
context, "use_ue_coefs", formsemestre_id context, "use_ue_coefs", formsemestre_id
) )
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list(
context, formsemestre_id=formsemestre_id context, formsemestre_id=formsemestre_id
@ -912,7 +921,9 @@ def formsemestre_status_head(
if not semlist: if not semlist:
raise ScoValueError("Session inexistante (elle a peut être été supprimée ?)") raise ScoValueError("Session inexistante (elle a peut être été supprimée ?)")
sem = semlist[0] sem = semlist[0]
F = sco_formations.formation_list(context, args={"formation_id": sem["formation_id"]})[0] F = sco_formations.formation_list(
context, args={"formation_id": sem["formation_id"]}
)[0]
parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"])
page_title = page_title or "Modules de " page_title = page_title or "Modules de "
@ -977,7 +988,7 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list( Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list(
context, formsemestre_id=formsemestre_id context, formsemestre_id=formsemestre_id
) )
# inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, # inscrits = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context,
# args={"formsemestre_id": formsemestre_id} # args={"formsemestre_id": formsemestre_id}
# ) # )
prev_ue_id = None prev_ue_id = None

View File

@ -55,11 +55,11 @@ def do_evaluation_listenotes(context, REQUEST):
if REQUEST.form.has_key("evaluation_id"): if REQUEST.form.has_key("evaluation_id"):
evaluation_id = REQUEST.form["evaluation_id"] evaluation_id = REQUEST.form["evaluation_id"]
mode = "eval" mode = "eval"
evals = context.do_evaluation_list({"evaluation_id": evaluation_id}) evals = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})
if REQUEST.form.has_key("moduleimpl_id"): if REQUEST.form.has_key("moduleimpl_id"):
moduleimpl_id = REQUEST.form["moduleimpl_id"] moduleimpl_id = REQUEST.form["moduleimpl_id"]
mode = "module" mode = "module"
evals = context.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) evals = sco_evaluations.do_evaluation_list(context, {"moduleimpl_id": moduleimpl_id})
if not mode: if not mode:
raise ValueError("missing argument: evaluation or module") raise ValueError("missing argument: evaluation or module")
if not evals: if not evals:
@ -706,7 +706,7 @@ def evaluation_check_absences(context, evaluation_id):
EXC et pas justifie EXC et pas justifie
Ramene 3 listes d'etudid Ramene 3 listes d'etudid
""" """
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
if not E["jour"]: if not E["jour"]:
return [], [], [], [], [] # evaluation sans date return [], [], [], [], [] # evaluation sans date
@ -762,7 +762,7 @@ def evaluation_check_absences_html(
): ):
"""Affiche etat verification absences d'une evaluation""" """Affiche etat verification absences d'une evaluation"""
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
am, pm, demijournee = _eval_demijournee(E) am, pm, demijournee = _eval_demijournee(E)
( (
@ -877,7 +877,7 @@ def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
context, formsemestre_id=formsemestre_id context, formsemestre_id=formsemestre_id
) )
for M in Mlist: for M in Mlist:
evals = context.do_evaluation_list({"moduleimpl_id": M["moduleimpl_id"]}) evals = sco_evaluations.do_evaluation_list(context, {"moduleimpl_id": M["moduleimpl_id"]})
if evals: if evals:
H.append( H.append(
'<div class="module_check_absences"><h2><a href="moduleimpl_status?moduleimpl_id=%s">%s: %s</a></h2>' '<div class="module_check_absences"><h2><a href="moduleimpl_status?moduleimpl_id=%s">%s: %s</a></h2>'

View File

@ -37,6 +37,9 @@ from sco_permissions import ScoImplement
from sco_exceptions import ScoValueError, AccessDenied from sco_exceptions import ScoValueError, AccessDenied
from notes_log import log from notes_log import log
import scolog import scolog
import sco_edit_matiere
import sco_edit_module
import sco_edit_ue
import sco_formsemestre import sco_formsemestre
# --- Gestion des "Implémentations de Modules" # --- Gestion des "Implémentations de Modules"
@ -132,10 +135,14 @@ def do_moduleimpl_withmodule_list(
del args["REQUEST"] del args["REQUEST"]
modimpls = do_moduleimpl_list(context, **args) modimpls = do_moduleimpl_list(context, **args)
for mo in modimpls: for mo in modimpls:
mo["module"] = sco_edit_module.do_module_list(context, args={"module_id": mo["module_id"]})[0] mo["module"] = sco_edit_module.do_module_list(
mo["ue"] = sco_edit_ue.do_ue_list(context, args={"ue_id": mo["module"]["ue_id"]})[0] context, args={"module_id": mo["module_id"]}
mo["matiere"] = sco_edit_matiere.do_matiere_list(context, )[0]
args={"matiere_id": mo["module"]["matiere_id"]} mo["ue"] = sco_edit_ue.do_ue_list(
context, args={"ue_id": mo["module"]["ue_id"]}
)[0]
mo["matiere"] = sco_edit_matiere.do_matiere_list(
context, args={"matiere_id": mo["module"]["matiere_id"]}
)[0] )[0]
# tri par semestre/UE/numero_matiere/numero_module # tri par semestre/UE/numero_matiere/numero_module
@ -232,8 +239,8 @@ def do_moduleimpl_inscrit_etuds(
""" """
# Verifie qu'ils sont tous bien inscrits au semestre # Verifie qu'ils sont tous bien inscrits au semestre
for etudid in etudids: for etudid in etudids:
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
args={"formsemestre_id": formsemestre_id, "etudid": etudid} context, args={"formsemestre_id": formsemestre_id, "etudid": etudid}
) )
if not insem: if not insem:
raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid) raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid)

View File

@ -59,7 +59,7 @@ import sco_abs
# menu evaluation dans moduleimpl # menu evaluation dans moduleimpl
def moduleimpl_evaluation_menu(context, evaluation_id, nbnotes=0, REQUEST=None): def moduleimpl_evaluation_menu(context, evaluation_id, nbnotes=0, REQUEST=None):
"Menu avec actions sur une evaluation" "Menu avec actions sur une evaluation"
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
modimpl = sco_moduleimpl.do_moduleimpl_list( modimpl = sco_moduleimpl.do_moduleimpl_list(
context, moduleimpl_id=E["moduleimpl_id"] context, moduleimpl_id=E["moduleimpl_id"]
)[0] )[0]
@ -171,7 +171,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
nt = sco_core.get_notes_cache( nt = sco_core.get_notes_cache(
context, context,
).get_NotesTable(context, formsemestre_id) ).get_NotesTable(context, formsemestre_id)
ModEvals = context.do_evaluation_list({"moduleimpl_id": moduleimpl_id}) ModEvals = sco_evaluations.do_evaluation_list(context, {"moduleimpl_id": moduleimpl_id})
ModEvals.sort( ModEvals.sort(
key=lambda x: (x["numero"], x["jour"], x["heure_debut"]), reverse=True key=lambda x: (x["numero"], x["jour"], x["heure_debut"]), reverse=True
) # la plus RECENTE en tête ) # la plus RECENTE en tête

View File

@ -54,7 +54,7 @@ def do_placement_selectetuds(context, REQUEST):
Choisi les étudiants et les infos sur la salle pour leur placement. Choisi les étudiants et les infos sur la salle pour leur placement.
""" """
evaluation_id = REQUEST.form["evaluation_id"] evaluation_id = REQUEST.form["evaluation_id"]
E = context.do_evaluation_list({"evaluation_id": evaluation_id}) E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})
if not E: if not E:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
E = E[0] E = E[0]
@ -236,7 +236,7 @@ def do_placement(context, REQUEST):
raise ScoValueError( raise ScoValueError(
"Formulaire incomplet ! Vous avez sans doute attendu trop longtemps, veuillez vous reconnecter. Si le problème persiste, contacter l'administrateur. Merci." "Formulaire incomplet ! Vous avez sans doute attendu trop longtemps, veuillez vous reconnecter. Si le problème persiste, contacter l'administrateur. Merci."
) )
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
# Check access # Check access
# (admin, respformation, and responsable_id) # (admin, respformation, and responsable_id)
@ -395,7 +395,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 = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
theeval = evals[0] theeval = evals[0]

View File

@ -57,7 +57,6 @@ import htmlutils
import sco_excel import sco_excel
import scolars import scolars
import sco_news import sco_news
from sco_news import NEWS_INSCR, NEWS_NOTE, NEWS_FORM, NEWS_SEM, NEWS_MISC
def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True): def can_edit_notes(context, authuser, moduleimpl_id, allow_ens=True):
@ -198,7 +197,7 @@ def do_evaluation_upload_xls(context, REQUEST):
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
evaluation_id = REQUEST.form["evaluation_id"] evaluation_id = REQUEST.form["evaluation_id"]
comment = REQUEST.form["comment"] comment = REQUEST.form["comment"]
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_withmodule_list( M = sco_moduleimpl.do_moduleimpl_withmodule_list(
context, moduleimpl_id=E["moduleimpl_id"] context, moduleimpl_id=E["moduleimpl_id"]
)[0] )[0]
@ -276,17 +275,21 @@ def do_evaluation_upload_xls(context, REQUEST):
context, authuser, evaluation_id, L, comment context, authuser, evaluation_id, L, comment
) )
# news # news
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(
context, {"evaluation_id": evaluation_id}
)[0]
M = sco_moduleimpl.do_moduleimpl_list( M = sco_moduleimpl.do_moduleimpl_list(
context, moduleimpl_id=E["moduleimpl_id"] context, moduleimpl_id=E["moduleimpl_id"]
)[0] )[0]
mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] mod = sco_edit_module.do_module_list(
context, args={"module_id": M["module_id"]}
)[0]
mod["moduleimpl_id"] = M["moduleimpl_id"] mod["moduleimpl_id"] = M["moduleimpl_id"]
mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod
sco_news.add( sco_news.add(
context, context,
REQUEST, REQUEST,
typ=NEWS_NOTE, typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"], object=M["moduleimpl_id"],
text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % mod, text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % mod,
url=mod["url"], url=mod["url"],
@ -319,7 +322,7 @@ def do_evaluation_set_missing(
"""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 = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_withmodule_list( M = sco_moduleimpl.do_moduleimpl_withmodule_list(
context, moduleimpl_id=E["moduleimpl_id"] context, moduleimpl_id=E["moduleimpl_id"]
)[0] )[0]
@ -377,7 +380,7 @@ def do_evaluation_set_missing(
sco_news.add( sco_news.add(
context, context,
REQUEST, REQUEST,
typ=NEWS_NOTE, typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"], object=M["moduleimpl_id"],
text='Initialisation notes dans <a href="%(url)s">%(titre)s</a>' % mod, text='Initialisation notes dans <a href="%(url)s">%(titre)s</a>' % mod,
url=mod["url"], url=mod["url"],
@ -400,7 +403,7 @@ def do_evaluation_set_missing(
def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=False): def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=False):
"suppress all notes in this eval" "suppress all notes in this eval"
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
if can_edit_notes(context, authuser, E["moduleimpl_id"], allow_ens=False): if can_edit_notes(context, authuser, E["moduleimpl_id"], allow_ens=False):
# On a le droit de modifier toutes les notes # On a le droit de modifier toutes les notes
@ -453,7 +456,7 @@ def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=F
sco_news.add( sco_news.add(
context, context,
REQUEST, REQUEST,
typ=NEWS_NOTE, typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"], object=M["moduleimpl_id"],
text='Suppression des notes d\'une évaluation dans <a href="%(url)s">%(titre)s</a>' text='Suppression des notes d\'une évaluation dans <a href="%(url)s">%(titre)s</a>'
% mod, % mod,
@ -499,7 +502,7 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
cursor = cnx.cursor(cursor_factory=ScoDocCursor) cursor = cnx.cursor(cursor_factory=ScoDocCursor)
nb_changed = 0 nb_changed = 0
nb_suppress = 0 nb_suppress = 0
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
existing_decisions = ( existing_decisions = (
[] []
@ -603,7 +606,9 @@ 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) authusername = str(authuser)
evals = context.do_evaluation_list({"evaluation_id": evaluation_id}) evals = sco_evaluations.do_evaluation_list(
context, {"evaluation_id": evaluation_id}
)
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
E = evals[0] E = evals[0]
@ -779,7 +784,9 @@ 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 = sco_evaluations.do_evaluation_list(
context, {"evaluation_id": evaluation_id}
)
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
E = evals[0] E = evals[0]
@ -880,7 +887,9 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER authuser = REQUEST.AUTHENTICATED_USER
authusername = str(authuser) authusername = str(authuser)
evals = context.do_evaluation_list({"evaluation_id": evaluation_id}) evals = sco_evaluations.do_evaluation_list(
context, {"evaluation_id": evaluation_id}
)
if not evals: if not evals:
raise ScoValueError("invalid evaluation_id") raise ScoValueError("invalid evaluation_id")
E = evals[0] E = evals[0]
@ -1006,8 +1015,8 @@ def _get_sorted_etuds(context, E, etudids, formsemestre_id):
scolars.format_etud_ident(e) scolars.format_etud_ident(e)
etuds.append(e) etuds.append(e)
# infos inscription dans ce semestre # infos inscription dans ce semestre
e["inscr"] = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, e["inscr"] = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
{"etudid": etudid, "formsemestre_id": formsemestre_id} context, {"etudid": etudid, "formsemestre_id": formsemestre_id}
)[0] )[0]
# Groupes auxquels appartient cet étudiant: # Groupes auxquels appartient cet étudiant:
e["groups"] = sco_groups.get_etud_groups(context, etudid, sem) e["groups"] = sco_groups.get_etud_groups(context, etudid, sem)
@ -1247,7 +1256,7 @@ def save_note(
"save_note: evaluation_id=%s etudid=%s uid=%s value=%s" "save_note: evaluation_id=%s etudid=%s uid=%s value=%s"
% (evaluation_id, etudid, authuser, value) % (evaluation_id, etudid, authuser, value)
) )
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0] Mod = sco_edit_module.do_module_list(context, args={"module_id": M["module_id"]})[0]
Mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % M Mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % M
@ -1264,7 +1273,7 @@ def save_note(
sco_news.add( sco_news.add(
context, context,
REQUEST, REQUEST,
typ=NEWS_NOTE, typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"], object=M["moduleimpl_id"],
text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % Mod, text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % Mod,
url=Mod["url"], url=Mod["url"],

View File

@ -148,7 +148,7 @@ def external_ue_inscrit_et_note(
) )
# Création d'une évaluation si il n'y en a pas déjà: # Création d'une évaluation si il n'y en a pas déjà:
ModEvals = context.do_evaluation_list(args={"moduleimpl_id": moduleimpl_id}) ModEvals = sco_evaluations.do_evaluation_list(context, args={"moduleimpl_id": moduleimpl_id})
if len(ModEvals): if len(ModEvals):
# met la note dans le première évaluation existante: # met la note dans le première évaluation existante:
evaluation_id = ModEvals[0]["evaluation_id"] evaluation_id = ModEvals[0]["evaluation_id"]

View File

@ -139,7 +139,7 @@ def list_operations(context, evaluation_id):
def evaluation_list_operations(context, REQUEST, evaluation_id): def evaluation_list_operations(context, REQUEST, evaluation_id):
"""Page listing operations on evaluation""" """Page listing operations on evaluation"""
E = context.do_evaluation_list({"evaluation_id": evaluation_id})[0] E = sco_evaluations.do_evaluation_list(context, {"evaluation_id": evaluation_id})[0]
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=E["moduleimpl_id"])[0]
Ops = list_operations(context, evaluation_id) Ops = list_operations(context, evaluation_id)

View File

@ -421,7 +421,7 @@ def formation_list(context, format=None, REQUEST=None, formation_id=None, args={
"""List formation(s) with given id, or matching args """List formation(s) with given id, or matching args
(when args is given, formation_id is ignored). (when args is given, formation_id is ignored).
""" """
r = sco_formation.formation_list(context, formation_id=formation_id, args=args) r = sco_formations.formation_list(context, formation_id=formation_id, args=args)
return scu.sendResult(REQUEST, r, name="formation", format=format) return scu.sendResult(REQUEST, r, name="formation", format=format)
@ -573,82 +573,13 @@ sco_publish(
"/matiere_is_locked", sco_edit_matiere.matiere_is_locked, Permission.ScoView "/matiere_is_locked", sco_edit_matiere.matiere_is_locked, Permission.ScoView
) )
sco_publish(
@bp.route("/module_move") "/module_move", sco_edit_formation.module_move, Permission.ScoChangeFormation
@permission_required(Permission.ScoChangeFormation) )
@scodoc7func(context) sco_publish("/ue_move", sco_edit_formation.ue_move, Permission.ScoChangeFormation)
def module_move(context, module_id, after=0, REQUEST=None, redirect=1):
"""Move before/after previous one (decrement/increment numero)"""
module = sco_edit_module.do_module_list(context, {"module_id": module_id})[0]
redirect = int(redirect)
after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1):
raise ValueError('invalid value for "after"')
formation_id = module["formation_id"]
others = sco_edit_module.do_module_list(
context, {"matiere_id": module["matiere_id"]}
)
# log('others=%s' % others)
if len(others) > 1:
idx = [p["module_id"] for p in others].index(module_id)
# log('module_move: after=%s idx=%s' % (after, idx))
neigh = None # object to swap with
if after == 0 and idx > 0:
neigh = others[idx - 1]
elif after == 1 and idx < len(others) - 1:
neigh = others[idx + 1]
if neigh: #
# swap numero between partition and its neighbor
# log('moving module %s' % module_id)
cnx = ndb.GetDBConnexion()
module["numero"], neigh["numero"] = neigh["numero"], module["numero"]
if module["numero"] == neigh["numero"]:
neigh["numero"] -= 2 * after - 1
_moduleEditor.edit(cnx, module)
_moduleEditor.edit(cnx, neigh)
# redirect to ue_list page:
if redirect:
return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + formation_id)
@bp.route("/ue_move")
@permission_required(Permission.ScoChangeFormation)
@scodoc7func(context)
def ue_move(context, ue_id, after=0, REQUEST=None, redirect=1):
"""Move UE before/after previous one (decrement/increment numero)"""
o = sco_edit_ue.do_ue_list(context, {"ue_id": ue_id})[0]
# log('ue_move %s (#%s) after=%s' % (ue_id, o['numero'], after))
redirect = int(redirect)
after = int(after) # 0: deplace avant, 1 deplace apres
if after not in (0, 1):
raise ValueError('invalid value for "after"')
formation_id = o["formation_id"]
others = sco_edit_ue.do_ue_list(context, {"formation_id": formation_id})
if len(others) > 1:
idx = [p["ue_id"] for p in others].index(ue_id)
neigh = None # object to swap with
if after == 0 and idx > 0:
neigh = others[idx - 1]
elif after == 1 and idx < len(others) - 1:
neigh = others[idx + 1]
if neigh: #
# swap numero between partition and its neighbor
# log('moving ue %s (neigh #%s)' % (ue_id, neigh['numero']))
cnx = ndb.GetDBConnexion()
o["numero"], neigh["numero"] = neigh["numero"], o["numero"]
if o["numero"] == neigh["numero"]:
neigh["numero"] -= 2 * after - 1
context._ueEditor.edit(cnx, o)
context._ueEditor.edit(cnx, neigh)
# redirect to ue_list page
if redirect:
return REQUEST.RESPONSE.redirect("ue_list?formation_id=" + o["formation_id"])
# --- Semestres de formation # --- Semestres de formation
@bp.route("/do_formsemestre_create") @bp.route("/do_formsemestre_create")
@permission_required(Permission.ScoImplement) @permission_required(Permission.ScoImplement)
@scodoc7func(context) @scodoc7func(context)
@ -1552,38 +1483,6 @@ sco_publish(
# --- Evaluations # --- Evaluations
_evaluationEditor = ndb.EditableTable(
"notes_evaluation",
"evaluation_id",
(
"evaluation_id",
"moduleimpl_id",
"jour",
"heure_debut",
"heure_fin",
"description",
"note_max",
"coefficient",
"visibulletin",
"publish_incomplete",
"evaluation_type",
"numero",
),
sortkey="numero desc, jour desc, heure_debut desc", # plus recente d'abord
output_formators={
"jour": ndb.DateISOtoDMY,
"visibulletin": str,
"publish_incomplete": str,
"numero": ndb.int_null_is_zero,
},
input_formators={
"jour": ndb.DateDMYtoISO,
"heure_debut": ndb.TimetoISO8601, # converti par do_evaluation_list
"heure_fin": ndb.TimetoISO8601, # converti par do_evaluation_list
"visibulletin": int,
"publish_incomplete": int,
},
)
def _evaluation_check_write_access(context, REQUEST, moduleimpl_id=None): def _evaluation_check_write_access(context, REQUEST, moduleimpl_id=None):
@ -1644,7 +1543,8 @@ def do_evaluation_create(
n = None n = None
# determine le numero avec la date # determine le numero avec la date
# Liste des eval existantes triees par date, la plus ancienne en tete # Liste des eval existantes triees par date, la plus ancienne en tete
ModEvals = context.do_evaluation_list( ModEvals = sco_evaluations.do_evaluation_list(
context,
args={"moduleimpl_id": moduleimpl_id}, args={"moduleimpl_id": moduleimpl_id},
sortkey="jour asc, heure_debut asc", sortkey="jour asc, heure_debut asc",
) )
@ -1678,7 +1578,7 @@ def do_evaluation_create(
# #
cnx = ndb.GetDBConnexion() cnx = ndb.GetDBConnexion()
r = context._evaluationEditor.create(cnx, args) r = sco_evaluations._evaluationEditor.create(cnx, args)
# news # news
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0] M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
@ -1754,7 +1654,9 @@ def _check_evaluation_args(context, args):
@scodoc7func(context) @scodoc7func(context)
def evaluation_delete(context, REQUEST, evaluation_id): def evaluation_delete(context, REQUEST, evaluation_id):
"""Form delete evaluation""" """Form delete evaluation"""
El = context.do_evaluation_list(args={"evaluation_id": evaluation_id}) El = sco_evaluations.do_evaluation_list(
context, args={"evaluation_id": evaluation_id}
)
if not El: if not El:
raise ValueError("Evalution inexistante ! (%s)" % evaluation_id) raise ValueError("Evalution inexistante ! (%s)" % evaluation_id)
E = El[0] E = El[0]
@ -1825,91 +1727,11 @@ def evaluation_delete(context, REQUEST, evaluation_id):
) )
@bp.route("/do_evaluation_list") sco_publish(
@permission_required(Permission.ScoView) "/do_evaluation_list",
@scodoc7func(context) sco_evaluations.do_evaluation_list,
def do_evaluation_list(context, args, sortkey=None): Permission.ScoView,
"""List evaluations, sorted by numero (or most recent date first). )
Ajoute les champs:
'duree' : '2h30'
'matin' : 1 (commence avant 12:00) ou 0
'apresmidi' : 1 (termine après 12:00) ou 0
'descrheure' : ' de 15h00 à 16h30'
"""
cnx = ndb.GetDBConnexion()
evals = context._evaluationEditor.list(cnx, args, sortkey=sortkey)
# calcule duree (chaine de car.) de chaque evaluation et ajoute jouriso, matin, apresmidi
for e in evals:
heure_debut_dt = e["heure_debut"] or datetime.time(
8, 00
) # au cas ou pas d'heure (note externe?)
heure_fin_dt = e["heure_fin"] or datetime.time(8, 00)
e["heure_debut"] = ndb.TimefromISO8601(e["heure_debut"])
e["heure_fin"] = ndb.TimefromISO8601(e["heure_fin"])
e["jouriso"] = ndb.DateDMYtoISO(e["jour"])
heure_debut, heure_fin = e["heure_debut"], e["heure_fin"]
d = ndb.TimeDuration(heure_debut, heure_fin)
if d is not None:
m = d % 60
e["duree"] = "%dh" % (d / 60)
if m != 0:
e["duree"] += "%02d" % m
else:
e["duree"] = ""
if heure_debut and (not heure_fin or heure_fin == heure_debut):
e["descrheure"] = " à " + heure_debut
elif heure_debut and heure_fin:
e["descrheure"] = " de %s à %s" % (heure_debut, heure_fin)
else:
e["descrheure"] = ""
# matin, apresmidi: utile pour se referer aux absences:
if heure_debut_dt < datetime.time(12, 00):
e["matin"] = 1
else:
e["matin"] = 0
if heure_fin_dt > datetime.time(12, 00):
e["apresmidi"] = 1
else:
e["apresmidi"] = 0
return evals
@bp.route("/do_evaluation_list_in_formsemestre")
@permission_required(Permission.ScoView)
@scodoc7func(context)
def do_evaluation_list_in_formsemestre(context, formsemestre_id):
"list evaluations in this formsemestre"
mods = sco_moduleimpl.do_moduleimpl_list(context, formsemestre_id=formsemestre_id)
evals = []
for mod in mods:
evals += context.do_evaluation_list(
args={"moduleimpl_id": mod["moduleimpl_id"]}
)
return evals
@bp.route("/do_evaluation_edit")
@permission_required(Permission.ScoEnsView)
@scodoc7func(context)
def do_evaluation_edit(context, REQUEST, args):
"edit a evaluation"
evaluation_id = args["evaluation_id"]
the_evals = context.do_evaluation_list({"evaluation_id": evaluation_id})
if not the_evals:
raise ValueError("evaluation inexistante !")
moduleimpl_id = the_evals[0]["moduleimpl_id"]
args["moduleimpl_id"] = moduleimpl_id
context._check_evaluation_args(args)
context._evaluation_check_write_access(REQUEST, moduleimpl_id=moduleimpl_id)
cnx = ndb.GetDBConnexion()
context._evaluationEditor.edit(cnx, args)
# inval cache pour ce semestre
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
sco_core.inval_cache(
context, formsemestre_id=M["formsemestre_id"]
) # > evaluation_edit (coef, ...)
@bp.route("/evaluation_edit") @bp.route("/evaluation_edit")

View File

@ -113,7 +113,7 @@ assert etat["evalcomplete"]
# Modifie l'évaluation 2 pour "prise en compte immédiate" # Modifie l'évaluation 2 pour "prise en compte immédiate"
e2["publish_incomplete"] = "1" e2["publish_incomplete"] = "1"
context.Notes.do_evaluation_edit(REQUEST, e2) sco_evaluations.do_evaluation_edit(context, REQUEST, e2)
etat = sco_evaluations.do_evaluation_etat(context.Notes, e2["evaluation_id"]) etat = sco_evaluations.do_evaluation_etat(context.Notes, e2["evaluation_id"])
assert etat["evalcomplete"] == False assert etat["evalcomplete"] == False
assert etat["nb_att"] == 0 # il n'y a pas de notes (explicitement) en attente assert etat["nb_att"] == 0 # il n'y a pas de notes (explicitement) en attente