(&self, exception: &Py<PyBaseException>)
| 2079 | } |
| 2080 | |
| 2081 | pub(crate) fn contextualize_exception(&self, exception: &Py<PyBaseException>) { |
| 2082 | if let Some(context_exc) = self.topmost_exception() |
| 2083 | && !context_exc.is(exception) |
| 2084 | { |
| 2085 | // Traverse the context chain to find `exception` and break cycles |
| 2086 | // Uses Floyd's cycle detection: o moves every step, slow_o every other step |
| 2087 | let mut o = context_exc.clone(); |
| 2088 | let mut slow_o = context_exc.clone(); |
| 2089 | let mut slow_update_toggle = false; |
| 2090 | while let Some(context) = o.__context__() { |
| 2091 | if context.is(exception) { |
| 2092 | o.set___context__(None); |
| 2093 | break; |
| 2094 | } |
| 2095 | o = context; |
| 2096 | if o.is(&slow_o) { |
| 2097 | // Pre-existing cycle detected - all exceptions on the path were visited |
| 2098 | break; |
| 2099 | } |
| 2100 | if slow_update_toggle && let Some(slow_context) = slow_o.__context__() { |
| 2101 | slow_o = slow_context; |
| 2102 | } |
| 2103 | slow_update_toggle = !slow_update_toggle; |
| 2104 | } |
| 2105 | exception.set___context__(Some(context_exc)) |
| 2106 | } |
| 2107 | } |
| 2108 | |
| 2109 | pub(crate) fn topmost_exception(&self) -> Option<PyBaseExceptionRef> { |
| 2110 | let excs = self.exceptions.borrow(); |
no test coverage detected