Skip to content

Commit 2788f4a

Browse files
authored
Merge pull request #3680 from davidhewitt/list2
implement `PyListMethods`
2 parents 5b12cf1 + ee1272e commit 2788f4a

File tree

4 files changed

+408
-66
lines changed

4 files changed

+408
-66
lines changed

src/instance.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,26 @@ unsafe impl<T> AsPyPointer for Py2<'_, T> {
221221
///
222222
/// The advantage of this over `&Py2` is that it avoids the need to have a pointer-to-pointer, as Py2
223223
/// is already a pointer to an `ffi::PyObject``.
224+
///
225+
/// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`).
224226
#[repr(transparent)]
225227
pub(crate) struct Py2Borrowed<'a, 'py, T>(
226228
NonNull<ffi::PyObject>,
227229
PhantomData<&'a Py<T>>,
228230
Python<'py>,
229231
);
230232

233+
impl<'py, T> Py2Borrowed<'_, 'py, T> {
234+
/// Creates a new owned `Py2` from this borrowed reference by increasing the reference count.
235+
pub(crate) fn to_owned(self) -> Py2<'py, T> {
236+
unsafe { ffi::Py_INCREF(self.as_ptr()) };
237+
Py2(
238+
self.py(),
239+
ManuallyDrop::new(unsafe { Py::from_non_null(self.0) }),
240+
)
241+
}
242+
}
243+
231244
impl<'a, 'py> Py2Borrowed<'a, 'py, PyAny> {
232245
/// # Safety
233246
/// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by
@@ -315,6 +328,14 @@ impl<'py, T> Deref for Py2Borrowed<'_, 'py, T> {
315328
}
316329
}
317330

331+
impl<T> Clone for Py2Borrowed<'_, '_, T> {
332+
fn clone(&self) -> Self {
333+
*self
334+
}
335+
}
336+
337+
impl<T> Copy for Py2Borrowed<'_, '_, T> {}
338+
318339
/// A GIL-independent reference to an object allocated on the Python heap.
319340
///
320341
/// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it.

src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub use crate::wrap_pyfunction;
3232
// pub(crate) use crate::types::bytes::PyBytesMethods;
3333
// pub(crate) use crate::types::dict::PyDictMethods;
3434
// pub(crate) use crate::types::float::PyFloatMethods;
35+
// pub(crate) use crate::types::list::PyListMethods;
3536
// pub(crate) use crate::types::mapping::PyMappingMethods;
3637
// pub(crate) use crate::types::sequence::PySequenceMethods;
3738
// pub(crate) use crate::types::string::PyStringMethods;

src/types/dict.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::PyMapping;
22
use crate::err::{self, PyErr, PyResult};
33
use crate::ffi::Py_ssize_t;
44
use crate::ffi_ptr_ext::FfiPtrExt;
5-
use crate::instance::Py2;
5+
use crate::instance::{Py2, Py2Borrowed};
66
use crate::py_result_ext::PyResultExt;
77
use crate::types::any::PyAnyMethods;
88
use crate::types::{PyAny, PyList};
@@ -406,7 +406,7 @@ impl<'py> PyDictMethods<'py> for Py2<'py, PyDict> {
406406
match unsafe {
407407
ffi::PyDict_GetItemWithError(dict.as_ptr(), key.as_ptr())
408408
.assume_borrowed_or_opt(py)
409-
.map(|borrowed_any| borrowed_any.clone())
409+
.map(Py2Borrowed::to_owned)
410410
} {
411411
some @ Some(_) => Ok(some),
412412
None => PyErr::take(py).map(Err).transpose(),
@@ -595,8 +595,8 @@ impl<'py> Iterator for PyDictIterator2<'py> {
595595
// - PyDict_Next returns borrowed values
596596
// - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null
597597
Some((
598-
unsafe { key.assume_borrowed_unchecked(py) }.clone(),
599-
unsafe { value.assume_borrowed_unchecked(py) }.clone(),
598+
unsafe { key.assume_borrowed_unchecked(py) }.to_owned(),
599+
unsafe { value.assume_borrowed_unchecked(py) }.to_owned(),
600600
))
601601
} else {
602602
None

0 commit comments

Comments
 (0)