Skip to content

Commit

Permalink
PyList: remove get_parked_item, use macros for speed on !abi3
Browse files Browse the repository at this point in the history
  • Loading branch information
birkenfeld committed Jun 6, 2021
1 parent 4d2c173 commit 3bebc19
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 52 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Remove `__doc__` from module's `__all__`. [#1509](https://github.com/PyO3/pyo3/pull/1509)
- Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality. [#1521](https://github.com/PyO3/pyo3/pull/1521)
- Remove `raw_pycfunction!` macro. [#1619](https://github.com/PyO3/pyo3/pull/1619)
- Remove `PyList::get_parked_item`. [#1664](https://github.com/PyO3/pyo3/pull/1664)

### Fixed
- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)
Expand Down
2 changes: 1 addition & 1 deletion src/types/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl PyDict {

/// Returns a new dictionary that contains the same key-value pairs as self.
///
/// This is equivalent to the Python expression `dict(self)`.
/// This is equivalent to the Python expression `self.copy()`.
pub fn copy(&self) -> PyResult<&PyDict> {
unsafe {
self.py()
Expand Down
82 changes: 31 additions & 51 deletions src/types/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,31 @@ pub struct PyList(PyAny);

pyobject_native_type_core!(PyList, ffi::PyList_Type, #checkfunction=ffi::PyList_Check);

#[inline]
unsafe fn new_from_iter<T>(
elements: impl ExactSizeIterator<Item = T>,
convert: impl Fn(T) -> PyObject,
) -> *mut ffi::PyObject {
let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
for (i, e) in elements.enumerate() {
let obj = convert(e).into_ptr();
#[cfg(not(Py_LIMITED_API))]
ffi::PyList_SET_ITEM(ptr, i as Py_ssize_t, obj);
#[cfg(Py_LIMITED_API)]
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
}
ptr
}

impl PyList {
/// Constructs a new list with the given elements.
pub fn new<T, U>(py: Python<'_>, elements: impl IntoIterator<Item = T, IntoIter = U>) -> &PyList
where
T: ToPyObject,
U: ExactSizeIterator<Item = T>,
{
let elements_iter = elements.into_iter();
let len = elements_iter.len();
unsafe {
let ptr = ffi::PyList_New(len as Py_ssize_t);
for (i, e) in elements_iter.enumerate() {
let obj = e.to_object(py).into_ptr();
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
}
py.from_owned_ptr::<PyList>(ptr)
py.from_owned_ptr::<PyList>(new_from_iter(elements.into_iter(), |e| e.to_object(py)))
}
}

Expand All @@ -41,8 +50,15 @@ impl PyList {

/// Returns the length of the list.
pub fn len(&self) -> usize {
// non-negative Py_ssize_t should always fit into Rust usize
unsafe { ffi::PyList_Size(self.as_ptr()) as usize }
unsafe {
#[cfg(not(Py_LIMITED_API))]
let size = ffi::PyList_GET_SIZE(self.as_ptr());
#[cfg(Py_LIMITED_API)]
let size = ffi::PyList_Size(self.as_ptr());

// non-negative Py_ssize_t should always fit into Rust usize
size as usize
}
}

/// Checks if the list is empty.
Expand All @@ -56,6 +72,9 @@ impl PyList {
pub fn get_item(&self, index: isize) -> &PyAny {
assert!((index.abs() as usize) < self.len());
unsafe {
#[cfg(not(Py_LIMITED_API))]
let ptr = ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t);
#[cfg(Py_LIMITED_API)]
let ptr = ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t);

// PyList_GetItem return borrowed ptr; must make owned for safety (see #890).
Expand All @@ -64,18 +83,6 @@ impl PyList {
}
}

/// Gets the item at the specified index.
///
/// Panics if the index is out of range.
pub fn get_parked_item(&self, index: isize) -> PyObject {
unsafe {
PyObject::from_borrowed_ptr(
self.py(),
ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t),
)
}
}

/// Sets the item at the specified index.
///
/// Panics if the index is out of range.
Expand Down Expand Up @@ -167,14 +174,7 @@ where
T: ToPyObject,
{
fn to_object(&self, py: Python<'_>) -> PyObject {
unsafe {
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
for (i, e) in self.iter().enumerate() {
let obj = e.to_object(py).into_ptr();
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
}
PyObject::from_owned_ptr(py, ptr)
}
unsafe { PyObject::from_owned_ptr(py, new_from_iter(self.iter(), |e| e.to_object(py))) }
}
}

Expand All @@ -192,14 +192,7 @@ where
T: IntoPy<PyObject>,
{
fn into_py(self, py: Python) -> PyObject {
unsafe {
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
for (i, e) in self.into_iter().enumerate() {
let obj = e.into_py(py).into_ptr();
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
}
PyObject::from_owned_ptr(py, ptr)
}
unsafe { PyObject::from_owned_ptr(py, new_from_iter(self.into_iter(), |e| e.into_py(py))) }
}
}

Expand Down Expand Up @@ -244,19 +237,6 @@ mod test {
assert_eq!(7, list.get_item(3).extract::<i32>().unwrap());
}

#[test]
fn test_get_parked_item() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert_eq!(2, list.get_parked_item(0).extract::<i32>(py).unwrap());
assert_eq!(3, list.get_parked_item(1).extract::<i32>(py).unwrap());
assert_eq!(5, list.get_parked_item(2).extract::<i32>(py).unwrap());
assert_eq!(7, list.get_parked_item(3).extract::<i32>(py).unwrap());
}

#[test]
fn test_set_item() {
let gil = Python::acquire_gil();
Expand Down

0 comments on commit 3bebc19

Please sign in to comment.