|
1 | 1 | use std;
|
| 2 | +use std::io; |
2 | 3 | use std::ffi::CString;
|
3 | 4 | use std::os::raw::c_char;
|
| 5 | +use std::error::Error; |
4 | 6 | use libc;
|
5 | 7 |
|
6 | 8 | use ffi;
|
@@ -369,6 +371,61 @@ impl std::convert::From<PyErr> for std::io::Error {
|
369 | 371 | }
|
370 | 372 | }
|
371 | 373 |
|
| 374 | +/// Converts into PyErr |
| 375 | +pub trait ToPyErr { |
| 376 | + fn to_pyerr(&self, Python) -> PyErr; |
| 377 | +} |
| 378 | + |
| 379 | +macro_rules! impl_to_pyerr { |
| 380 | + ($err: ty, $pyexc: ty) => { |
| 381 | + impl $crate::ToPyErr for $err { |
| 382 | + fn to_pyerr(&self, py: $crate::Python) -> PyErr { |
| 383 | + PyErr::new::<$pyexc, _>(py, self.description()) |
| 384 | + } |
| 385 | + } |
| 386 | + } |
| 387 | +} |
| 388 | + |
| 389 | +/// Create OSError from io::Error |
| 390 | +impl ToPyErr for io::Error { |
| 391 | + |
| 392 | + fn to_pyerr(&self, py: Python) -> PyErr { |
| 393 | + let tp = match self.kind() { |
| 394 | + io::ErrorKind::BrokenPipe => py.get_type::<exc::BrokenPipeError>(), |
| 395 | + io::ErrorKind::ConnectionRefused => py.get_type::<exc::ConnectionRefusedError>(), |
| 396 | + io::ErrorKind::ConnectionAborted => py.get_type::<exc::ConnectionAbortedError>(), |
| 397 | + io::ErrorKind::ConnectionReset => py.get_type::<exc::ConnectionResetError>(), |
| 398 | + io::ErrorKind::Interrupted => py.get_type::<exc::InterruptedError>(), |
| 399 | + io::ErrorKind::NotFound => py.get_type::<exc::FileNotFoundError>(), |
| 400 | + io::ErrorKind::WouldBlock => py.get_type::<exc::BlockingIOError>(), |
| 401 | + io::ErrorKind::TimedOut => py.get_type::<exc::TimeoutError>(), |
| 402 | + _ => py.get_type::<exc::OSError>(), |
| 403 | + }; |
| 404 | + |
| 405 | + let errno = self.raw_os_error().unwrap_or(0); |
| 406 | + let errdesc = self.description(); |
| 407 | + |
| 408 | + PyErr::new_err(py, &tp, (errno, errdesc)) |
| 409 | + } |
| 410 | +} |
| 411 | + |
| 412 | +impl<W: Send + std::fmt::Debug> ToPyErr for std::io::IntoInnerError<W> { |
| 413 | + fn to_pyerr(&self, py: Python) -> PyErr { |
| 414 | + PyErr::new::<exc::OSError, _>(py, self.description()) |
| 415 | + } |
| 416 | +} |
| 417 | + |
| 418 | +impl_to_pyerr!(std::num::ParseIntError, exc::ValueError); |
| 419 | +impl_to_pyerr!(std::num::ParseFloatError, exc::ValueError); |
| 420 | +impl_to_pyerr!(std::string::ParseError, exc::ValueError); |
| 421 | +impl_to_pyerr!(std::str::ParseBoolError, exc::ValueError); |
| 422 | +impl_to_pyerr!(std::ffi::IntoStringError, exc::UnicodeDecodeError); |
| 423 | +impl_to_pyerr!(std::str::Utf8Error, exc::UnicodeDecodeError); |
| 424 | +impl_to_pyerr!(std::string::FromUtf8Error, exc::UnicodeDecodeError); |
| 425 | +impl_to_pyerr!(std::string::FromUtf16Error, exc::UnicodeDecodeError); |
| 426 | +impl_to_pyerr!(std::char::DecodeUtf16Error, exc::UnicodeDecodeError); |
| 427 | +impl_to_pyerr!(std::net::AddrParseError, exc::ValueError); |
| 428 | + |
372 | 429 | pub fn panic_after_error() -> ! {
|
373 | 430 | unsafe { ffi::PyErr_Print(); }
|
374 | 431 | panic!("Python API called failed");
|
|
0 commit comments