From c22f4571fabaa3e61e3ae2ba6763389165322a84 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Sat, 21 Aug 2021 15:17:14 +0200
Subject: [PATCH] Fix imports portails + petits bugs

---
 app/scodoc/html_sidebar.py            |  2 +-
 app/scodoc/sco_archives.py            |  5 +--
 app/scodoc/sco_bulletins_pdf.py       |  4 ++-
 app/scodoc/sco_bulletins_signature.py |  2 +-
 app/scodoc/sco_etud.py                |  2 +-
 app/scodoc/sco_export_results.py      |  2 +-
 app/scodoc/sco_inscr_passage.py       | 13 ++++----
 app/scodoc/sco_pdf.py                 |  4 ++-
 app/scodoc/sco_permissions.py         |  2 +-
 app/scodoc/sco_photos.py              | 22 ++++++-------
 app/scodoc/sco_portal_apogee.py       | 47 ++++++++++++---------------
 app/scodoc/sco_pvpdf.py               |  2 +-
 app/scodoc/sco_saisie_notes.py        |  1 -
 app/scodoc/sco_synchro_etuds.py       | 14 ++++----
 app/scodoc/sco_utils.py               |  3 --
 scotests/fakeportal/fakeportal.py     |  1 +
 16 files changed, 61 insertions(+), 65 deletions(-)

diff --git a/app/scodoc/html_sidebar.py b/app/scodoc/html_sidebar.py
index 838fc9b4f..43e2e6eaf 100644
--- a/app/scodoc/html_sidebar.py
+++ b/app/scodoc/html_sidebar.py
@@ -48,7 +48,7 @@ def sidebar_common():
         "authuser": current_user.user_name,
     }
     H = [
-        f"""<a class="scodoc_title" href="about">ScoDoc 8</a>
+        f"""<a class="scodoc_title" href="about">ScoDoc 9</a>
         <div id="authuser"><a id="authuserlink" href="{
             url_for("users.user_info_page", scodoc_dept=g.scodoc_dept, user_name=current_user.user_name)
             }">{current_user.user_name}</a>
diff --git a/app/scodoc/sco_archives.py b/app/scodoc/sco_archives.py
index 2dc2f65fb..66c8c2d7e 100644
--- a/app/scodoc/sco_archives.py
+++ b/app/scodoc/sco_archives.py
@@ -53,6 +53,7 @@ import shutil
 import glob
 
 import flask
+from flask import g
 
 import app.scodoc.sco_utils as scu
 from config import Config
@@ -95,7 +96,7 @@ class BaseArchiver(object):
         :return: path to directory of archives for this object (eg formsemestre_id or etudid).
         If directory does not yet exist, create it.
         """
-        dept_dir = os.path.join(self.root, scu.get_dept_id())
+        dept_dir = os.path.join(self.root, g.scodoc_dept)
         try:
             scu.GSL.acquire()
             if not os.path.isdir(dept_dir):
@@ -113,7 +114,7 @@ class BaseArchiver(object):
         """
         :return: list of archive oids
         """
-        base = os.path.join(self.root, scu.get_dept_id()) + os.path.sep
+        base = os.path.join(self.root, g.scodoc_dept) + os.path.sep
         dirs = glob.glob(base + "*")
         return [os.path.split(x)[1] for x in dirs]
 
diff --git a/app/scodoc/sco_bulletins_pdf.py b/app/scodoc/sco_bulletins_pdf.py
index 9892850ed..ff05f7221 100644
--- a/app/scodoc/sco_bulletins_pdf.py
+++ b/app/scodoc/sco_bulletins_pdf.py
@@ -58,6 +58,8 @@ import traceback
 
 from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
 
+from flask import g, url_for
+
 from app.scodoc import VERSION
 import app.scodoc.sco_utils as scu
 from app.scodoc.notes_log import log
@@ -139,7 +141,7 @@ def process_field(field, cdict, style, suppress_empty_pars=False, format="pdf"):
         return text
     # --- PDF format:
     # handle logos:
-    image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id() + "/"
+    image_dir = scu.SCODOC_LOGOS_DIR + "/logos_" + g.scodoc_dept + "/"
     if not os.path.exists(image_dir):
         image_dir = scu.SCODOC_LOGOS_DIR + "/"  # use global logos
         if not os.path.exists(image_dir):
diff --git a/app/scodoc/sco_bulletins_signature.py b/app/scodoc/sco_bulletins_signature.py
index 120cbbf8a..fead3aa8a 100644
--- a/app/scodoc/sco_bulletins_signature.py
+++ b/app/scodoc/sco_bulletins_signature.py
@@ -85,7 +85,7 @@ et sur page "réglages bulletin" (avec formsemestre_id)
 # def _sig_filename(side, formsemestre_id=None):
 #     if not side in ("left", "right"):
 #         raise ValueError("side must be left or right")
-#     dirs = [SCODOC_LOGOS_DIR, scu.get_dept_id()]
+#     dirs = [SCODOC_LOGOS_DIR, g.scodoc_dept]
 #     if formsemestre_id:
 #         dirs.append(formsemestre_id)
 #     dirs.append("bul_sig_{}".format(side))
diff --git a/app/scodoc/sco_etud.py b/app/scodoc/sco_etud.py
index d8e5a74f5..6736ad699 100644
--- a/app/scodoc/sco_etud.py
+++ b/app/scodoc/sco_etud.py
@@ -911,7 +911,7 @@ def fill_etuds_info(etuds):
     # open('/tmp/t','w').write( str(etuds) )
     for etud in etuds:
         etudid = etud["etudid"]
-        etud["dept"] = scu.get_dept_id()
+        etud["dept"] = g.scodoc_dept
         adrs = adresse_list(cnx, {"etudid": etudid})
         if not adrs:
             # certains "vieux" etudiants n'ont pas d'adresse
diff --git a/app/scodoc/sco_export_results.py b/app/scodoc/sco_export_results.py
index 168abc639..12e1e8aa3 100644
--- a/app/scodoc/sco_export_results.py
+++ b/app/scodoc/sco_export_results.py
@@ -195,7 +195,7 @@ def _build_results_list(dpv_by_sem, etuds_infos):
                     int(sem["annee_debut"]), sem["mois_debut_ord"]
                 )
                 r["sid"] = "{} {} {}".format(
-                    sem["sem_id_txt"], scu.get_dept_id(), sem["modalite"]
+                    sem["sem_id_txt"], g.scodoc_dept, sem["modalite"]
                 )
                 rows.append(r)
 
diff --git a/app/scodoc/sco_inscr_passage.py b/app/scodoc/sco_inscr_passage.py
index de5670144..90f89db9a 100644
--- a/app/scodoc/sco_inscr_passage.py
+++ b/app/scodoc/sco_inscr_passage.py
@@ -145,12 +145,13 @@ def list_inscrits_date(sem):
     cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
     sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"])
     cursor.execute(
-        """select I.etudid
-                      from notes_formsemestre_inscription I, notes_formsemestre S
-                      where I.formsemestre_id = S.formsemestre_id
-                      and I.formsemestre_id != %(formsemestre_id)s
-                      and S.date_debut <= %(date_debut_iso)s
-                      and S.date_fin >= %(date_debut_iso)s""",
+        """SELECT I.etudid
+        FROM notes_formsemestre_inscription I, notes_formsemestre S
+        WHERE I.formsemestre_id = S.id
+        AND S.id != %(formsemestre_id)s
+        AND S.date_debut <= %(date_debut_iso)s
+        AND S.date_fin >= %(date_debut_iso)s
+        """,
         sem,
     )
     return [x[0] for x in cursor.fetchall()]
diff --git a/app/scodoc/sco_pdf.py b/app/scodoc/sco_pdf.py
index 5eaa40e64..7b219e853 100755
--- a/app/scodoc/sco_pdf.py
+++ b/app/scodoc/sco_pdf.py
@@ -52,6 +52,8 @@ from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
 from reportlab.lib import styles
 from reportlab.lib.pagesizes import letter, A4, landscape
 
+from flask import g
+
 import app.scodoc.sco_utils as scu
 from app.scodoc.sco_utils import (
     CONFIG,
@@ -203,7 +205,7 @@ class ScolarsPageTemplate(PageTemplate):
         # XXX COPIED from sco_pvpdf, to be refactored (no time now)
         # Search background in dept specific dir, then in global config dir
         for image_dir in (
-            SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id() + "/",
+            SCODOC_LOGOS_DIR + "/logos_" + g.scodoc_dept + "/",
             SCODOC_LOGOS_DIR + "/",  # global logos
         ):
             for suffix in LOGOS_IMAGES_ALLOWED_TYPES:
diff --git a/app/scodoc/sco_permissions.py b/app/scodoc/sco_permissions.py
index a5419d4e0..4eee09dab 100644
--- a/app/scodoc/sco_permissions.py
+++ b/app/scodoc/sco_permissions.py
@@ -1,7 +1,7 @@
 # -*- mode: python -*-
 # -*- coding: utf-8 -*-
 
-"""Definition of ScoDoc 8 permissions
+"""Definition of ScoDoc permissions
     used by auth
 """
 
diff --git a/app/scodoc/sco_photos.py b/app/scodoc/sco_photos.py
index 6e6732fe5..e3f31a0bf 100644
--- a/app/scodoc/sco_photos.py
+++ b/app/scodoc/sco_photos.py
@@ -43,18 +43,18 @@ Les images sont servies par ScoDoc, via la méthode getphotofile?etudid=xxx
 
 """
 
+import datetime
+import glob
 import io
 import os
-import time
-import datetime
 import random
-import six.moves.urllib.request, six.moves.urllib.error, six.moves.urllib.parse
+import requests
+import time
 import traceback
+
 from PIL import Image as PILImage
 
-import glob
-
-from flask import request
+from flask import request, g
 
 from config import Config
 
@@ -318,7 +318,7 @@ def get_new_filename(etudid):
     """Constructs a random filename to store a new image.
     The path is constructed as: Fxx/etudid
     """
-    dept = scu.get_dept_id()
+    dept = g.scodoc_dept
     return find_new_dir() + dept + "_" + str(etudid)
 
 
@@ -351,17 +351,15 @@ def copy_portal_photo_to_fs(etud):
     f = None
     try:
         log("copy_portal_photo_to_fs: getting %s" % url)
-        f = six.moves.urllib.request.urlopen(
-            url, timeout=portal_timeout
-        )  # python >= 2.7
+        r = requests.get(url, timeout=portal_timeout)
     except:
         log("download failed: exception:\n%s" % traceback.format_exc())
         log("called from:\n" + "".join(traceback.format_stack()))
         return None, "%s: erreur chargement de %s" % (etud["nomprenom"], url)
-    if not f:
+    if r.status_code != 200:
         log("download failed")
         return None, "%s: erreur chargement de %s" % (etud["nomprenom"], url)
-    data = f.read()
+    data = r.content  # image bytes
     try:
         status, diag = store_photo(etud, data)
     except:
diff --git a/app/scodoc/sco_portal_apogee.py b/app/scodoc/sco_portal_apogee.py
index 2278e9910..fe827683a 100644
--- a/app/scodoc/sco_portal_apogee.py
+++ b/app/scodoc/sco_portal_apogee.py
@@ -27,20 +27,19 @@
 
 """Liaison avec le portail ENT (qui donne accès aux infos Apogée)
 """
-
-import os, time
-import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
+import datetime
+import os
+import time
+import urllib
 import xml
 import xml.sax.saxutils
 import xml.dom.minidom
-import datetime
 
 import app.scodoc.sco_utils as scu
 from app.scodoc.notes_log import log
 from app.scodoc.sco_exceptions import ScoValueError
 from app.scodoc import sco_preferences
 import six
-from six.moves import range
 
 SCO_CACHE_ETAPE_FILENAME = os.path.join(scu.SCO_TMP_DIR, "last_etapes.xml")
 
@@ -52,17 +51,19 @@ def has_portal():
 
 class PortalInterface(object):
     def __init__(self):
-        self.warning = False
+        self.first_time = True
 
     def get_portal_url(self):
         "URL of portal"
         portal_url = sco_preferences.get_preference("portal_url")
-        if not self.warning:
+        if portal_url and not portal_url.endswith("/"):
+            portal_url += "/"
+        if self.first_time:
             if portal_url:
                 log("Portal URL=%s" % portal_url)
             else:
                 log("Portal not configured")
-            self.warning = True
+            self.first_time = False
         return portal_url
 
     def get_etapes_url(self):
@@ -157,14 +158,10 @@ def get_inscrits_etape(code_etape, anneeapogee=None, ntrials=2):
         req = (
             etud_url
             + "?"
-            + six.moves.urllib.parse.urlencode(
-                (("etape", code_etape), ("annee", anneeapogee))
-            )
+            + urllib.parse.urlencode((("etape", code_etape), ("annee", anneeapogee)))
         )
     else:
-        req = (
-            etud_url + "?" + six.moves.urllib.parse.urlencode((("etape", code_etape),))
-        )
+        req = etud_url + "?" + urllib.parse.urlencode((("etape", code_etape),))
     actual_timeout = float(portal_timeout) / ntrials
     if portal_timeout > 0:
         actual_timeout = max(1, actual_timeout)
@@ -209,7 +206,7 @@ def query_apogee_portal(**args):
             # XXX TODO : va poser problème pour la page modif données étudiants : A VOIR
             return []
     portal_timeout = sco_preferences.get_preference("portal_timeout")
-    req = etud_url + "?" + six.moves.urllib.parse.urlencode(list(args.items()))
+    req = etud_url + "?" + urllib.parse.urlencode(list(args.items()))
     doc = scu.query_portal(req, timeout=portal_timeout)  # sco_utils
     return xml_to_list_of_dicts(doc, req=req)
 
@@ -242,7 +239,7 @@ def xml_to_list_of_dicts(doc, req=None):
         )
     infos = []
     try:
-        if dom.childNodes[0].nodeName != u"etudiants":
+        if dom.childNodes[0].nodeName != "etudiants":
             raise ValueError
         etudiants = dom.getElementsByTagName("etudiant")
         for etudiant in etudiants:
@@ -252,9 +249,7 @@ def xml_to_list_of_dicts(doc, req=None):
                 if e.nodeType == e.ELEMENT_NODE:
                     childs = e.childNodes
                     if len(childs):
-                        d[str(e.nodeName)] = childs[0].nodeValue.encode(
-                            scu.SCO_ENCODING
-                        )
+                        d[str(e.nodeName)] = childs[0].nodeValue
             infos.append(d)
     except:
         log("*** invalid XML response from Etudiant Web Service")
@@ -320,7 +315,7 @@ def get_etud_apogee(code_nip):
     if not etud_url:
         return {}
     portal_timeout = sco_preferences.get_preference("portal_timeout")
-    req = etud_url + "?" + six.moves.urllib.parse.urlencode((("nip", code_nip),))
+    req = etud_url + "?" + urllib.parse.urlencode((("nip", code_nip),))
     doc = scu.query_portal(req, timeout=portal_timeout)
     d = _normalize_apo_fields(xml_to_list_of_dicts(doc, req=req))
     if not d:
@@ -356,13 +351,13 @@ def _parse_etapes_from_xml(doc):
     # parser XML
     dom = xml.dom.minidom.parseString(doc)
     infos = {}
-    if dom.childNodes[0].nodeName != u"etapes":
+    if dom.childNodes[0].nodeName != "etapes":
         raise ValueError
     if xml_etapes_by_dept:
         # Ancien format XML avec des sections par departement:
         for d in dom.childNodes[0].childNodes:
             if d.nodeType == d.ELEMENT_NODE:
-                dept = d.nodeName.encode(scu.SCO_ENCODING)
+                dept = d.nodeName
                 _xml_list_codes(infos, dept, d.childNodes)
     else:
         # Toutes les étapes:
@@ -411,8 +406,8 @@ def get_etapes_apogee():
 def _xml_list_codes(target_dict, dept, nodes):
     for e in nodes:
         if e.nodeType == e.ELEMENT_NODE:
-            intitule = e.childNodes[0].nodeValue.encode(scu.SCO_ENCODING)
-            code = e.attributes["code"].value.encode(scu.SCO_ENCODING)
+            intitule = e.childNodes[0].nodeValue
+            code = e.attributes["code"].value
             if dept in target_dict:
                 target_dict[dept][code] = intitule
             else:
@@ -558,9 +553,7 @@ def get_maquette_apogee(etape="", annee_scolaire=""):
     req = (
         maquette_url
         + "?"
-        + six.moves.urllib.parse.urlencode(
-            (("etape", etape), ("annee", annee_scolaire))
-        )
+        + urllib.parse.urlencode((("etape", etape), ("annee", annee_scolaire)))
     )
     doc = scu.query_portal(req, timeout=portal_timeout)
     return doc
diff --git a/app/scodoc/sco_pvpdf.py b/app/scodoc/sco_pvpdf.py
index 2872c2acb..262d77506 100644
--- a/app/scodoc/sco_pvpdf.py
+++ b/app/scodoc/sco_pvpdf.py
@@ -200,7 +200,7 @@ class CourrierIndividuelTemplate(PageTemplate):
         self.logo_header = None
         # Search logos in dept specific dir, then in global scu.CONFIG dir
         for image_dir in (
-            scu.SCODOC_LOGOS_DIR + "/logos_" + scu.get_dept_id(),
+            scu.SCODOC_LOGOS_DIR + "/logos_" + g.scodoc_dept,
             scu.SCODOC_LOGOS_DIR,  # global logos
         ):
             for suffix in scu.LOGOS_IMAGES_ALLOWED_TYPES:
diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py
index 8f7209f24..e7890a847 100644
--- a/app/scodoc/sco_saisie_notes.py
+++ b/app/scodoc/sco_saisie_notes.py
@@ -958,7 +958,6 @@ def saisie_notes(evaluation_id, group_ids=[], REQUEST=None):
     )
     if form is None:
         log(f"redirecting to {destination}")
-        stop
         return flask.redirect(destination)
     H.append(form)
     #
diff --git a/app/scodoc/sco_synchro_etuds.py b/app/scodoc/sco_synchro_etuds.py
index 92012a4f3..c9d0bb4a2 100644
--- a/app/scodoc/sco_synchro_etuds.py
+++ b/app/scodoc/sco_synchro_etuds.py
@@ -114,10 +114,11 @@ def formsemestre_synchro_etuds(
     if anneeapogee:
         base_url += "&anneeapogee=%s" % anneeapogee
 
-    if anneeapogee == None:  # année d'inscription par défaut
-        anneeapogee = str(
-            scu.annee_scolaire_debut(sem["annee_debut"], sem["mois_debut_ord"])
+    if anneeapogee is None:  # année d'inscription par défaut
+        anneeapogee = scu.annee_scolaire_debut(
+            sem["annee_debut"], sem["mois_debut_ord"]
         )
+    anneeapogee = str(anneeapogee)
 
     if type(etuds) == type(""):
         etuds = etuds.split(",")  # vient du form de confirmation
@@ -132,7 +133,7 @@ def formsemestre_synchro_etuds(
         inscrits_without_key_all,
         etudsapo_ident,
     ) = list_synch(sem, anneeapogee=anneeapogee)
-
+    breakpoint()
     if export_cat_xls:
         filename = export_cat_xls
         xls = build_page(
@@ -155,6 +156,7 @@ def formsemestre_synchro_etuds(
             read_only=read_only,
         )
     else:
+        breakpoint()
         etuds_set = set(etuds)
         a_importer = a_importer.intersection(etuds_set)
         a_desinscrire = inscrits_set - etuds_set
@@ -499,7 +501,7 @@ def list_all(etudsapo_set):
     # d'interrogation par etudiant.
     cnx = ndb.GetDBConnexion()
     cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
-    cursor.execute("select " + EKEY_SCO + ", etudid from identite")
+    cursor.execute("SELECT " + EKEY_SCO + ", id AS etudid FROM identite")
     key2etudid = dict([(x[0], x[1]) for x in cursor.fetchall()])
     all_set = set(key2etudid.keys())
 
@@ -654,7 +656,7 @@ def do_import_etuds_from_portal(sem, a_importer, etudsapo_ident, REQUEST):
                 {"etudid": etudid},
             )
             cursor.execute(
-                "delete from identite where etudid=%(etudid)s", {"etudid": etudid}
+                "delete from identite where id=%(etudid)s", {"etudid": etudid}
             )
         cnx.commit()
         log("do_import_etuds_from_portal: re-raising exception")
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 853a23b15..ec6b492ff 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -317,9 +317,6 @@ TYPES_ADMISSION = (TYPE_ADMISSION_DEFAULT, "APB", "APB-PC", "CEF", "Direct")
 BULLETINS_VERSIONS = ("short", "selectedevals", "long")
 
 # Support for ScoDoc7 compatibility
-def get_dept_id():
-    "acronyme du dept courant"
-    return g.scodoc_dept  # en scodoc 8.1 #sco8
 
 
 def ScoURL():
diff --git a/scotests/fakeportal/fakeportal.py b/scotests/fakeportal/fakeportal.py
index 94b2a78a7..0775729c3 100755
--- a/scotests/fakeportal/fakeportal.py
+++ b/scotests/fakeportal/fakeportal.py
@@ -53,6 +53,7 @@ def make_random_etape_etuds(etape, annee):
     """Liste d'etudiants d'une etape"""
     random.seed(etape + annee)
     nb = random.randint(0, 50)
+    print(f"generating {nb} students")
     L = []
     for i in range(nb):
         if i % 2: