diff --git a/src/err.rs b/src/err.rs index cd6d2a11..71bb9ae8 100644 --- a/src/err.rs +++ b/src/err.rs @@ -17,7 +17,7 @@ // DEALINGS IN THE SOFTWARE. use std; -use python::{PythonObject, Python, ToPythonPointer, PythonObjectDowncastError}; +use python::{PythonObject, Python, ToPythonPointer, PythonObjectDowncastError, PythonObjectWithTypeObject}; use objects::{PyObject, PyType, exc}; #[cfg(feature="python27-sys")] use objects::oldstyle::PyClass; @@ -80,16 +80,39 @@ impl <'p> PyErr<'p> { } } - /// Creates a new PyErr. + /// Creates a new PyErr of type `T`. /// - /// If `obj` is a Python exception instance, the PyErr will use that instance. - /// If `obj` is a Python exception type object, the PyErr will (lazily) create a new instance of that type. - /// Otherwise, a `TypeError` is created instead. - pub fn new(obj: O) -> PyErr<'p> where O: PythonObject<'p> { - PyErr::new_from_object(obj.into_object()) + /// `value` can be: + /// * `NoArgs`: the exception instance will be created using python `T()` + /// * a tuple: the exception instance will be created using python `T(*tuple)` + /// * any other value: the exception instance will be created using python `T(value)` + /// + /// Panics if `T` is not a python class derived from `BaseException`. + pub fn new(py: Python<'p>, value: V) -> PyErr<'p> + where T: PythonObjectWithTypeObject<'p>, V: ToPyObject<'p> + { + PyErr::new_helper(py.get_type::(), value.to_py_object(py).into_object()) } - fn new_from_object(obj: PyObject<'p>) -> PyErr<'p> { + fn new_helper(ty: PyType<'p>, value: PyObject<'p>) -> PyErr<'p> { + assert!(unsafe { ffi::PyExceptionClass_Check(ty.as_object().as_ptr()) } != 0); + PyErr { + ptype: ty.into_object(), + pvalue: Some(value), + ptraceback: None + } + } + + /// Creates a new PyErr. + /// + /// `obj` must be an Python exception instance, the PyErr will use that instance. + /// If `obj` is a Python exception type object, the PyErr will (lazily) create a new instance of that type. + /// Otherwise, a `TypeError` is created instead. + pub fn from_instance(obj: O) -> PyErr<'p> where O: PythonObject<'p> { + PyErr::from_instance_helper(obj.into_object()) + } + + fn from_instance_helper(obj: PyObject<'p>) -> PyErr<'p> { let py = obj.python(); if unsafe { ffi::PyExceptionInstance_Check(obj.as_ptr()) } != 0 { PyErr { diff --git a/src/objects/exc.rs b/src/objects/exc.rs index 7bbfcbf8..b8f02f37 100644 --- a/src/objects/exc.rs +++ b/src/objects/exc.rs @@ -66,9 +66,6 @@ macro_rules! exc_type( } } ); - ($name:ident : $base:ident) => ( - exc_type!($name); - ); ); exc_type!(BaseException, PyExc_BaseException); diff --git a/src/objects/module.rs b/src/objects/module.rs index 3164e780..8b848ca5 100644 --- a/src/objects/module.rs +++ b/src/objects/module.rs @@ -66,7 +66,7 @@ impl <'p> PyModule<'p> { let slice = CStr::from_ptr(ptr).to_bytes(); match std::str::from_utf8(slice) { Ok(s) => Ok(s), - Err(e) => Err(PyErr::new(try!(exc::UnicodeDecodeError::new_utf8(py, slice, e)))) + Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, slice, e)))) } } } diff --git a/src/objects/string.rs b/src/objects/string.rs index 5ac5d799..4a25c0ab 100644 --- a/src/objects/string.rs +++ b/src/objects/string.rs @@ -100,7 +100,7 @@ impl <'p> PyUnicode<'p> { }; match str::from_utf8(bytes.as_slice()) { Ok(s) => Ok(Cow::Owned(s.to_owned())), - Err(e) => Err(PyErr::new(try!(exc::UnicodeDecodeError::new_utf8(py, bytes.as_slice(), e)))) + Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, bytes.as_slice(), e)))) } } @@ -216,7 +216,7 @@ impl <'p> PyString<'p> { let py = self.python(); match str::from_utf8(self.as_slice()) { Ok(s) => Ok(Cow::Borrowed(s)), - Err(e) => Err(PyErr::new(try!(exc::UnicodeDecodeError::new_utf8(py, self.as_slice(), e)))) + Err(e) => Err(PyErr::from_instance(try!(exc::UnicodeDecodeError::new_utf8(py, self.as_slice(), e)))) } }