diff --git a/app/scodoc/gen_tables.py b/app/scodoc/gen_tables.py index a318f93ee..e594cdb2d 100644 --- a/app/scodoc/gen_tables.py +++ b/app/scodoc/gen_tables.py @@ -60,6 +60,7 @@ from app.scodoc import sco_pdf from app.scodoc import sco_xml from app.scodoc.sco_pdf import SU from app import log +from app.scodoc.sco_utils import flaskPDFResponse def mark_paras(L, tags): @@ -648,30 +649,35 @@ class GenTable(object): objects, title=title, preferences=self.preferences ) if publish: - return scu.sendPDFFile(REQUEST, doc, filename + ".pdf") + return scu.PDF_FORMAT.send_file(doc, filename, add_suffix=True, attached=True) + # return scu.flaskPDFResponse(doc, filename + ".pdf") + # return scu.sendPDFFile(REQUEST, doc, filename + ".pdf") else: return doc elif format == "xls" or format == "xlsx": xls = self.excel() if publish: - return sco_excel.send_excel_file( - REQUEST, xls, filename + scu.XLSX_SUFFIX - ) + return scu.XLSX_FORMAT.send_file(xls, filename, add_suffix=True, attached=True) + # return sco_excel.send_from_flask(xls, filename + scu.XLSX_SUFFIX) + # return sco_excel.send_excel_file(REQUEST, xls, filename + scu.XLSX_SUFFIX) else: return xls elif format == "text": return self.text() elif format == "csv": - return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv") + return scu.CSV_FORMAT.send_file(self.text(), filename, add_suffix=True, attached=True) + # return scu.sendCSVFile(REQUEST, self.text(), filename + ".csv") elif format == "xml": xml = self.xml() - if REQUEST and publish: - REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) - return xml + if publish: + # REQUEST.RESPONSE.setHeader("content-type", scu.XML_MIMETYPE) + # return xml + return scu.XML_FORMAT.send_file(self.xml) elif format == "json": js = self.json() - if REQUEST and publish: - REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE) + if publish: + return scu.JSON_FORMAT.send_file(self.xml) + # REQUEST.RESPONSE.setHeader("content-type", scu.JSON_MIMETYPE) return js else: log("make_page: format=%s" % format) diff --git a/app/scodoc/sco_excel.py b/app/scodoc/sco_excel.py index 337d33f08..54728a16c 100644 --- a/app/scodoc/sco_excel.py +++ b/app/scodoc/sco_excel.py @@ -66,7 +66,7 @@ class COLORS(Enum): def send_from_flask(data, filename, mime=scu.XLSX_MIMETYPE): - scu.make_filename(filename) + filename = scu.make_filename(filename) response = make_response(data) response.headers['Content-Type'] = mime response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index e39d5f747..500c5a98b 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -310,10 +310,7 @@ class PlacementRunner: return plan def _production_xls(self): - filename = scu.make_filename( - "placement_%s_%s%s" - % (self.evalname, self.gr_title_filename, scu.XLSX_SUFFIX) - ) + filename = "placement_%s_%s%s" % (self.evalname, self.gr_title_filename, scu.XLSX_SUFFIX) xls = self._excel_feuille_placement() return sco_excel.send_from_flask(xls, filename) @@ -323,8 +320,8 @@ class PlacementRunner: "Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" % self.eval_data ) - - filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self + breakpoint() + filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % self.__dict__ titles = { "nom": "Nom", "prenom": "Prenom", @@ -339,7 +336,7 @@ class PlacementRunner: columns_ids = ["nom", "prenom", "place"] rows = [] - for etud in sorted(plan, key=lambda etud: etud[0][0]): # sort by name + for etud in sorted(self.plan, key=lambda item: item[0][0]): # sort by name if self.etiquetage == COORD: rows.append( { @@ -362,7 +359,7 @@ class PlacementRunner: + "", pdf_title=pdf_title, # pdf_shorttitle = '', - preferences=sco_preferences.SemPreferences(M["formsemestre_id"]), + preferences=sco_preferences.SemPreferences(self.moduleimpl_data["formsemestre_id"]), # html_generate_cells=False # la derniere ligne (moyennes) est incomplete ) t = tab.make_page(format="pdf", with_html_headers=False, REQUEST=REQUEST) diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index b897110fd..96a4d796c 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -49,7 +49,7 @@ import unicodedata import urllib from xml.etree import ElementTree -from flask import g, current_app +from flask import g, current_app, make_response from PIL import Image as PILImage @@ -64,7 +64,6 @@ from app.scodoc import sco_exceptions from app.scodoc import sco_xml import sco_version - # ----- CALCUL ET PRESENTATION DES NOTES NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis NOTES_MIN = 0.0 # valeur minimale admise pour une note (sauf malus, dans [-20, 20]) @@ -73,7 +72,6 @@ NOTES_NEUTRALISE = -1000.0 # notes non prises en comptes dans moyennes NOTES_SUPPRESS = -1001.0 # note a supprimer NOTES_ATTENTE = -1002.0 # note "en attente" (se calcule comme une note neutralisee) - # Types de modules MODULE_STANDARD = 0 MODULE_MALUS = 1 @@ -88,7 +86,7 @@ IT_SITUATION_MISSING_STR = ( "____" # shown on ficheEtud (devenir) in place of empty situation ) -RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente +RANG_ATTENTE_STR = "(attente)" # rang affiché sur bulletins quand notes en attente # borne supérieure de chaque mention NOTES_MENTIONS_TH = ( @@ -234,11 +232,9 @@ if not os.path.exists(SCO_TMP_DIR): SCODOC_LOGOS_DIR = os.path.join(SCODOC_CFG_DIR, "logos") LOGOS_IMAGES_ALLOWED_TYPES = ("jpg", "jpeg", "png") # remind that PIL does not read pdf - # ----- Les outils distribués SCO_TOOLS_DIR = os.path.join(Config.SCODOC_DIR, "tools") - # ----- Lecture du fichier de configuration from app.scodoc import sco_config from app.scodoc import sco_config_load @@ -272,7 +268,6 @@ else: SCO_ENCODING = "utf-8" # used by Excel, XML, PDF, ... - SCO_DEFAULT_SQL_USER = "scodoc" # should match Zope process UID SCO_DEFAULT_SQL_PORT = "5432" SCO_DEFAULT_SQL_USERS_CNX = "dbname=SCOUSERS port=%s" % SCO_DEFAULT_SQL_PORT @@ -304,8 +299,11 @@ XLS_MIMETYPE = "application/vnd.ms-excel" XLSX_MIMETYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" XLSX_SUFFIX = ".xlsx" PDF_MIMETYPE = "application/pdf" +PDF_SUFFIX = ".pdf" XML_MIMETYPE = "text/xml" +XML_SUFFIX = ".xml" JSON_MIMETYPE = "application/json" +JSON_SUFFIX = ".json" # Admissions des étudiants # Différents types de voies d'admission: @@ -315,6 +313,31 @@ TYPES_ADMISSION = (TYPE_ADMISSION_DEFAULT, "APB", "APB-PC", "CEF", "Direct") BULLETINS_VERSIONS = ("short", "selectedevals", "long") + +# File format management +class FileFormat: + def __init__(self, suffix, mime): + self._mime = mime + self._suffix = suffix + + def send_file(self, data, filename, add_suffix=False, attached=False): + filename = make_filename(filename) + if add_suffix: + filename += self._suffix + response = make_response(data) + response.headers['Content-Type'] = self._mime + if attached: + response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename + return response + + +CSV_FORMAT = FileFormat(CSV_SUFFIX, CSV_MIMETYPE) +XLSX_FORMAT = FileFormat(XLSX_SUFFIX, XLSX_MIMETYPE) +XLS_FORMAT = FileFormat(XLS_SUFFIX, XLS_MIMETYPE) +PDF_FORMAT = FileFormat(PDF_SUFFIX, PDF_MIMETYPE) +XML_FORMAT = FileFormat(XML_SUFFIX, XML_MIMETYPE) +JSON_FORMAT = FileFormat(JSON_SUFFIX, JSON_MIMETYPE) + # Support for ScoDoc7 compatibility @@ -324,8 +347,8 @@ def ScoURL(): = page accueil département """ return url_for("scolar.index_html", scodoc_dept=g.scodoc_dept)[ - : -len("/index_html") - ] + : -len("/index_html") + ] def NotesURL(): @@ -352,8 +375,8 @@ def EntreprisesURL(): def AbsencesURL(): """URL of Absences""" return url_for("absences.index_html", scodoc_dept=g.scodoc_dept)[ - : -len("/index_html") - ] + : -len("/index_html") + ] def UsersURL(): @@ -439,8 +462,8 @@ def suppress_accents(s): if isinstance(s, str): return ( unicodedata.normalize("NFD", s) - .encode("ascii", "ignore") - .decode(SCO_ENCODING) + .encode("ascii", "ignore") + .decode(SCO_ENCODING) ) return s # may be int @@ -504,6 +527,14 @@ def sendCSVFile(REQUEST, data, filename): return data +def flaskPDFResponse(data, filename, mime=PDF_MIMETYPE): + filename = make_filename(filename) + response = make_response(data) + response.headers['Content-Type'] = mime + response.headers['Content-Disposition'] = 'attachment; filename="%s"' % filename + return response + + def sendPDFFile(REQUEST, data, filename): filename = ( unescape_html(suppress_accents(filename)).replace("&", "").replace(" ", "_") @@ -641,7 +672,7 @@ def sem_decale_str(sem): if sem["semestre_id"] <= 0: return "" if (sem["semestre_id"] % 2 and sem["mois_debut_ord"] <= 6) or ( - not sem["semestre_id"] % 2 and sem["mois_debut_ord"] > 6 + not sem["semestre_id"] % 2 and sem["mois_debut_ord"] > 6 ): return "D" else: @@ -800,15 +831,15 @@ def return_text_if_published(val, REQUEST): def confirm_dialog( - message="
Confirmer ?
", - OK="OK", - Cancel="Annuler", - dest_url="", - cancel_url="", - target_variable="dialog_confirmed", - parameters={}, - add_headers=True, # complete page - helpmsg=None, + message="Confirmer ?
", + OK="OK", + Cancel="Annuler", + dest_url="", + cancel_url="", + target_variable="dialog_confirmed", + parameters={}, + add_headers=True, # complete page + helpmsg=None, ): from app.scodoc import html_sco_header @@ -850,7 +881,7 @@ def confirm_dialog( H.append('' + helpmsg + "
") if add_headers: return ( - html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer() + html_sco_header.sco_header() + "\n".join(H) + html_sco_header.sco_footer() ) else: return "\n".join(H)