refactoring & tests, cont.

This commit is contained in:
Emmanuel Viennet 2021-08-01 11:16:16 +03:00
parent 56f935b2a8
commit f5dbbaa207
35 changed files with 256 additions and 128 deletions

View File

@ -52,6 +52,8 @@ import re
import shutil
import glob
import flask
import app.scodoc.sco_utils as scu
from config import Config
from app.scodoc.notes_log import log

View File

@ -28,6 +28,8 @@
"""Ajout/Modification/Supression formations
(portage from DTML)
"""
import flask
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app.scodoc.notes_log import log
@ -114,6 +116,7 @@ def do_formation_delete(context, oid):
typ=sco_news.NEWS_FORM,
object=oid,
text="Suppression de la formation %(acronyme)s" % F,
max_frequency=3,
)
@ -271,6 +274,7 @@ def do_formation_create(context, args):
sco_news.add(
typ=sco_news.NEWS_FORM,
text="Création de la formation %(titre)s (%(acronyme)s)" % args,
max_frequency=3,
)
return r

View File

@ -28,6 +28,8 @@
"""Ajout/Modification/Supression matieres
(portage from DTML)
"""
import flask
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu
from app.scodoc.notes_log import log
@ -88,6 +90,7 @@ def do_matiere_create(context, args):
typ=sco_news.NEWS_FORM,
object=ue["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)
return r
@ -185,6 +188,7 @@ def do_matiere_delete(context, oid):
typ=sco_news.NEWS_FORM,
object=ue["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)

View File

@ -115,6 +115,7 @@ def do_module_create(context, args):
typ=sco_news.NEWS_FORM,
object=args["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)
return r
@ -280,6 +281,7 @@ def do_module_delete(context, oid):
typ=sco_news.NEWS_FORM,
object=mod["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)

View File

@ -109,6 +109,7 @@ def do_ue_create(context, args):
typ=sco_news.NEWS_FORM,
object=args["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)
return r
@ -170,6 +171,7 @@ def do_ue_delete(context, ue_id, delete_validations=False, REQUEST=None, force=F
typ=sco_news.NEWS_FORM,
object=ue["formation_id"],
text="Modification de la formation %(acronyme)s" % F,
max_frequency=3,
)
#
if not force:

View File

@ -31,6 +31,7 @@
from io import StringIO
from zipfile import ZipFile
import flask
from flask import url_for, g
import app.scodoc.sco_utils as scu

View File

@ -27,6 +27,7 @@
"""Recherche d'étudiants
"""
import flask
from flask import url_for, g
from flask_login import current_user

View File

@ -30,6 +30,8 @@
from operator import itemgetter
import xml.dom.minidom
import flask
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
@ -134,13 +136,22 @@ def formation_export(
)
def formation_import_xml(context, REQUEST, doc, import_tags=True):
def formation_import_xml(context, doc, import_tags=True):
"""Create a formation from XML representation
(format dumped by formation_export( format='xml' ))
XML may contain object (UE, modules) ids: this function returns two
dicts mapping these ids to the created ids.
Args:
doc: str, xml data
import_tags: if false, does not import tags on modules.
Returns:
formation_id, modules_old2new, ues_old2new
"""
from app.scodoc import sco_edit_formation
log("formation_import_xml: doc=%s" % doc)
# log("formation_import_xml: doc=%s" % doc)
try:
dom = xml.dom.minidom.parseString(doc)
except:
@ -341,7 +352,7 @@ def formation_list_table(context, formation_id=None, args={}, REQUEST=None):
def formation_create_new_version(context, formation_id, redirect=True, REQUEST=None):
"duplicate formation, with new version number"
xml = formation_export(context, formation_id, export_ids=True, format="xml")
new_id, modules_old2new, ues_old2new = formation_import_xml(context, REQUEST, xml)
new_id, modules_old2new, ues_old2new = formation_import_xml(context, xml)
# news
F = formation_list(context, args={"formation_id": new_id})[0]
sco_news.add(

View File

@ -27,7 +27,7 @@
"""Menu "custom" (défini par l'utilisateur) dans les semestres
"""
import flask
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb

View File

@ -27,6 +27,7 @@
"""Form choix modules / responsables et creation formsemestre
"""
import flask
from flask import url_for, g
from app.auth.models import User

View File

@ -33,6 +33,7 @@ Ces semestres n'auront qu'un seul inscrit !
"""
import time
import flask
from flask import url_for, g
import app.scodoc.sco_utils as scu

View File

@ -29,6 +29,7 @@
"""
import time
import flask
from flask import url_for, g
import app.scodoc.sco_utils as scu

View File

@ -29,6 +29,7 @@
"""
import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error, time, datetime
import flask
from flask import url_for, g
import app.scodoc.notesdb as ndb

View File

@ -30,6 +30,7 @@
import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
from operator import itemgetter
import flask
from flask import url_for, g
import app.scodoc.sco_utils as scu

View File

@ -29,6 +29,7 @@
"""
from operator import itemgetter
import flask
from flask import url_for, g
import app.scodoc.notesdb as ndb

View File

@ -97,15 +97,15 @@ def add(typ, object=None, text="", url=None, max_frequency=False):
"text": text,
"url": url,
}
log("news: %s" % args)
t = time.time()
if max_frequency:
last_news_time = _LAST_NEWS.get((authuser_name, typ, object), False)
if last_news_time and (t - last_news_time < max_frequency):
log("not recording")
# log("not recording")
return
log("news: %s" % args)
_LAST_NEWS[(authuser_name, typ, object)] = t
_send_news_by_mail(args)

View File

@ -33,6 +33,8 @@ Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016
import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
import random
import flask
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.notes_log import log

View File

@ -110,6 +110,7 @@ get_base_preferences(formsemestre_id)
Return base preferences for current scodoc_dept (instance BasePreferences)
"""
import flask
from flask import g
from app.scodoc import sco_cache

View File

@ -51,6 +51,7 @@ from operator import itemgetter
from reportlab.platypus import Paragraph
from reportlab.lib import styles
import flask
from flask import url_for, g
import app.scodoc.sco_utils as scu

View File

@ -33,6 +33,7 @@ import time
import datetime
import psycopg2
import flask
from flask_login import current_user
import app.scodoc.sco_utils as scu

View File

@ -39,6 +39,8 @@ sem_set_list(context)
"""
import flask
from app.scodoc import html_sco_header
from app.scodoc import sco_cache
from app.scodoc import sco_etape_apogee

View File

@ -80,7 +80,7 @@ class ScoTag(object):
self.tag_id = r[0]["tag_id"]
else:
# Create new tag:
log("creating new tag: %s" % self.title)
# log("creating new tag: %s" % self.title)
cnx = ndb.GetDBConnexion()
oid = ndb.DBInsertDict(
cnx, self.tag_table, {"title": self.title}, commit=True
@ -121,7 +121,7 @@ class ScoTag(object):
args,
)
if not r:
log("tag %s with %s" % (object_id, self.title))
# log("tag %s with %s" % (object_id, self.title))
cnx = ndb.GetDBConnexion()
ndb.DBInsertDict(cnx, self.assoc_table, args, commit=True)
@ -130,7 +130,7 @@ class ScoTag(object):
If no more modules tagged with this tag, delete it.
Return True if Tag still exists.
"""
log("removing tag %s from %s" % (self.title, object_id))
# log("removing tag %s from %s" % (self.title, object_id))
args = {"object_id": object_id, "tag_id": self.tag_id}
ndb.SimpleQuery(
self.context,
@ -225,26 +225,17 @@ def module_tag_list(context, module_id=""):
return [x["title"] for x in r]
def module_tag_set(context, module_id="", taglist=[], REQUEST=None):
def module_tag_set(context, module_id="", taglist=None):
"""taglist may either be:
a string with tag names separated by commas ("un;deux")
or a list of strings (["un", "deux"])
"""
# We check permission here to allow old Admins (with only ScoChangeFormation perm)
if REQUEST: # called from Web
authuser = REQUEST.AUTHENTICATED_USER
tag_editable = authuser.has_permission(
Permission.ScoEditFormationTags
) or authuser.has_permission(Permission.ScoChangeFormation)
if not tag_editable:
raise AccessDenied("Modification des tags impossible pour %s" % authuser)
#
if not taglist:
taglist = []
elif isinstance(taglist, str):
taglist = taglist.split(",")
taglist = [t.strip() for t in taglist]
log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist))
# log("module_tag_set: module_id=%s taglist=%s" % (module_id, taglist))
# Sanity check:
Mod = sco_edit_module.do_module_list(context, args={"module_id": module_id})
if not Mod:

View File

@ -43,6 +43,7 @@ from reportlab.lib.colors import Color
from reportlab.lib import colors
from PIL import Image as PILImage
import flask
from flask import url_for, g
from app.scodoc.notes_log import log

View File

@ -53,6 +53,7 @@ Solution proposée (nov 2014):
- seront aussi présentées (à part) sur la page "Voir les inscriptions aux modules"
"""
import flask
import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu

View File

@ -57,6 +57,7 @@ import string
import time
from xml.etree import ElementTree
import flask
from flask import g
from flask import url_for
from flask import current_app

View File

@ -37,6 +37,7 @@ import pprint
from operator import itemgetter
from xml.etree import ElementTree
import flask
from flask import url_for, g
from flask import current_app
@ -449,11 +450,11 @@ def formation_export(
@bp.route("/formation_import_xml")
@permission_required(Permission.ScoChangeFormation)
@scodoc7func(context)
def formation_import_xml(context, file, REQUEST):
def formation_import_xml(context, file):
"import d'une formation en XML"
log("formation_import_xml")
doc = file.read()
return sco_formations.formation_import_xml(context, REQUEST, doc)
return sco_formations.formation_import_xml(context, doc)
@bp.route("/formation_import_xml_form", methods=["GET", "POST"])
@ -482,7 +483,7 @@ def formation_import_xml_form(context, REQUEST):
return flask.redirect(scu.NotesURL())
else:
formation_id, _, _ = sco_formations.formation_import_xml(
context, tf[2]["xmlfile"], REQUEST
context, tf[2]["xmlfile"]
)
return (

View File

@ -40,6 +40,7 @@ from io import StringIO
from zipfile import ZipFile
import psycopg2
import flask
from flask import g, url_for
from flask import current_app

View File

@ -37,6 +37,7 @@ import datetime
import re
from xml.etree import ElementTree
import flask
from flask import g
from flask_login import current_user

View File

@ -20,7 +20,7 @@ file.close()
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres

View File

@ -1,5 +1,6 @@
import sco_formations
import random
# La variable context est définie par le script de lancement
# l'affecte ainsi pour évietr les warnins pylint:
context = context # pylint: disable=undefined-variable
@ -18,7 +19,7 @@ print(doc)
print("\n \n \n")
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres
@ -75,5 +76,7 @@ for mod in li_module :
# --- Test de export_formation format xml
form_exp = context.Notes.formation_export(formation_id=f[0], format="xml", REQUEST=REQUEST)
form_exp = context.Notes.formation_export(
formation_id=f[0], format="xml", REQUEST=REQUEST
)
print(form_exp[39:])

View File

@ -1,5 +1,6 @@
import sco_formations
import random
# La variable context est définie par le script de lancement
# l'affecte ainsi pour évietr les warnins pylint:
context = context # pylint: disable=undefined-variable
@ -17,7 +18,7 @@ file.close()
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres

View File

@ -1,5 +1,6 @@
import sco_formations
import random
# La variable context est définie par le script de lancement
# l'affecte ainsi pour évietr les warnins pylint:
context = context # pylint: disable=undefined-variable
@ -17,7 +18,7 @@ file.close()
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres
@ -82,7 +83,7 @@ for nom, prenom in [
("Semestre35", "EtudiantNumero5"),
("Semestre36", "EtudiantNumero6"),
("Semestre47", "EtudiantNumero7"),
("Semestre48", "EtudiantNumero8")
("Semestre48", "EtudiantNumero8"),
]:
etud = G.create_etud(
nom=nom,

View File

@ -1,6 +1,7 @@
import sco_formations
import json
import random
# La variable context est définie par le script de lancement
# l'affecte ainsi pour évietr les warnins pylint:
context = context # pylint: disable=undefined-variable
@ -18,7 +19,7 @@ file.close()
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres
@ -83,7 +84,7 @@ for nom, prenom in [
("Semestre35", "EtudiantNumero5"),
("Semestre36", "EtudiantNumero6"),
("Semestre47", "EtudiantNumero7"),
("Semestre48", "EtudiantNumero8")
("Semestre48", "EtudiantNumero8"),
]:
etud = G.create_etud(
nom=nom,
@ -107,16 +108,24 @@ for etud in etuds[6:]:
# --- Création d'une évaluation pour chaque UE
lim_sem1 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem1["formsemestre_id"], REQUEST=REQUEST)
lim_sem1 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem1["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem1 = json.loads(lim_sem1)
lim_sem2 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem2["formsemestre_id"], REQUEST=REQUEST)
lim_sem2 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem2["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem2 = json.loads(lim_sem2)
lim_sem3 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem3["formsemestre_id"], REQUEST=REQUEST)
lim_sem3 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem3["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem3 = json.loads(lim_sem3)
lim_sem4 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem4["formsemestre_id"], REQUEST=REQUEST)
lim_sem4 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem4["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem4 = json.loads(lim_sem4)
@ -132,4 +141,9 @@ for moduleimpl_id, jour, description, coefficient in [
(load_lim_sem4[9]["moduleimpl_id"], "04/02/2021", "InterroTestSemestre4", 1.0),
(load_lim_sem4[13]["moduleimpl_id"], "05/02/2021", "InterroTestSemestre4", 1.0),
]:
e = G.create_evaluation(moduleimpl_id=moduleimpl_id, jour=jour, description=description, coefficient=coefficient)
e = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
jour=jour,
description=description,
coefficient=coefficient,
)

View File

@ -1,6 +1,7 @@
import sco_formations
import json
import random
# La variable context est définie par le script de lancement
# l'affecte ainsi pour évietr les warnins pylint:
context = context # pylint: disable=undefined-variable
@ -16,10 +17,9 @@ doc = file.read()
file.close()
# --- Création de la formation
f = sco_formations.formation_import_xml(REQUEST=REQUEST, doc=doc, context=context.Notes)
f = sco_formations.formation_import_xml(doc=doc, context=context.Notes)
# --- Création des semestres
@ -84,7 +84,7 @@ for nom, prenom in [
("Semestre35", "EtudiantNumero5"),
("Semestre36", "EtudiantNumero6"),
("Semestre47", "EtudiantNumero7"),
("Semestre48", "EtudiantNumero8")
("Semestre48", "EtudiantNumero8"),
]:
etud = G.create_etud(
nom=nom,
@ -108,16 +108,24 @@ for etud in etuds[6:]:
# --- Création d'une évaluation pour chaque UE
lim_sem1 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem1["formsemestre_id"], REQUEST=REQUEST)
lim_sem1 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem1["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem1 = json.loads(lim_sem1)
lim_sem2 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem2["formsemestre_id"], REQUEST=REQUEST)
lim_sem2 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem2["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem2 = json.loads(lim_sem2)
lim_sem3 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem3["formsemestre_id"], REQUEST=REQUEST)
lim_sem3 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem3["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem3 = json.loads(lim_sem3)
lim_sem4 = sco_moduleimpl.do_moduleimpl_list(context.Notes, formsemestre_id=sem4["formsemestre_id"], REQUEST=REQUEST)
lim_sem4 = sco_moduleimpl.do_moduleimpl_list(
context.Notes, formsemestre_id=sem4["formsemestre_id"], REQUEST=REQUEST
)
load_lim_sem4 = json.loads(lim_sem4)
@ -133,41 +141,70 @@ for moduleimpl_id, jour, description, coefficient in [
(load_lim_sem4[9]["moduleimpl_id"], "04/02/2021", "InterroTestSemestre4", 1.0),
(load_lim_sem4[13]["moduleimpl_id"], "05/02/2021", "InterroTestSemestre4", 1.0),
]:
e = G.create_evaluation(moduleimpl_id=moduleimpl_id, jour=jour, description=description, coefficient=coefficient)
e = G.create_evaluation(
moduleimpl_id=moduleimpl_id,
jour=jour,
description=description,
coefficient=coefficient,
)
# --- Saisie des notes des étudiants (un élève a 12, un autre a 7 pour chaque semestre)
lie1 = context.Notes.do_evaluation_list_in_formsemestre(formsemestre_id=sem1["formsemestre_id"])
lie2 = context.Notes.do_evaluation_list_in_formsemestre(formsemestre_id=sem2["formsemestre_id"])
lie3 = context.Notes.do_evaluation_list_in_formsemestre(formsemestre_id=sem3["formsemestre_id"])
lie4 = context.Notes.do_evaluation_list_in_formsemestre(formsemestre_id=sem4["formsemestre_id"])
lie1 = context.Notes.do_evaluation_list_in_formsemestre(
formsemestre_id=sem1["formsemestre_id"]
)
lie2 = context.Notes.do_evaluation_list_in_formsemestre(
formsemestre_id=sem2["formsemestre_id"]
)
lie3 = context.Notes.do_evaluation_list_in_formsemestre(
formsemestre_id=sem3["formsemestre_id"]
)
lie4 = context.Notes.do_evaluation_list_in_formsemestre(
formsemestre_id=sem4["formsemestre_id"]
)
for eval in lie1:
for etud in etuds[:2]:
if etud == etuds[0]:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=12.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=12.0
)
else:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=7.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=7.0
)
for eval in lie2:
for etud in etuds[2:4]:
if etud == etuds[2]:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=12.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=12.0
)
else:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=7.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=7.0
)
for eval in lie3:
for etud in etuds[4:6]:
if etud == etuds[4]:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=12.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=12.0
)
else:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=7.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=7.0
)
for eval in lie4:
for etud in etuds[6:]:
if etud == etuds[6]:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=12.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=12.0
)
else:
nb_changed, nb_suppress, existing_decisions = G.create_note(evaluation=eval, etud=etud, note=7.0)
nb_changed, nb_suppress, existing_decisions = G.create_note(
evaluation=eval, etud=etud, note=7.0
)

View File

@ -53,7 +53,6 @@ from app.scodoc import sco_edit_module
from app.scodoc import sco_edit_ue
from app.scodoc import sco_formations
from app.scodoc import sco_formsemestre_edit
from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_moduleimpl
from app.views import notes
@ -344,3 +343,39 @@ def test_formations(test_client):
assert isinstance(lif3, str)
load_lif3 = json.loads(lif3)
assert len(load_lif3) == 1
def test_import_formation(test_client):
"""Test import/export formations"""
G = sco_fake_gen.ScoFake(verbose=False)
# Lecture fichier XML local:
with open("tests/unit/formation-exemple-1.xml") as f:
doc = f.read()
# --- Création de la formation
f = sco_formations.formation_import_xml(context, doc)
assert len(f) == 3 # 3-uple
formation_id = f[0]
# --- Mise en place de 4 semestres
sems = [
G.create_formsemestre(
formation_id=formation_id,
semestre_id=x[0],
date_debut=x[1],
date_fin=x[2],
)
for x in (
(1, "05/09/2019", "05/01/2020"),
(2, "06/01/2020", "30/06/2020"),
(3, "01/09/2020", "05/01/2021"),
(4, "06/01/2021", "30/06/2021"),
)
]
# et les modules
modules = sco_edit_module.do_module_list(context, {"formation_id": formation_id})
for mod in modules:
mi = G.create_moduleimpl(
module_id=mod["module_id"],
formsemestre_id=sems[mod["semestre_id"] - 1],
responsable_id="bach",
)