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

@ -5,13 +5,13 @@
Lancer ScoDoc ainsi: (comme root)
/opt/scodoc/bin/zopectl debug
/opt/scodoc/bin/zopectl debug
Puis
from debug import *
context = go(app)
# ou
context = go(app)
# ou
context = go_dept(app, 'CJ')
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 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

@ -31,7 +31,7 @@
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,
envois par mail).

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):
@ -376,7 +379,7 @@ def do_formsemestre_moyennes(context, nt, formsemestre_id):
liste des moduleimpls avec notes en attente.
"""
# 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}
# )
# etudids = [x["etudid"] for x in inscr]
@ -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 "
@ -977,7 +988,7 @@ def formsemestre_status(context, formsemestre_id=None, REQUEST=None):
Mlist = sco_moduleimpl.do_moduleimpl_withmodule_list(
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}
# )
prev_ue_id = None

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