devjas1 commited on
Commit
177dc98
Β·
1 Parent(s): 566edf3

(FEAT) add centralized error handling utilty for the polymer classification app: utils/error.py

Browse files

Improves code maintainability and clarity

Lays groundwork for consistent error management across the project

Files changed (1) hide show
  1. utils/errors.py +126 -0
utils/errors.py CHANGED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Centralized error handling utility for the polymer classification app.
2
+ Provides consistent error logging and graceful UI error reporting"""
3
+
4
+ import streamlit as st
5
+ import traceback
6
+
7
+ # Define a constant for error messages
8
+ ERROR = "[ERROR]"
9
+
10
+ class ErrorHandler:
11
+ """Centralized error handler for the application"""
12
+
13
+ @staticmethod
14
+ def log_error(error: Exception, context: str = "", include_traceback: bool = False) -> None:
15
+ """Log error to session state for display in UI"""
16
+ if "log_messages" not in st.session_state:
17
+ st.session_state["log_messages"] = []
18
+
19
+ error_msg = f"{ERROR} {context}: {str(error)}" if context else f"{ERROR} {str(error)}"
20
+
21
+ if include_traceback:
22
+ error_msg += f"\nTraceback: {traceback.format_exc()}"
23
+
24
+ st.session_state["log_messages"].append(error_msg)
25
+
26
+ @staticmethod
27
+ def log_warning(message: str, context: str = "") -> None:
28
+ """Log warning to session state"""
29
+ if "log_messages" not in st.session_state:
30
+ st.session_state["log_messages"] = []
31
+
32
+ warning_msg = f"[WARNING] {context}: {message}" if context else f"[WARNING] {message}"
33
+ st.session_state["log_messages"].append(warning_msg)
34
+
35
+ @staticmethod
36
+ def log_info(message: str, context: str = "") -> None:
37
+ """Log info message to session state"""
38
+ if "log_messages" not in st.session_state:
39
+ st.session_state["log_messages"] = []
40
+
41
+ info_msg = f"[INFO] {context}: {message}" if context else f"[INFO] {message}"
42
+ st.session_state["log_messages"].append(info_msg)
43
+
44
+ @staticmethod
45
+ def handle_file_error(filename: str, error: Exception) -> str:
46
+ """Handle file processing errors and return user-friendly message"""
47
+ ErrorHandler.log_error(error, f"File processing: {filename}")
48
+
49
+ if isinstance(error, FileNotFoundError):
50
+ return f"❌ File not found: {filename}"
51
+ elif isinstance(error, PermissionError):
52
+ return f"❌ Permission denied accessing: {filename}"
53
+ elif isinstance(error, (ValueError, TypeError)):
54
+ return f"❌ Invalid file format in: {filename}. Please ensure it contains wavenumber and intensity columns."
55
+ else:
56
+ return f"❌ Error processing file: {filename}. {str(error)}"
57
+
58
+ @staticmethod
59
+ def handle_inference_error(model_name: str, error: Exception) -> str:
60
+ """Handle model inference errors and return user-friendly message"""
61
+ ErrorHandler.log_error(error, f"Model inference: {model_name}")
62
+
63
+ if "CUDA" in str(error) or "device" in str(error).lower():
64
+ return f"❌ Device error with model {model_name}. Falling back to CPU."
65
+ elif "shape" in str(error).lower() or "dimension" in str(error).lower():
66
+ return f"❌ Input shape mismatch for model {model_name}. Please check spectrum data format."
67
+ else:
68
+ return f"❌ Inference failed for model {model_name}: {str(error)}"
69
+
70
+ @staticmethod
71
+ def handle_parsing_error(filename: str, error: Exception) -> str:
72
+ """Handle spectrum parsing errors and return user-friendly message"""
73
+ ErrorHandler.log_error(error, f"Spectrum parsing: {filename}")
74
+
75
+ if "could not convert" in str(error).lower():
76
+ return f"❌ Invalid data format in {filename}. Expected numeric wavenumber and intensity columns."
77
+ elif "empty" in str(error).lower():
78
+ return f"❌ File {filename} appears to be empty or contains no valid data."
79
+ elif "columns" in str(error).lower():
80
+ return f"❌ File {filename} must contain exactly 2 columns (wavenumber, intensity)."
81
+ else:
82
+ return f"❌ Failed to parse spectrum data from {filename}: {str(error)}"
83
+
84
+ @staticmethod
85
+ def clear_logs() -> None:
86
+ """Clear all logged messages"""
87
+ st.session_state["log_messages"] = []
88
+
89
+ @staticmethod
90
+ def get_logs() -> list[str]:
91
+ """Get all logged messages"""
92
+ return st.session_state.get("log_messages", [])
93
+
94
+ @staticmethod
95
+ def display_error_ui(error_message: str, show_details: bool = False) -> None:
96
+ """Display error in Streamlit UI with optional details"""
97
+ st.error(error_message)
98
+
99
+ if show_details and st.session_state.get("log_messages"):
100
+ with st.expander("Error Details", expanded=False):
101
+ for msg in st.session_state["log_messages"][-5:]: # Show last 5 log entries
102
+ st.text(msg)
103
+
104
+ def safe_execute(func, *args, error_context: str = "", show_error: bool = True, **kwargs):
105
+ """
106
+ Safely execute a function with error handling
107
+
108
+ Args:
109
+ func: Function to execute
110
+ *args: Arguments for the function
111
+ error_context: Context description for error logging
112
+ show_error: Whether to show error in UI
113
+ **kwargs: Keyword arguments for the function
114
+
115
+ Returns:
116
+ Tuple of (result, success_flag)
117
+ """
118
+ try:
119
+ result = func(*args, **kwargs)
120
+ return result, True
121
+ except Exception as e:
122
+ ErrorHandler.log_error(e, error_context)
123
+ if show_error:
124
+ error_msg = f"Error in {error_context}: {str(e)}" if error_context else str(e)
125
+ st.error(error_msg)
126
+ return None, False