robust null checking for process_response
Browse files- python_code_executor_service.py +71 -43
python_code_executor_service.py
CHANGED
@@ -196,54 +196,82 @@ class PythonExecutor:
|
|
196 |
return str(result)
|
197 |
|
198 |
async def process_response(self, response: CsvChatResult, chat_id: str) -> str:
|
199 |
-
|
200 |
-
|
|
|
|
|
|
|
201 |
|
202 |
-
|
203 |
-
|
|
|
204 |
operation = response.analysis_operations
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
elif result is not None:
|
214 |
-
# Handle empty/None results
|
215 |
-
if result is None or (hasattr(result, '__len__') and len(result) == 0):
|
216 |
-
output_parts.append(f"\n⚠️ Values are missing - Operation '{operation.result_var}' returned no data")
|
217 |
else:
|
218 |
-
|
219 |
-
|
220 |
-
else:
|
221 |
-
output_str = execution_result['output'].strip()
|
222 |
-
if output_str:
|
223 |
-
output_parts.append("```\n" + output_str + "\n```")
|
224 |
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
output_parts.append(
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
else:
|
246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
|
248 |
return "\n".join(output_parts)
|
249 |
|
|
|
196 |
return str(result)
|
197 |
|
198 |
async def process_response(self, response: CsvChatResult, chat_id: str) -> str:
|
199 |
+
"""Process the response with comprehensive error handling"""
|
200 |
+
if not response or not response.casual_response:
|
201 |
+
return "⚠️ Error: Empty response received"
|
202 |
+
|
203 |
+
output_parts = [response.casual_response]
|
204 |
|
205 |
+
# Process analysis operation if present and valid
|
206 |
+
if hasattr(response, 'analysis_operations') and response.analysis_operations:
|
207 |
+
try:
|
208 |
operation = response.analysis_operations
|
209 |
+
|
210 |
+
# Validate operation structure
|
211 |
+
if not hasattr(operation, 'code') or not operation.code:
|
212 |
+
output_parts.append("\n⚠️ Analysis operation missing code")
|
213 |
+
elif not hasattr(operation.code, 'code') or not operation.code.code:
|
214 |
+
output_parts.append("\n⚠️ Analysis operation has empty code")
|
215 |
+
elif not hasattr(operation, 'result_var') or not operation.result_var:
|
216 |
+
output_parts.append("\n⚠️ Analysis operation missing result variable")
|
|
|
|
|
|
|
|
|
217 |
else:
|
218 |
+
# Execute the operation if all checks pass
|
219 |
+
execution_result = self.execute_code(operation.code.code)
|
|
|
|
|
|
|
|
|
220 |
|
221 |
+
if execution_result.get('error'):
|
222 |
+
output_parts.append(f"\n❌ Error in analysis operation:")
|
223 |
+
output_parts.append("```python\n" + execution_result['error']['message'] + "\n```")
|
224 |
+
else:
|
225 |
+
result = self.exec_locals.get(operation.result_var)
|
226 |
+
|
227 |
+
if result is None:
|
228 |
+
output_parts.append(f"\n⚠️ Operation completed but no result found in variable '{operation.result_var}'")
|
229 |
+
elif hasattr(result, '__len__') and len(result) == 0:
|
230 |
+
output_parts.append("\n⚠️ Operation returned empty results")
|
231 |
+
else:
|
232 |
+
output_parts.append(f"\n🔹 Operation results:")
|
233 |
+
output_parts.append("```python\n" + self._format_result(result) + "\n```")
|
234 |
+
|
235 |
+
if execution_result.get('output'):
|
236 |
+
output_parts.append("Console output:\n```\n" + execution_result['output'] + "\n```")
|
237 |
+
|
238 |
+
except Exception as e:
|
239 |
+
output_parts.append(f"\n❌ Unexpected error processing analysis operation: {str(e)}")
|
240 |
+
|
241 |
+
# Process chart if present and valid
|
242 |
+
if hasattr(response, 'charts') and response.charts:
|
243 |
+
try:
|
244 |
+
chart = response.charts
|
245 |
+
|
246 |
+
# Validate chart structure
|
247 |
+
if not hasattr(chart, 'image_description') or not chart.image_description:
|
248 |
+
output_parts.append("\n⚠️ Chart missing description")
|
249 |
+
elif not hasattr(chart, 'code') or not chart.code:
|
250 |
+
output_parts.append("\n⚠️ Chart specification missing code")
|
251 |
else:
|
252 |
+
chart_result = self.execute_code(chart.code)
|
253 |
+
|
254 |
+
if chart_result.get('error'):
|
255 |
+
output_parts.append(f"\n❌ Error generating chart '{chart.image_description}':")
|
256 |
+
output_parts.append("```python\n" + chart_result['error']['message'] + "\n```")
|
257 |
+
elif not chart_result.get('plots'):
|
258 |
+
output_parts.append(f"\n⚠️ No chart generated for '{chart.image_description}'")
|
259 |
+
else:
|
260 |
+
output_parts.append("\n📊 Visualization:")
|
261 |
+
for plot_data in chart_result['plots']:
|
262 |
+
try:
|
263 |
+
public_url = await self.save_plot_to_supabase(
|
264 |
+
plot_data=plot_data,
|
265 |
+
description=chart.image_description,
|
266 |
+
chat_id=chat_id
|
267 |
+
)
|
268 |
+
output_parts.append(f"\n🖼️ {chart.image_description}")
|
269 |
+
output_parts.append(f"")
|
270 |
+
except Exception as upload_error:
|
271 |
+
output_parts.append(f"\n⚠️ Failed to upload chart: {str(upload_error)}")
|
272 |
+
|
273 |
+
except Exception as e:
|
274 |
+
output_parts.append(f"\n❌ Unexpected error processing chart: {str(e)}")
|
275 |
|
276 |
return "\n".join(output_parts)
|
277 |
|