Skip to content

Commit

Permalink
reintroduce a bunch of type contructors (#4432)
Browse files Browse the repository at this point in the history
* reintroduce `PyCFunction` constructors

* reintroduce `PyIterator` contructors

* reintroduce `PyMemoryView` contructors

* reintroduce `PyNone` contructors

* reintroduce `PyNotImplemented` contructors

* reintroduce `PySuper` contructors

* reintroduce `PySlice` contructors

* reintroduce `PyType` contructors
  • Loading branch information
Icxolu authored Aug 10, 2024
1 parent cc4b108 commit f53971e
Show file tree
Hide file tree
Showing 22 changed files with 151 additions and 57 deletions.
2 changes: 1 addition & 1 deletion pytests/src/buf_and_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl BytesExtractor {
#[pyfunction]
fn return_memoryview(py: Python<'_>) -> PyResult<Bound<'_, PyMemoryView>> {
let bytes = PyBytes::new(py, b"hello world");
PyMemoryView::from_bound(&bytes)
PyMemoryView::from(&bytes)
}

#[pymodule]
Expand Down
2 changes: 1 addition & 1 deletion src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl Coroutine {
if let Some(future) = self.waker.as_ref().unwrap().initialize_future(py)? {
// `asyncio.Future` must be awaited; fortunately, it implements `__iter__ = __await__`
// and will yield itself if its result has not been set in polling above
if let Some(future) = PyIterator::from_bound_object(&future.as_borrowed())
if let Some(future) = PyIterator::from_object(&future.as_borrowed())
.unwrap()
.next()
{
Expand Down
2 changes: 1 addition & 1 deletion src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl PyErr {
///
/// Python::with_gil(|py| {
/// let err: PyErr = PyTypeError::new_err(("some type error",));
/// assert!(err.get_type_bound(py).is(&PyType::new_bound::<PyTypeError>(py)));
/// assert!(err.get_type_bound(py).is(&PyType::new::<PyTypeError>(py)));
/// });
/// ```
pub fn get_type_bound<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {
Expand Down
2 changes: 1 addition & 1 deletion src/impl_/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ impl<T> Deref for UnknownReturnResultType<T> {
impl EmptyTupleConverter<PyResult<()>> {
#[inline]
pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<*mut ffi::PyObject> {
obj.map(|_| PyNone::get_bound(py).to_owned().into_ptr())
obj.map(|_| PyNone::get(py).to_owned().into_ptr())
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ impl<'py> Python<'py> {
#[allow(non_snake_case)] // the Python keyword starts with uppercase
#[inline]
pub fn None(self) -> PyObject {
PyNone::get_bound(self).into_py(self)
PyNone::get(self).into_py(self)
}

/// Gets the Python builtin value `Ellipsis`, or `...`.
Expand All @@ -684,7 +684,7 @@ impl<'py> Python<'py> {
#[allow(non_snake_case)] // the Python keyword starts with uppercase
#[inline]
pub fn NotImplemented(self) -> PyObject {
PyNotImplemented::get_bound(self).into_py(self)
PyNotImplemented::get(self).into_py(self)
}

/// Gets the running Python interpreter version as a string.
Expand Down
4 changes: 2 additions & 2 deletions src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
}

fn iter(&self) -> PyResult<Bound<'py, PyIterator>> {
PyIterator::from_bound_object(self)
PyIterator::from_object(self)
}

fn get_type(&self) -> Bound<'py, PyType> {
Expand Down Expand Up @@ -1466,7 +1466,7 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {

#[cfg(not(any(PyPy, GraalPy)))]
fn py_super(&self) -> PyResult<Bound<'py, PySuper>> {
PySuper::new_bound(&self.get_type(), self)
PySuper::new(&self.get_type(), self)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/types/frozenset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ pub struct BoundFrozenSetIterator<'p> {
impl<'py> BoundFrozenSetIterator<'py> {
pub(super) fn new(set: Bound<'py, PyFrozenSet>) -> Self {
Self {
it: PyIterator::from_bound_object(&set).unwrap(),
it: PyIterator::from_object(&set).unwrap(),
remaining: set.len(),
}
}
Expand Down
50 changes: 46 additions & 4 deletions src/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl PyCFunction {
///
/// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals),
/// use the [`c_str!`](crate::ffi::c_str) macro.
pub fn new_with_keywords_bound<'py>(
pub fn new_with_keywords<'py>(
py: Python<'py>,
fun: ffi::PyCFunctionWithKeywords,
name: &'static CStr,
Expand All @@ -39,11 +39,24 @@ impl PyCFunction {
)
}

/// Deprecated name for [`PyCFunction::new_with_keywords`].
#[deprecated(since = "0.23.0", note = "renamed to `PyCFunction::new_with_keywords`")]
#[inline]
pub fn new_with_keywords_bound<'py>(
py: Python<'py>,
fun: ffi::PyCFunctionWithKeywords,
name: &'static CStr,
doc: &'static CStr,
module: Option<&Bound<'py, PyModule>>,
) -> PyResult<Bound<'py, Self>> {
Self::new_with_keywords(py, fun, name, doc, module)
}

/// Create a new built-in function which takes no arguments.
///
/// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals),
/// use the [`c_str!`](crate::ffi::c_str) macro.
pub fn new_bound<'py>(
pub fn new<'py>(
py: Python<'py>,
fun: ffi::PyCFunction,
name: &'static CStr,
Expand All @@ -53,6 +66,19 @@ impl PyCFunction {
Self::internal_new(py, &PyMethodDef::noargs(name, fun, doc), module)
}

/// Deprecated name for [`PyCFunction::new`].
#[deprecated(since = "0.23.0", note = "renamed to `PyCFunction::new`")]
#[inline]
pub fn new_bound<'py>(
py: Python<'py>,
fun: ffi::PyCFunction,
name: &'static CStr,
doc: &'static CStr,
module: Option<&Bound<'py, PyModule>>,
) -> PyResult<Bound<'py, Self>> {
Self::new(py, fun, name, doc, module)
}

/// Create a new function from a closure.
///
/// # Examples
Expand All @@ -66,11 +92,11 @@ impl PyCFunction {
/// let i = args.extract::<(i64,)>()?.0;
/// Ok(i+1)
/// };
/// let add_one = PyCFunction::new_closure_bound(py, None, None, add_one).unwrap();
/// let add_one = PyCFunction::new_closure(py, None, None, add_one).unwrap();
/// py_run!(py, add_one, "assert add_one(42) == 43");
/// });
/// ```
pub fn new_closure_bound<'py, F, R>(
pub fn new_closure<'py, F, R>(
py: Python<'py>,
name: Option<&'static CStr>,
doc: Option<&'static CStr>,
Expand Down Expand Up @@ -105,6 +131,22 @@ impl PyCFunction {
}
}

/// Deprecated name for [`PyCFunction::new_closure`].
#[deprecated(since = "0.23.0", note = "renamed to `PyCFunction::new_closure`")]
#[inline]
pub fn new_closure_bound<'py, F, R>(
py: Python<'py>,
name: Option<&'static CStr>,
doc: Option<&'static CStr>,
closure: F,
) -> PyResult<Bound<'py, Self>>
where
F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static,
R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>,
{
Self::new_closure(py, name, doc, closure)
}

#[doc(hidden)]
pub fn internal_new<'py>(
py: Python<'py>,
Expand Down
11 changes: 9 additions & 2 deletions src/types/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,20 @@ impl PyIterator {
///
/// Usually it is more convenient to write [`obj.iter()`][crate::types::any::PyAnyMethods::iter],
/// which is a more concise way of calling this function.
pub fn from_bound_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyIterator>> {
pub fn from_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyIterator>> {
unsafe {
ffi::PyObject_GetIter(obj.as_ptr())
.assume_owned_or_err(obj.py())
.downcast_into_unchecked()
}
}

/// Deprecated name for [`PyIterator::from_object`].
#[deprecated(since = "0.23.0", note = "renamed to `PyIterator::from_object`")]
#[inline]
pub fn from_bound_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyIterator>> {
Self::from_object(obj)
}
}

impl<'py> Iterator for Bound<'py, PyIterator> {
Expand Down Expand Up @@ -232,7 +239,7 @@ def fibonacci(target):
fn int_not_iterable() {
Python::with_gil(|py| {
let x = 5.to_object(py);
let err = PyIterator::from_bound_object(x.bind(py)).unwrap_err();
let err = PyIterator::from_object(x.bind(py)).unwrap_err();

assert!(err.is_instance_of::<PyTypeError>(py));
});
Expand Down
11 changes: 9 additions & 2 deletions src/types/memoryview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ pyobject_native_type_core!(PyMemoryView, pyobject_native_static_type_object!(ffi
impl PyMemoryView {
/// Creates a new Python `memoryview` object from another Python object that
/// implements the buffer protocol.
pub fn from_bound<'py>(src: &Bound<'py, PyAny>) -> PyResult<Bound<'py, Self>> {
pub fn from<'py>(src: &Bound<'py, PyAny>) -> PyResult<Bound<'py, Self>> {
unsafe {
ffi::PyMemoryView_FromObject(src.as_ptr())
.assume_owned_or_err(src.py())
.downcast_into_unchecked()
}
}

/// Deprecated name for [`PyMemoryView::from`].
#[deprecated(since = "0.23.0", note = "renamed to `PyMemoryView::from`")]
#[inline]
pub fn from_bound<'py>(src: &Bound<'py, PyAny>) -> PyResult<Bound<'py, Self>> {
Self::from(src)
}
}

impl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyMemoryView> {
Expand All @@ -30,6 +37,6 @@ impl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyMemoryView> {
/// Creates a new Python `memoryview` object from another Python object that
/// implements the buffer protocol.
fn try_from(value: &Bound<'py, PyAny>) -> Result<Self, Self::Error> {
PyMemoryView::from_bound(value)
PyMemoryView::from(value)
}
}
26 changes: 15 additions & 11 deletions src/types/none.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@ pyobject_native_type_named!(PyNone);
impl PyNone {
/// Returns the `None` object.
#[inline]
pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNone> {
pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNone> {
unsafe { ffi::Py_None().assume_borrowed(py).downcast_unchecked() }
}

/// Deprecated name for [`PyNone::get`].
#[deprecated(since = "0.23.0", note = "renamed to `PyNone::get`")]
#[inline]
pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNone> {
Self::get(py)
}
}

unsafe impl PyTypeInfo for PyNone {
Expand All @@ -38,21 +45,21 @@ unsafe impl PyTypeInfo for PyNone {

#[inline]
fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
object.is(&**Self::get_bound(object.py()))
object.is(&**Self::get(object.py()))
}
}

/// `()` is converted to Python `None`.
impl ToPyObject for () {
fn to_object(&self, py: Python<'_>) -> PyObject {
PyNone::get_bound(py).into_py(py)
PyNone::get(py).into_py(py)
}
}

impl IntoPy<PyObject> for () {
#[inline]
fn into_py(self, py: Python<'_>) -> PyObject {
PyNone::get_bound(py).into_py(py)
PyNone::get(py).into_py(py)
}
}

Expand All @@ -64,15 +71,15 @@ mod tests {
#[test]
fn test_none_is_itself() {
Python::with_gil(|py| {
assert!(PyNone::get_bound(py).is_instance_of::<PyNone>());
assert!(PyNone::get_bound(py).is_exact_instance_of::<PyNone>());
assert!(PyNone::get(py).is_instance_of::<PyNone>());
assert!(PyNone::get(py).is_exact_instance_of::<PyNone>());
})
}

#[test]
fn test_none_type_object_consistent() {
Python::with_gil(|py| {
assert!(PyNone::get_bound(py)
assert!(PyNone::get(py)
.get_type()
.is(&PyNone::type_object_bound(py)));
})
Expand All @@ -81,10 +88,7 @@ mod tests {
#[test]
fn test_none_is_none() {
Python::with_gil(|py| {
assert!(PyNone::get_bound(py)
.downcast::<PyNone>()
.unwrap()
.is_none());
assert!(PyNone::get(py).downcast::<PyNone>().unwrap().is_none());
})
}

Expand Down
17 changes: 12 additions & 5 deletions src/types/notimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ pyobject_native_type_named!(PyNotImplemented);
impl PyNotImplemented {
/// Returns the `NotImplemented` object.
#[inline]
pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {
pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {
unsafe {
ffi::Py_NotImplemented()
.assume_borrowed(py)
.downcast_unchecked()
}
}

/// Deprecated name for [`PyNotImplemented::get`].
#[deprecated(since = "0.23.0", note = "renamed to `PyNotImplemented::get`")]
#[inline]
pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {
Self::get(py)
}
}

unsafe impl PyTypeInfo for PyNotImplemented {
Expand All @@ -40,7 +47,7 @@ unsafe impl PyTypeInfo for PyNotImplemented {

#[inline]
fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool {
object.is(&**Self::get_bound(object.py()))
object.is(&**Self::get(object.py()))
}
}

Expand All @@ -53,15 +60,15 @@ mod tests {
#[test]
fn test_notimplemented_is_itself() {
Python::with_gil(|py| {
assert!(PyNotImplemented::get_bound(py).is_instance_of::<PyNotImplemented>());
assert!(PyNotImplemented::get_bound(py).is_exact_instance_of::<PyNotImplemented>());
assert!(PyNotImplemented::get(py).is_instance_of::<PyNotImplemented>());
assert!(PyNotImplemented::get(py).is_exact_instance_of::<PyNotImplemented>());
})
}

#[test]
fn test_notimplemented_type_object_consistent() {
Python::with_gil(|py| {
assert!(PyNotImplemented::get_bound(py)
assert!(PyNotImplemented::get(py)
.get_type()
.is(&PyNotImplemented::type_object_bound(py)));
})
Expand Down
12 changes: 11 additions & 1 deletion src/types/pysuper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl PySuper {
/// }
/// }
/// ```
pub fn new_bound<'py>(
pub fn new<'py>(
ty: &Bound<'py, PyType>,
obj: &Bound<'py, PyAny>,
) -> PyResult<Bound<'py, PySuper>> {
Expand All @@ -68,4 +68,14 @@ impl PySuper {
unsafe { any.downcast_into_unchecked() }
})
}

/// Deprecated name for [`PySuper::new`].
#[deprecated(since = "0.23.0", note = "renamed to `PySuper::new`")]
#[inline]
pub fn new_bound<'py>(
ty: &Bound<'py, PyType>,
obj: &Bound<'py, PyAny>,
) -> PyResult<Bound<'py, PySuper>> {
Self::new(ty, obj)
}
}
2 changes: 1 addition & 1 deletion src/types/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub struct BoundSetIterator<'p> {
impl<'py> BoundSetIterator<'py> {
pub(super) fn new(set: Bound<'py, PySet>) -> Self {
Self {
it: PyIterator::from_bound_object(&set).unwrap(),
it: PyIterator::from_object(&set).unwrap(),
remaining: set.len(),
}
}
Expand Down
Loading

0 comments on commit f53971e

Please sign in to comment.