@@ -3,7 +3,8 @@ use std::cell::UnsafeCell;
3
3
use crate :: {
4
4
exceptions:: { PyBaseException , PyTypeError } ,
5
5
ffi,
6
- types:: { PyTraceback , PyType } ,
6
+ ffi_ptr_ext:: FfiPtrExt ,
7
+ types:: { PyAnyMethods , PyTraceback , PyType } ,
7
8
Bound , Py , PyAny , PyErrArguments , PyObject , PyTypeInfo , Python ,
8
9
} ;
9
10
@@ -34,19 +35,6 @@ impl PyErrState {
34
35
} ) ) )
35
36
}
36
37
37
- #[ cfg( not( Py_3_12 ) ) ]
38
- pub ( crate ) fn ffi_tuple (
39
- ptype : PyObject ,
40
- pvalue : Option < PyObject > ,
41
- ptraceback : Option < PyObject > ,
42
- ) -> Self {
43
- Self :: from_inner ( PyErrStateInner :: FfiTuple {
44
- ptype,
45
- pvalue,
46
- ptraceback,
47
- } )
48
- }
49
-
50
38
pub ( crate ) fn normalized ( normalized : PyErrStateNormalized ) -> Self {
51
39
Self :: from_inner ( PyErrStateInner :: Normalized ( normalized) )
52
40
}
@@ -151,19 +139,61 @@ impl PyErrStateNormalized {
151
139
152
140
#[ cfg( Py_3_12 ) ]
153
141
pub ( crate ) fn ptraceback < ' py > ( & self , py : Python < ' py > ) -> Option < Bound < ' py , PyTraceback > > {
154
- use crate :: ffi_ptr_ext:: FfiPtrExt ;
155
- use crate :: types:: any:: PyAnyMethods ;
156
142
unsafe {
157
143
ffi:: PyException_GetTraceback ( self . pvalue . as_ptr ( ) )
158
144
. assume_owned_or_opt ( py)
159
145
. map ( |b| b. downcast_into_unchecked ( ) )
160
146
}
161
147
}
162
148
163
- #[ cfg( Py_3_12 ) ]
164
149
pub ( crate ) fn take ( py : Python < ' _ > ) -> Option < PyErrStateNormalized > {
165
- unsafe { Py :: from_owned_ptr_or_opt ( py, ffi:: PyErr_GetRaisedException ( ) ) }
166
- . map ( |pvalue| PyErrStateNormalized { pvalue } )
150
+ #[ cfg( Py_3_12 ) ]
151
+ {
152
+ // Safety: PyErr_GetRaisedException can be called when attached to Python and
153
+ // returns either NULL or an owned reference.
154
+ unsafe { ffi:: PyErr_GetRaisedException ( ) . assume_owned_or_opt ( py) } . map ( |pvalue| {
155
+ PyErrStateNormalized {
156
+ // Safety: PyErr_GetRaisedException returns a valid exception type.
157
+ pvalue : unsafe { pvalue. downcast_into_unchecked ( ) } . unbind ( ) ,
158
+ }
159
+ } )
160
+ }
161
+
162
+ #[ cfg( not( Py_3_12 ) ) ]
163
+ {
164
+ let ( ptype, pvalue, ptraceback) = unsafe {
165
+ let mut ptype: * mut ffi:: PyObject = std:: ptr:: null_mut ( ) ;
166
+ let mut pvalue: * mut ffi:: PyObject = std:: ptr:: null_mut ( ) ;
167
+ let mut ptraceback: * mut ffi:: PyObject = std:: ptr:: null_mut ( ) ;
168
+
169
+ ffi:: PyErr_Fetch ( & mut ptype, & mut pvalue, & mut ptraceback) ;
170
+
171
+ // Ensure that the exception coming from the interpreter is normalized.
172
+ if !ptype. is_null ( ) {
173
+ ffi:: PyErr_NormalizeException ( & mut ptype, & mut pvalue, & mut ptraceback) ;
174
+ }
175
+
176
+ // Safety: PyErr_NormalizeException will have produced up to three owned
177
+ // references of the correct types.
178
+ (
179
+ ptype
180
+ . assume_owned_or_opt ( py)
181
+ . map ( |b| b. downcast_into_unchecked ( ) ) ,
182
+ pvalue
183
+ . assume_owned_or_opt ( py)
184
+ . map ( |b| b. downcast_into_unchecked ( ) ) ,
185
+ ptraceback
186
+ . assume_owned_or_opt ( py)
187
+ . map ( |b| b. downcast_into_unchecked ( ) ) ,
188
+ )
189
+ } ;
190
+
191
+ ptype. map ( |ptype| PyErrStateNormalized {
192
+ ptype : ptype. unbind ( ) ,
193
+ pvalue : pvalue. expect ( "normalized exception value missing" ) . unbind ( ) ,
194
+ ptraceback : ptraceback. map ( Bound :: unbind) ,
195
+ } )
196
+ }
167
197
}
168
198
169
199
#[ cfg( not( Py_3_12 ) ) ]
@@ -204,12 +234,6 @@ pub(crate) type PyErrStateLazyFn =
204
234
205
235
enum PyErrStateInner {
206
236
Lazy ( Box < PyErrStateLazyFn > ) ,
207
- #[ cfg( not( Py_3_12 ) ) ]
208
- FfiTuple {
209
- ptype : PyObject ,
210
- pvalue : Option < PyObject > ,
211
- ptraceback : Option < PyObject > ,
212
- } ,
213
237
Normalized ( PyErrStateNormalized ) ,
214
238
}
215
239
@@ -231,20 +255,6 @@ impl PyErrStateInner {
231
255
PyErrStateNormalized :: take ( py)
232
256
. expect ( "exception missing after writing to the interpreter" )
233
257
}
234
- #[ cfg( not( Py_3_12 ) ) ]
235
- PyErrStateInner :: FfiTuple {
236
- ptype,
237
- pvalue,
238
- ptraceback,
239
- } => {
240
- let mut ptype = ptype. into_ptr ( ) ;
241
- let mut pvalue = pvalue. map_or ( std:: ptr:: null_mut ( ) , Py :: into_ptr) ;
242
- let mut ptraceback = ptraceback. map_or ( std:: ptr:: null_mut ( ) , Py :: into_ptr) ;
243
- unsafe {
244
- ffi:: PyErr_NormalizeException ( & mut ptype, & mut pvalue, & mut ptraceback) ;
245
- PyErrStateNormalized :: from_normalized_ffi_tuple ( py, ptype, pvalue, ptraceback)
246
- }
247
- }
248
258
PyErrStateInner :: Normalized ( normalized) => normalized,
249
259
}
250
260
}
@@ -253,15 +263,6 @@ impl PyErrStateInner {
253
263
fn restore ( self , py : Python < ' _ > ) {
254
264
let ( ptype, pvalue, ptraceback) = match self {
255
265
PyErrStateInner :: Lazy ( lazy) => lazy_into_normalized_ffi_tuple ( py, lazy) ,
256
- PyErrStateInner :: FfiTuple {
257
- ptype,
258
- pvalue,
259
- ptraceback,
260
- } => (
261
- ptype. into_ptr ( ) ,
262
- pvalue. map_or ( std:: ptr:: null_mut ( ) , Py :: into_ptr) ,
263
- ptraceback. map_or ( std:: ptr:: null_mut ( ) , Py :: into_ptr) ,
264
- ) ,
265
266
PyErrStateInner :: Normalized ( PyErrStateNormalized {
266
267
ptype,
267
268
pvalue,
0 commit comments