From 2d6d74737150ac8720a3a18baef0ec940868e909 Mon Sep 17 00:00:00 2001 From: theo Date: Wed, 15 Apr 2026 18:44:44 +0200 Subject: [PATCH] Rendre le script portable (Docker/Windows) et ajout de l'auto-ouverture du navigateur --- webapp.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/webapp.py b/webapp.py index 59f2cf6..4824c07 100644 --- a/webapp.py +++ b/webapp.py @@ -6,18 +6,24 @@ import pandas as pd import pdfplumber import unicodedata import traceback +import webbrowser +from threading import Timer from flask import Flask, request, render_template_string, Response, send_from_directory, redirect app = Flask(__name__) -# Dossiers et fichiers -TEMP_DIR = "/app/downloads" -if not os.path.exists(TEMP_DIR): os.makedirs(TEMP_DIR) +# --- ADAPTATION DES CHEMINS (AUTO-DETECTION) --- +# Si on est dans Docker, on utilise /app, sinon le dossier local +BASE_DIR = "/app" if os.path.exists("/app") else os.getcwd() + +TEMP_DIR = os.path.join(BASE_DIR, "downloads") +if not os.path.exists(TEMP_DIR): + os.makedirs(TEMP_DIR) TEMP_DATA_FILE = os.path.join(TEMP_DIR, "temp_data.json") TEMP_MISSING_FILE = os.path.join(TEMP_DIR, "temp_missing.json") -CSV_FILE = "/app/corresp_IGPDE.csv" -ODS_FILE = "/app/corresp_IGPDE.ods" +CSV_FILE = os.path.join(BASE_DIR, "corresp_IGPDE.csv") +ODS_FILE = os.path.join(BASE_DIR, "corresp_IGPDE.ods") RESULT_FILE = os.path.join(TEMP_DIR, "resultat.xlsx") # --- GESTION DE LA BASE DE DONNÉES --- @@ -47,11 +53,10 @@ COMMON_STYLE = """ .nav-btn { background: #fff; border: 1px solid #cbd5e0; padding: 8px 15px; border-radius: 8px; text-decoration: none; color: #4a5568; font-size: 0.9rem; transition: 0.2s; } .nav-btn:hover { background: #edf2f7; } .nav-btn.active { background: #3182ce; color: white; border-color: #3182ce; } - .card { background: white; padding: 2rem; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); max-width: 1200px; margin: 0 auto; } + .card { background: white; padding: 2rem; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); max-width: 1100px; margin: 0 auto; } h1 { color: #2d3748; margin-top: 0; font-size: 1.5rem; } .header-box { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .btn-submit { background: #3182ce; color: white; border: none; padding: 10px 20px; border-radius: 8px; font-size: 0.9rem; cursor: pointer; font-weight: 600; text-decoration: none; display: inline-block; } - .btn-submit:hover { background: #2b6cb0; } #log-window { background: #1a202c; color: #cbd5e0; padding: 15px; border-radius: 10px; height: 350px; overflow-y: auto; font-family: 'Courier New', monospace; font-size: 0.85rem; text-align: left; margin-top: 20px; line-height: 1.6; border: 1px solid #2d3748; } .log-success { color: #68d391; font-weight: bold; } .log-warn { color: #fc8181; } @@ -129,6 +134,7 @@ def process(): data[col] = row[1].replace('\n', ' ').strip() break all_formations.append(data) + # Nettoyage sécurisé pour les logs JS t_log = titre_brut[:40].replace("'", " ").replace('"', ' ') yield f"" except Exception: pass @@ -194,14 +200,22 @@ def finalize(): f['Nouvelle nomenclature'] = mapping_dict.get(super_norm(key), mapping_dict.get(super_norm(f['Chapitre']), "")) df = pd.DataFrame(all_formations).fillna('') cols = ['Nouvelle nomenclature', 'Chapitre', 'Sous-chapitre', 'Titre', 'Page_Source'] + [c for c in df.columns if c not in ['Nouvelle nomenclature', 'Chapitre', 'Sous-chapitre', 'Titre', 'Page_Source']] - df_f = df[[c for c in cols if c in df.columns]] - df_f.to_excel(RESULT_FILE, index=False, engine='xlsxwriter') + df_cols = [c for c in cols if c in df.columns] + df[df_cols].to_excel(RESULT_FILE, index=False, engine='xlsxwriter') return redirect("/view_result") @app.route("/download") def download(): return send_from_directory(TEMP_DIR, "resultat.xlsx", as_attachment=True) @app.route("/download_db") -def download_db(): return send_from_directory("/app", "corresp_IGPDE.csv", as_attachment=True) +def download_db(): return send_from_directory(BASE_DIR, "corresp_IGPDE.csv", as_attachment=True) -if __name__ == "__main__": app.run(host='0.0.0.0', port=5000) +# --- LANCEMENT AUTOMATIQUE --- +def open_browser(): + webbrowser.open_new("http://127.0.0.1:5000") + +if __name__ == "__main__": + # N'ouvre le navigateur que si on n'est PAS dans Docker + if not os.path.exists("/app"): + Timer(1.5, open_browser).start() + app.run(host='0.0.0.0', port=5000)