(
zelf: PyRef<Self>,
exception: PyObjectRef,
vm: &VirtualMachine,
)
| 278 | |
| 279 | #[pymethod] |
| 280 | fn set_exception( |
| 281 | zelf: PyRef<Self>, |
| 282 | exception: PyObjectRef, |
| 283 | vm: &VirtualMachine, |
| 284 | ) -> PyResult<()> { |
| 285 | if zelf.fut_loop.read().is_none() { |
| 286 | return Err(vm.new_runtime_error("Future object is not initialized.")); |
| 287 | } |
| 288 | if zelf.fut_state.load() != FutureState::Pending { |
| 289 | return Err(new_invalid_state_error(vm, "invalid state")); |
| 290 | } |
| 291 | |
| 292 | // Normalize the exception |
| 293 | let exc = if exception.fast_isinstance(vm.ctx.types.type_type) { |
| 294 | exception.call((), vm)? |
| 295 | } else { |
| 296 | exception |
| 297 | }; |
| 298 | |
| 299 | if !exc.fast_isinstance(vm.ctx.exceptions.base_exception_type) { |
| 300 | return Err(vm.new_type_error(format!( |
| 301 | "exception must be a BaseException, not {}", |
| 302 | exc.class().name() |
| 303 | ))); |
| 304 | } |
| 305 | |
| 306 | // Wrap StopIteration in RuntimeError |
| 307 | let exc = if exc.fast_isinstance(vm.ctx.exceptions.stop_iteration) { |
| 308 | let msg = "StopIteration interacts badly with generators and cannot be raised into a Future"; |
| 309 | let runtime_err = vm.new_runtime_error(msg.to_string()); |
| 310 | // Set cause and context to the original StopIteration |
| 311 | let stop_iter: PyRef<PyBaseException> = exc.downcast().unwrap(); |
| 312 | runtime_err.set___cause__(Some(stop_iter.clone())); |
| 313 | runtime_err.set___context__(Some(stop_iter)); |
| 314 | runtime_err.into() |
| 315 | } else { |
| 316 | exc |
| 317 | }; |
| 318 | |
| 319 | // Save the original traceback for later restoration |
| 320 | if let Ok(exc_ref) = exc.clone().downcast::<PyBaseException>() { |
| 321 | let tb = exc_ref.__traceback__().map(|tb| tb.into()); |
| 322 | *zelf.fut_exception_tb.write() = tb; |
| 323 | } |
| 324 | |
| 325 | *zelf.fut_exception.write() = Some(exc); |
| 326 | zelf.fut_state.store(FutureState::Finished); |
| 327 | zelf.fut_log_tb.store(true, Ordering::Relaxed); |
| 328 | Self::schedule_callbacks(&zelf, vm)?; |
| 329 | Ok(()) |
| 330 | } |
| 331 | |
| 332 | #[pymethod] |
| 333 | fn add_done_callback( |
nothing calls this directly
no test coverage detected