-
Notifications
You must be signed in to change notification settings - Fork 778
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
Tuple/List get_item to fallible #1733
Conversation
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 kicking this off!
Another way to design this which is potentially better for migration is to deprecate .get_item()
and to introduce two new methods:
.get() -> PyResult<&PyAny>
.get_unchecked() -> &PyAny
, doesn't do checking and only available on#[cfg(not(Py_LIMITED_API))]
Or .get() -> Option<&PyAny>
, if handling the error internally feels appropriate. I'd be open to opinions on this.
Regarding the .extract()
error, you should check for uses of .get_item()
inside pyo3-macros-backend
. TBH this is an example why deprecating get_item
might be the better idea - the compilation will still go through and you'll just get warnings of where it's used, which can be fixed instead.
@davidhewitt |
8e5484e
to
c4216a1
Compare
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, this is taking shape!
@birkenfeld as you came up with the proposals in #1667 I'd be really interested for your opinion on this.
c598465
to
996b677
Compare
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 :)
I do have some suggestions..
src/types/list.rs
Outdated
@@ -83,6 +84,24 @@ impl PyList { | |||
} | |||
} | |||
|
|||
/// Gets the list item at the specified index. | |||
pub fn get(&self, index: usize) -> PyResult<&PyAny> { |
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.
We should consider using isize
rather than usize
for this, if we still want negative indexing per #1667 (?).
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.
We want negative indexing, but when using index (slicing). There's no real sense in implementing it at this function level.
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.
Personally I'm leaning towards using usize everywhere, anyway 👍
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 don't see why this should only be relevant for slicing. Python allows negative indices for single item access as well as for slices. IMO either we allow negative indices for both, or none.
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 happy with returning PyResult
. The new name makes the API asymmetric (get
vs set_item
, and btw why is there is no del_item
or remove
...) Are we still allowed to break APIs if the result is a clear compile error?
usize
vs isize
needs to be discussed still.
A follow-up to this is the implementation of Index
traits.
src/types/list.rs
Outdated
@@ -83,6 +84,24 @@ impl PyList { | |||
} | |||
} | |||
|
|||
/// Gets the list item at the specified index. | |||
pub fn get(&self, index: usize) -> PyResult<&PyAny> { |
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 don't see why this should only be relevant for slicing. Python allows negative indices for single item access as well as for slices. IMO either we allow negative indices for both, or none.
src/types/list.rs
Outdated
let item = self.list.get_item(self.index); | ||
if self.index < self.list.len() { | ||
#[cfg(any(Py_LIMITED_API, PyPy))] | ||
let item = self.list.get(self.index).expect("tuple.get failed"); |
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's a list here
Yes, we could change Sorry @aviramha you picked a ticket which has a lot of open design questions 🙃 I definitely think if we call it |
That's OK. the get_item of Python is actually usize, so it might be more confusing that it works with negative indices. I guess it's a question whether you want the API to feel like a Rust wrapper to the CPython or a rust wrapper to the Python API. |
That's a fair question. I think I'm now leaning towards this matching the C API, so would vote for |
Goes without saying that I am too. How do we make this call? 🙃 |
If it looks like a majority of us agree, I'm happy for us to commit to this plan (cc @birkenfeld @mejrs @messense). |
Where would |
To be clear, I'm not opposed to doing away with |
@birkenfeld I understand your concern but I believe that's CPython inconsistency issue. It depends on what we value more - being consistent with it or improving it. |
To make myself more clear (previous comment was from mobile) - when coding in PyO3 I often use the CPython docs to understand how stuff works - having different API (i.e get_item of PyO3 accepts negative indices vs CPython not) can easily cause confusion for anyone. |
The expectation of each PyO3 method mapping exactly to one Python C-API call is misguided, though. If you are missing info from the PyO3 docs which is integral to understanding the API in question, it is a bug and should be fixed; please report that here. And of course, in the case we're discussing here, the documentation would need to state that negative indices are supported and how they are interpreted. (That this is not documented currently is one of the points of #1667.) |
I definitely agree that we should go for all- Here's the arguments I can see either way: usizeGood:
Bad:
isizeGood:
Bad:
An alternative... what if we made I think this "mixed-mode" would match the C-API in every way except |
@davidhewitt thanks for the recap Indexing and slicing with negative numbers doesn't seem like a good idea to me:
|
Cool. @davidhewitt Waiting for your review : |
👍 will try to give a full read within the next few days! |
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 pushing forward on this! I'm afraid there's a few bits and pieces which still need tidying up. Comments scattered below.
@davidhewitt should I change get_slice to also use usize?
Before we release 0.15 we'll need to change all these tuple / list / sequence APIs which currently take isize
to take usize
. This PR is already big enough, so maybe it's better to make a list of what still needs to change in #1667 and then make follow-up PRs.
9880cb4
to
8cbf9f9
Compare
Thanks for the review. I think I fixed all of the comments :) |
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.
The changes are looking reasonable to me... but CI has a segfault?
Oopsie, I thought the CI failure was main's fault |
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.
Ahh I think I've found another cause of segfault... Fingers crossed CI green after 🤞
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.
👍 looks brilliant! Thanks again for your patience and many iterations as we worked out the design for this.
I'll merge this shortly (just going to cherry-pick some fixes for a 0.14.3 bugfix release first).
(See #1796 - as soon as that release is live I'll merge this. It just makes my life easier if I try to cherry-pick other stuff and there's no more breaking changes 😉) |
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.
LGTM.
You're welcome! Glad to contribute to an awesome framework. |
🚀 If you want to own this, that would be awesome! The easiest way might be to create a new issue where you can own a list of checkboxes and close them as we make progress? |
Since 0.14.x is going to be in a branch, can we merge this? |
Ok 👍 I'm getting more used to doing the cherry-picking onto the 0.14.3 branch now, so let's proceed with this. I see I created a merge conflict by merging #1802, so I'll fixup this quickly now... |
e32641a
to
33b056b
Compare
…`usize` indices instead of `isize`. - `PyList` and `PyTuple`'s `get_item` now always uses the safe API. See `get_item_unchecked` for retrieving index without checks.
33b056b
to
c6255e6
Compare
Hey, trying to help with:
#1667
specifically:
make PyTuple::get_item and PyList::get_item fallible
I'm not quite sure about the extract thingy, any guidance or feedback will be welcome.