Merge #2911
2911: add `Ellipsis()` and `is_ellipsis()` methods r=mejrs,davidhewitt a=samuelcolvin fix #2906 Please consider adding the following to your pull request: - [x] an entry for this PR in newsfragments - see [https://pyo3.rs/main/contributing.html#documenting-changes] - [x] docs to all new functions and / or detail in the guide - [x] tests for all new or changed functions Co-authored-by: Samuel Colvin <s@muelcolvin.com>
This commit is contained in:
commit
794e19d796
|
@ -0,0 +1 @@
|
||||||
|
Add `py.Ellipsis()` and `py_any.is_ellipsis()` methods.
|
|
@ -2,6 +2,7 @@ use crate::object::*;
|
||||||
use crate::pyport::Py_ssize_t;
|
use crate::pyport::Py_ssize_t;
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
|
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[cfg_attr(PyPy, link_name = "_PyPy_EllipsisObject")]
|
#[cfg_attr(PyPy, link_name = "_PyPy_EllipsisObject")]
|
||||||
static mut _Py_EllipsisObject: PyObject;
|
static mut _Py_EllipsisObject: PyObject;
|
||||||
|
|
|
@ -519,6 +519,13 @@ impl<T> Py<T> {
|
||||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the object is Ellipsis, e.g. `...`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `self is ...`.
|
||||||
|
pub fn is_ellipsis(&self) -> bool {
|
||||||
|
unsafe { ffi::Py_Ellipsis() == self.as_ptr() }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns whether the object is considered to be true.
|
/// Returns whether the object is considered to be true.
|
||||||
///
|
///
|
||||||
/// This is equivalent to the Python expression `bool(self)`.
|
/// This is equivalent to the Python expression `bool(self)`.
|
||||||
|
@ -1147,6 +1154,22 @@ a = A()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_ellipsis() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let v = py
|
||||||
|
.eval("...", None, None)
|
||||||
|
.map_err(|e| e.print(py))
|
||||||
|
.unwrap()
|
||||||
|
.to_object(py);
|
||||||
|
|
||||||
|
assert!(v.is_ellipsis());
|
||||||
|
|
||||||
|
let not_ellipsis = 5.to_object(py);
|
||||||
|
assert!(!not_ellipsis.is_ellipsis());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
mod using_macros {
|
mod using_macros {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -619,6 +619,13 @@ impl<'py> Python<'py> {
|
||||||
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_None()) }
|
unsafe { PyObject::from_borrowed_ptr(self, ffi::Py_None()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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()) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the Python builtin value `NotImplemented`.
|
/// Gets the Python builtin value `NotImplemented`.
|
||||||
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
#[allow(non_snake_case)] // the Python keyword starts with uppercase
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1032,4 +1039,15 @@ mod tests {
|
||||||
let state = unsafe { crate::ffi::PyGILState_Check() };
|
let state = unsafe { crate::ffi::PyGILState_Check() };
|
||||||
assert_eq!(state, GIL_NOT_HELD);
|
assert_eq!(state, GIL_NOT_HELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ellipsis() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
assert_eq!(py.Ellipsis().to_string(), "Ellipsis");
|
||||||
|
|
||||||
|
let v = py.eval("...", None, None).map_err(|e| e.print(py)).unwrap();
|
||||||
|
|
||||||
|
assert!(v.eq(py.Ellipsis()).unwrap());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -669,6 +669,13 @@ impl PyAny {
|
||||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the object is Ellipsis, e.g. `...`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to the Python expression `self is ...`.
|
||||||
|
pub fn is_ellipsis(&self) -> bool {
|
||||||
|
unsafe { ffi::Py_Ellipsis() == self.as_ptr() }
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the sequence or mapping has a length of 0.
|
/// Returns true if the sequence or mapping has a length of 0.
|
||||||
///
|
///
|
||||||
/// This is equivalent to the Python expression `len(self) == 0`.
|
/// This is equivalent to the Python expression `len(self) == 0`.
|
||||||
|
@ -1135,4 +1142,16 @@ class SimpleClass:
|
||||||
let bools = [true, false];
|
let bools = [true, false];
|
||||||
test_eq_methods_generic(&bools);
|
test_eq_methods_generic(&bools);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_ellipsis() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let v = py.eval("...", None, None).map_err(|e| e.print(py)).unwrap();
|
||||||
|
|
||||||
|
assert!(v.is_ellipsis());
|
||||||
|
|
||||||
|
let not_ellipsis = 5.to_object(py).into_ref(py);
|
||||||
|
assert!(!not_ellipsis.is_ellipsis());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue