diff --git a/newsfragments/3577.added.md b/newsfragments/3577.added.md new file mode 100644 index 00000000000..632274984ec --- /dev/null +++ b/newsfragments/3577.added.md @@ -0,0 +1 @@ +Implement `PyTypeInfo` for `PyEllipsis`, `PyNone` and `PyNotImplemented`. diff --git a/src/types/ellipsis.rs b/src/types/ellipsis.rs index f0603b664c9..c1d77681399 100644 --- a/src/types/ellipsis.rs +++ b/src/types/ellipsis.rs @@ -1,4 +1,4 @@ -use crate::{ffi, PyAny, PyDowncastError, PyTryFrom, Python}; +use crate::{ffi, PyAny, PyTypeInfo, Python}; /// Represents the Python `Ellipsis` object. #[repr(transparent)] @@ -15,24 +15,26 @@ impl PyEllipsis { } } -impl<'v> PyTryFrom<'v> for PyEllipsis { - fn try_from>(value: V) -> Result<&'v Self, crate::PyDowncastError<'v>> { - let value: &PyAny = value.into(); - if unsafe { ffi::Py_Ellipsis() == value.as_ptr() } { - return unsafe { Ok(value.downcast_unchecked()) }; - } - Err(PyDowncastError::new(value, "ellipsis")) +unsafe impl PyTypeInfo for PyEllipsis { + const NAME: &'static str = "ellipsis"; + + const MODULE: Option<&'static str> = None; + + type AsRefTarget = PyEllipsis; + + fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { + unsafe { ffi::Py_TYPE(ffi::Py_Ellipsis()) } } - fn try_from_exact>( - value: V, - ) -> Result<&'v Self, crate::PyDowncastError<'v>> { - value.into().downcast() + #[inline] + fn is_type_of(object: &PyAny) -> bool { + // ellipsis is not usable as a base type + Self::is_exact_type_of(object) } - unsafe fn try_from_unchecked>(value: V) -> &'v Self { - let ptr = value.into() as *const _ as *const PyEllipsis; - &*ptr + #[inline] + fn is_exact_type_of(object: &PyAny) -> bool { + object.is(PyEllipsis::get(object.py())) } } diff --git a/src/types/none.rs b/src/types/none.rs index d80faac20be..fedb0a69fa6 100644 --- a/src/types/none.rs +++ b/src/types/none.rs @@ -1,4 +1,4 @@ -use crate::{ffi, IntoPy, PyAny, PyDowncastError, PyObject, PyTryFrom, Python, ToPyObject}; +use crate::{ffi, IntoPy, PyAny, PyObject, PyTypeInfo, Python, ToPyObject}; /// Represents the Python `None` object. #[repr(transparent)] @@ -15,24 +15,26 @@ impl PyNone { } } -impl<'v> PyTryFrom<'v> for PyNone { - fn try_from>(value: V) -> Result<&'v Self, crate::PyDowncastError<'v>> { - let value: &PyAny = value.into(); - if value.is_none() { - return unsafe { Ok(value.downcast_unchecked()) }; - } - Err(PyDowncastError::new(value, "NoneType")) +unsafe impl PyTypeInfo for PyNone { + const NAME: &'static str = "NoneType"; + + const MODULE: Option<&'static str> = None; + + type AsRefTarget = PyNone; + + fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { + unsafe { ffi::Py_TYPE(ffi::Py_None()) } } - fn try_from_exact>( - value: V, - ) -> Result<&'v Self, crate::PyDowncastError<'v>> { - value.into().downcast() + #[inline] + fn is_type_of(object: &PyAny) -> bool { + // NoneType is not usable as a base type + Self::is_exact_type_of(object) } - unsafe fn try_from_unchecked>(value: V) -> &'v Self { - let ptr = value.into() as *const _ as *const PyNone; - &*ptr + #[inline] + fn is_exact_type_of(object: &PyAny) -> bool { + object.is_none() } } diff --git a/src/types/notimplemented.rs b/src/types/notimplemented.rs index 2f08f94566e..72c58efa851 100644 --- a/src/types/notimplemented.rs +++ b/src/types/notimplemented.rs @@ -1,4 +1,4 @@ -use crate::{ffi, PyAny, PyDowncastError, PyTryFrom, Python}; +use crate::{ffi, PyAny, PyTypeInfo, Python}; /// Represents the Python `NotImplemented` object. #[repr(transparent)] @@ -15,24 +15,26 @@ impl PyNotImplemented { } } -impl<'v> PyTryFrom<'v> for PyNotImplemented { - fn try_from>(value: V) -> Result<&'v Self, crate::PyDowncastError<'v>> { - let value: &PyAny = value.into(); - if unsafe { ffi::Py_NotImplemented() == value.as_ptr() } { - return unsafe { Ok(value.downcast_unchecked()) }; - } - Err(PyDowncastError::new(value, "NotImplementedType")) +unsafe impl PyTypeInfo for PyNotImplemented { + const NAME: &'static str = "NotImplementedType"; + + const MODULE: Option<&'static str> = None; + + type AsRefTarget = PyNotImplemented; + + fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { + unsafe { ffi::Py_TYPE(ffi::Py_NotImplemented()) } } - fn try_from_exact>( - value: V, - ) -> Result<&'v Self, crate::PyDowncastError<'v>> { - value.into().downcast() + #[inline] + fn is_type_of(object: &PyAny) -> bool { + // NoneType is not usable as a base type + Self::is_exact_type_of(object) } - unsafe fn try_from_unchecked>(value: V) -> &'v Self { - let ptr = value.into() as *const _ as *const PyNotImplemented; - &*ptr + #[inline] + fn is_exact_type_of(object: &PyAny) -> bool { + object.is(PyNotImplemented::get(object.py())) } }