Small improvements around function calling

This commit is contained in:
konstin 2018-10-31 11:38:45 +01:00
parent 625a3f6738
commit dbaa2de061
9 changed files with 66 additions and 78 deletions

View File

@ -43,10 +43,7 @@ extern "C" {
value: *const c_char,
) -> c_int;
#[cfg(all(
target_pointer_width = "64",
not(py_sys_config = "Py_TRACE_REFS")
))]
#[cfg(all(target_pointer_width = "64", not(py_sys_config = "Py_TRACE_REFS")))]
fn Py_InitModule4_64(
name: *const c_char,
methods: *mut PyMethodDef,
@ -64,10 +61,7 @@ extern "C" {
apiver: c_int,
) -> *mut PyObject;
#[cfg(all(
not(target_pointer_width = "64"),
not(py_sys_config = "Py_TRACE_REFS")
))]
#[cfg(all(not(target_pointer_width = "64"), not(py_sys_config = "Py_TRACE_REFS")))]
pub fn Py_InitModule4(
name: *const c_char,
methods: *mut PyMethodDef,
@ -76,10 +70,7 @@ extern "C" {
apiver: c_int,
) -> *mut PyObject;
#[cfg(all(
not(target_pointer_width = "64"),
py_sys_config = "Py_TRACE_REFS"
))]
#[cfg(all(not(target_pointer_width = "64"), py_sys_config = "Py_TRACE_REFS"))]
fn Py_InitModule4TraceRefs(
name: *const c_char,
methods: *mut PyMethodDef,
@ -91,10 +82,7 @@ extern "C" {
pub const PYTHON_API_VERSION: c_int = 1013;
#[cfg(all(
target_pointer_width = "64",
not(py_sys_config = "Py_TRACE_REFS")
))]
#[cfg(all(target_pointer_width = "64", not(py_sys_config = "Py_TRACE_REFS")))]
#[inline]
pub unsafe fn Py_InitModule4(
name: *const c_char,
@ -118,10 +106,7 @@ pub unsafe fn Py_InitModule4(
Py_InitModule4TraceRefs_64(name, methods, doc, _self, apiver)
}
#[cfg(all(
not(target_pointer_width = "64"),
py_sys_config = "Py_TRACE_REFS"
))]
#[cfg(all(not(target_pointer_width = "64"), py_sys_config = "Py_TRACE_REFS"))]
#[inline]
pub unsafe fn Py_InitModule4(
name: *const c_char,

View File

@ -216,10 +216,11 @@ pub unsafe fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int {
#[inline]
pub unsafe fn PyIter_Check(obj: *mut PyObject) -> c_int {
let t = (*obj).ob_type;
(PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER) != 0 && match (*t).tp_iternext {
None => false,
Some(f) => f as *const c_void != _PyObject_NextNotImplemented as *const c_void,
}) as c_int
(PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER) != 0
&& match (*t).tp_iternext {
None => false,
Some(f) => f as *const c_void != _PyObject_NextNotImplemented as *const c_void,
}) as c_int
}
#[inline]

View File

@ -39,10 +39,11 @@ pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
/// Test if an object has a GC head
#[inline]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
(PyType_IS_GC(Py_TYPE(o)) != 0 && match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
(PyType_IS_GC(Py_TYPE(o)) != 0
&& match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
}
/* Test if a type supports weak references */

View File

@ -58,10 +58,11 @@ pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
#[inline]
#[cfg(not(Py_LIMITED_API))]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
(PyType_IS_GC(Py_TYPE(o)) != 0 && match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
(PyType_IS_GC(Py_TYPE(o)) != 0
&& match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
}
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -12,9 +12,9 @@ use object::PyObject;
use objectprotocol::ObjectProtocol;
use python::{IntoPyPointer, Python, ToPyPointer};
use pythonrun;
use typeob::PyTypeCreate;
use typeob::{PyTypeInfo, PyTypeObject};
use types::PyObjectRef;
use typeob::PyTypeCreate;
pub struct PyToken(PhantomData<Rc<()>>);

View File

@ -199,16 +199,13 @@ impl PyObject {
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
pub fn call_method<A>(
pub fn call_method(
&self,
py: Python,
name: &str,
args: A,
kwargs: Option<PyDict>,
) -> PyResult<PyObject>
where
A: IntoPyTuple,
{
args: impl IntoPyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<PyObject> {
name.with_borrowed_ptr(py, |name| unsafe {
let args = args.into_tuple(py).into_ptr();
let kwargs = kwargs.into_ptr();
@ -232,10 +229,12 @@ impl PyObject {
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name(*args)'
pub fn call_method1<A>(&self, py: Python, name: &str, args: A) -> PyResult<PyObject>
where
A: IntoPyTuple,
{
pub fn call_method1(
&self,
py: Python,
name: &str,
args: impl IntoPyTuple,
) -> PyResult<PyObject> {
self.call_method(py, name, args, None)
}
}
@ -328,10 +327,9 @@ mod test {
let py = gil.python();
let obj: PyObject = PyDict::new(py).into();
assert!(obj.call_method0(py, "asdf").is_err());
assert!(
obj.call_method(py, "nonexistent_method", (1,), None)
.is_err()
);
assert!(obj
.call_method(py, "nonexistent_method", (1,), None)
.is_err());
assert!(obj.call_method0(py, "nonexistent_method").is_err());
assert!(obj.call_method1(py, "nonexistent_method", (1,)).is_err());
}

View File

@ -102,20 +102,23 @@ pub trait ObjectProtocol {
/// This is equivalent to the Python expression: `self.name(*args, **kwargs)`
///
/// # Example
/// ```rust,ignore
/// let obj = SomePyObject::new();
/// let args = (arg1, arg2, arg3);
/// let kwargs = ((key1, value1), (key2, value2));
/// let pid = obj.call_method("do_something", args, kwargs.into_py_dict());
/// ```rust
/// # use pyo3::prelude::*;
/// use pyo3::types::IntoPyDict;
///
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// let list = vec![3, 6, 5, 4, 7].to_object(py);
/// let dict = vec![("reverse", true)].into_py_dict(py);
/// list.call_method(py, "sort", (), Some(dict)).unwrap();
/// assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3]);
/// ```
fn call_method<A>(
fn call_method(
&self,
name: &str,
args: A,
args: impl IntoPyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<&PyObjectRef>
where
A: IntoPyTuple;
) -> PyResult<&PyObjectRef>;
/// Calls a method on the object.
/// This is equivalent to the Python expression: `self.name()`
@ -123,7 +126,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<A: IntoPyTuple>(&self, name: &str, args: A) -> PyResult<&PyObjectRef>;
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef>;
/// Retrieves the hash code of the object.
/// This is equivalent to the Python expression: `hash(self)`
@ -346,10 +349,12 @@ where
self.call(args, None)
}
fn call_method<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
where
A: IntoPyTuple,
{
fn call_method(
&self,
name: &str,
args: impl IntoPyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<&PyObjectRef> {
name.with_borrowed_ptr(self.py(), |name| unsafe {
let py = self.py();
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
@ -371,7 +376,7 @@ where
self.call_method(name, PyTuple::empty(self.py()), None)
}
fn call_method1<A: IntoPyTuple>(&self, name: &str, args: A) -> PyResult<&PyObjectRef> {
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef> {
self.call_method(name, args, None)
}
@ -531,10 +536,10 @@ mod test {
fn test_call_with_kwargs() {
let gil = Python::acquire_gil();
let py = gil.python();
let list = py.eval("list([3, 6, 5, 4, 7])", None, None).unwrap();
let list = vec![3, 6, 5, 4, 7].to_object(py);
let dict = vec![("reverse", true)].into_py_dict(py);
list.call_method("sort", (), Some(dict)).unwrap();
assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![7, 6, 5, 4, 3]);
list.call_method(py, "sort", (), Some(dict)).unwrap();
assert_eq!(list.extract::<Vec<i32>>(py).unwrap(), vec![7, 6, 5, 4, 3]);
}
#[test]

View File

@ -532,10 +532,9 @@ mod test {
fn test_is_instance() {
let gil = Python::acquire_gil();
let py = gil.python();
assert!(
py.is_instance::<PyBool, PyObjectRef>(PyBool::new(py, true).into())
.unwrap()
);
assert!(py
.is_instance::<PyBool, PyObjectRef>(PyBool::new(py, true).into())
.unwrap());
let list = PyList::new(py, &[1, 2, 3, 4]);
assert!(!py.is_instance::<PyBool, _>(list.as_ref()).unwrap());
assert!(py.is_instance::<PyList, _>(list.as_ref()).unwrap());

View File

@ -21,13 +21,11 @@ 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, None)
.unwrap()
.cast_as::<EmptyClassWithNew>()
.is_ok());
}
#[pyclass]