Spaces:
Build error
Build error
Update src/dashboard_app.py
Browse files- src/dashboard_app.py +86 -5
src/dashboard_app.py
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
import streamlit as st
|
| 3 |
import pandas as pd
|
|
@@ -76,14 +99,52 @@ def load_data(source_type, source_value, header_param, sep=None, db_config=None)
|
|
| 76 |
if not sep: sep = '\t'
|
| 77 |
data = pd.read_csv(io.StringIO(pasted_str), sep=sep, header=header_param)
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
elif source_type == "database" and db_config:
|
| 80 |
-
|
| 81 |
query = db_config['query']
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
-
if data is not None and error_message is None:
|
| 87 |
if data.empty:
|
| 88 |
error_message = "Les données chargées sont vides."
|
| 89 |
data = None
|
|
@@ -1574,6 +1635,26 @@ with manual_tab:
|
|
| 1574 |
st.markdown("""
|
| 1575 |
Bienvenue ! Ce guide vous aide à utiliser efficacement cette application pour analyser vos données.
|
| 1576 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1577 |
---
|
| 1578 |
### 1. Chargement des Données (Barre Latérale ⚙️)
|
| 1579 |
- **Choisir une méthode** : Sélectionnez l'une des options proposées (URL, Coller depuis presse-papiers, Charger depuis une base de données).
|
|
|
|
| 1 |
+
# Copyright (c) 2025 Sidoine YEBADOKPO
|
| 2 |
+
# All rights reserved.
|
| 3 |
+
#
|
| 4 |
+
# Redistribution and use in source and binary forms, with or without
|
| 5 |
+
# modification, are permitted provided that the following conditions are met:
|
| 6 |
+
#
|
| 7 |
+
# 1. Redistributions of source code must retain the above copyright notice, this
|
| 8 |
+
# list of conditions and the following disclaimer.
|
| 9 |
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
| 10 |
+
# this list of conditions and the following disclaimer in the documentation
|
| 11 |
+
# and/or other materials provided with the distribution.
|
| 12 |
+
#
|
| 13 |
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
| 14 |
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 15 |
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 16 |
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
| 17 |
+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 18 |
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| 19 |
+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
| 20 |
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 21 |
+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| 22 |
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 23 |
+
|
| 24 |
import os
|
| 25 |
import streamlit as st
|
| 26 |
import pandas as pd
|
|
|
|
| 99 |
if not sep: sep = '\t'
|
| 100 |
data = pd.read_csv(io.StringIO(pasted_str), sep=sep, header=header_param)
|
| 101 |
|
| 102 |
+
elif source_type == "url" and source_value:
|
| 103 |
+
url = source_value
|
| 104 |
+
source_info_text = f"URL chargée : {url}"
|
| 105 |
+
data_id = f"url_{hash(url)}"
|
| 106 |
+
# Basic URL validation
|
| 107 |
+
if not (url.startswith('http://') or url.startswith('https://')):
|
| 108 |
+
error_message = "L'URL doit commencer par http:// ou https://."
|
| 109 |
+
elif url.endswith('.csv'):
|
| 110 |
+
data = pd.read_csv(url, header=header_param)
|
| 111 |
+
elif url.endswith('.xlsx'):
|
| 112 |
+
data = pd.read_excel(url, header=header_param, engine='openpyxl')
|
| 113 |
+
else:
|
| 114 |
+
error_message = "URL non supportée (doit finir par .csv ou .xlsx)."
|
| 115 |
+
|
| 116 |
+
elif source_type == "paste" and source_value:
|
| 117 |
+
pasted_str = source_value
|
| 118 |
+
source_info_text = "Données collées"
|
| 119 |
+
data_id = f"paste_{hash(pasted_str)}"
|
| 120 |
+
if not sep: sep = '\t'
|
| 121 |
+
data = pd.read_csv(io.StringIO(pasted_str), sep=selected_sep, header=header_param)
|
| 122 |
+
|
| 123 |
elif source_type == "database" and db_config:
|
| 124 |
+
db_path = db_config['database']
|
| 125 |
query = db_config['query']
|
| 126 |
+
source_info_text = f"Base de données : {db_path}"
|
| 127 |
+
data_id = f"db_{hash(db_path)}_{hash(query)}"
|
| 128 |
+
|
| 129 |
+
# --- Sécurité: Validation basique de la requête SQL ---
|
| 130 |
+
# AVERTISSEMENT: Ceci n'est PAS une protection complète contre l'injection SQL.
|
| 131 |
+
# Une protection robuste nécessiterait de ne pas permettre des requêtes arbitraires
|
| 132 |
+
# ou d'utiliser des requêtes paramétrées si l'input utilisateur est limité aux valeurs.
|
| 133 |
+
# Ici, nous ajoutons une vérification basique pour les mots-clés dangereux.
|
| 134 |
+
# L'utilisateur doit être conscient des risques s'il utilise des sources non fiables.
|
| 135 |
+
dangerous_keywords = ['DROP TABLE', 'DELETE FROM', 'UPDATE', 'INSERT INTO', 'ALTER TABLE', 'CREATE TABLE']
|
| 136 |
+
if any(keyword in query.upper() for keyword in dangerous_keywords):
|
| 137 |
+
error_message = "La requête contient des mots-clés potentiellement dangereux (DROP, DELETE, UPDATE, INSERT, ALTER, CREATE). Requête bloquée pour des raisons de sécurité."
|
| 138 |
+
data = None # Assurez-vous que data est None en cas d'erreur de sécurité
|
| 139 |
+
else:
|
| 140 |
+
try:
|
| 141 |
+
conn = sqlite3.connect(db_path)
|
| 142 |
+
data = pd.read_sql_query(query, conn)
|
| 143 |
+
except Exception as db_e:
|
| 144 |
+
error_message = f"Erreur base de données: {db_e}"
|
| 145 |
+
data = None # Assurez-vous que data est None en cas d'erreur
|
| 146 |
|
| 147 |
+
if data is not None and error_message is None: # Vérifier data is not None ici aussi
|
| 148 |
if data.empty:
|
| 149 |
error_message = "Les données chargées sont vides."
|
| 150 |
data = None
|
|
|
|
| 1635 |
st.markdown("""
|
| 1636 |
Bienvenue ! Ce guide vous aide à utiliser efficacement cette application pour analyser vos données.
|
| 1637 |
|
| 1638 |
+
---
|
| 1639 |
+
### Comment Citer cette Application
|
| 1640 |
+
Si vous utilisez la "Suite d'Analyse de Données Interactive" dans vos travaux, présentations ou publications, nous vous serions reconnaissants de la citer comme suit :
|
| 1641 |
+
|
| 1642 |
+
**YEBADOKPO, Sidoine. (2025). *Suite d'Analyse de Données Interactive* (Version 1.0) \[Application Web]. Hugging Face Spaces. Accessible à : `https://huggingface.co/spaces/Sidoineko/Exploratory`**
|
| 1643 |
+
|
| 1644 |
+
Pour une citation incluant la date de consultation :
|
| 1645 |
+
|
| 1646 |
+
YEBADOKPO, S. (2025). Suite d'Analyse de Données Interactive (Version 1.0). https://huggingface.co/spaces/Sidoineko/Exploratory
|
| 1647 |
+
|
| 1648 |
+
Concernant le nom "Exploratory" vs "Suite d'Analyse de Données Interactive" :
|
| 1649 |
+
L'URL de votre Space est .../Exploratory. C'est l'identifiant technique sur Hugging Face.
|
| 1650 |
+
Le titre affiché dans l'application (via st.set_page_config(page_title="Suite d'Analyse Interactive") et vos st.markdown) est "Suite d'Analyse Interactive" ou "Suite d'Analyse de Données Interactive".
|
| 1651 |
+
Pour la citation, il est généralement préférable d'utiliser le titre le plus complet et descriptif que vous utilisez pour présenter l'application à l'utilisateur. Donc, "Suite d'Analyse de Données Interactive" est un bon choix. L'URL avec /Exploratory pointe simplement vers l'emplacement technique.
|
| 1652 |
+
|
| 1653 |
+
Ce que vous pouvez mettre dans la vidéo (slide de fin ou mention orale) :
|
| 1654 |
+
"Retrouvez la Suite d'Analyse de Données Interactive (v1.0) par Sidoine YEBADOKPO sur huggingface.co/spaces/Sidoineko/Exploratory."
|
| 1655 |
+
Ou, si vous incluez une section "Comment Citer" dans l'application :
|
| 1656 |
+
"Pour savoir comment citer cet outil, consultez la section 'Manuel d'Utilisation' directement dans l'application."
|
| 1657 |
+
|
| 1658 |
---
|
| 1659 |
### 1. Chargement des Données (Barre Latérale ⚙️)
|
| 1660 |
- **Choisir une méthode** : Sélectionnez l'une des options proposées (URL, Coller depuis presse-papiers, Charger depuis une base de données).
|