# impls.rs - source
Source of the Rust file `/home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/pyo3-0.13.2/src/err/impls.rs`.
Keywords: rust, rustlang, rust-lang

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114

    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 => exceptions::PyBrokenPipeError::new_err(err),
                io::ErrorKind::ConnectionRefused => exceptions::PyConnectionRefusedError::new_err(err),
                io::ErrorKind::ConnectionAborted => exceptions::PyConnectionAbortedError::new_err(err),
                io::ErrorKind::ConnectionReset => exceptions::PyConnectionResetError::new_err(err),
                io::ErrorKind::Interrupted => exceptions::PyInterruptedError::new_err(err),
                io::ErrorKind::NotFound => exceptions::PyFileNotFoundError::new_err(err),
                io::ErrorKind::WouldBlock => exceptions::PyBlockingIOError::new_err(err),
                io::ErrorKind::TimedOut => exceptions::PyTimeoutError::new_err(err),
                _ => exceptions::PyOSError::new_err(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 {
            exceptions::PyOSError::new_err(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 std::convert::From<std::convert::Infallible> for PyErr {
        fn from(_: std::convert::Infallible) -> PyErr {
            unreachable!()
        }
    }

    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 {
                    <$pyexc>::new_err(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);

    #[cfg(test)]
    mod tests {
        use crate::PyErr;
        use std::io;

        #[test]
        fn io_errors() {
            let check_err = |kind, expected_ty| {
                let py_err: PyErr = io::Error::new(kind, "some error msg").into();
                let err_msg = format!("{}: some error msg", expected_ty);
                assert_eq!(py_err.to_string(), err_msg);

                let os_err: io::Error = py_err.into();
                assert_eq!(os_err.to_string(), format!("Python exception: {}", err_msg));
            };

            check_err(io::ErrorKind::BrokenPipe, "BrokenPipeError");
            check_err(io::ErrorKind::ConnectionRefused, "ConnectionRefusedError");
            check_err(io::ErrorKind::ConnectionAborted, "ConnectionAbortedError");
            check_err(io::ErrorKind::ConnectionReset, "ConnectionResetError");
            check_err(io::ErrorKind::Interrupted, "InterruptedError");
            check_err(io::ErrorKind::NotFound, "FileNotFoundError");
            check_err(io::ErrorKind::WouldBlock, "BlockingIOError");
            check_err(io::ErrorKind::TimedOut, "TimeoutError");
        }
    }