-
Notifications
You must be signed in to change notification settings - Fork 769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Adds the Bound<'_, PyMappingProxy> type #4644
Conversation
Adds in the MappingProxy type.
Thanks for the PR! This is in draft status; is there more you want to add before review? |
Nope! Just got busy yesterday and wanted to do a final look through. Please review when ready. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for picking this up; overall this looks close to merge. While I have added a bunch of comments, they're primarily small tweaks where I think the design is relatively clear 😄
pyo3-ffi/src/descrobject.rs
Outdated
#[inline] | ||
pub unsafe fn PyDictProxy_Check(op: *mut PyObject) -> c_int { | ||
PyObject_TypeCheck(op, std::ptr::addr_of_mut!(PyDictProxy_Type)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function doesn't exist in https://github.com/python/cpython/blob/3.13/Include/descrobject.h (indeed I couldn't find it anywhere). So we shouldn't add this.
#[inline] | |
pub unsafe fn PyDictProxy_Check(op: *mut PyObject) -> c_int { | |
PyObject_TypeCheck(op, std::ptr::addr_of_mut!(PyDictProxy_Type)) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed!
src/types/dict.rs
Outdated
@@ -780,7 +780,7 @@ where | |||
} | |||
|
|||
/// Represents a tuple which can be used as a PyDict item. | |||
trait PyDictItem<'py> { | |||
pub trait PyDictItem<'py> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a possibly unintentional change
pub trait PyDictItem<'py> { | |
trait PyDictItem<'py> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed! For some reason I thought I needed this for one of the tests.
src/types/mappingproxy.rs
Outdated
#checkfunction=ffi::PyDictProxy_Check | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think rather than the ffi function (as discussed, it doesn't seem to exist in CPython), we should just have fn PyDictProxy_Check
defined in this file.
#checkfunction=ffi::PyDictProxy_Check | |
); | |
#checkfunction=PyDictProxy_Check | |
); | |
#[inline] | |
unsafe fn PyDictProxy_Check(op: *mut PyObject) -> c_int { | |
ffi::PyObject_TypeCheck(op, std::ptr::addr_of_mut!(PyDictProxy_Type)) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it looks like subclassing mappingproxy
is not allowed so we can probably just do Py_IS_TYPE
here.
>>> class F(types.MappingProxyType):
... pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'mappingproxy' is not an acceptable base type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, I changed the check function to the following:
#[inline]
unsafe fn dict_proxy_check(op: *mut ffi::PyObject) -> c_int {
ffi::Py_IS_TYPE(op, std::ptr::addr_of_mut!(ffi::PyDictProxy_Type))
}
src/types/mappingproxy.rs
Outdated
fn copy(&self) -> PyResult<Bound<'_, PyMappingProxy>> { | ||
let res = self.call_method0("copy")?; | ||
unsafe { Ok(res.downcast_into_unchecked::<PyMappingProxy>()) } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the type here is incorrect, it looks like .copy()
returns a copy of the underlying mapping, perhaps?
>>> type(types.MappingProxyType({}).copy())
<class 'dict'>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to return PyMapping
instead.
src/types/mappingproxy.rs
Outdated
#[inline] | ||
fn keys(&self) -> PyResult<Bound<'py, PySequence>> { | ||
unsafe { | ||
Ok(ffi::PyMapping_Keys(self.as_ptr()) | ||
.assume_owned_or_err(self.py())? | ||
.downcast_into_unchecked()) | ||
} | ||
} | ||
|
||
#[inline] | ||
fn values(&self) -> PyResult<Bound<'py, PySequence>> { | ||
unsafe { | ||
Ok(ffi::PyMapping_Values(self.as_ptr()) | ||
.assume_owned_or_err(self.py())? | ||
.downcast_into_unchecked()) | ||
} | ||
} | ||
|
||
#[inline] | ||
fn items(&self) -> PyResult<Bound<'py, PySequence>> { | ||
unsafe { | ||
Ok(ffi::PyMapping_Items(self.as_ptr()) | ||
.assume_owned_or_err(self.py())? | ||
.downcast_into_unchecked()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like since 3.7 (our minimum supported version) these FFI functions are now guaranteed to return lists: https://docs.python.org/3/c-api/mapping.html#c.PyMapping_Keys
So I think we can use PyList
as the return type. It would allow for performance gains versus going through the sequence abstraction.
Similarly, would you be willing to update PyMappingMethods
in the same way (maybe as a separate PR)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Made the changes and opened #4661
src/conversions/std/map.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to considering the conversion changes in this file, but these changes might break existing users' code silently. I'm unsure both if it's worth the churn and also what the performance cost might be.
If we move ahead with these we should also include the corresponding changes to the index map and hash brown conversions.
At a minimum I would at like to see these changes split off into a separate PR, although I will be honest that there is a chance we might decide not to have these. Was it critical for your use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Went ahead and removed the conversion changes. It isn't necessary for me, I just had it in there because of the previous PR.
* Addressing more comments * Remove extract_bound. * Remove extract methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great to me, thanks very much for helping get this one finally over the line!
Continuation of #2435 and #3521. Implement the
PyMappingProxy
type (calledPyDictProxy
in CPython).Resolves #2108.