-
Notifications
You must be signed in to change notification settings - Fork 784
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
Remove PyObject, rename PyAny -> PyObject #863
Conversation
In general, I'm delighted with this.
Although While we are bold, let me throw renaming Unfortunately I don't have a good name in mind, let's call it |
Thank you for the hard work!
It sounds better to rename |
I'm open to renaming Given that
Another named for |
Also, I'm kinda hoping in the long run that we don't use |
Added |
I'm kinda for keeping
Sounds good to make that more explicit. |
how about |
b9f741a
to
6fed82f
Compare
I find this option quite interesting too. In code where I'm interacting with Python a lot I feel that typing I think there's a lot of ideas here around naming of |
6fed82f
to
86185a2
Compare
I did some cleanups and rebased. CI might even be green this time! I moved the question of names to #873. |
391f156
to
060f094
Compare
I have been thinking further about this and I think it is the correct decision. Especially in the future when we have |
b796776
to
a566b8d
Compare
// /// Extracts some type from the Python object. | ||
// /// | ||
// /// This is a wrapper function around `FromPyObject::extract()`. | ||
// pub fn extract<'p, D>(&'p self, py: Python<'p>) -> PyResult<D> | ||
// where | ||
// D: FromPyObject<'p>, | ||
// { | ||
// FromPyObject::extract(self.as_ref(py)) | ||
// } | ||
|
||
// /// Retrieves an attribute value. | ||
// /// | ||
// /// This is equivalent to the Python expression `self.attr_name`. | ||
// pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject> | ||
// where | ||
// N: ToPyObject, | ||
// { | ||
// attr_name.with_borrowed_ptr(py, |attr_name| unsafe { | ||
// PyObject::from_owned_ptr_or_err(py, ffi::PyObject_GetAttr(self.as_ptr(), attr_name)) | ||
// }) | ||
// } | ||
|
||
// /// Calls the object. | ||
// /// | ||
// /// This is equivalent to the Python expression `self(*args, **kwargs)`. | ||
// pub fn call( | ||
// &self, | ||
// py: Python, | ||
// args: impl IntoPy<Py<PyTuple>>, | ||
// kwargs: Option<&PyDict>, | ||
// ) -> PyResult<PyObject> { | ||
// let args = args.into_py(py).into_ptr(); | ||
// let kwargs = kwargs.into_ptr(); | ||
// let result = unsafe { | ||
// PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(self.as_ptr(), args, kwargs)) | ||
// }; | ||
// unsafe { | ||
// ffi::Py_XDECREF(args); | ||
// ffi::Py_XDECREF(kwargs); | ||
// } | ||
// result | ||
// } | ||
|
||
// /// Calls the object with only positional arguments. | ||
// /// | ||
// /// This is equivalent to the Python expression `self(*args)`. | ||
// pub fn call1(&self, py: Python, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> { | ||
// self.call(py, args, None) | ||
// } | ||
|
||
// /// Calls the object without arguments. | ||
// /// | ||
// /// This is equivalent to the Python expression `self()`. | ||
// pub fn call0(&self, py: Python) -> PyResult<PyObject> { | ||
// self.call(py, (), None) | ||
// } | ||
|
||
// /// Calls a method on the object. | ||
// /// | ||
// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. | ||
// pub fn call_method( | ||
// &self, | ||
// py: Python, | ||
// name: &str, | ||
// args: impl IntoPy<Py<PyTuple>>, | ||
// kwargs: Option<&PyDict>, | ||
// ) -> PyResult<PyObject> { | ||
// name.with_borrowed_ptr(py, |name| unsafe { | ||
// let args = args.into_py(py).into_ptr(); | ||
// let kwargs = kwargs.into_ptr(); | ||
// let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name); | ||
// if ptr.is_null() { | ||
// return Err(PyErr::fetch(py)); | ||
// } | ||
// let result = PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(ptr, args, kwargs)); | ||
// ffi::Py_DECREF(ptr); | ||
// ffi::Py_XDECREF(args); | ||
// ffi::Py_XDECREF(kwargs); | ||
// result | ||
// }) | ||
// } | ||
|
||
// /// Calls a method on the object with only positional arguments. | ||
// /// | ||
// /// This is equivalent to the Python expression `self.name(*args)`. | ||
// pub fn call_method1( | ||
// &self, | ||
// py: Python, | ||
// name: &str, | ||
// args: impl IntoPy<Py<PyTuple>>, | ||
// ) -> PyResult<PyObject> { | ||
// self.call_method(py, name, args, None) | ||
// } | ||
|
||
// /// Calls a method on the object with no arguments. | ||
// /// | ||
// /// This is equivalent to the Python expression `self.name()`. | ||
// pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> { | ||
// self.call_method(py, name, (), 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.
These methods used to exist on PyObject
. I'm trying to decide if we should move them to Py<T>
, or delete them.
src/instance.rs
Outdated
/// }; | ||
/// let gil = Python::acquire_gil(); | ||
/// let py = gil.python(); | ||
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0); // PyAny implements ObjectProtocol | ||
/// assert_eq!(obj.as_ref(py).len().unwrap(), 0); // PyObject implements ObjectProtocol | ||
/// ``` | ||
pub trait AsPyRef: Sized { |
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.
Now that the old PyObject
doesn't exist, I'm wondering if AsPyRef
trait should be moved to be just a method on Py<T>
. I don't think there is value in it being a trait any more.
4e15824
to
841408b
Compare
@kngwyu this is now looking good to me; would be curious to hear what you have to say about it! 😄 |
I tried this with my (smallish) extension module, and there was no unexpected fallout. I changed existing Finally, I just had remove a bunch of 👍 However, this needs a good step-by-step guide in the release notes, since the errors I got trying to compile the original code were mostly not particularly helpful. |
Where you changed
I agree. It would be interesting to see if I could write I also wondered about adding to |
@davidhewitt no, it's not unfortunately. I have a few other projects waiting for PyO3 bindings but can only start them once it compiles on stable... |
Yeah, thank you for trying it out. @davidhewitt But my main concern is... should we do this now? This change would force users to replace many However, since
Isn't it confusing? Indeed, we cannot avoid this curse of renaming and at last, should replace |
@kngwyu that's a good question. I actually had started on this change by working on #679 in totality (both PyAny ownership change and PyAny rename). It seemed too much to do in one go so I did this bit first. I'd be happy to instead try out the Give me a few days to make a draft PR for that. Don't worry about reviewing this one in the meanwhile 👍 |
Firstly, how about rethinking the usage of |
👍 can have a look there. Though I think we might want to get to the "lightweight" For example I foresee already that But maybe that particular one cannot be avoided if we are using GIL lifetimes... |
841408b
to
bdf2bb6
Compare
I've rebased this PR on master, and converted back to draft. I think it's still interesting to continue to explore this branch, and I will continue to rebase it as we go. You're right that we can probably improve the design of |
bdf2bb6
to
c802a17
Compare
On the other hand, large incompatible changes with every version are also tiring... |
That's fair - maybe we'll save it for In all serious I'm happy to get this into |
Personally, I'm fine with either name, as long as there's only one of them remaining. (PyAny has the very slight advantage of not clashing with the ffi PyObject, but most users won't ever need the latter.) |
c802a17
to
8e90d48
Compare
This draft PR is now massively out-of-date. Also, I think that there are enough breaking changes with this PR that it probably doesn't make sense to push forward as-is with it until we've got a final design for the rest of the conversion traits. As a result, I'm going to close this. I do still think that the rough objective of this PR is still relevant - it'll shrink PyO3's range of names and types, which is a common criticism of the PyO3 API. I've got a lot of notes on what I learned from trying this, which I'll write up as an issue later so that we can pick up this and continue to design API improvements. |
Fixes #356
This is an experiment to solve the well-known confusion around
PyObject
andPyAny
by removingPyObject
and then renamingPyAny
toPyObject
, roughly as suggested in #679All the tests pass except for doc tests. I think there's a lot of documentation that would need fixing up.
I wanted to open this PR as an experiment; there will be plenty of things we can improve in it and I'm prepared to keep rebasing this and fixing it up against
master
as we go.Most notable changes that I think might want discussion:
FromPy<T> for T
to get conversionsPy<T> -> Py<PyObject>
to compile. We might want to rethink this. Maybemin_specialization
feature would allow these conflicting impls.ToPyObject::to_object()
trait now returns&PyObject
. Not sure if maybePy<PyObject>
is better.Bikeshed:I've been wondering what happens if we renamedMoved bikeshed to #873PyObject
to justObject
- I don't think thePy
is particularly interesting and typingPy<Object>
is heck of a lot less annoying thanPy<PyObject>
. This would be a good moment to do such a rename if we're breaking everything anyway.TODO:
FromPy
changeToPyObject
change