-
Notifications
You must be signed in to change notification settings - Fork 763
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement std::error::Error for PyErr
- Loading branch information
1 parent
ffe543f
commit 381ae23
Showing
27 changed files
with
451 additions
and
400 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use crate::{ | ||
exceptions::PyBaseException, ffi, types::PyType, IntoPyPointer, Py, PyObject, Python, | ||
ToPyObject, | ||
}; | ||
|
||
pub(crate) enum PyErrValue { | ||
ToArgs(Box<dyn PyErrArguments + Send + Sync>), | ||
ToObject(Box<dyn ToPyObject + Send + Sync>), | ||
} | ||
|
||
#[derive(Clone)] | ||
pub(crate) struct PyErrStateNormalized { | ||
pub ptype: Py<PyType>, | ||
pub pvalue: Py<PyBaseException>, | ||
pub ptraceback: Option<PyObject>, | ||
} | ||
|
||
pub(crate) enum PyErrState { | ||
Lazy { | ||
ptype: Py<PyType>, | ||
pvalue: Option<PyErrValue>, | ||
}, | ||
FfiTuple { | ||
ptype: Option<PyObject>, | ||
pvalue: Option<PyObject>, | ||
ptraceback: Option<PyObject>, | ||
}, | ||
Normalized(PyErrStateNormalized), | ||
} | ||
|
||
/// Helper conversion trait that allows to use custom arguments for exception constructor. | ||
pub trait PyErrArguments { | ||
/// Arguments for exception | ||
fn arguments(&self, _: Python) -> PyObject; | ||
} | ||
|
||
impl PyErrState { | ||
pub fn into_ffi_tuple( | ||
self, | ||
py: Python, | ||
) -> (*mut ffi::PyObject, *mut ffi::PyObject, *mut ffi::PyObject) { | ||
match self { | ||
PyErrState::Lazy { ptype, pvalue } => { | ||
let pvalue = match pvalue { | ||
Some(PyErrValue::ToArgs(ob)) => ob.arguments(py).into_ptr(), | ||
Some(PyErrValue::ToObject(ob)) => ob.to_object(py).into_ptr(), | ||
None => std::ptr::null_mut(), | ||
}; | ||
(ptype.into_ptr(), pvalue, std::ptr::null_mut()) | ||
} | ||
PyErrState::FfiTuple { | ||
ptype, | ||
pvalue, | ||
ptraceback, | ||
} => (ptype.into_ptr(), pvalue.into_ptr(), ptraceback.into_ptr()), | ||
PyErrState::Normalized(PyErrStateNormalized { | ||
ptype, | ||
pvalue, | ||
ptraceback, | ||
}) => (ptype.into_ptr(), pvalue.into_ptr(), ptraceback.into_ptr()), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use crate::{err::PyErrArguments, exceptions, IntoPy, PyErr, PyObject, Python}; | ||
use std::io; | ||
|
||
/// Convert `PyErr` to `io::Error` | ||
impl std::convert::From<PyErr> for io::Error { | ||
fn from(err: PyErr) -> Self { | ||
io::Error::new(io::ErrorKind::Other, format!("Python exception: {:?}", err)) | ||
} | ||
} | ||
|
||
/// Create `OSError` from `io::Error` | ||
impl std::convert::From<io::Error> for PyErr { | ||
fn from(err: io::Error) -> PyErr { | ||
match err.kind() { | ||
io::ErrorKind::BrokenPipe => { | ||
PyErr::from_err_args::<exceptions::PyBrokenPipeError, _>(err) | ||
} | ||
io::ErrorKind::ConnectionRefused => { | ||
PyErr::from_err_args::<exceptions::PyConnectionRefusedError, _>(err) | ||
} | ||
io::ErrorKind::ConnectionAborted => { | ||
PyErr::from_err_args::<exceptions::PyConnectionAbortedError, _>(err) | ||
} | ||
io::ErrorKind::ConnectionReset => { | ||
PyErr::from_err_args::<exceptions::PyConnectionResetError, _>(err) | ||
} | ||
io::ErrorKind::Interrupted => { | ||
PyErr::from_err_args::<exceptions::PyInterruptedError, _>(err) | ||
} | ||
io::ErrorKind::NotFound => { | ||
PyErr::from_err_args::<exceptions::PyFileNotFoundError, _>(err) | ||
} | ||
io::ErrorKind::WouldBlock => { | ||
PyErr::from_err_args::<exceptions::PyBlockingIOError, _>(err) | ||
} | ||
io::ErrorKind::TimedOut => PyErr::from_err_args::<exceptions::PyTimeoutError, _>(err), | ||
_ => PyErr::from_err_args::<exceptions::PyOSError, _>(err), | ||
} | ||
} | ||
} | ||
|
||
impl PyErrArguments for io::Error { | ||
fn arguments(&self, py: Python) -> PyObject { | ||
self.to_string().into_py(py) | ||
} | ||
} | ||
|
||
impl<W: 'static + Send + Sync + std::fmt::Debug> std::convert::From<std::io::IntoInnerError<W>> | ||
for PyErr | ||
{ | ||
fn from(err: std::io::IntoInnerError<W>) -> PyErr { | ||
PyErr::from_err_args::<exceptions::PyOSError, _>(err) | ||
} | ||
} | ||
|
||
impl<W: Send + Sync + std::fmt::Debug> PyErrArguments for std::io::IntoInnerError<W> { | ||
fn arguments(&self, py: Python) -> PyObject { | ||
self.to_string().into_py(py) | ||
} | ||
} | ||
|
||
impl PyErrArguments for std::convert::Infallible { | ||
fn arguments(&self, py: Python) -> PyObject { | ||
"Infalliable!".into_py(py) | ||
} | ||
} | ||
|
||
impl std::convert::From<std::convert::Infallible> for PyErr { | ||
fn from(_: std::convert::Infallible) -> PyErr { | ||
PyErr::new::<exceptions::PyValueError, _>("Infalliable!") | ||
} | ||
} | ||
|
||
macro_rules! impl_to_pyerr { | ||
($err: ty, $pyexc: ty) => { | ||
impl PyErrArguments for $err { | ||
fn arguments(&self, py: Python) -> PyObject { | ||
self.to_string().into_py(py) | ||
} | ||
} | ||
|
||
impl std::convert::From<$err> for PyErr { | ||
fn from(err: $err) -> PyErr { | ||
PyErr::from_err_args::<$pyexc, _>(err) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
impl_to_pyerr!(std::array::TryFromSliceError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::num::ParseIntError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::num::ParseFloatError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::num::TryFromIntError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::str::ParseBoolError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::ffi::IntoStringError, exceptions::PyUnicodeDecodeError); | ||
impl_to_pyerr!(std::ffi::NulError, exceptions::PyValueError); | ||
impl_to_pyerr!(std::str::Utf8Error, exceptions::PyUnicodeDecodeError); | ||
impl_to_pyerr!(std::string::FromUtf8Error, exceptions::PyUnicodeDecodeError); | ||
impl_to_pyerr!( | ||
std::string::FromUtf16Error, | ||
exceptions::PyUnicodeDecodeError | ||
); | ||
impl_to_pyerr!( | ||
std::char::DecodeUtf16Error, | ||
exceptions::PyUnicodeDecodeError | ||
); | ||
impl_to_pyerr!(std::net::AddrParseError, exceptions::PyValueError); |
Oops, something went wrong.