diff --git a/app/__init__.py b/app/__init__.py index 7521520e0..76760bd79 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -10,6 +10,7 @@ import traceback import logging from logging.handlers import SMTPHandler, WatchedFileHandler +from threading import Thread from flask import current_app, g, request from flask import Flask @@ -27,6 +28,7 @@ import sqlalchemy from app.scodoc.sco_exceptions import ( AccessDenied, + ScoBugCatcher, ScoGenError, ScoValueError, APIInvalidParams, @@ -77,6 +79,28 @@ def internal_server_error(exc): ) +def handle_sco_bug(exc): + """Un bug, en général rare, sur lequel les dev cherchent des + informations pour le corriger. + """ + Thread( + target=_async_dump, args=(current_app._get_current_object(), request.url) + ).start() + + return internal_server_error(exc) + + +def _async_dump(app, request_url: str): + from app.scodoc.sco_dump_db import sco_dump_and_send_db + + with app.app_context(): + ndb.open_db_connection() + try: + sco_dump_and_send_db("ScoBugCatcher", request_url=request_url) + except ScoValueError: + pass + + def handle_invalid_usage(error): response = jsonify(error.to_dict()) response.status_code = error.status_code @@ -196,7 +220,7 @@ def create_app(config_class=DevConfig): app.register_error_handler(ScoGenError, handle_sco_value_error) app.register_error_handler(ScoValueError, handle_sco_value_error) - + app.register_error_handler(ScoBugCatcher, handle_sco_bug) app.register_error_handler(AccessDenied, handle_access_denied) app.register_error_handler(500, internal_server_error) app.register_error_handler(503, postgresql_server_error) diff --git a/app/scodoc/sco_bulletins_standard.py b/app/scodoc/sco_bulletins_standard.py index f1b2b7cc7..e42a38847 100644 --- a/app/scodoc/sco_bulletins_standard.py +++ b/app/scodoc/sco_bulletins_standard.py @@ -49,6 +49,7 @@ Balises img: actuellement interdites. from reportlab.platypus import KeepTogether, Paragraph, Spacer, Table from reportlab.lib.units import cm, mm from reportlab.lib.colors import Color, blue +from app.scodoc.sco_exceptions import ScoBugCatcher import app.scodoc.sco_utils as scu from app.scodoc.sco_pdf import SU @@ -416,7 +417,11 @@ class BulletinGeneratorStandard(sco_bulletins_generator.BulletinGenerator): # Chaque UE: for ue in I["ues"]: ue_type = None - coef_ue = ue["coef_ue_txt"] if prefs["bul_show_ue_coef"] else "" + try: + coef_ue = ue["coef_ue_txt"] if prefs["bul_show_ue_coef"] else "" + except TypeError as exc: + raise ScoBugCatcher(f"ue={ue!r}") from exc + ue_descr = ue["ue_descr_txt"] rowstyle = "" plusminus = minuslink # diff --git a/app/scodoc/sco_dump_db.py b/app/scodoc/sco_dump_db.py index 190cec961..fd0b15c0d 100644 --- a/app/scodoc/sco_dump_db.py +++ b/app/scodoc/sco_dump_db.py @@ -51,14 +51,12 @@ import fcntl import subprocess import requests -from flask import flash, request +from flask import g, request from flask_login import current_user import app.scodoc.notesdb as ndb import app.scodoc.sco_utils as scu from app import log -from app.scodoc import html_sco_header -from app.scodoc import sco_preferences from app.scodoc import sco_users import sco_version from app.scodoc.sco_exceptions import ScoValueError @@ -68,8 +66,7 @@ SCO_DUMP_LOCK = "/tmp/scodump.lock" def sco_dump_and_send_db(message: str = "", request_url: str = ""): """Dump base de données et l'envoie anonymisée pour debug""" - H = [html_sco_header.sco_header(page_title="Assistance technique")] - # get currect (dept) DB name: + # get current (dept) DB name: cursor = ndb.SimpleQuery("SELECT current_database()", {}) db_name = cursor.fetchone()[0] ano_db_name = "ANO" + db_name @@ -96,27 +93,7 @@ def sco_dump_and_send_db(message: str = "", request_url: str = ""): # Send r = _send_db(ano_db_name, message, request_url) - if ( - r.status_code - == requests.codes.INSUFFICIENT_STORAGE # pylint: disable=no-member - ): - H.append( - """

- Erreur: espace serveur trop plein. - Merci de contacter {0}

""".format( - scu.SCO_DEV_MAIL - ) - ) - elif r.status_code == requests.codes.OK: # pylint: disable=no-member - H.append("""

Opération effectuée.

""") - else: - H.append( - """

- Erreur: code {0} {1} - Merci de contacter {2}

""".format( - r.status_code, r.reason, scu.SCO_DEV_MAIL - ) - ) + code = r.status_code finally: # Drop anonymized database @@ -125,8 +102,8 @@ def sco_dump_and_send_db(message: str = "", request_url: str = ""): fcntl.flock(x, fcntl.LOCK_UN) log("sco_dump_and_send_db: done.") - flash("Données envoyées au serveur d'assistance") - return "\n".join(H) + html_sco_header.sco_footer() + + return code def _duplicate_db(db_name, ano_db_name): @@ -195,7 +172,7 @@ def _send_db(ano_db_name: str, message: str = "", request_url: str = ""): scu.SCO_DUMP_UP_URL, files=files, data={ - "dept_name": sco_preferences.get_preference("DeptName"), + "dept_name": getattr(g, "scodoc_dept", "-"), "message": message or "", "request_url": request_url or request.url, "serial": _get_scodoc_serial(), diff --git a/app/scodoc/sco_exceptions.py b/app/scodoc/sco_exceptions.py index 394dbf1e5..35d2d9d6e 100644 --- a/app/scodoc/sco_exceptions.py +++ b/app/scodoc/sco_exceptions.py @@ -47,9 +47,12 @@ class ScoValueError(ScoException): self.dest_url = dest_url +class ScoBugCatcher(ScoException): + "bug avec enquete en cours" + + class NoteProcessError(ScoValueError): "Valeurs notes invalides" - pass class InvalidEtudId(NoteProcessError): diff --git a/app/views/notes.py b/app/views/notes.py index c8587c4fb..7a9e50673 100644 --- a/app/views/notes.py +++ b/app/views/notes.py @@ -73,6 +73,7 @@ from app.scodoc.scolog import logdb from app.scodoc.sco_exceptions import ( AccessDenied, + ScoBugCatcher, ScoException, ScoValueError, ScoInvalidIdType, diff --git a/app/views/scolar.py b/app/views/scolar.py index 67cb7b7b6..a25994bd9 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -30,7 +30,7 @@ issu de ScoDoc7 / ZScolar.py Emmanuel Viennet, 2021 """ -import os +import requests import time import flask @@ -2198,4 +2198,24 @@ def stat_bac(formsemestre_id): @scodoc7func def sco_dump_and_send_db(message="", request_url=""): "Send anonymized data to supervision" - return sco_dump_db.sco_dump_and_send_db(message, request_url) + + status_code = sco_dump_db.sco_dump_and_send_db(message, request_url) + H = [html_sco_header.sco_header(page_title="Assistance technique")] + if status_code == requests.codes.INSUFFICIENT_STORAGE: # pylint: disable=no-member + H.append( + """

+ Erreur: espace serveur trop plein. + Merci de contacter {0}

""".format( + scu.SCO_DEV_MAIL + ) + ) + elif status_code == requests.codes.OK: # pylint: disable=no-member + H.append("""

Opération effectuée.

""") + else: + H.append( + f"""

+ Erreur: code {status_code} + Merci de contacter {scu.SCO_DEV_MAIL}

""" + ) + flash("Données envoyées au serveur d'assistance") + return "\n".join(H) + html_sco_header.sco_footer() diff --git a/sco_version.py b/sco_version.py index 0cedeb3dc..547202122 100644 --- a/sco_version.py +++ b/sco_version.py @@ -1,7 +1,7 @@ # -*- mode: python -*- # -*- coding: utf-8 -*- -SCOVERSION = "9.1.82" +SCOVERSION = "9.1.83" SCONAME = "ScoDoc"