Introduce IntoPyDictPointer similar to IntoPyTuple #69
This commit is contained in:
parent
032f2e0b3c
commit
cd6558a19b
|
@ -18,6 +18,8 @@ Changes
|
|||
|
||||
* Better `Iterator` support for PyTuple, PyList, PyDict #75
|
||||
|
||||
* Introduce IntoPyDictPointer similar to IntoPyTuple #69
|
||||
|
||||
|
||||
0.1.0 (07-23-2017)
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -623,7 +623,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let array = py.import("array").unwrap().call_method(
|
||||
"array", ("f", (1.0, 1.5, 2.0, 2.5)), None).unwrap();
|
||||
"array", ("f", (1.0, 1.5, 2.0, 2.5)), NoArgs).unwrap();
|
||||
let buffer = PyBuffer::get(py, array.into()).unwrap();
|
||||
assert_eq!(buffer.dimensions(), 1);
|
||||
assert_eq!(buffer.item_count(), 4);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use ffi;
|
||||
use err::{PyResult, PyDowncastError};
|
||||
use python::{Python, ToPyPointer};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyTuple};
|
||||
use typeob::PyTypeInfo;
|
||||
|
@ -36,9 +36,9 @@ impl<T> ToBorrowedObject for T where T: ToPyObject {
|
|||
default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
{
|
||||
let obj = self.to_object(py);
|
||||
let result = f(obj.as_ptr());
|
||||
py.release(obj);
|
||||
let ptr = self.to_object(py).into_ptr();
|
||||
let result = f(ptr);
|
||||
py.xdecref(ptr);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,6 @@ pub trait IntoPyTuple {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/// `FromPyObject` is implemented by various types that can be extracted from
|
||||
/// a Python object reference.
|
||||
///
|
||||
|
@ -144,11 +143,13 @@ impl ToPyObject for () {
|
|||
py.None()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyObject for () {
|
||||
fn into_object(self, py: Python) -> PyObject {
|
||||
py.None()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoPyObject for &'a T where T: ToPyPointer
|
||||
{
|
||||
#[inline]
|
||||
|
@ -156,6 +157,7 @@ impl<'a, T> IntoPyObject for &'a T where T: ToPyPointer
|
|||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoPyObject for &'a mut T where T: ToPyPointer
|
||||
{
|
||||
#[inline]
|
||||
|
|
|
@ -67,7 +67,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
let py = gil.python();
|
||||
|
||||
let result = f(py, self.as_ref(py));
|
||||
py.release(self);
|
||||
py.xdecref(self.into_ptr());
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ pub trait AsPyRef<T>: Sized {
|
|||
let py = gil.python();
|
||||
|
||||
let result = f(py, self.as_mut(py));
|
||||
py.release(self);
|
||||
py.xdecref(self.into_ptr());
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ pub use err::{PyErr, PyErrValue, PyResult, PyDowncastError, PyErrArguments};
|
|||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use object::PyObject;
|
||||
pub use noargs::NoArgs;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
pub use pythonrun::{GILGuard, GILPool, prepare_freethreaded_python, prepare_pyo3_library};
|
||||
pub use instance::{PyToken, PyObjectWithToken, AsPyRef, Py, PyNativeType};
|
||||
|
@ -190,6 +191,7 @@ mod instance;
|
|||
mod object;
|
||||
mod objects;
|
||||
mod objectprotocol;
|
||||
mod noargs;
|
||||
mod pythonrun;
|
||||
#[doc(hidden)]
|
||||
pub mod callback;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use ffi;
|
||||
use instance::Py;
|
||||
use python::{Python, IntoPyDictPointer};
|
||||
use conversion::{ToPyObject, IntoPyObject, IntoPyTuple};
|
||||
use object::PyObject;
|
||||
use objects::PyTuple;
|
||||
|
||||
/// An empty struct that represents the empty argument list.
|
||||
/// Corresponds to the empty tuple `()` in Python.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// let gil = pyo3::Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let os = py.import("os").unwrap();
|
||||
/// let pid = os.call("get_pid", pyo3::NoArgs, pyo3::NoArgs);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct NoArgs;
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl IntoPyTuple for NoArgs {
|
||||
|
||||
fn into_tuple(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> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl ToPyObject for NoArgs {
|
||||
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
PyTuple::empty(py).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl IntoPyObject for NoArgs {
|
||||
|
||||
fn into_object(self, py: Python) -> PyObject {
|
||||
PyTuple::empty(py).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `NoArgs` to an null pointer.
|
||||
impl IntoPyDictPointer for NoArgs {
|
||||
|
||||
fn into_dict_ptr(self, _: Python) -> *mut ffi::PyObject {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `()` to an null pointer.
|
||||
impl IntoPyDictPointer for () {
|
||||
|
||||
fn into_dict_ptr(self, _: Python) -> *mut ffi::PyObject {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
|
@ -6,9 +6,10 @@ use ffi;
|
|||
use pythonrun;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use instance::{AsPyRef, PyObjectWithToken};
|
||||
use objects::{PyObjectRef, PyDict};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyObject, IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use objects::PyObjectRef;
|
||||
use conversion::{ToPyObject, ToBorrowedObject,
|
||||
IntoPyObject, IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer, IntoPyDictPointer};
|
||||
|
||||
|
||||
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
|
||||
|
@ -86,7 +87,6 @@ impl PyObject {
|
|||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
|
@ -99,7 +99,6 @@ impl PyObject {
|
|||
/// Creates a `PyObject` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Returns `None` if the pointer is `null`.
|
||||
#[inline]
|
||||
pub fn from_borrowed_ptr_or_opt(py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
|
@ -110,7 +109,6 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Gets the reference count of the ffi::PyObject pointer.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.0) }
|
||||
}
|
||||
|
@ -124,14 +122,12 @@ impl PyObject {
|
|||
|
||||
/// Returns whether the object is considered to be None.
|
||||
/// This is equivalent to the Python expression: 'is None'
|
||||
#[inline]
|
||||
pub fn is_none(&self) -> bool {
|
||||
unsafe { ffi::Py_None() == self.as_ptr() }
|
||||
}
|
||||
|
||||
/// Returns whether the object is considered to be true.
|
||||
/// This is equivalent to the Python expression: 'not not self'
|
||||
#[inline]
|
||||
pub fn is_true(&self, py: Python) -> PyResult<bool> {
|
||||
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
|
||||
if v == -1 {
|
||||
|
@ -142,7 +138,6 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
#[inline]
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, <D as PyTryFrom>::Error>
|
||||
where D: PyTryFrom<Error=PyDowncastError>
|
||||
{
|
||||
|
@ -151,7 +146,6 @@ impl PyObject {
|
|||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
pub fn extract<'p, D>(&'p self, py: Python) -> PyResult<D> where D: FromPyObject<'p>
|
||||
{
|
||||
FromPyObject::extract(self.as_ref(py))
|
||||
|
@ -159,7 +153,6 @@ impl PyObject {
|
|||
|
||||
/// Retrieves an attribute value.
|
||||
/// This is equivalent to the Python expression 'self.attr_name'.
|
||||
#[inline]
|
||||
pub fn getattr<N>(&self, py: Python, attr_name: N) -> PyResult<PyObject>
|
||||
where N: ToPyObject
|
||||
{
|
||||
|
@ -171,34 +164,37 @@ impl PyObject {
|
|||
|
||||
/// Calls the object.
|
||||
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
||||
#[inline]
|
||||
pub fn call<A>(&self, py: Python, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
pub fn call<A, K>(&self, py: Python, args: A, kwargs: K) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer
|
||||
{
|
||||
let t = args.into_tuple(py);
|
||||
let args = args.into_tuple(py).into_ptr();
|
||||
let kwargs = kwargs.into_dict_ptr(py);
|
||||
let result = unsafe {
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
py, ffi::PyObject_Call(self.as_ptr(), args, kwargs))
|
||||
};
|
||||
py.release(t);
|
||||
py.xdecref(args);
|
||||
py.xdecref(kwargs);
|
||||
result
|
||||
}
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
#[inline]
|
||||
pub fn call_method<A>(&self, py: Python,
|
||||
name: &str, args: A,
|
||||
kwargs: Option<&PyDict>) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple
|
||||
pub fn call_method<A, K>(&self, py: Python,
|
||||
name: &str, args: A, kwargs: K) -> PyResult<PyObject>
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer
|
||||
{
|
||||
name.with_borrowed_ptr(py, |name| unsafe {
|
||||
let t = args.into_tuple(py);
|
||||
let args = args.into_tuple(py).into_ptr();
|
||||
let kwargs = kwargs.into_dict_ptr(py);
|
||||
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
|
||||
let result = PyObject::from_owned_ptr_or_err(
|
||||
py, ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()));
|
||||
py, ffi::PyObject_Call(ptr, args, kwargs));
|
||||
ffi::Py_DECREF(ptr);
|
||||
py.release(t);
|
||||
py.xdecref(args);
|
||||
py.xdecref(kwargs);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use err::{self, PyErr, PyResult, PyDowncastError};
|
||||
use python::{Python, ToPyPointer};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer, IntoPyDictPointer};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use objects::{PyObjectRef, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, ToBorrowedObject,
|
||||
IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use instance::PyObjectWithToken;
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
|
@ -76,14 +77,16 @@ 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<A, K>(&self, args: A, kwargs: K) -> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer;
|
||||
|
||||
/// Calls a method on the object.
|
||||
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
||||
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>)
|
||||
fn call_method<A, K>(&self, name: &str, args: A, kwargs: K)
|
||||
-> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple;
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer;
|
||||
|
||||
/// Retrieves the hash code of the object.
|
||||
/// This is equivalent to the Python expression: 'hash(self)'
|
||||
|
@ -240,29 +243,35 @@ impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
|||
}
|
||||
}
|
||||
|
||||
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple
|
||||
fn call<A, K>(&self, args: A, kwargs: K) -> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer
|
||||
{
|
||||
let t = args.into_tuple(self.py());
|
||||
let args = args.into_tuple(self.py()).into_ptr();
|
||||
let kw_ptr = kwargs.into_dict_ptr(self.py());
|
||||
let result = unsafe {
|
||||
self.py().from_owned_ptr_or_err(
|
||||
ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
||||
ffi::PyObject_Call(self.as_ptr(), args, kw_ptr))
|
||||
};
|
||||
self.py().release(t);
|
||||
self.py().xdecref(args);
|
||||
self.py().xdecref(kw_ptr);
|
||||
result
|
||||
}
|
||||
|
||||
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>)
|
||||
fn call_method<A, K>(&self, name: &str, args: A, kwargs: K)
|
||||
-> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer
|
||||
{
|
||||
name.with_borrowed_ptr(self.py(), |name| unsafe {
|
||||
let t = args.into_tuple(self.py());
|
||||
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
|
||||
let args = args.into_tuple(self.py()).into_ptr();
|
||||
let kw_ptr = kwargs.into_dict_ptr(self.py());
|
||||
let result = self.py().from_owned_ptr_or_err(
|
||||
ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()));
|
||||
ffi::PyObject_Call(ptr, args, kw_ptr));
|
||||
ffi::Py_DECREF(ptr);
|
||||
self.py().release(t);
|
||||
self.py().xdecref(args);
|
||||
self.py().xdecref(kw_ptr);
|
||||
result
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ use std::{mem, collections, hash, cmp};
|
|||
|
||||
use ffi;
|
||||
use object::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use python::{Python, ToPyPointer};
|
||||
use instance::{Py, PyObjectWithToken};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer, IntoPyDictPointer};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyObject};
|
||||
use objects::{PyObjectRef, PyList};
|
||||
use err::{self, PyResult, PyErr};
|
||||
|
@ -155,6 +155,20 @@ impl<'a> std::iter::IntoIterator for &'a PyDict {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPyDictPointer for &'a PyDict {
|
||||
#[must_use]
|
||||
fn into_dict_ptr(self, _py: Python) -> *mut ffi::PyObject {
|
||||
self.into_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyDictPointer for Py<PyDict> {
|
||||
#[must_use]
|
||||
fn into_dict_ptr(self, _py: Python) -> *mut ffi::PyObject {
|
||||
self.into_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl <K, V, H> ToPyObject for collections::HashMap<K, V, H>
|
||||
where K: hash::Hash+cmp::Eq+ToPyObject,
|
||||
V: ToPyObject,
|
||||
|
@ -209,14 +223,43 @@ impl <K, V> IntoPyObject for collections::BTreeMap<K, V>
|
|||
}
|
||||
}
|
||||
|
||||
impl <K, V, H> IntoPyDictPointer for collections::HashMap<K, V, H>
|
||||
where K: hash::Hash+cmp::Eq+ToPyObject,
|
||||
V: ToPyObject,
|
||||
H: hash::BuildHasher
|
||||
{
|
||||
#[must_use]
|
||||
fn into_dict_ptr(self, py: Python) -> *mut ffi::PyObject {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(key, value).expect("Failed to set_item on dict");
|
||||
};
|
||||
dict.into_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl <K, V> IntoPyDictPointer for collections::BTreeMap<K, V>
|
||||
where K: cmp::Eq+ToPyObject,
|
||||
V: ToPyObject
|
||||
{
|
||||
#[must_use]
|
||||
fn into_dict_ptr(self, py: Python) -> *mut ffi::PyObject {
|
||||
let dict = PyDict::new(py);
|
||||
for (key, value) in self {
|
||||
dict.set_item(key, value).expect("Failed to set_item on dict");
|
||||
};
|
||||
dict.into_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use python::Python;
|
||||
use python::{Python, IntoPyDictPointer};
|
||||
use instance::AsPyRef;
|
||||
use conversion::{PyTryFrom, ToPyObject, IntoPyObject};
|
||||
use objects::{PyDict, PyTuple};
|
||||
use ObjectProtocol;
|
||||
use {PyObject, ObjectProtocol};
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
|
@ -493,7 +536,23 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_btreemap_into_python() {
|
||||
fn test_hashmap_into_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let mut map = HashMap::<i32, i32>::new();
|
||||
map.insert(1, 1);
|
||||
|
||||
let m = map.into_dict_ptr(py);
|
||||
let ob = unsafe{PyObject::from_owned_ptr(py, m)};
|
||||
let py_map = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_btreemap_into_object() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
|
@ -506,4 +565,20 @@ mod test {
|
|||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_btreemap_into_dict() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let mut map = BTreeMap::<i32, i32>::new();
|
||||
map.insert(1, 1);
|
||||
|
||||
let m = map.into_dict_ptr(py);
|
||||
let ob = unsafe{PyObject::from_owned_ptr(py, m)};
|
||||
let py_map = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,20 +304,18 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_append_refcnt() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let cnt;
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let _pool = ::GILPool::new();
|
||||
let list = PyList::empty(py);
|
||||
let none = py.None();
|
||||
cnt = none.get_refcnt();
|
||||
list.append(none).unwrap();
|
||||
}
|
||||
{
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert_eq!(cnt, py.None().get_refcnt());
|
||||
}
|
||||
assert_eq!(cnt, py.None().get_refcnt());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -6,8 +6,8 @@ pub use self::typeobject::PyType;
|
|||
pub use self::module::PyModule;
|
||||
pub use self::iterator::PyIterator;
|
||||
pub use self::boolobject::PyBool;
|
||||
pub use self::bytearray::{PyByteArray};
|
||||
pub use self::tuple::{PyTuple, NoArgs};
|
||||
pub use self::bytearray::PyByteArray;
|
||||
pub use self::tuple::PyTuple;
|
||||
pub use self::dict::PyDict;
|
||||
pub use self::list::PyList;
|
||||
pub use self::floatob::PyFloat;
|
||||
|
|
|
@ -10,7 +10,7 @@ use ffi;
|
|||
use typeob::{PyTypeInfo, initialize_type};
|
||||
use conversion::{ToPyObject, IntoPyTuple};
|
||||
use object::PyObject;
|
||||
use python::{Python, ToPyPointer};
|
||||
use python::{Python, ToPyPointer, IntoPyDictPointer};
|
||||
use objects::{PyObjectRef, PyDict, PyType, exc};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use instance::PyObjectWithToken;
|
||||
|
@ -81,8 +81,9 @@ 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<A, K>(&self, name: &str, args: A, kwargs: K) -> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple,
|
||||
K: IntoPyDictPointer
|
||||
{
|
||||
self.getattr(name)?.call(args, kwargs)
|
||||
}
|
||||
|
|
|
@ -217,63 +217,6 @@ tuple_conversion!(8, (ref0, 0, A), (ref1, 1, B), (ref2, 2, C), (ref3, 3, D),
|
|||
tuple_conversion!(9, (ref0, 0, A), (ref1, 1, B), (ref2, 2, C), (ref3, 3, D),
|
||||
(ref4, 4, E), (ref5, 5, F), (ref6, 6, G), (ref7, 7, H), (ref8, 8, I));
|
||||
|
||||
// Empty tuple:
|
||||
|
||||
/// An empty struct that represents the empty argument list.
|
||||
/// Corresponds to the empty tuple `()` in Python.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// let gil = pyo3::Python::acquire_gil();
|
||||
/// let py = gil.python();
|
||||
/// let os = py.import("os").unwrap();
|
||||
/// let pid = os.call("get_pid", pyo3::NoArgs, None);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct NoArgs;
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl ToPyObject for NoArgs {
|
||||
|
||||
fn to_object(&self, py: Python) -> PyObject {
|
||||
PyTuple::empty(py).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyObject for NoArgs {
|
||||
|
||||
fn into_object(self, py: Python) -> PyObject {
|
||||
PyTuple::empty(py).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts `NoArgs` to an empty Python tuple.
|
||||
impl IntoPyTuple for NoArgs {
|
||||
|
||||
fn into_tuple(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> {
|
||||
PyTuple::empty(py)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(NoArgs)` if the input is an empty Python tuple.
|
||||
/// Otherwise, returns an error.
|
||||
pyobject_extract!(obj to NoArgs => {
|
||||
let t = PyTuple::try_from(obj)?;
|
||||
if t.len() == 0 {
|
||||
Ok(NoArgs)
|
||||
} else {
|
||||
Err(wrong_tuple_length(t, 0))
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
|
|
@ -15,6 +15,7 @@ pub use class::*;
|
|||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use object::PyObject;
|
||||
pub use noargs::NoArgs;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
pub use err::{PyErr, PyErrValue, PyResult, PyDowncastError, PyErrArguments};
|
||||
pub use pythonrun::GILGuard;
|
||||
|
|
|
@ -43,6 +43,16 @@ pub trait IntoPyPointer {
|
|||
fn into_ptr(self) -> *mut ffi::PyObject;
|
||||
}
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into `PyDict` object pointer.
|
||||
/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.
|
||||
pub trait IntoPyDictPointer {
|
||||
|
||||
/// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed
|
||||
/// depends on implementation.
|
||||
fn into_dict_ptr(self, py: Python) -> *mut ffi::PyObject;
|
||||
|
||||
}
|
||||
|
||||
/// Convert `None` into a null pointer.
|
||||
impl<'p, T> ToPyPointer for Option<&'p T> where T: ToPyPointer {
|
||||
#[inline]
|
||||
|
@ -377,14 +387,12 @@ impl<'p> Python<'p> {
|
|||
self.unchecked_mut_downcast(p)
|
||||
}
|
||||
|
||||
/// Release PyObject reference.
|
||||
/// Release `ffi::PyObject` pointer.
|
||||
/// Undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub fn release<T>(self, ob: T) where T: IntoPyPointer {
|
||||
unsafe {
|
||||
let ptr = ob.into_ptr();
|
||||
if !ptr.is_null() {
|
||||
ffi::Py_DECREF(ptr);
|
||||
}
|
||||
pub fn xdecref(self, ptr: *mut ffi::PyObject) {
|
||||
if !ptr.is_null() {
|
||||
unsafe {ffi::Py_DECREF(ptr)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ fn empty_class() {
|
|||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClass>();
|
||||
// By default, don't allow creating instances from python.
|
||||
assert!(typeobj.call(NoArgs, None).is_err());
|
||||
assert!(typeobj.call(NoArgs, NoArgs).is_err());
|
||||
|
||||
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ fn empty_class_with_new() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClassWithNew>();
|
||||
assert!(typeobj.call(NoArgs, None).unwrap().cast_as::<EmptyClassWithNew>().is_ok());
|
||||
assert!(typeobj.call(NoArgs, NoArgs).unwrap().cast_as::<EmptyClassWithNew>().is_ok());
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
@ -132,7 +132,7 @@ fn new_with_one_arg() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithOneArg>();
|
||||
let wrp = typeobj.call((42,), None).unwrap();
|
||||
let wrp = typeobj.call((42,), NoArgs).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithOneArg>().unwrap();
|
||||
assert_eq!(obj._data, 42);
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ fn new_with_two_args() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<NewWithTwoArgs>();
|
||||
let wrp = typeobj.call((10, 20), None).unwrap();
|
||||
let wrp = typeobj.call((10, 20), NoArgs).unwrap();
|
||||
let obj = wrp.cast_as::<NewWithTwoArgs>().unwrap();
|
||||
assert_eq!(obj._data1, 10);
|
||||
assert_eq!(obj._data2, 20);
|
||||
|
|
Loading…
Reference in New Issue