From 70db38bbb4e870bb26886eb2b32c48f1396bac8e Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Tue, 12 Apr 2022 11:32:13 +0200 Subject: [PATCH] added python-docx --- app/scodoc/sco_news.py | 274 ----------------------------------------- requirements-3.9.txt | 4 +- 2 files changed, 3 insertions(+), 275 deletions(-) delete mode 100644 app/scodoc/sco_news.py diff --git a/app/scodoc/sco_news.py b/app/scodoc/sco_news.py deleted file mode 100644 index a516ddba..00000000 --- a/app/scodoc/sco_news.py +++ /dev/null @@ -1,274 +0,0 @@ -# -*- mode: python -*- -# -*- coding: utf-8 -*- - -############################################################################## -# -# Gestion scolarite IUT -# -# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Emmanuel Viennet emmanuel.viennet@viennet.net -# -############################################################################## - -"""Gestion des "nouvelles" -""" -import re -import time - - -from operator import itemgetter - -from flask import g -from flask_login import current_user - -import app.scodoc.sco_utils as scu -import app.scodoc.notesdb as ndb -from app import log -from app.scodoc import sco_formsemestre -from app.scodoc import sco_moduleimpl -from app.scodoc import sco_preferences -from app import email - - -_scolar_news_editor = ndb.EditableTable( - "scolar_news", - "news_id", - ("date", "authenticated_user", "type", "object", "text", "url"), - filter_dept=True, - sortkey="date desc", - output_formators={"date": ndb.DateISOtoDMY}, - input_formators={"date": ndb.DateDMYtoISO}, - html_quote=False, # no user supplied data, needed to store html links -) - -NEWS_INSCR = "INSCR" # inscription d'étudiants (object=None ou formsemestre_id) -NEWS_NOTE = "NOTES" # saisie note (object=moduleimpl_id) -NEWS_FORM = "FORM" # modification formation (object=formation_id) -NEWS_SEM = "SEM" # creation semestre (object=None) -NEWS_MISC = "MISC" # unused -NEWS_MAP = { - NEWS_INSCR: "inscription d'étudiants", - NEWS_NOTE: "saisie note", - NEWS_FORM: "modification formation", - NEWS_SEM: "création semestre", - NEWS_MISC: "opération", # unused -} -NEWS_TYPES = list(NEWS_MAP.keys()) - -scolar_news_create = _scolar_news_editor.create -scolar_news_list = _scolar_news_editor.list - -_LAST_NEWS = {} # { (authuser_name, type, object) : time } - - -def add(typ, object=None, text="", url=None, max_frequency=False): - """Ajoute une nouvelle. - Si max_frequency, ne genere pas 2 nouvelles identiques à moins de max_frequency - secondes d'intervalle. - """ - from app.scodoc import sco_users - - authuser_name = current_user.user_name - cnx = ndb.GetDBConnexion() - args = { - "authenticated_user": authuser_name, - "user_info": sco_users.user_info(authuser_name), - "type": typ, - "object": object, - "text": text, - "url": url, - } - 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") - return - - log("news: %s" % args) - - _LAST_NEWS[(authuser_name, typ, object)] = t - - _send_news_by_mail(args) - return scolar_news_create(cnx, args) - - -def scolar_news_summary(n=5): - """Return last n news. - News are "compressed", ie redondant events are joined. - """ - from app.scodoc import sco_users - - cnx = ndb.GetDBConnexion() - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - cursor.execute( - """SELECT id AS news_id, * - FROM scolar_news - WHERE dept_id=%(dept_id)s - ORDER BY date DESC LIMIT 100 - """, - {"dept_id": g.scodoc_dept_id}, - ) - selected_news = {} # (type,object) : news dict - news = cursor.dictfetchall() # la plus récente d'abord - - for r in reversed(news): # la plus ancienne d'abord - # si on a deja une news avec meme (type,object) - # et du meme jour, on la remplace - dmy = ndb.DateISOtoDMY(r["date"]) # round - key = (r["type"], r["object"], dmy) - selected_news[key] = r - - news = list(selected_news.values()) - # sort by date, descending - news.sort(key=itemgetter("date"), reverse=True) - news = news[:n] - # mimic EditableTable.list output formatting: - for n in news: - n["date822"] = n["date"].strftime("%a, %d %b %Y %H:%M:%S %z") - # heure - n["hm"] = n["date"].strftime("%Hh%M") - for k in n.keys(): - if n[k] is None: - n[k] = "" - if k in _scolar_news_editor.output_formators: - n[k] = _scolar_news_editor.output_formators[k](n[k]) - # date resumee - j, m = n["date"].split("/")[:2] - mois = scu.MONTH_NAMES_ABBREV[int(m) - 1] - n["formatted_date"] = f'{j} {mois} {n["hm"]}' - # indication semestre si ajout notes: - infos = _get_formsemestre_infos_from_news(n) - if infos: - n["text"] += ( - ' (%(descr_sem)s)' - % infos - ) - n["text"] += ( - " par " + sco_users.user_info(n["authenticated_user"])["nomcomplet"] - ) - return news - - -def _get_formsemestre_infos_from_news(n): - """Informations sur le semestre concerné par la nouvelle n - {} si inexistant - """ - formsemestre_id = None - if n["type"] == NEWS_INSCR: - formsemestre_id = n["object"] - elif n["type"] == NEWS_NOTE: - moduleimpl_id = n["object"] - if n["object"]: - mods = sco_moduleimpl.moduleimpl_list(moduleimpl_id=moduleimpl_id) - if not mods: - return {} # module does not exists anymore - mod = mods[0] - formsemestre_id = mod["formsemestre_id"] - - if not formsemestre_id: - return {} - - try: - sem = sco_formsemestre.get_formsemestre(formsemestre_id) - except ValueError: - # semestre n'existe plus - return {} - - if sem["semestre_id"] > 0: - descr_sem = f'S{sem["semestre_id"]}' - else: - descr_sem = "" - if sem["modalite"]: - descr_sem += " " + sem["modalite"] - return {"formsemestre_id": formsemestre_id, "sem": sem, "descr_sem": descr_sem} - - -def scolar_news_summary_html(n=5): - """News summary, formated in HTML""" - news = scolar_news_summary(n=n) - if not news: - return "" - H = ['
Dernières opérations'] - H.append('") - - # Informations générales - H.append( - """
- Pour être informé des évolutions de ScoDoc, - vous pouvez vous - - abonner à la liste de diffusion. -
- """ - % scu.SCO_ANNONCES_WEBSITE - ) - - H.append("
") - return "\n".join(H) - - -def _send_news_by_mail(n): - """Notify by email""" - infos = _get_formsemestre_infos_from_news(n) - formsemestre_id = infos.get("formsemestre_id", None) - prefs = sco_preferences.SemPreferences(formsemestre_id=formsemestre_id) - destinations = prefs["emails_notifications"] or "" - destinations = [x.strip() for x in destinations.split(",")] - destinations = [x for x in destinations if x] - if not destinations: - return - # - txt = n["text"] - if infos: - txt += "\n\nSemestre %(titremois)s\n\n" % infos["sem"] - txt += ( - """%(descr_sem)s - """ - % infos - ) - txt += "\n\nEffectué par: %(nomcomplet)s\n" % n["user_info"] - - txt = ( - "\n" - + txt - + """\n ---- Ceci est un message de notification automatique issu de ScoDoc ---- vous recevez ce message car votre adresse est indiquée dans les paramètres de ScoDoc. -""" - ) - - # Transforme les URL en URL absolue - base = scu.ScoURL() - txt = re.sub('href=.*?"', 'href="' + base + "/", txt) - - # Transforme les liens HTML en texte brut: 'texte' devient 'texte: url' - # (si on veut des messages non html) - txt = re.sub(r'(.*?)', r"\2: \1", txt) - - subject = "[ScoDoc] " + NEWS_MAP.get(n["type"], "?") - sender = prefs["email_from_addr"] - - email.send_email(subject, sender, destinations, txt) diff --git a/requirements-3.9.txt b/requirements-3.9.txt index b4a10ac1..2f91f07a 100755 --- a/requirements-3.9.txt +++ b/requirements-3.9.txt @@ -1,5 +1,5 @@ alembic==1.7.5 -astroid==2.9.1 +astroid==2.11.2 attrs==21.4.0 Babel==2.9.1 blinker==1.4 @@ -35,6 +35,7 @@ isort==5.10.1 itsdangerous==2.0.1 Jinja2==3.0.3 lazy-object-proxy==1.7.1 +lxml==4.8.0 Mako==1.1.6 MarkupSafe==2.0.1 mccabe==0.6.1 @@ -53,6 +54,7 @@ pyOpenSSL==21.0.0 pyparsing==3.0.6 pytest==6.2.5 python-dateutil==2.8.2 +python-docx==0.8.11 python-dotenv==0.19.2 python-editor==1.0.4 pytz==2021.3