From ecadc62f24359d9c6b8c942bd50b6b7336ecc542 Mon Sep 17 00:00:00 2001 From: Ryan Lowe Date: Fri, 18 Aug 2023 17:55:58 -0400 Subject: [PATCH] Add types for built-in singletons None, Ellipsis, and NotImplemented --- src/conversion.rs | 13 ------------- src/marker.rs | 10 ++++++---- src/types/ellipsis.rs | 19 +++++++++++++++++++ src/types/mod.rs | 6 ++++++ src/types/none.rs | 33 +++++++++++++++++++++++++++++++++ src/types/notimplemented.rs | 19 +++++++++++++++++++ 6 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 src/types/ellipsis.rs create mode 100644 src/types/none.rs create mode 100644 src/types/notimplemented.rs diff --git a/src/conversion.rs b/src/conversion.rs index 95151242713..a68aa7731b3 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -263,19 +263,6 @@ where } } -/// `()` is converted to Python `None`. -impl ToPyObject for () { - fn to_object(&self, py: Python<'_>) -> PyObject { - py.None() - } -} - -impl IntoPy for () { - fn into_py(self, py: Python<'_>) -> PyObject { - py.None() - } -} - impl IntoPy for &'_ T where T: AsPyPointer, diff --git a/src/marker.rs b/src/marker.rs index 58a1104d764..2d130ae4ad1 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -118,7 +118,9 @@ use crate::err::{self, PyDowncastError, PyErr, PyResult}; use crate::gil::{GILGuard, GILPool, SuspendGIL}; use crate::impl_::not_send::NotSend; -use crate::types::{PyAny, PyDict, PyModule, PyString, PyType}; +use crate::types::{ + PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType, +}; use crate::version::PythonVersionInfo; use crate::{ffi, FromPyPointer, IntoPy, Py, PyNativeType, PyObject, PyTryFrom, PyTypeInfo}; use std::ffi::{CStr, CString}; @@ -690,21 +692,21 @@ impl<'py> Python<'py> { #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn None(self) -> PyObject { - unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_None()) } + PyNone::get(self).into() } /// Gets the Python builtin value `Ellipsis`, or `...`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn Ellipsis(self) -> PyObject { - unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_Ellipsis()) } + PyEllipsis::get(self).into() } /// Gets the Python builtin value `NotImplemented`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn NotImplemented(self) -> PyObject { - unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_NotImplemented()) } + PyNotImplemented::get(self).into() } /// Gets the running Python interpreter version as a string. diff --git a/src/types/ellipsis.rs b/src/types/ellipsis.rs new file mode 100644 index 00000000000..ac50e11bdd7 --- /dev/null +++ b/src/types/ellipsis.rs @@ -0,0 +1,19 @@ +use crate::{ffi, PyAny, Python}; + +/// Represents the Python `Ellipsis` object. +#[repr(transparent)] +pub struct PyEllipsis(PyAny); + +pyobject_native_type!( + PyEllipsis, + ffi::PyObject, + pyobject_native_static_type_object!(ffi::PyEllipsis_Type) +); + +impl PyEllipsis { + /// Returns the `Ellipsis` object. + #[inline] + pub fn get(py: Python<'_>) -> &PyEllipsis { + unsafe { py.from_borrowed_ptr(ffi::Py_Ellipsis()) } + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 4d8b0513adf..dc6e6d69a57 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -16,6 +16,7 @@ pub use self::datetime::{ pub use self::dict::{IntoPyDict, PyDict}; #[cfg(not(PyPy))] pub use self::dict::{PyDictItems, PyDictKeys, PyDictValues}; +pub use self::ellipsis::PyEllipsis; pub use self::floatob::PyFloat; #[cfg(all(not(Py_LIMITED_API), not(PyPy)))] pub use self::frame::PyFrame; @@ -27,6 +28,8 @@ pub use self::iterator::PyIterator; pub use self::list::PyList; pub use self::mapping::PyMapping; pub use self::module::PyModule; +pub use self::none::PyNone; +pub use self::notimplemented::PyNotImplemented; pub use self::num::PyLong; pub use self::num::PyLong as PyInt; #[cfg(not(PyPy))] @@ -278,6 +281,7 @@ mod complex; #[cfg(not(Py_LIMITED_API))] mod datetime; mod dict; +mod ellipsis; mod floatob; #[cfg(all(not(Py_LIMITED_API), not(PyPy)))] mod frame; @@ -287,6 +291,8 @@ mod iterator; pub(crate) mod list; mod mapping; mod module; +mod none; +mod notimplemented; mod num; #[cfg(not(PyPy))] mod pysuper; diff --git a/src/types/none.rs b/src/types/none.rs new file mode 100644 index 00000000000..fed30e636c5 --- /dev/null +++ b/src/types/none.rs @@ -0,0 +1,33 @@ +use crate::{ffi, IntoPy, PyAny, PyObject, Python, ToPyObject}; + +/// Represents the Python `None` object. +#[repr(transparent)] +pub struct PyNone(PyAny); + +pyobject_native_type!( + PyNone, + ffi::PyObject, + pyobject_native_static_type_object!(ffi::_PyNone_Type) +); + +impl PyNone { + /// Returns the `None` object. + #[inline] + pub fn get(py: Python<'_>) -> &PyNone { + unsafe { py.from_borrowed_ptr(ffi::Py_None()) } + } +} + +/// `()` is converted to Python `None`. +impl ToPyObject for () { + fn to_object(&self, py: Python<'_>) -> PyObject { + PyNone::get(py).into() + } +} + +impl IntoPy for () { + #[inline] + fn into_py(self, py: Python<'_>) -> PyObject { + PyNone::get(py).into() + } +} diff --git a/src/types/notimplemented.rs b/src/types/notimplemented.rs new file mode 100644 index 00000000000..213a0c158c1 --- /dev/null +++ b/src/types/notimplemented.rs @@ -0,0 +1,19 @@ +use crate::{ffi, PyAny, Python}; + +/// Represents the Python `NotImplemented` object. +#[repr(transparent)] +pub struct PyNotImplemented(PyAny); + +pyobject_native_type!( + PyNotImplemented, + ffi::PyObject, + pyobject_native_static_type_object!(ffi::_PyNotImplemented_Type) +); + +impl PyNotImplemented { + /// Returns the `NotImplemented` object. + #[inline] + pub fn get(py: Python<'_>) -> &PyNotImplemented { + unsafe { py.from_borrowed_ptr(ffi::Py_NotImplemented()) } + } +}