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 notesdb as ndb
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 gen_tables import GenTable
from sco_exceptions import (
@ -57,6 +50,14 @@ from sco_exceptions import (
ScoLockedFormError,
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_FILE = "misc/format_import_etudiants.txt"
@ -476,7 +477,7 @@ def scolars_import_excel_file(
sco_news.add(
context,
REQUEST,
typ=NEWS_INSCR,
typ=sco_news.NEWS_INSCR,
text="Inscription de %d étudiants" # peuvent avoir ete inscrits a des semestres differents
% len(created_etudids),
object=formsemestre_id,

View File

@ -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 notesdb as ndb
from notesdb import * # pylint: disable=unused-wildcard-import
from notes_log import log
import sco_utils as scu
from sco_utils import * # pylint: disable=unused-wildcard-import
import app.scodoc.notesdb as ndb
from app.scodoc.notesdb import * # pylint: disable=unused-wildcard-import
from app.scodoc.notes_log import log
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import * # pylint: disable=unused-wildcard-import
from gen_tables import GenTable
import sco_archives

View File

@ -626,7 +626,8 @@ class GenTable:
if with_html_headers:
H.append(
self.html_header
or html_sco_header.sco_header(context,
or html_sco_header.sco_header(
context,
REQUEST,
page_title=page_title,
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"):
H = [
HTML_BEGIN % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING},
TOP_LEVEL_CSS,
_HTML_BEGIN % {"page_title": "ScoDoc: bienvenue", "encoding": scu.SCO_ENCODING},
_TOP_LEVEL_CSS,
"""</head><body class="gtrcontent" id="gtrcontent">""",
scu.CUSTOM_HTML_HEADER_CNX,
]

View File

@ -29,7 +29,7 @@ import sco_utils as scu
import sco_preferences
from sco_abs import getAbsSemEtud
from app.scodoc.sco_permissions import Permission
import scolars
"""
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
else:
li_id = ""
if "endpoint" in items:
if "endpoint" in item:
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:
item["urlq"] = "#"
item["attr"] = item.get("attr", "")

View File

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

View File

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

View File

@ -32,22 +32,9 @@ import time
import pdb
import inspect
import sco_core
import scolars
import sco_groups
from notes_log import log, logCallStack
import sco_utils as scu
import notesdb as ndb
import sco_codes_parcours
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 notes_log import log, logCallStack
from sco_formulas import NoteVector
from sco_exceptions import (
AccessDenied,
@ -55,6 +42,25 @@ from sco_exceptions import (
ScoException,
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:
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 = {}
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
if not mod["ue_id"] in uedict:
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
)
# Infos sur les etudiants
self.inscrlist = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context,
args={"formsemestre_id": formsemestre_id}
self.inscrlist = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
context, args={"formsemestre_id": formsemestre_id}
)
# infos identite etudiant
# xxx sous-optimal: 1/select par etudiant -> 0.17" pour identdict sur GTR1 !
@ -224,13 +232,15 @@ class NotesTable:
ue = uedict[mod["ue_id"]]
modimpl["ue"] = ue # add ue dict to moduleimpl
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
# calcul moyennes du module et stocke dans le module
# nb_inscrits, nb_notes, nb_abs, nb_neutre, moy, median, last_modif=
self.formation = sco_formations.formation_list(context,
args={"formation_id": self.sem["formation_id"]}
self.formation = sco_formations.formation_list(
context, args={"formation_id": self.sem["formation_id"]}
)[0]
self.parcours = sco_codes_parcours.get_parcours_from_code(
self.formation["type_parcours"]
@ -1175,7 +1185,7 @@ class NotesTable:
"comp_ue_capitalisees: recomputing UE moy (etudid=%s, ue_id=%s formsemestre_id=%s)"
% (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"]
) # > UE capitalisees par un etud
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()
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
from notes_log import log
import scolars
import sco_preferences
import pe_jurype, pe_tagtable, pe_tools
from gen_tables import GenTable, SeqGenTable

View File

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

View File

@ -38,9 +38,12 @@ import calendar
import cgi
import notesdb
from scodoc_manager import sco_mgr
from sco_exceptions import ScoValueError, ScoInvalidDateError
import sco_formsemestre
import sco_compute_moy
import sco_preferences
import scolars
def is_work_saturday(context):
@ -589,7 +592,7 @@ def getAbsSemEtud(context, sem, etudid):
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:
ABS_CACHE_INST[u] = {}
C = ABS_CACHE_INST[u]

View File

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

View File

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

View File

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

View File

@ -99,14 +99,15 @@ import sco_utils as scu
import notesdb as ndb
from notes_log import log
from sco_exceptions import ScoValueError, FormatError
import sco_formsemestre
from gen_tables import GenTable
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 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 = (
"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
import notesdb as ndb
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
import sco_bulletins_pdf
from TrivialFormulator import TrivialFormulator
from sco_exceptions import (
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:

View File

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

View File

@ -45,22 +45,23 @@ import mails
import sco_utils as scu
import notesdb as ndb
from notes_log import log
import scolars
from sco_permissions import ScoImplement, ScoEtudInscrit
from sco_permissions import Permission
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_views
import sco_preferences
import sco_codes_parcours
import sco_bulletins_generator
import sco_bulletins_xml
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):
@ -131,8 +132,8 @@ def formsemestre_bulletinetud_dict(
I["server_name"] = ""
# Formation et parcours
I["formation"] = sco_formations.formation_list(context,
args={"formation_id": I["sem"]["formation_id"]}
I["formation"] = sco_formations.formation_list(
context, args={"formation_id": I["sem"]["formation_id"]}
)[0]
I["parcours"] = sco_codes_parcours.get_parcours_from_code(
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
):
complete_eval_ids = set([e["evaluation_id"] for e in evals])
all_evals = context.do_evaluation_list(
args={"moduleimpl_id": modimpl["moduleimpl_id"]}
all_evals = sco_evaluations.do_evaluation_list(
context, args={"moduleimpl_id": modimpl["moduleimpl_id"]}
)
all_evals.reverse() # plus ancienne d'abord
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):
"""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:
gen_class = bulletin_get_class(bul_class_name)
return gen_class.description
@ -223,8 +225,8 @@ class BulletinGenerator:
margins=self.margins,
server_name=self.server_name,
filigranne=self.filigranne,
preferences=self.sco_preferences.SemPreferences(
context, formsemestre_id
preferences=sco_preferences.SemPreferences(
self.context, formsemestre_id
),
)
)
@ -275,7 +277,9 @@ def make_formsemestre_bulletinetud(
raise ValueError("invalid version code !")
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:
gen_class = bulletin_get_class(bul_class_name)
except:

View File

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

View File

@ -35,10 +35,8 @@
"""
import traceback, re
import sco_utils as scu
from sco_permissions import ScoEtudInscrit
from sco_permissions import Permission
import sco_formsemestre
import sco_pdf
from sco_pdf import Color, Paragraph, Spacer, Table
@ -90,8 +88,8 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
formsemestre_id = self.infos["formsemestre_id"]
context = self.context
bul_show_abs_modules = sco_preferences.get_preference(context,
"bul_show_abs_modules", formsemestre_id
bul_show_abs_modules = sco_preferences.get_preference(
context, "bul_show_abs_modules", 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":
continue # saute les modules où on n'est pas inscrit
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>' % (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
@ -178,7 +178,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
rowstyle = ""
plusminus = minuslink #
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
hide = ""
else:
@ -208,7 +210,9 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
)
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 = (
'%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()
P = [] # elems pour gen. pdf
formsemestre_id = I["formsemestre_id"]
bul_show_abs_modules = sco_preferences.get_preference(context,
"bul_show_abs_modules", formsemestre_id
bul_show_abs_modules = sco_preferences.get_preference(
context, "bul_show_abs_modules", 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":
continue # saute les modules où on n'est pas inscrit
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>' % (
mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
@ -510,7 +516,9 @@ def _bulletin_pdf_table_legacy(context, I, version="long"):
coef_ue = ""
ue_descr = "(en cours, non prise en compte)"
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"])
ue_type = "cur"

View File

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

View File

@ -59,7 +59,7 @@ from sco_pdf import blue, cm, mm
from sco_pdf import SU
import sco_preferences
from notes_log import log
from sco_permissions import ScoEtudInscrit
from sco_permissions import Permission
from sco_codes_parcours import (
UE_COLORS,
UE_DEFAULT_COLOR,
@ -105,7 +105,7 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator):
columns_ids=colkeys,
pdf_table_style=pdf_style,
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_ignore_default=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
"""
import traceback
import sco_utils as scu
import sco_formsemestre
@ -195,7 +194,9 @@ class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):
ue_type = None
# --- UE capitalisée:
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"])
hidden = False
cssstyle = ""

View File

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

View File

@ -33,6 +33,7 @@ import pprint
from types import FloatType
import sco_utils as scu
import notesdb as ndb
from sco_utils import (
NOTES_ATTENTE,
NOTES_NEUTRALISE,
@ -43,12 +44,14 @@ from sco_utils import (
from sco_exceptions import ScoException
from notesdb import EditableTable, quote_html
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_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):
@ -390,7 +393,9 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id):
mods_att = []
expr_diags = []
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)
moduleimpl_id = modimpl["moduleimpl_id"]
assert not D.has_key(moduleimpl_id)

View File

@ -4,14 +4,19 @@
"""essai: ceci serait un module scodoc/sco_xxx.py
"""
import time
import thread
import types
from flask import url_for
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 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):
@ -19,30 +24,32 @@ def sco_get_version(context, REQUEST=None):
return """<html><body><p>%s</p></body></html>""" % scu.SCOVERSION
def test_refactor(context, x=1):
x = context.toto()
y = ("context=" + sco_edit_module.module_is_locked(context, "alpha")) + "23"
z = html_sco_header.sco_header(
context,
a_long_argument_hahahahaha=1,
another_very_long_arggggggggggggg=2,
z=6,
u=99,
kkkkkk=1,
)
# def test_refactor(context, x=1):
# x = context.toto()
# y = ("context=" + sco_edit_module.module_is_locked(context, "alpha")) + "23"
# z = html_sco_header.sco_header(
# context,
# a_long_argument_hahahahaha=1,
# another_very_long_arggggggggggggg=2,
# z=6,
# u=99,
# kkkkkk=1,
# )
#
# Cache global: chaque instance, repérée par sa connexion db, a un cache
# qui est recréé à la demande
#
NOTES_CACHE_INST = {} # { db_cnx_string : CacheNotesTable instance }
CACHE_formsemestre_inscription = {}
CACHE_evaluations = {}
# cache notes evaluations
def get_evaluations_cache(context):
"""returns cache for evaluations"""
u = context.GetDBConnexionString()
u = sco_mgr.get_db_uri()
if CACHE_evaluations.has_key(u):
return CACHE_evaluations[u]
else:
@ -51,6 +58,183 @@ def get_evaluations_cache(context):
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):
"returns CacheNotesTable instance for us"
u = sco_mgr.get_db_uri() # identifie le dept de facon unique
@ -81,7 +265,7 @@ def inval_cache(
# Cache inscriptions semestres
def get_formsemestre_inscription_cache(context, format=None):
u = context.GetDBConnexionString()
u = sco_mgr.get_db_uri()
if CACHE_formsemestre_inscription.has_key(u):
return CACHE_formsemestre_inscription[u]
else:

View File

@ -33,6 +33,8 @@ import sco_utils as scu
from notes_log import log
from TrivialFormulator import TrivialFormulator, TF, tf_error_message
import sco_codes_parcours
import sco_edit_module
import sco_edit_ue
import sco_formsemestre
from sco_exceptions import ScoValueError
import sco_formations
@ -305,3 +307,69 @@ def do_formation_edit(context, args):
sco_core.inval_cache(
context, formsemestre_id=sem["formsemestre_id"]
) # > 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"
cnx = ndb.GetDBConnexion()
# check duplicates
ues = do_ue_list(context,
{"formation_id": args["formation_id"], "acronyme": args["acronyme"]}
ues = do_ue_list(
context, {"formation_id": args["formation_id"], "acronyme": args["acronyme"]}
)
if ues:
raise ScoValueError('Acronyme d\'UE "%s" déjà utilisé !' % args["acronyme"])
# create
r = context._ueEditor.create(cnx, args)
r = _ueEditor.create(cnx, args)
# news
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}
)
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 ?):
sco_core.inval_cache(context)
# 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)
if parcours.UE_IS_MODULE or tf[2]["create_matiere"]:
matiere_id = sco_edit_matiere.do_matiere_create(context,
{"ue_id": ue_id, "titre": tf[2]["titre"], "numero": 1}, REQUEST
matiere_id = sco_edit_matiere.do_matiere_create(
context,
{"ue_id": ue_id, "titre": tf[2]["titre"], "numero": 1},
REQUEST,
)
if parcours.UE_IS_MODULE:
# 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"],
"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('<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
for Mod in Modlist:
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
if args.has_key("acronyme"):
new_acro = args["acronyme"]
ues = do_ue_list(context,
{"formation_id": ue["formation_id"], "acronyme": new_acro}
ues = do_ue_list(
context, {"formation_id": ue["formation_id"], "acronyme": new_acro}
)
if ues and ues[0]["ue_id"] != ue_id:
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"]
cnx = ndb.GetDBConnexion()
context._ueEditor.edit(cnx, args)
_ueEditor.edit(cnx, args)
if not dont_invalidate_cache:
# 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:
Matlist = sco_edit_matiere.do_matiere_list(context, args={"ue_id": UE["ue_id"]})
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:
Mod["nb_moduleimpls"] = sco_edit_module.module_count_moduleimpls(
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):
"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:
raise ValueError("evaluation inexistante !")
@ -164,7 +274,7 @@ def do_evaluation_etat(
else:
last_modif = None
# ---- 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]
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
@ -530,7 +640,7 @@ def evaluation_date_first_completion(context, evaluation_id):
# Il faut considerer les inscriptions au semestre
# (pour avoir l'etat et le groupe) et aussi les inscriptions
# 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]
# formsemestre_id = M["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(
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]
if (e["evaluation_type"] != scu.EVALUATION_NORMALE) or (
Mod["module_type"] == scu.MODULE_MALUS
):
@ -644,8 +756,8 @@ def module_evaluation_insert_before(context, ModEvals, next_eval, REQUEST):
if not n:
log("renumbering old evals")
module_evaluation_renumber(context, next_eval["moduleimpl_id"], REQUEST)
next_eval = context.do_evaluation_list(
args={"evaluation_id": next_eval["evaluation_id"]}
next_eval = do_evaluation_list(
context, args={"evaluation_id": next_eval["evaluation_id"]}
)[0]
n = next_eval["numero"]
else:
@ -656,7 +768,7 @@ def module_evaluation_insert_before(context, ModEvals, next_eval, REQUEST):
if e["numero"] >= n:
e["numero"] += 1
# log('incrementing %s to %s' % (e['evaluation_id'], e['numero']))
context.do_evaluation_edit(REQUEST, e)
do_evaluation_edit(context, REQUEST, e)
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)
(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)
# 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(
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
if after not in (0, 1):
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] )
if len(ModEvals) > 1:
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: #
# swap numero with neighbor
e["numero"], neigh["numero"] = neigh["numero"], e["numero"]
context.do_evaluation_edit(REQUEST, e)
context.do_evaluation_edit(REQUEST, neigh)
do_evaluation_edit(context, REQUEST, e)
do_evaluation_edit(context, REQUEST, neigh)
# redirect to moduleimpl page:
if redirect:
return REQUEST.RESPONSE.redirect(
@ -711,8 +823,10 @@ def module_evaluation_renumber(
# log('module_evaluation_renumber( moduleimpl_id=%s )' % moduleimpl_id )
# List sorted according to date/heure, ignoring numeros:
# (note that we place evaluations with NULL date at the end)
ModEvals = context.do_evaluation_list(
args={"moduleimpl_id": moduleimpl_id}, sortkey="jour asc, heure_debut asc"
ModEvals = do_evaluation_list(
context,
args={"moduleimpl_id": moduleimpl_id},
sortkey="jour asc, heure_debut asc",
)
all_numbered = False not in [x["numero"] > 0 for x in ModEvals]
@ -724,7 +838,7 @@ def module_evaluation_renumber(
i = 1
for e in ModEvals:
e["numero"] = i
context.do_evaluation_edit(REQUEST, e)
do_evaluation_edit(context, REQUEST, e)
i += 1
# 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
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"]
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]
@ -816,7 +930,7 @@ def evaluation_create_form(
):
"formulaire creation/edition des evaluations (pas des notes)"
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"]
#
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])
return REQUEST.RESPONSE.redirect(dest_url)
else:
context.do_evaluation_edit(REQUEST, tf[2])
do_evaluation_edit(context, REQUEST, tf[2])
return REQUEST.RESPONSE.redirect(dest_url)

View File

@ -37,7 +37,7 @@ from TrivialFormulator import TrivialFormulator, TF
import notes_table
from sco_exceptions import AccessDenied, ScoValueError
from sco_formsemestre import ApoEtapeVDI
from sco_permissions import ScoImplement
from sco_permissions import Permission
import sco_codes_parcours
import sco_compute_moy
import sco_formsemestre
@ -197,7 +197,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
for ue in uelist:
matlist = sco_edit_matiere.do_matiere_list(context, {"ue_id": ue["ue_id"]})
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
for m in modsmat:
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],
}
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"])]
# INSCRIPTIONS DES ETUDIANTS
log(
@ -798,7 +802,9 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
sco_moduleimpl.do_moduleimpl_edit(
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:
msg_html = (
@ -836,7 +842,9 @@ def formsemestre_delete_moduleimpls(context, formsemestre_id, module_ids_to_del)
)[0]["moduleimpl_id"]
mod = sco_edit_module.do_module_list(context, {"module_id": module_id})[0]
# 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:
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>'
@ -1020,8 +1028,8 @@ def do_formsemestre_clone(
sco_moduleimpl.do_ens_create(context, args)
# optionally, copy evaluations
if clone_evaluations:
evals = context.do_evaluation_list(
args={"moduleimpl_id": mod_orig["moduleimpl_id"]}
evals = sco_evaluations.do_evaluation_list(
context, args={"moduleimpl_id": mod_orig["moduleimpl_id"]}
)
for e in evals:
args = e.copy()
@ -1109,7 +1117,9 @@ def formsemestre_associate_new_version(
if not dialog_confirmed:
# dresse le liste des semestres de la meme formation et version
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(
context,
args={
@ -1227,7 +1237,9 @@ def _reassociate_moduleimpls(
def formsemestre_delete(context, formsemestre_id, REQUEST=None):
"""Delete a formsemestre (affiche avertissements)"""
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 = [
html_sco_header.html_sem_header(
context, REQUEST, "Suppression du semestre", sem
@ -1244,7 +1256,7 @@ def formsemestre_delete(context, formsemestre_id, REQUEST=None):
</ol></div>""",
]
evals = context.do_evaluation_list_in_formsemestre(formsemestre_id)
evals = sco_evaluations.do_evaluation_list_in_formsemestre(context, formsemestre_id)
if evals:
H.append(
"""<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)
for mod in mods:
# 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:
ndb.SimpleQuery(
context,

View File

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

View File

@ -55,11 +55,11 @@ def do_evaluation_listenotes(context, REQUEST):
if REQUEST.form.has_key("evaluation_id"):
evaluation_id = REQUEST.form["evaluation_id"]
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"):
moduleimpl_id = REQUEST.form["moduleimpl_id"]
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:
raise ValueError("missing argument: evaluation or module")
if not evals:
@ -706,7 +706,7 @@ def evaluation_check_absences(context, evaluation_id):
EXC et pas justifie
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"]:
return [], [], [], [], [] # evaluation sans date
@ -762,7 +762,7 @@ def evaluation_check_absences_html(
):
"""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)
(
@ -877,7 +877,7 @@ def formsemestre_check_absences_html(context, formsemestre_id, REQUEST=None):
context, formsemestre_id=formsemestre_id
)
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:
H.append(
'<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 notes_log import log
import scolog
import sco_edit_matiere
import sco_edit_module
import sco_edit_ue
import sco_formsemestre
# --- Gestion des "Implémentations de Modules"
@ -132,10 +135,14 @@ def do_moduleimpl_withmodule_list(
del args["REQUEST"]
modimpls = do_moduleimpl_list(context, **args)
for mo in modimpls:
mo["module"] = sco_edit_module.do_module_list(context, args={"module_id": mo["module_id"]})[0]
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"]}
mo["module"] = sco_edit_module.do_module_list(
context, args={"module_id": mo["module_id"]}
)[0]
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]
# 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
for etudid in etudids:
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context,
args={"formsemestre_id": formsemestre_id, "etudid": etudid}
insem = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
context, args={"formsemestre_id": formsemestre_id, "etudid": etudid}
)
if not insem:
raise ScoValueError("%s n'est pas inscrit au semestre !" % etudid)

View File

@ -59,7 +59,7 @@ import sco_abs
# menu evaluation dans moduleimpl
def moduleimpl_evaluation_menu(context, evaluation_id, nbnotes=0, REQUEST=None):
"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(
context, moduleimpl_id=E["moduleimpl_id"]
)[0]
@ -171,7 +171,7 @@ def moduleimpl_status(context, moduleimpl_id=None, partition_id=None, REQUEST=No
nt = sco_core.get_notes_cache(
context,
).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(
key=lambda x: (x["numero"], x["jour"], x["heure_debut"]), reverse=True
) # 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.
"""
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:
raise ScoValueError("invalid evaluation_id")
E = E[0]
@ -236,7 +236,7 @@ def do_placement(context, REQUEST):
raise ScoValueError(
"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
# (admin, respformation, and responsable_id)
@ -395,7 +395,7 @@ def do_placement(context, REQUEST):
def placement_eval_selectetuds(context, evaluation_id, REQUEST=None):
"""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:
raise ScoValueError("invalid evaluation_id")
theeval = evals[0]

View File

@ -57,7 +57,6 @@ import htmlutils
import sco_excel
import scolars
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):
@ -198,7 +197,7 @@ def do_evaluation_upload_xls(context, REQUEST):
authuser = REQUEST.AUTHENTICATED_USER
evaluation_id = REQUEST.form["evaluation_id"]
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(
context, moduleimpl_id=E["moduleimpl_id"]
)[0]
@ -276,17 +275,21 @@ def do_evaluation_upload_xls(context, REQUEST):
context, authuser, evaluation_id, L, comment
)
# 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(
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["moduleimpl_id"] = M["moduleimpl_id"]
mod["url"] = "Notes/moduleimpl_status?moduleimpl_id=%(moduleimpl_id)s" % mod
sco_news.add(
context,
REQUEST,
typ=NEWS_NOTE,
typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"],
text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % mod,
url=mod["url"],
@ -319,7 +322,7 @@ def do_evaluation_set_missing(
"""Initialisation des notes manquantes"""
authuser = REQUEST.AUTHENTICATED_USER
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(
context, moduleimpl_id=E["moduleimpl_id"]
)[0]
@ -377,7 +380,7 @@ def do_evaluation_set_missing(
sco_news.add(
context,
REQUEST,
typ=NEWS_NOTE,
typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"],
text='Initialisation notes dans <a href="%(url)s">%(titre)s</a>' % mod,
url=mod["url"],
@ -400,7 +403,7 @@ def do_evaluation_set_missing(
def evaluation_suppress_alln(context, evaluation_id, REQUEST, dialog_confirmed=False):
"suppress all notes in this eval"
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):
# 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(
context,
REQUEST,
typ=NEWS_NOTE,
typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"],
text='Suppression des notes d\'une évaluation dans <a href="%(url)s">%(titre)s</a>'
% mod,
@ -499,7 +502,7 @@ def _notes_add(context, uid, evaluation_id, notes, comment=None, do_it=True):
cursor = cnx.cursor(cursor_factory=ScoDocCursor)
nb_changed = 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]
existing_decisions = (
[]
@ -603,7 +606,9 @@ def saisie_notes_tableur(context, evaluation_id, group_ids=[], REQUEST=None):
"""Saisie des notes via un fichier Excel"""
authuser = REQUEST.AUTHENTICATED_USER
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:
raise ScoValueError("invalid evaluation_id")
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):
"""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:
raise ScoValueError("invalid evaluation_id")
E = evals[0]
@ -880,7 +887,9 @@ def saisie_notes(context, evaluation_id, group_ids=[], REQUEST=None):
authuser = REQUEST.AUTHENTICATED_USER
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:
raise ScoValueError("invalid evaluation_id")
E = evals[0]
@ -1006,8 +1015,8 @@ def _get_sorted_etuds(context, E, etudids, formsemestre_id):
scolars.format_etud_ident(e)
etuds.append(e)
# infos inscription dans ce semestre
e["inscr"] = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context,
{"etudid": etudid, "formsemestre_id": formsemestre_id}
e["inscr"] = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
context, {"etudid": etudid, "formsemestre_id": formsemestre_id}
)[0]
# Groupes auxquels appartient cet étudiant:
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"
% (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]
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
@ -1264,7 +1273,7 @@ def save_note(
sco_news.add(
context,
REQUEST,
typ=NEWS_NOTE,
typ=sco_news.NEWS_NOTE,
object=M["moduleimpl_id"],
text='Chargement notes dans <a href="%(url)s">%(titre)s</a>' % Mod,
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à:
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):
# met la note dans le première évaluation existante:
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):
"""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]
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
(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)
@ -573,82 +573,13 @@ sco_publish(
"/matiere_is_locked", sco_edit_matiere.matiere_is_locked, Permission.ScoView
)
@bp.route("/module_move")
@permission_required(Permission.ScoChangeFormation)
@scodoc7func(context)
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"])
sco_publish(
"/module_move", sco_edit_formation.module_move, Permission.ScoChangeFormation
)
sco_publish("/ue_move", sco_edit_formation.ue_move, Permission.ScoChangeFormation)
# --- Semestres de formation
@bp.route("/do_formsemestre_create")
@permission_required(Permission.ScoImplement)
@scodoc7func(context)
@ -1552,38 +1483,6 @@ sco_publish(
# --- 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):
@ -1644,7 +1543,8 @@ def do_evaluation_create(
n = None
# determine le numero avec la date
# 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},
sortkey="jour asc, heure_debut asc",
)
@ -1678,7 +1578,7 @@ def do_evaluation_create(
#
cnx = ndb.GetDBConnexion()
r = context._evaluationEditor.create(cnx, args)
r = sco_evaluations._evaluationEditor.create(cnx, args)
# news
M = sco_moduleimpl.do_moduleimpl_list(context, moduleimpl_id=moduleimpl_id)[0]
@ -1754,7 +1654,9 @@ def _check_evaluation_args(context, args):
@scodoc7func(context)
def evaluation_delete(context, REQUEST, evaluation_id):
"""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:
raise ValueError("Evalution inexistante ! (%s)" % evaluation_id)
E = El[0]
@ -1825,91 +1727,11 @@ def evaluation_delete(context, REQUEST, evaluation_id):
)
@bp.route("/do_evaluation_list")
@permission_required(Permission.ScoView)
@scodoc7func(context)
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 = 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, ...)
sco_publish(
"/do_evaluation_list",
sco_evaluations.do_evaluation_list,
Permission.ScoView,
)
@bp.route("/evaluation_edit")

View File

@ -113,7 +113,7 @@ assert etat["evalcomplete"]
# Modifie l'évaluation 2 pour "prise en compte immédiate"
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"])
assert etat["evalcomplete"] == False
assert etat["nb_att"] == 0 # il n'y a pas de notes (explicitement) en attente