@@ -49,51 +49,61 @@ along with pythonOCC. If not, see <http://www.gnu.org/licenses/>.
49
49
#endif
50
50
51
51
// Utility function to get a readable class name
52
- const char * get_readable_class_name (const char * class_name) noexcept {
53
- if (! class_name || strcmp (class_name, " $parentclassname " ) == 0 || class_name[ 0 ] == ' \0 ' ) {
52
+ std::string get_readable_class_name (const std::string& class_name) {
53
+ if (class_name. empty () || class_name == " $parentclassname " ) {
54
54
return " Unknown" ;
55
55
}
56
56
return class_name;
57
57
}
58
58
59
59
// Utility function to get a readable method name
60
- const char * get_readable_method_name (const char * method_name) noexcept {
61
- if (! method_name || strcmp (method_name, " $name " ) == 0 || method_name[ 0 ] == ' \0 ' ) {
60
+ std::string get_readable_method_name (const std::string& method_name) {
61
+ if (method_name. empty () || method_name == " $name " ) {
62
62
return " Unknown" ;
63
63
}
64
64
return method_name;
65
65
}
66
66
67
67
// Mapping OpenCASCADE exceptions to appropriate Python exceptions
68
68
PyObject* get_exception_type (const Standard_Failure& error) {
69
- static const std::vector<std::pair<std::string, PyObject*>> exception_map = {
70
- {" OutOfRange" , PyExc_IndexError},
71
- {" RangeError" , PyExc_IndexError},
72
- {" OutOfMemory" , PyExc_MemoryError},
73
- {" NullObject" , PyExc_ValueError},
74
- {" NullValue" , PyExc_ValueError},
75
- {" TypeMismatch" , PyExc_TypeError},
76
- {" NotImplemented" , PyExc_NotImplementedError},
77
- {" NoSuchObject" , PyExc_KeyError},
78
- {" DimensionError" , PyExc_ValueError},
79
- {" DomainError" , PyExc_ValueError},
80
- {" NumericError" , PyExc_ArithmeticError},
81
- {" Overflow" , PyExc_ArithmeticError},
82
- {" Underflow" , PyExc_ArithmeticError},
83
- {" TooManyUsers" , PyExc_ResourceWarning}
84
- };
85
-
86
- const char * type_name_cstr = error.DynamicType ()->Name ();
87
- const std::string type_name (type_name_cstr);
88
-
89
- // Iterate over the table to find the mapping
90
- for (const auto & mapping : exception_map) {
91
- if (type_name.find (mapping.first ) != std::string::npos) {
92
- return mapping.second ;
93
- }
69
+ const Handle (Standard_Type)& error_type = error.DynamicType ();
70
+ const std::string type_name = error_type->Name ();
71
+
72
+ // Specific error type mapping
73
+ if (type_name.find (" OutOfRange" ) != std::string::npos ||
74
+ type_name.find (" RangeError" ) != std::string::npos) {
75
+ return PyExc_IndexError;
94
76
}
95
-
96
- // Valeur par défaut si aucune correspondance n'est trouvée.
77
+ else if (type_name.find (" OutOfMemory" ) != std::string::npos) {
78
+ return PyExc_MemoryError;
79
+ }
80
+ else if (type_name.find (" NullObject" ) != std::string::npos ||
81
+ type_name.find (" NullValue" ) != std::string::npos) {
82
+ return PyExc_ValueError;
83
+ }
84
+ else if (type_name.find (" TypeMismatch" ) != std::string::npos) {
85
+ return PyExc_TypeError;
86
+ }
87
+ else if (type_name.find (" NotImplemented" ) != std::string::npos) {
88
+ return PyExc_NotImplementedError;
89
+ }
90
+ else if (type_name.find (" NoSuchObject" ) != std::string::npos) {
91
+ return PyExc_KeyError;
92
+ }
93
+ else if (type_name.find (" DimensionError" ) != std::string::npos ||
94
+ type_name.find (" DomainError" ) != std::string::npos) {
95
+ return PyExc_ValueError;
96
+ }
97
+ else if (type_name.find (" NumericError" ) != std::string::npos ||
98
+ type_name.find (" Overflow" ) != std::string::npos ||
99
+ type_name.find (" Underflow" ) != std::string::npos) {
100
+ return PyExc_ArithmeticError;
101
+ }
102
+ else if (type_name.find (" TooManyUsers" ) != std::string::npos) {
103
+ return PyExc_ResourceWarning;
104
+ }
105
+
106
+ // Default to RuntimeError
97
107
return PyExc_RuntimeError;
98
108
}
99
109
@@ -102,38 +112,39 @@ void process_opencascade_exception(const Standard_Failure& error,
102
112
const std::string& method_name,
103
113
const std::string& class_name) {
104
114
std::ostringstream oss;
105
-
115
+
106
116
// Basic error information
107
- const char * error_type = error.DynamicType ()->Name ();
108
- const char * error_message = error.GetMessageString ();
109
- const char * readable_class = get_readable_class_name (class_name. c_str () );
110
- const char * readable_method = get_readable_method_name (method_name. c_str () );
111
-
117
+ const std::string error_type = error.DynamicType ()->Name ();
118
+ const std::string error_message = error.GetMessageString ();
119
+ const std::string readable_class = get_readable_class_name (class_name);
120
+ const std::string readable_method = get_readable_method_name (method_name);
121
+
112
122
// Error message construction
113
123
oss << " OpenCASCADE Error [" << error_type << " ]" ;
114
-
115
- if (error_message && *error_message) { // check c string is not empty or null
124
+
125
+ if (! error_message. empty ()) {
116
126
oss << " : " << error_message;
117
127
}
118
-
128
+
119
129
oss << " (in " << readable_class;
120
- if (strcmp ( readable_method, " Unknown " ) != 0 ) {
130
+ if (readable_method != " Unknown " ) {
121
131
oss << " ::" << readable_method;
122
132
}
123
133
oss << " )" ;
124
-
134
+
125
135
// Debug information if enabled
126
136
#if PYTHONOCC_DEBUG_EXCEPTIONS
127
137
std::cerr << " [pythonOCC Debug] " << oss.str () << std::endl;
128
138
#endif
129
-
139
+
130
140
// Set Python exception with appropriate type
131
141
PyObject* exception_type = get_exception_type (error);
132
142
PyErr_SetString (exception_type, oss.str ().c_str ());
133
143
}
134
144
135
145
%}
136
146
147
+ // Enhanced exception macro with hierarchical exception handling
137
148
%exception
138
149
{
139
150
try
0 commit comments