Skip to content

Commit

Permalink
Make is_instance() and is_subclass() take &PyAny
Browse files Browse the repository at this point in the history
Should be (mostly?) compatible since `&PyType` auto-derefs to `&PyAny`.

Fixes #2694
  • Loading branch information
birkenfeld committed Oct 18, 2022
1 parent bec726c commit eec701a
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 14 deletions.
2 changes: 0 additions & 2 deletions guide/src/ecosystem/async-await.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,8 +540,6 @@ fn main() -> PyResult<()> {
uvloop
.as_ref(py)
.getattr("Loop")?
.downcast::<PyType>()
.unwrap()
)?);
Ok(())
})?;
Expand Down
3 changes: 3 additions & 0 deletions newsfragments/2695.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
`PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now take
`&PyAny` instead of `&PyType` arguments, so that they work with objects that
pretend to be types using `__subclasscheck__` and `__instancecheck__`.
3 changes: 1 addition & 2 deletions src/conversions/path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::intern;
use crate::types::PyType;
use crate::{FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject};
use std::borrow::Cow;
use std::ffi::OsString;
Expand All @@ -20,7 +19,7 @@ impl FromPyObject<'_> for PathBuf {
Err(err) => {
let py = ob.py();
let pathlib = py.import(intern!(py, "pathlib"))?;
let pathlib_path: &PyType = pathlib.getattr(intern!(py, "Path"))?.downcast()?;
let pathlib_path = pathlib.getattr(intern!(py, "Path"))?;
if ob.is_instance(pathlib_path)? {
let path_str = ob.call_method0(intern!(py, "__str__"))?;
OsString::extract(path_str)?
Expand Down
2 changes: 1 addition & 1 deletion src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ impl PyErr {

/// Returns true if the current exception is instance of `T`.
#[inline]
pub fn is_instance(&self, py: Python<'_>, typ: &PyType) -> bool {
pub fn is_instance(&self, py: Python<'_>, typ: &PyAny) -> bool {
unsafe { ffi::PyErr_GivenExceptionMatches(self.type_ptr(py), typ.as_ptr()) != 0 }
}

Expand Down
6 changes: 3 additions & 3 deletions src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,7 @@ impl PyAny {
/// Checks whether this object is an instance of type `ty`.
///
/// This is equivalent to the Python expression `isinstance(self, ty)`.
pub fn is_instance(&self, ty: &PyType) -> PyResult<bool> {
pub fn is_instance(&self, ty: &PyAny) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) };
err::error_on_minusone(self.py(), result)?;
Ok(result == 1)
Expand Down Expand Up @@ -985,7 +985,7 @@ class SimpleClass:
}

#[test]
fn test_any_isinstance() {
fn test_any_isinstance_of() {
Python::with_gil(|py| {
let x = 5.to_object(py).into_ref(py);
assert!(x.is_instance_of::<PyLong>().unwrap());
Expand All @@ -996,7 +996,7 @@ class SimpleClass:
}

#[test]
fn test_any_isinstance_of() {
fn test_any_isinstance() {
Python::with_gil(|py| {
let l = vec![1u8, 2].to_object(py).into_ref(py);
assert!(l.is_instance(PyList::type_object(py)).unwrap());
Expand Down
9 changes: 4 additions & 5 deletions src/types/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,7 @@ mod tests {
#[cfg(not(PyPy))]
use crate::exceptions;
#[cfg(not(PyPy))]
use crate::{types::PyList, PyTypeInfo};
use crate::{types::PyTuple, IntoPy, PyObject, PyTryFrom, Python, ToPyObject};
use crate::{types::PyList, types::PyTuple, IntoPy, PyObject, PyTryFrom, Python, ToPyObject};
use std::collections::{BTreeMap, HashMap};

#[test]
Expand Down Expand Up @@ -1042,7 +1041,7 @@ mod tests {
Python::with_gil(|py| {
let dict = abc_dict(py);
let keys = dict.call_method0("keys").unwrap();
assert!(keys.is_instance(PyDictKeys::type_object(py)).unwrap());
assert!(keys.is_instance_of::<PyDictKeys>().unwrap());
})
}

Expand All @@ -1052,7 +1051,7 @@ mod tests {
Python::with_gil(|py| {
let dict = abc_dict(py);
let values = dict.call_method0("values").unwrap();
assert!(values.is_instance(PyDictValues::type_object(py)).unwrap());
assert!(values.is_instance_of::<PyDictValues>().unwrap());
})
}

Expand All @@ -1062,7 +1061,7 @@ mod tests {
Python::with_gil(|py| {
let dict = abc_dict(py);
let items = dict.call_method0("items").unwrap();
assert!(items.is_instance(PyDictItems::type_object(py)).unwrap());
assert!(items.is_instance_of::<PyDictItems>().unwrap());
})
}
}
2 changes: 1 addition & 1 deletion src/types/typeobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl PyType {
/// Checks whether `self` is a subclass of `other`.
///
/// Equivalent to the Python expression `issubclass(self, other)`.
pub fn is_subclass(&self, other: &PyType) -> PyResult<bool> {
pub fn is_subclass(&self, other: &PyAny) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsSubclass(self.as_ptr(), other.as_ptr()) };
err::error_on_minusone(self.py(), result)?;
Ok(result == 1)
Expand Down

0 comments on commit eec701a

Please sign in to comment.