Merge pull request #343 from PyO3/into_py_tuple_no_more
Replace IntoPyTuple with IntoPy<Py<PyTuple>>
This commit is contained in:
commit
37088024f1
|
@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
* Renamed `py_exception` to `create_exception` and refactored the error macros.
|
||||
* Renamed `wrap_function!` to `wrap_pyfunction!`
|
||||
* Migrated to the 2018 edition
|
||||
* Replace `IntoPyTuple` with `IntoPy<Py<PyTuple>>`. Eventually `IntoPy<T>` should replace `ToPyObject` and be itself implemented through `FromPy<T>`
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
@ -10,22 +10,6 @@ The easiest way to convert a python object to a rust value is using `.extract()?
|
|||
|
||||
[`ToPyObject`] trait is a conversion trait that allows various objects to be converted into [`PyObject`][PyObject]. [`IntoPyObject`][IntoPyObject] serves the same purpose except it consumes `self`.
|
||||
|
||||
## `IntoPyTuple` trait
|
||||
|
||||
[`IntoPyTuple`][IntoPyTuple] trait is a conversion trait that allows various objects to be converted into [`PyTuple`][PyTuple] object.
|
||||
|
||||
For example, [`IntoPyTuple`][IntoPyTuple] trait is implemented for `()` so that you can convert it into a empty [`PyTuple`][PyTuple]
|
||||
|
||||
```rust
|
||||
use pyo3::{Python, IntoPyTuple};
|
||||
|
||||
fn main() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let py_tuple = ().into_tuple(py);
|
||||
}
|
||||
```
|
||||
|
||||
## `FromPyObject` and `RefFromPyObject` trait
|
||||
|
||||
## `*args` and `**kwargs` for python object call
|
||||
|
@ -37,9 +21,7 @@ provides two methods:
|
|||
* `call` - call callable python object.
|
||||
* `call_method` - call specific method on the object.
|
||||
|
||||
Both methods accept `args` and `kwargs` arguments. `args` argument is generate over
|
||||
[`IntoPyTuple`][IntoPyTuple] trait. So args could be `PyTuple` instance or
|
||||
rust tuple with up to 10 elements. Or `NoArgs` object which represents empty tuple object.
|
||||
Both methods accept `args` and `kwargs` arguments. The `NoArgs` object represents an empty tuple object.
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
|
@ -118,12 +100,15 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
TODO
|
||||
## `IntoPy<T>`
|
||||
|
||||
Many conversions in pyo3 can't use `std::convert::Into` because they need a gil token. That's why the `IntoPy<T>` trait offers an `into_py` methods that works just like `into` except for taking a `Python<'_>` as argument.
|
||||
|
||||
Eventually, traits such as `IntoPyObject` will be replaces by this trait and a `FromPy` trait will be added that will implement `IntoPy`, just like with `From` and `Into`.
|
||||
|
||||
[`ToPyObject`]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ToPyObject.html
|
||||
[IntoPyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyObject.html
|
||||
[PyObject]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyObject.html
|
||||
[IntoPyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyTuple.html
|
||||
[PyTuple]: https://docs.rs/pyo3/0.6.0-alpha.2/struct.PyTuple.html
|
||||
[ObjectProtocol]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.ObjectProtocol.html
|
||||
[IntoPyDict]: https://docs.rs/pyo3/0.6.0-alpha.2/trait.IntoPyDict.html
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
|
||||
use crate::err::{PyDowncastError, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::instance::Py;
|
||||
use crate::object::PyObject;
|
||||
use crate::python::{IntoPyPointer, Python, ToPyPointer};
|
||||
use crate::typeob::PyTypeInfo;
|
||||
use crate::types::{PyObjectRef, PyTuple};
|
||||
use crate::types::PyObjectRef;
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`
|
||||
pub trait ToPyObject {
|
||||
|
@ -53,6 +52,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Similar to [std::convert::Into], just that it requires a gil token and there's
|
||||
/// currently no corresponding [std::convert::From] part.
|
||||
pub trait IntoPy<T>: Sized {
|
||||
fn into_py(self, py: Python) -> T;
|
||||
}
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyObject`
|
||||
/// by consuming original object.
|
||||
pub trait IntoPyObject {
|
||||
|
@ -60,12 +65,6 @@ pub trait IntoPyObject {
|
|||
fn into_object(self, py: Python) -> PyObject;
|
||||
}
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyTuple` object.
|
||||
pub trait IntoPyTuple {
|
||||
/// Converts self into a PyTuple object.
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple>;
|
||||
}
|
||||
|
||||
/// `FromPyObject` is implemented by various types that can be extracted from
|
||||
/// a Python object reference.
|
||||
///
|
||||
|
|
|
@ -129,7 +129,7 @@
|
|||
|
||||
pub use crate::class::*;
|
||||
pub use crate::conversion::{
|
||||
FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult,
|
||||
FromPyObject, IntoPy, IntoPyObject, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult,
|
||||
ToBorrowedObject, ToPyObject,
|
||||
};
|
||||
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use crate::conversion::{IntoPyObject, IntoPyTuple, ToPyObject};
|
||||
use crate::conversion::{IntoPy, IntoPyObject, ToPyObject};
|
||||
use crate::instance::Py;
|
||||
use crate::object::PyObject;
|
||||
use crate::python::Python;
|
||||
|
@ -22,15 +22,15 @@ use crate::types::PyTuple;
|
|||
pub struct NoArgs;
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl IntoPyTuple for NoArgs {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
impl IntoPy<Py<PyTuple>> for NoArgs {
|
||||
fn into_py(self, py: Python) -> Py<PyTuple> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `()` to an empty Python tuple.
|
||||
impl IntoPyTuple for () {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
impl IntoPy<Py<PyTuple>> for () {
|
||||
fn into_py(self, py: Python) -> Py<PyTuple> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::ptr::NonNull;
|
||||
|
||||
use crate::conversion::{
|
||||
FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, ToBorrowedObject, ToPyObject,
|
||||
FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToBorrowedObject, ToPyObject,
|
||||
};
|
||||
use crate::err::{PyDowncastError, PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
|
@ -11,6 +11,7 @@ use crate::instance::{AsPyRef, PyObjectWithGIL, PyRef, PyRefMut};
|
|||
use crate::python::{IntoPyPointer, Python, ToPyPointer};
|
||||
use crate::pythonrun;
|
||||
use crate::types::{PyDict, PyObjectRef, PyTuple};
|
||||
use crate::Py;
|
||||
|
||||
/// A python object
|
||||
///
|
||||
|
@ -181,11 +182,13 @@ impl PyObject {
|
|||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
pub fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
{
|
||||
let args = args.into_tuple(py).into_ptr();
|
||||
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))
|
||||
|
@ -205,10 +208,7 @@ impl PyObject {
|
|||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args)'
|
||||
pub fn call1<A>(&self, py: Python, args: A) -> PyResult<PyObject>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
{
|
||||
pub fn call1(&self, py: Python, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> {
|
||||
self.call(py, args, None)
|
||||
}
|
||||
|
||||
|
@ -218,11 +218,11 @@ impl PyObject {
|
|||
&self,
|
||||
py: Python,
|
||||
name: &str,
|
||||
args: impl IntoPyTuple,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<PyObject> {
|
||||
name.with_borrowed_ptr(py, |name| unsafe {
|
||||
let args = args.into_tuple(py).into_ptr();
|
||||
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() {
|
||||
|
@ -248,7 +248,7 @@ impl PyObject {
|
|||
&self,
|
||||
py: Python,
|
||||
name: &str,
|
||||
args: impl IntoPyTuple,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
) -> PyResult<PyObject> {
|
||||
self.call_method(py, name, args, None)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use crate::conversion::{FromPyObject, IntoPyTuple, PyTryFrom, ToBorrowedObject, ToPyObject};
|
||||
use crate::conversion::{FromPyObject, IntoPy, PyTryFrom, ToBorrowedObject, ToPyObject};
|
||||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
||||
use crate::exceptions::TypeError;
|
||||
use crate::ffi;
|
||||
|
@ -9,6 +9,7 @@ use crate::object::PyObject;
|
|||
use crate::python::{IntoPyPointer, Python, ToPyPointer};
|
||||
use crate::typeob::PyTypeInfo;
|
||||
use crate::types::{PyDict, PyIterator, PyObjectRef, PyString, PyTuple, PyType};
|
||||
use crate::Py;
|
||||
use std::cmp::Ordering;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
|
@ -84,9 +85,11 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self(*args, **kwargs)`
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple;
|
||||
fn call(
|
||||
&self,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyObjectRef>;
|
||||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self()`
|
||||
|
@ -94,9 +97,7 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: `self(*args)`
|
||||
fn call1<A>(&self, args: A) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple;
|
||||
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef>;
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: `self.name(*args, **kwargs)`
|
||||
|
@ -116,7 +117,7 @@ pub trait ObjectProtocol {
|
|||
fn call_method(
|
||||
&self,
|
||||
name: &str,
|
||||
args: impl IntoPyTuple,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyObjectRef>;
|
||||
|
||||
|
@ -126,7 +127,7 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Calls a method on the object with positional arguments only .
|
||||
/// This is equivalent to the Python expression: `self.name(*args)`
|
||||
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef>;
|
||||
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef>;
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: `hash(self)`
|
||||
|
@ -321,11 +322,12 @@ where
|
|||
unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 }
|
||||
}
|
||||
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
{
|
||||
let args = args.into_tuple(self.py()).into_ptr();
|
||||
fn call(
|
||||
&self,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyObjectRef> {
|
||||
let args = args.into_py(self.py()).into_ptr();
|
||||
let kwargs = kwargs.into_ptr();
|
||||
let result = unsafe {
|
||||
let return_value = ffi::PyObject_Call(self.as_ptr(), args, kwargs);
|
||||
|
@ -342,17 +344,14 @@ where
|
|||
self.call(PyTuple::empty(self.py()), None)
|
||||
}
|
||||
|
||||
fn call1<A>(&self, args: A) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
{
|
||||
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> {
|
||||
self.call(args, None)
|
||||
}
|
||||
|
||||
fn call_method(
|
||||
&self,
|
||||
name: &str,
|
||||
args: impl IntoPyTuple,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyObjectRef> {
|
||||
name.with_borrowed_ptr(self.py(), |name| unsafe {
|
||||
|
@ -361,7 +360,7 @@ where
|
|||
if ptr.is_null() {
|
||||
return Err(PyErr::fetch(py));
|
||||
}
|
||||
let args = args.into_tuple(py).into_ptr();
|
||||
let args = args.into_py(py).into_ptr();
|
||||
let kwargs = kwargs.into_ptr();
|
||||
let result_ptr = ffi::PyObject_Call(ptr, args, kwargs);
|
||||
let result = py.from_owned_ptr_or_err(result_ptr);
|
||||
|
@ -376,7 +375,7 @@ where
|
|||
self.call_method(name, PyTuple::empty(self.py()), None)
|
||||
}
|
||||
|
||||
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef> {
|
||||
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyObjectRef> {
|
||||
self.call_method(name, args, None)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use crate::conversion::{IntoPyTuple, ToPyObject};
|
||||
use crate::conversion::{IntoPy, ToPyObject};
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::instance::PyObjectWithGIL;
|
||||
|
@ -10,7 +10,9 @@ use crate::object::PyObject;
|
|||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::python::{Python, ToPyPointer};
|
||||
use crate::typeob::PyTypeCreate;
|
||||
use crate::types::PyTuple;
|
||||
use crate::types::{exceptions, PyDict, PyObjectRef};
|
||||
use crate::Py;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
use std::str;
|
||||
|
@ -104,10 +106,12 @@ impl PyModule {
|
|||
|
||||
/// Calls a function in the module.
|
||||
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
|
||||
pub fn call<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
{
|
||||
pub fn call(
|
||||
&self,
|
||||
name: &str,
|
||||
args: impl IntoPy<Py<PyTuple>>,
|
||||
kwargs: Option<&PyDict>,
|
||||
) -> PyResult<&PyObjectRef> {
|
||||
self.getattr(name)?.call(args, kwargs)
|
||||
}
|
||||
|
||||
|
@ -121,7 +125,7 @@ impl PyModule {
|
|||
/// This is equivalent to the Python expression: `getattr(module, name)(*args)`
|
||||
pub fn call1<A>(&self, name: &str, args: A) -> PyResult<&PyObjectRef>
|
||||
where
|
||||
A: IntoPyTuple,
|
||||
A: IntoPy<Py<PyTuple>>,
|
||||
{
|
||||
self.getattr(name)?.call1(args)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use super::exceptions;
|
||||
use crate::conversion::{FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, ToPyObject};
|
||||
use crate::conversion::{FromPyObject, IntoPy, IntoPyObject, PyTryFrom, ToPyObject};
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi::{self, Py_ssize_t};
|
||||
use crate::instance::{AsPyRef, Py, PyObjectWithGIL};
|
||||
|
@ -131,20 +131,20 @@ impl<'a> IntoIterator for &'a PyTuple {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPyTuple for &'a PyTuple {
|
||||
fn into_tuple(self, _py: Python) -> Py<PyTuple> {
|
||||
impl<'a> IntoPy<Py<PyTuple>> for &'a PyTuple {
|
||||
fn into_py(self, _py: Python) -> Py<PyTuple> {
|
||||
unsafe { Py::from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyTuple for Py<PyTuple> {
|
||||
fn into_tuple(self, _py: Python) -> Py<PyTuple> {
|
||||
impl IntoPy<Py<PyTuple>> for Py<PyTuple> {
|
||||
fn into_py(self, _py: Python) -> Py<PyTuple> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPyTuple for &'a str {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
impl<'a> IntoPy<Py<PyTuple>> for &'a str {
|
||||
fn into_py(self, py: Python) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyTuple_New(1);
|
||||
ffi::PyTuple_SetItem(ptr, 0, self.into_object(py).into_ptr());
|
||||
|
@ -182,8 +182,8 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
}
|
||||
}
|
||||
|
||||
impl <$($T: IntoPyObject),+> IntoPyTuple for ($($T,)+) {
|
||||
fn into_tuple(self, py: Python) -> Py<PyTuple> {
|
||||
impl <$($T: IntoPyObject),+> IntoPy<Py<PyTuple>> for ($($T,)+) {
|
||||
fn into_py(self, py: Python) -> Py<PyTuple> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyTuple_New($length);
|
||||
$(ffi::PyTuple_SetItem(ptr, $n, self.$n.into_object(py).into_ptr());)+;
|
||||
|
|
Loading…
Reference in a new issue