Convert some std error types to PyErr (#22)

* Convert some std error types to PyErr

* Add ToPyErr trait
This commit is contained in:
messense 2017-06-08 09:40:30 +08:00 committed by GitHub
parent a584ce12e5
commit e12e98a7c1
2 changed files with 58 additions and 1 deletions

View file

@ -1,6 +1,8 @@
use std;
use std::io;
use std::ffi::CString;
use std::os::raw::c_char;
use std::error::Error;
use libc;
use ffi;
@ -369,6 +371,61 @@ impl std::convert::From<PyErr> for std::io::Error {
}
}
/// Converts into PyErr
pub trait ToPyErr {
fn to_pyerr(&self, Python) -> PyErr;
}
macro_rules! impl_to_pyerr {
($err: ty, $pyexc: ty) => {
impl $crate::ToPyErr for $err {
fn to_pyerr(&self, py: $crate::Python) -> PyErr {
PyErr::new::<$pyexc, _>(py, self.description())
}
}
}
}
/// Create OSError from io::Error
impl ToPyErr for io::Error {
fn to_pyerr(&self, py: Python) -> PyErr {
let tp = match self.kind() {
io::ErrorKind::BrokenPipe => py.get_type::<exc::BrokenPipeError>(),
io::ErrorKind::ConnectionRefused => py.get_type::<exc::ConnectionRefusedError>(),
io::ErrorKind::ConnectionAborted => py.get_type::<exc::ConnectionAbortedError>(),
io::ErrorKind::ConnectionReset => py.get_type::<exc::ConnectionResetError>(),
io::ErrorKind::Interrupted => py.get_type::<exc::InterruptedError>(),
io::ErrorKind::NotFound => py.get_type::<exc::FileNotFoundError>(),
io::ErrorKind::WouldBlock => py.get_type::<exc::BlockingIOError>(),
io::ErrorKind::TimedOut => py.get_type::<exc::TimeoutError>(),
_ => py.get_type::<exc::OSError>(),
};
let errno = self.raw_os_error().unwrap_or(0);
let errdesc = self.description();
PyErr::new_err(py, &tp, (errno, errdesc))
}
}
impl<W: Send + std::fmt::Debug> ToPyErr for std::io::IntoInnerError<W> {
fn to_pyerr(&self, py: Python) -> PyErr {
PyErr::new::<exc::OSError, _>(py, self.description())
}
}
impl_to_pyerr!(std::num::ParseIntError, exc::ValueError);
impl_to_pyerr!(std::num::ParseFloatError, exc::ValueError);
impl_to_pyerr!(std::string::ParseError, exc::ValueError);
impl_to_pyerr!(std::str::ParseBoolError, exc::ValueError);
impl_to_pyerr!(std::ffi::IntoStringError, exc::UnicodeDecodeError);
impl_to_pyerr!(std::str::Utf8Error, exc::UnicodeDecodeError);
impl_to_pyerr!(std::string::FromUtf8Error, exc::UnicodeDecodeError);
impl_to_pyerr!(std::string::FromUtf16Error, exc::UnicodeDecodeError);
impl_to_pyerr!(std::char::DecodeUtf16Error, exc::UnicodeDecodeError);
impl_to_pyerr!(std::net::AddrParseError, exc::ValueError);
pub fn panic_after_error() -> ! {
unsafe { ffi::PyErr_Print(); }
panic!("Python API called failed");

View file

@ -70,7 +70,7 @@ pub use pointers::PyPtr;
mod token;
pub use token::{PyToken, PyObjectWithToken, ToInstancePtr, InstancePtr};
pub use err::{PyErr, PyResult, PyDowncastError};
pub use err::{PyErr, PyResult, PyDowncastError, ToPyErr};
pub use objects::*;
pub use objectprotocol::ObjectProtocol;
pub use python::{Python, ToPyPointer, IntoPyPointer, PyClone,