Implement PyErr::get_type_bound (#3819)
* Implement PyErr::get_type_bound * Update docs for PyErr::get_type_bound * Fix doctest for cloning PyErr * Import the whole prelude in docs example Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Remove unnecessary self lifetime Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Remove more unnecessary self lifetimes * Use variables to avoid dangling pointers Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Avoid using ffi in fn ptype on Py_3_12 Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Add missing imports to fn ptype --------- Co-authored-by: David Hewitt <mail@davidhewitt.dev>
This commit is contained in:
parent
c56cd3dd65
commit
baf5c8ec0a
|
@ -479,7 +479,7 @@ class House(object):
|
|||
}
|
||||
Err(e) => {
|
||||
house
|
||||
.call_method1("__exit__", (e.get_type(py), e.value(py), e.traceback_bound(py)))
|
||||
.call_method1("__exit__", (e.get_type_bound(py), e.value(py), e.traceback_bound(py)))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,15 @@ pub(crate) struct PyErrStateNormalized {
|
|||
|
||||
impl PyErrStateNormalized {
|
||||
#[cfg(not(Py_3_12))]
|
||||
pub(crate) fn ptype<'py>(&'py self, py: Python<'py>) -> &'py PyType {
|
||||
self.ptype.as_ref(py)
|
||||
pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {
|
||||
self.ptype.bind(py).clone()
|
||||
}
|
||||
|
||||
#[cfg(Py_3_12)]
|
||||
pub(crate) fn ptype<'py>(&'py self, py: Python<'py>) -> &'py PyType {
|
||||
self.pvalue.as_ref(py).get_type()
|
||||
pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {
|
||||
use crate::instance::PyNativeType;
|
||||
use crate::types::any::PyAnyMethods;
|
||||
self.pvalue.bind(py).get_type().as_borrowed().to_owned()
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_12))]
|
||||
|
|
|
@ -225,18 +225,30 @@ impl PyErr {
|
|||
PyErr::from_state(state)
|
||||
}
|
||||
|
||||
/// Deprecated form of [`PyErr::get_type_bound`].
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyErr::get_type` will be replaced by `PyErr::get_type_bound` in a future PyO3 version"
|
||||
)
|
||||
)]
|
||||
pub fn get_type<'py>(&'py self, py: Python<'py>) -> &'py PyType {
|
||||
self.get_type_bound(py).into_gil_ref()
|
||||
}
|
||||
|
||||
/// Returns the type of this exception.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust
|
||||
/// use pyo3::{exceptions::PyTypeError, types::PyType, PyErr, Python};
|
||||
/// use pyo3::{prelude::*, exceptions::PyTypeError, types::PyType};
|
||||
///
|
||||
/// Python::with_gil(|py| {
|
||||
/// let err: PyErr = PyTypeError::new_err(("some type error",));
|
||||
/// assert!(err.get_type(py).is(PyType::new::<PyTypeError>(py)));
|
||||
/// assert!(err.get_type_bound(py).is(PyType::new::<PyTypeError>(py)));
|
||||
/// });
|
||||
/// ```
|
||||
pub fn get_type<'py>(&'py self, py: Python<'py>) -> &'py PyType {
|
||||
pub fn get_type_bound<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {
|
||||
self.normalized(py).ptype(py)
|
||||
}
|
||||
|
||||
|
@ -493,8 +505,9 @@ impl PyErr {
|
|||
// after the argument got evaluated, leading to call with a dangling
|
||||
// pointer.
|
||||
let traceback = self.traceback_bound(py);
|
||||
let type_bound = self.get_type_bound(py);
|
||||
ffi::PyErr_Display(
|
||||
self.get_type(py).as_ptr(),
|
||||
type_bound.as_ptr(),
|
||||
self.value(py).as_ptr(),
|
||||
traceback
|
||||
.as_ref()
|
||||
|
@ -531,7 +544,8 @@ impl PyErr {
|
|||
/// Returns true if the current exception is instance of `T`.
|
||||
#[inline]
|
||||
pub fn is_instance(&self, py: Python<'_>, ty: &PyAny) -> bool {
|
||||
(unsafe { ffi::PyErr_GivenExceptionMatches(self.get_type(py).as_ptr(), ty.as_ptr()) }) != 0
|
||||
let type_bound = self.get_type_bound(py);
|
||||
(unsafe { ffi::PyErr_GivenExceptionMatches(type_bound.as_ptr(), ty.as_ptr()) }) != 0
|
||||
}
|
||||
|
||||
/// Returns true if the current exception is instance of `T`.
|
||||
|
@ -680,7 +694,7 @@ impl PyErr {
|
|||
/// Python::with_gil(|py| {
|
||||
/// let err: PyErr = PyTypeError::new_err(("some type error",));
|
||||
/// let err_clone = err.clone_ref(py);
|
||||
/// assert!(err.get_type(py).is(err_clone.get_type(py)));
|
||||
/// assert!(err.get_type_bound(py).is(&err_clone.get_type_bound(py)));
|
||||
/// assert!(err.value(py).is(err_clone.value(py)));
|
||||
/// match err.traceback_bound(py) {
|
||||
/// None => assert!(err_clone.traceback_bound(py).is_none()),
|
||||
|
@ -763,7 +777,7 @@ impl std::fmt::Debug for PyErr {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
Python::with_gil(|py| {
|
||||
f.debug_struct("PyErr")
|
||||
.field("type", self.get_type(py))
|
||||
.field("type", &self.get_type_bound(py))
|
||||
.field("value", self.value(py))
|
||||
.field("traceback", &self.traceback_bound(py))
|
||||
.finish()
|
||||
|
|
|
@ -165,7 +165,8 @@ pub fn from_py_with_with_default<'py, T>(
|
|||
#[doc(hidden)]
|
||||
#[cold]
|
||||
pub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) -> PyErr {
|
||||
if error.get_type(py).is(py.get_type::<PyTypeError>()) {
|
||||
use crate::types::any::PyAnyMethods;
|
||||
if error.get_type_bound(py).is(py.get_type::<PyTypeError>()) {
|
||||
let remapped_error =
|
||||
PyTypeError::new_err(format!("argument '{}': {}", arg_name, error.value(py)));
|
||||
remapped_error.set_cause(py, error.cause(py));
|
||||
|
|
Loading…
Reference in New Issue