Cyrano2 commited on
Commit
b3c128e
·
verified ·
1 Parent(s): 155e956

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -0
app.py CHANGED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MimiReady Python Executor Backend
3
+ Exécute du code Python avec TensorFlow/Keras sur Hugging Face Spaces
4
+ """
5
+
6
+ from fastapi import FastAPI, HTTPException
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from pydantic import BaseModel
9
+ from typing import List, Optional
10
+ import sys
11
+ import io
12
+ import base64
13
+ import traceback
14
+ from contextlib import redirect_stdout, redirect_stderr
15
+
16
+ # Configuration matplotlib avant import
17
+ import matplotlib
18
+ matplotlib.use('Agg')
19
+ import matplotlib.pyplot as plt
20
+
21
+ app = FastAPI(title="MimiReady Python Executor")
22
+
23
+ # CORS pour permettre les requêtes depuis le frontend
24
+ app.add_middleware(
25
+ CORSMiddleware,
26
+ allow_origins=["*"],
27
+ allow_credentials=True,
28
+ allow_methods=["*"],
29
+ allow_headers=["*"],
30
+ )
31
+
32
+ class CodeRequest(BaseModel):
33
+ code: str
34
+ timeout: int = 30
35
+
36
+ class CodeResponse(BaseModel):
37
+ stdout: str
38
+ stderr: str
39
+ plots: List[str]
40
+ success: bool
41
+ error: Optional[str] = None
42
+
43
+ # Variables globales pour capturer les plots
44
+ _plot_images: List[str] = []
45
+
46
+ def capture_plots():
47
+ """Capture tous les plots matplotlib en base64"""
48
+ global _plot_images
49
+ _plot_images = []
50
+
51
+ original_show = plt.show
52
+
53
+ def patched_show(*args, **kwargs):
54
+ global _plot_images
55
+ buf = io.BytesIO()
56
+ plt.savefig(buf, format='png', dpi=100, bbox_inches='tight', facecolor='white')
57
+ buf.seek(0)
58
+ img_str = base64.b64encode(buf.read()).decode('utf-8')
59
+ _plot_images.append(img_str)
60
+ plt.clf()
61
+ plt.close('all')
62
+
63
+ plt.show = patched_show
64
+ return original_show
65
+
66
+ def restore_show(original_show):
67
+ """Restaure plt.show original"""
68
+ plt.show = original_show
69
+
70
+ @app.get("/")
71
+ def read_root():
72
+ return {
73
+ "service": "MimiReady Python Executor",
74
+ "status": "running",
75
+ "capabilities": ["numpy", "pandas", "matplotlib", "scikit-learn", "tensorflow", "keras"]
76
+ }
77
+
78
+ @app.get("/health")
79
+ def health_check():
80
+ return {"status": "healthy"}
81
+
82
+ @app.post("/execute", response_model=CodeResponse)
83
+ async def execute_code(request: CodeRequest):
84
+ """Exécute du code Python et retourne les résultats"""
85
+ global _plot_images
86
+
87
+ stdout_capture = io.StringIO()
88
+ stderr_capture = io.StringIO()
89
+
90
+ # Préparer l'environnement d'exécution
91
+ exec_globals = {
92
+ "__builtins__": __builtins__,
93
+ "__name__": "__main__",
94
+ }
95
+
96
+ # Pre-import des bibliothèques courantes
97
+ try:
98
+ import numpy as np
99
+ exec_globals["np"] = np
100
+ exec_globals["numpy"] = np
101
+ except ImportError:
102
+ pass
103
+
104
+ try:
105
+ import pandas as pd
106
+ exec_globals["pd"] = pd
107
+ exec_globals["pandas"] = pd
108
+ except ImportError:
109
+ pass
110
+
111
+ try:
112
+ import sklearn
113
+ exec_globals["sklearn"] = sklearn
114
+ except ImportError:
115
+ pass
116
+
117
+ # TensorFlow/Keras
118
+ try:
119
+ import tensorflow as tf
120
+ from tensorflow import keras
121
+ exec_globals["tf"] = tf
122
+ exec_globals["tensorflow"] = tf
123
+ exec_globals["keras"] = keras
124
+ except ImportError as e:
125
+ print(f"TensorFlow import warning: {e}")
126
+
127
+ # Matplotlib
128
+ exec_globals["plt"] = plt
129
+ exec_globals["matplotlib"] = matplotlib
130
+
131
+ success = True
132
+ error_msg = None
133
+
134
+ original_show = capture_plots()
135
+
136
+ try:
137
+ with redirect_stdout(stdout_capture), redirect_stderr(stderr_capture):
138
+ exec(request.code, exec_globals)
139
+ except Exception as e:
140
+ success = False
141
+ error_msg = f"{type(e).__name__}: {str(e)}\n{traceback.format_exc()}"
142
+ finally:
143
+ restore_show(original_show)
144
+
145
+ return CodeResponse(
146
+ stdout=stdout_capture.getvalue(),
147
+ stderr=stderr_capture.getvalue(),
148
+ plots=_plot_images.copy(),
149
+ success=success,
150
+ error=error_msg
151
+ )
152
+
153
+ if __name__ == "__main__":
154
+ import uvicorn
155
+ uvicorn.run(app, host="0.0.0.0", port=7860)