diff --git a/CHANGELOG.md b/CHANGELOG.md index f287b08790e..d813ae839a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Change `PyErr::print()` and `PyErr::print_and_set_sys_last_vars()` to take `&self` instead of `self`. - Remove `PyErr::from_value`, `PyErr::into_normalized()` and `PyErr::normalize()`. - Change `PyErrValue` to be a private type. + - Remove `PyException::into()` and `Into>` for `PyErr` and `PyException`. + - Rename `PyException::py_err()` to `PyException::new_err()`. + - Rename `PyUnicodeDecodeErr::new_err()` to `PyUnicodeDecodeErr::new()`. ### Removed diff --git a/guide/src/exception.md b/guide/src/exception.md index 3a9144f1dee..1d02b86eb43 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -76,7 +76,7 @@ If you already have a Python exception instance, you can simply call [`PyErr::fr PyErr::from_instance(py, err).restore(py); ``` -If a Rust type exists for the exception, then it is possible to use the `py_err` method. +If a Rust type exists for the exception, then it is possible to use the `new_err` method. For example, each standard exception defined in the `pyo3::exceptions` module has a corresponding Rust type, exceptions defined by [`create_exception!`] and [`import_exception!`] macro have Rust types as well. @@ -87,7 +87,7 @@ have Rust types as well. # fn check_for_error() -> bool {false} fn my_func(arg: PyObject) -> PyResult<()> { if check_for_error() { - Err(PyValueError::py_err("argument is wrong")) + Err(PyValueError::new_err("argument is wrong")) } else { Ok(()) } @@ -123,7 +123,7 @@ To check the type of an exception, you can simply do: # fn main() { # let gil = Python::acquire_gil(); # let py = gil.python(); -# let err = PyTypeError::py_err(()); +# let err = PyTypeError::new_err(()); err.is_instance::(py); # } ``` @@ -170,7 +170,7 @@ until a `Python` object is available. # } impl std::convert::From for PyErr { fn from(err: CustomIOError) -> PyErr { - PyOSError::py_err(err.to_string()) + PyOSError::new_err(err.to_string()) } } @@ -213,7 +213,7 @@ fn tell(file: &PyAny) -> PyResult { use pyo3::exceptions::*; match file.call_method0("tell") { - Err(_) => Err(io::UnsupportedOperation::py_err("not supported: tell")), + Err(_) => Err(io::UnsupportedOperation::new_err("not supported: tell")), Ok(x) => x.extract::(), } } diff --git a/src/buffer.rs b/src/buffer.rs index 4cbb16e1109..2e7c401377f 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -156,10 +156,10 @@ pub unsafe trait Element: Copy { fn validate(b: &ffi::Py_buffer) -> PyResult<()> { // shape and stride information must be provided when we use PyBUF_FULL_RO if b.shape.is_null() { - return Err(exceptions::PyBufferError::py_err("Shape is Null")); + return Err(exceptions::PyBufferError::new_err("Shape is Null")); } if b.strides.is_null() { - return Err(exceptions::PyBufferError::py_err( + return Err(exceptions::PyBufferError::new_err( "PyBuffer: Strides is Null", )); } @@ -190,7 +190,7 @@ impl PyBuffer { { Ok(buf) } else { - Err(exceptions::PyBufferError::py_err( + Err(exceptions::PyBufferError::new_err( "Incompatible type as buffer", )) } @@ -441,7 +441,7 @@ impl PyBuffer { fn copy_to_slice_impl(&self, py: Python, target: &mut [T], fort: u8) -> PyResult<()> { if mem::size_of_val(target) != self.len_bytes() { - return Err(exceptions::PyBufferError::py_err( + return Err(exceptions::PyBufferError::new_err( "Slice length does not match buffer length.", )); } @@ -528,7 +528,7 @@ impl PyBuffer { return buffer_readonly_error(); } if mem::size_of_val(source) != self.len_bytes() { - return Err(exceptions::PyBufferError::py_err( + return Err(exceptions::PyBufferError::new_err( "Slice length does not match buffer length.", )); } @@ -564,7 +564,7 @@ impl PyBuffer { #[inline(always)] fn buffer_readonly_error() -> PyResult<()> { - Err(exceptions::PyBufferError::py_err( + Err(exceptions::PyBufferError::new_err( "Cannot write to read-only buffer.", )) } diff --git a/src/callback.rs b/src/callback.rs index 5f83cfaa96a..2f2632c63c9 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -86,7 +86,7 @@ impl IntoPyCallbackOutput for usize { if self <= (isize::MAX as usize) { Ok(self as isize) } else { - Err(PyOverflowError::py_err(())) + Err(PyOverflowError::new_err(())) } } } @@ -244,11 +244,11 @@ macro_rules! callback_body_without_convert { Err(e) => { // Try to format the error in the same way panic does if let Some(string) = e.downcast_ref::() { - Err($crate::panic::PanicException::py_err((string.clone(),))) + Err($crate::panic::PanicException::new_err((string.clone(),))) } else if let Some(s) = e.downcast_ref::<&str>() { - Err($crate::panic::PanicException::py_err((s.to_string(),))) + Err($crate::panic::PanicException::new_err((s.to_string(),))) } else { - Err($crate::panic::PanicException::py_err(( + Err($crate::panic::PanicException::new_err(( "panic from Rust code", ))) } diff --git a/src/class/iter.rs b/src/class/iter.rs index 0818feb0a44..057eea57807 100644 --- a/src/class/iter.rs +++ b/src/class/iter.rs @@ -112,7 +112,7 @@ impl IntoPyCallbackOutput<*mut ffi::PyObject> for PyIterNextOutput { fn convert(self, _py: Python) -> PyResult<*mut ffi::PyObject> { match self { IterNextOutput::Yield(o) => Ok(o.into_ptr()), - IterNextOutput::Return(opt) => Err(crate::exceptions::PyStopIteration::py_err((opt,))), + IterNextOutput::Return(opt) => Err(crate::exceptions::PyStopIteration::new_err((opt,))), } } } diff --git a/src/class/pyasync.rs b/src/class/pyasync.rs index 82548835c7f..ddf30b56d3a 100644 --- a/src/class/pyasync.rs +++ b/src/class/pyasync.rs @@ -119,7 +119,7 @@ impl IntoPyCallbackOutput<*mut ffi::PyObject> for PyIterANextOutput { match self { IterANextOutput::Yield(o) => Ok(o.into_ptr()), IterANextOutput::Return(opt) => { - Err(crate::exceptions::PyStopAsyncIteration::py_err((opt,))) + Err(crate::exceptions::PyStopAsyncIteration::new_err((opt,))) } } } diff --git a/src/derive_utils.rs b/src/derive_utils.rs index 2a736d7ebcd..ead7a42d867 100644 --- a/src/derive_utils.rs +++ b/src/derive_utils.rs @@ -43,7 +43,7 @@ pub fn parse_fn_args<'p>( let nargs = args.len(); let mut used_args = 0; macro_rules! raise_error { - ($s: expr $(,$arg:expr)*) => (return Err(PyTypeError::py_err(format!( + ($s: expr $(,$arg:expr)*) => (return Err(PyTypeError::new_err(format!( concat!("{} ", $s), fname.unwrap_or("function") $(,$arg)* )))) } diff --git a/src/err/mod.rs b/src/err/mod.rs index 2e39d414068..dbd2678a6f0 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -79,8 +79,7 @@ impl PyErr { /// In most cases, you can use a concrete exception's constructors instead: /// the example is equivalent to /// ```ignore - /// return Err(exceptions::PyTypeError::py_err("Error message")); - /// return exceptions::PyTypeError::into("Error message"); + /// return Err(exceptions::PyTypeError::new_err("Error message")); /// ``` pub fn new(value: V) -> PyErr where @@ -174,7 +173,7 @@ impl PyErr { /// ```rust /// use pyo3::{Python, PyErr, exceptions::PyTypeError, types::PyType}; /// Python::with_gil(|py| { - /// let err = PyTypeError::py_err(("some type error",)); + /// let err = PyTypeError::new_err(("some type error",)); /// assert_eq!(err.ptype(py), PyType::new::(py)); /// }); /// ``` @@ -190,7 +189,7 @@ impl PyErr { /// ```rust /// use pyo3::{Python, PyErr, exceptions::PyTypeError, types::PyType}; /// Python::with_gil(|py| { - /// let err = PyTypeError::py_err(("some type error",)); + /// let err = PyTypeError::new_err(("some type error",)); /// assert_eq!(err.pvalue(py).to_string(), "TypeError: some type error"); /// }); /// ``` @@ -206,7 +205,7 @@ impl PyErr { /// ```rust /// use pyo3::{Python, PyErr, exceptions::PyTypeError, types::PyType}; /// Python::with_gil(|py| { - /// let err = PyTypeError::py_err(("some type error",)); + /// let err = PyTypeError::new_err(("some type error",)); /// assert_eq!(err.ptraceback(py), None); /// }); /// ``` @@ -426,7 +425,7 @@ impl PyErr { ptype: Py::from_owned_ptr_or_opt(py, ptype) .unwrap_or_else(|| exceptions::PySystemError::type_object(py).into()), pvalue: Py::from_owned_ptr_or_opt(py, pvalue).unwrap_or_else(|| { - exceptions::PySystemError::py_err("Exception value missing") + exceptions::PySystemError::new_err("Exception value missing") .instance(py) .into_py(py) }), @@ -476,7 +475,7 @@ impl<'a> IntoPy for &'a PyErr { /// Convert `PyDowncastError` to Python `TypeError`. impl<'a> std::convert::From> for PyErr { fn from(err: PyDowncastError) -> PyErr { - exceptions::PyTypeError::py_err(err.to_string()) + exceptions::PyTypeError::new_err(err.to_string()) } } @@ -496,13 +495,6 @@ impl<'a> std::fmt::Display for PyDowncastError<'a> { } } -/// Convert `PyErr` to `PyResult` -impl std::convert::Into> for PyErr { - fn into(self) -> PyResult { - Err(self) - } -} - pub fn panic_after_error(_py: Python) -> ! { unsafe { ffi::PyErr_Print(); @@ -531,7 +523,7 @@ mod tests { fn set_typeerror() { let gil = Python::acquire_gil(); let py = gil.python(); - let err: PyErr = exceptions::PyTypeError::py_err(()); + let err: PyErr = exceptions::PyTypeError::new_err(()); err.restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); @@ -549,7 +541,7 @@ mod tests { let gil = Python::acquire_gil(); let py = gil.python(); - let err: PyErr = PanicException::py_err("new panic"); + let err: PyErr = PanicException::new_err("new panic"); err.restore(py); assert!(PyErr::occurred(py)); let started_unwind = diff --git a/src/exceptions.rs b/src/exceptions.rs index 317ef2d6c03..774a1347615 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -3,7 +3,7 @@ //! Exception types defined by Python. use crate::type_object::PySizedLayout; -use crate::types::{PyAny, PyTuple}; +use crate::types::PyTuple; use crate::{ffi, AsPyPointer, PyResult, Python}; use std::ffi::CStr; use std::ops; @@ -19,20 +19,11 @@ macro_rules! impl_exception_boilerplate { } } - impl std::convert::Into<$crate::PyResult> for $name { - fn into(self) -> $crate::PyResult { - $crate::PyErr::new::<$name, _>(()).into() - } - } - impl $name { - pub fn py_err(args: V) -> $crate::PyErr { - $crate::PyErr::new::<$name, V>(args) - } - pub fn into( + pub fn new_err( args: V, - ) -> $crate::PyResult { - $crate::PyErr::new::<$name, V>(args).into() + ) -> $crate::PyErr { + $crate::PyErr::new::<$name, V>(args) } } @@ -451,13 +442,13 @@ impl_native_exception!(PyIOError, IOError, PyExc_IOError); impl_native_exception!(PyWindowsError, WindowsError, PyExc_WindowsError); impl PyUnicodeDecodeError { - pub fn new_err<'p>( + pub fn new<'p>( py: Python<'p>, encoding: &CStr, input: &[u8], range: ops::Range, reason: &CStr, - ) -> PyResult<&'p PyAny> { + ) -> PyResult<&'p PyUnicodeDecodeError> { unsafe { let input: &[c_char] = &*(input as *const [u8] as *const [c_char]); py.from_owned_ptr_or_err(ffi::PyUnicodeDecodeError_Create( @@ -476,9 +467,9 @@ impl PyUnicodeDecodeError { py: Python<'p>, input: &[u8], err: std::str::Utf8Error, - ) -> PyResult<&'p PyAny> { + ) -> PyResult<&'p PyUnicodeDecodeError> { let pos = err.valid_up_to(); - PyUnicodeDecodeError::new_err( + PyUnicodeDecodeError::new( py, CStr::from_bytes_with_nul(b"utf-8\0").unwrap(), input, @@ -523,7 +514,6 @@ mod test { use crate::types::{IntoPyDict, PyDict}; use crate::{PyErr, Python}; use std::error::Error; - use std::fmt::Write; import_exception!(socket, gaierror); import_exception!(email.errors, MessageError); @@ -533,7 +523,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); - let err: PyErr = gaierror::py_err(()); + let err: PyErr = gaierror::new_err(()); let socket = py .import("socket") .map_err(|e| e.print(py)) @@ -558,7 +548,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); - let err: PyErr = MessageError::py_err(()); + let err: PyErr = MessageError::new_err(()); let email = py .import("email") .map_err(|e| e.print(py)) @@ -605,35 +595,30 @@ mod test { #[test] fn native_exception_display() { - let mut out = String::new(); let gil = Python::acquire_gil(); let py = gil.python(); - let err = py + let exc = py .run("raise Exception('banana')", None, None) - .expect_err("raising should have given us an error"); - write!(&mut out, "{}", err.instance(py)).expect("successful format"); - assert_eq!(out, "Exception: banana"); + .expect_err("raising should have given us an error") + .into_instance(py); + assert_eq!(exc.to_string(), "Exception: banana"); } #[test] fn native_exception_chain() { - let mut out = String::new(); let gil = Python::acquire_gil(); let py = gil.python(); - let err = py + let exc = py .run( "raise Exception('banana') from TypeError('peach')", None, None, ) - .expect_err("raising should have given us an error"); - let instance = err.instance(py); - write!(&mut out, "{}", instance).expect("successful format"); - assert_eq!(out, "Exception: banana"); - out.clear(); - let source = instance.source().expect("cause should exist"); - write!(&mut out, "{}", source).expect("successful format"); - assert_eq!(out, "TypeError: peach"); + .expect_err("raising should have given us an error") + .into_instance(py); + assert_eq!(exc.to_string(), "Exception: banana"); + let source = exc.as_ref(py).source().expect("cause should exist"); + assert_eq!(source.to_string(), "TypeError: peach"); let source_source = source.source(); assert!(source_source.is_none(), "source_source should be None"); } diff --git a/src/pycell.rs b/src/pycell.rs index ef1acb92372..d0d498d2d8e 100644 --- a/src/pycell.rs +++ b/src/pycell.rs @@ -730,7 +730,7 @@ impl fmt::Display for PyBorrowError { impl From for PyErr { fn from(other: PyBorrowError) -> Self { - PyRuntimeError::py_err(other.to_string()) + PyRuntimeError::new_err(other.to_string()) } } @@ -755,6 +755,6 @@ impl fmt::Display for PyBorrowMutError { impl From for PyErr { fn from(other: PyBorrowMutError) -> Self { - PyRuntimeError::py_err(other.to_string()) + PyRuntimeError::new_err(other.to_string()) } } diff --git a/src/pyclass.rs b/src/pyclass.rs index a4c10876493..52cc3910ca1 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -218,7 +218,7 @@ where if ffi::PyType_Ready(type_object) == 0 { Ok(()) } else { - PyErr::fetch(py).into() + Err(PyErr::fetch(py)) } } } diff --git a/src/types/any.rs b/src/types/any.rs index aec69743427..cd973b0011d 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -163,7 +163,7 @@ impl PyAny { } else if do_compare(other, ffi::Py_GT)? { Ok(Ordering::Greater) } else { - Err(PyTypeError::py_err( + Err(PyTypeError::new_err( "PyAny::compare(): All comparisons returned false", )) } diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index 095c7564c99..ae7333825d6 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -295,7 +295,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); let py_bytearray_result = PyByteArray::new_with(py, 10, |_b: &mut [u8]| { - Err(PyValueError::py_err("Hello Crustaceans!")) + Err(PyValueError::new_err("Hello Crustaceans!")) }); assert!(py_bytearray_result.is_err()); assert!(py_bytearray_result diff --git a/src/types/bytes.rs b/src/types/bytes.rs index 135b38cc025..ab5b13290a0 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -159,7 +159,7 @@ mod test { let gil = Python::acquire_gil(); let py = gil.python(); let py_bytes_result = PyBytes::new_with(py, 10, |_b: &mut [u8]| { - Err(PyValueError::py_err("Hello Crustaceans!")) + Err(PyValueError::new_err("Hello Crustaceans!")) }); assert!(py_bytes_result.is_err()); assert!(py_bytes_result diff --git a/src/types/num.rs b/src/types/num.rs index 14ab4b33ce4..09944d84486 100644 --- a/src/types/num.rs +++ b/src/types/num.rs @@ -40,7 +40,7 @@ macro_rules! int_fits_larger_int { fn extract(obj: &'source PyAny) -> PyResult { let val: $larger_type = obj.extract()?; <$rust_type>::try_from(val) - .map_err(|e| exceptions::PyOverflowError::py_err(e.to_string())) + .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } } }; @@ -86,7 +86,7 @@ macro_rules! int_fits_c_long { } }?; <$rust_type>::try_from(val) - .map_err(|e| exceptions::PyOverflowError::py_err(e.to_string())) + .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } } }; diff --git a/src/types/sequence.rs b/src/types/sequence.rs index 1b84352a5b0..67818de169a 100644 --- a/src/types/sequence.rs +++ b/src/types/sequence.rs @@ -361,7 +361,7 @@ where { let seq = ::try_from(obj)?; if seq.len()? as usize != slice.len() { - return Err(exceptions::PyBufferError::py_err( + return Err(exceptions::PyBufferError::new_err( "Slice length does not match buffer length.", )); } diff --git a/src/types/tuple.rs b/src/types/tuple.rs index f1433deb2fb..22a44c9c864 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -135,7 +135,7 @@ fn wrong_tuple_length(t: &PyTuple, expected_length: usize) -> PyErr { expected_length, t.len() ); - exceptions::PyValueError::py_err(msg) + exceptions::PyValueError::new_err(msg) } macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => { diff --git a/tests/test_buffer_protocol.rs b/tests/test_buffer_protocol.rs index c7343e19331..aca7ef1ca4e 100644 --- a/tests/test_buffer_protocol.rs +++ b/tests/test_buffer_protocol.rs @@ -21,11 +21,11 @@ struct TestBufferClass { impl PyBufferProtocol for TestBufferClass { fn bf_getbuffer(slf: PyRefMut, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> { if view.is_null() { - return Err(PyBufferError::py_err("View is null")); + return Err(PyBufferError::new_err("View is null")); } if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE { - return Err(PyBufferError::py_err("Object is not writable")); + return Err(PyBufferError::new_err("Object is not writable")); } unsafe { diff --git a/tests/test_exceptions.rs b/tests/test_exceptions.rs index 3726dfb7e39..2c71669a2f8 100644 --- a/tests/test_exceptions.rs +++ b/tests/test_exceptions.rs @@ -46,7 +46,7 @@ impl fmt::Display for CustomError { impl std::convert::From for PyErr { fn from(err: CustomError) -> PyErr { - exceptions::PyOSError::py_err(err.to_string()) + exceptions::PyOSError::new_err(err.to_string()) } } diff --git a/tests/test_mapping.rs b/tests/test_mapping.rs index 35369e01b4e..2e5f42df130 100644 --- a/tests/test_mapping.rs +++ b/tests/test_mapping.rs @@ -40,7 +40,7 @@ impl PyMappingProtocol for Mapping { self.index .get(&query) .copied() - .ok_or_else(|| PyKeyError::py_err("unknown key")) + .ok_or_else(|| PyKeyError::new_err("unknown key")) } fn __setitem__(&mut self, key: String, value: usize) { @@ -49,7 +49,7 @@ impl PyMappingProtocol for Mapping { fn __delitem__(&mut self, key: String) -> PyResult<()> { if self.index.remove(&key).is_none() { - PyKeyError::py_err("unknown key").into() + Err(PyKeyError::new_err("unknown key")) } else { Ok(()) } diff --git a/tests/test_sequence.rs b/tests/test_sequence.rs index d46edfb3b45..0a4c4afd1f8 100644 --- a/tests/test_sequence.rs +++ b/tests/test_sequence.rs @@ -41,7 +41,7 @@ impl PySequenceProtocol for ByteSequence { self.elements .get(idx as usize) .copied() - .ok_or_else(|| PyIndexError::py_err("list index out of range")) + .ok_or_else(|| PyIndexError::new_err("list index out of range")) } fn __setitem__(&mut self, idx: isize, value: u8) { @@ -53,7 +53,7 @@ impl PySequenceProtocol for ByteSequence { self.elements.remove(idx as usize); Ok(()) } else { - Err(PyIndexError::py_err("list index out of range")) + Err(PyIndexError::new_err("list index out of range")) } } @@ -78,7 +78,7 @@ impl PySequenceProtocol for ByteSequence { } Ok(Self { elements }) } else { - Err(PyValueError::py_err("invalid repeat count")) + Err(PyValueError::new_err("invalid repeat count")) } } } @@ -242,7 +242,7 @@ impl PySequenceProtocol for OptionList { fn __getitem__(&self, idx: isize) -> PyResult> { match self.items.get(idx as usize) { Some(x) => Ok(*x), - None => Err(PyIndexError::py_err("Index out of bounds")), + None => Err(PyIndexError::new_err("Index out of bounds")), } } } diff --git a/tests/test_various.rs b/tests/test_various.rs index 87270c39186..49923bf299a 100644 --- a/tests/test_various.rs +++ b/tests/test_various.rs @@ -191,7 +191,7 @@ impl fmt::Display for MyError { /// Important for the automatic conversion to `PyErr`. impl From for PyErr { fn from(err: MyError) -> pyo3::PyErr { - pyo3::exceptions::PyOSError::py_err(err.to_string()) + pyo3::exceptions::PyOSError::new_err(err.to_string()) } }