pyo3/src/objectprotocol.rs

549 lines
17 KiB
Rust
Raw Normal View History

// Copyright (c) 2017-present PyO3 Project and Contributors
2015-04-19 03:22:03 +00:00
2019-02-23 17:01:22 +00:00
use crate::class::basic::CompareOp;
2018-10-31 10:43:21 +00:00
use crate::err::{self, PyDowncastError, PyErr, PyResult};
2018-11-12 20:36:08 +00:00
use crate::exceptions::TypeError;
2019-03-04 04:50:43 +00:00
use crate::types::{PyAny, PyDict, PyIterator, PyString, PyTuple, PyType};
use crate::{
ffi, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, Py, PyNativeType, PyObject, PyTryFrom,
Python, ToBorrowedObject, ToPyObject,
};
use std::cmp::Ordering;
use std::os::raw::c_int;
2015-01-04 20:37:43 +00:00
2017-07-18 17:13:50 +00:00
/// Python object model helper methods
2017-06-03 01:58:16 +00:00
pub trait ObjectProtocol {
2017-05-28 15:57:34 +00:00
/// Determines whether this object has the given attribute.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `hasattr(self, attr_name)`.
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>
where
N: ToPyObject;
2017-05-28 15:57:34 +00:00
/// Retrieves an attribute value.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `self.attr_name`.
2019-03-04 04:50:43 +00:00
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyAny>
where
N: ToPyObject;
2017-05-28 15:57:34 +00:00
/// Sets an attribute value.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `self.attr_name = value`.
2017-06-22 08:04:37 +00:00
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
where
N: ToBorrowedObject,
V: ToBorrowedObject;
2017-05-28 15:57:34 +00:00
/// Deletes an attribute.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `del self.attr_name`.
fn delattr<N>(&self, attr_name: N) -> PyResult<()>
where
N: ToPyObject;
2017-05-28 15:57:34 +00:00
/// Compares two Python objects.
///
/// This is equivalent to:
2018-10-03 19:04:24 +00:00
/// ```python
2017-05-28 15:57:34 +00:00
/// if self == other:
/// return Equal
/// elif a < b:
/// return Less
/// elif a > b:
/// return Greater
/// else:
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
/// ```
fn compare<O>(&self, other: O) -> PyResult<Ordering>
where
O: ToPyObject;
2017-05-28 15:57:34 +00:00
/// Compares two Python objects.
///
2020-03-17 14:16:15 +00:00
/// Depending on the value of `compare_op`, this is equivalent to one of the
/// following Python expressions:
2017-05-28 15:57:34 +00:00
/// * CompareOp::Eq: `self == other`
/// * CompareOp::Ne: `self != other`
/// * CompareOp::Lt: `self < other`
/// * CompareOp::Le: `self <= other`
/// * CompareOp::Gt: `self > other`
/// * CompareOp::Ge: `self >= other`
2019-02-23 17:01:22 +00:00
fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<PyObject>
where
O: ToPyObject;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Computes the "repr" representation of self.
///
/// This is equivalent to the Python expression `repr(self)`.
2017-06-22 08:04:37 +00:00
fn repr(&self) -> PyResult<&PyString>;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Computes the "str" representation of self.
///
/// This is equivalent to the Python expression `str(self)`.
2017-06-22 08:04:37 +00:00
fn str(&self) -> PyResult<&PyString>;
2017-05-28 15:57:34 +00:00
/// Determines whether this object is callable.
2017-06-22 08:04:37 +00:00
fn is_callable(&self) -> bool;
2017-05-28 15:57:34 +00:00
/// Calls the object.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `self(*args, **kwargs)`.
2019-03-04 04:50:43 +00:00
fn call(&self, args: impl IntoPy<Py<PyTuple>>, kwargs: Option<&PyDict>) -> PyResult<&PyAny>;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Calls the object with only positional arguments.
///
/// This is equivalent to the Python expression `self(*args)`.
2019-03-04 04:50:43 +00:00
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>;
2020-03-17 14:16:15 +00:00
/// Calls the object without arguments.
///
/// This is equivalent to the Python expression `self()`.
fn call0(&self) -> PyResult<&PyAny>;
2017-05-28 15:57:34 +00:00
/// Calls a method on the object.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `self.name(*args, **kwargs)`.
2017-08-03 22:42:32 +00:00
///
/// # Example
/// ```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]);
2017-08-03 22:42:32 +00:00
/// ```
fn call_method(
&self,
name: &str,
args: impl IntoPy<Py<PyTuple>>,
kwargs: Option<&PyDict>,
2019-03-04 04:50:43 +00:00
) -> PyResult<&PyAny>;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Calls a method on the object with only positional arguments.
///
/// This is equivalent to the Python expression `self.name(*args)`.
2019-03-04 04:50:43 +00:00
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny>;
2020-03-17 14:16:15 +00:00
/// Calls a method on the object without arguments.
///
/// This is equivalent to the Python expression `self.name()`.
fn call_method0(&self, name: &str) -> PyResult<&PyAny>;
2017-05-28 15:57:34 +00:00
/// Retrieves the hash code of the object.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `hash(self)`.
2017-06-24 15:42:13 +00:00
fn hash(&self) -> PyResult<isize>;
2017-05-28 15:57:34 +00:00
/// Returns whether the object is considered to be true.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `bool(self)`.
2017-06-22 08:04:37 +00:00
fn is_true(&self) -> PyResult<bool>;
2017-05-28 15:57:34 +00:00
/// Returns whether the object is considered to be None.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `self is None`.
2017-06-22 08:04:37 +00:00
fn is_none(&self) -> bool;
2017-05-28 15:57:34 +00:00
/// Returns the length of the sequence or mapping.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `len(self)`.
2017-06-22 08:04:37 +00:00
fn len(&self) -> PyResult<usize>;
2017-05-28 15:57:34 +00:00
/// Returns true if the sequence or mapping has a length of 0.
2020-03-17 14:16:15 +00:00
///
/// This is equivalent to the Python expression `len(self) == 0`.
fn is_empty(&self) -> PyResult<bool>;
2020-03-17 14:16:15 +00:00
/// Gets an item from the collections.
///
/// This is equivalent to the Python expression `self[key]`.
2019-03-04 04:50:43 +00:00
fn get_item<K>(&self, key: K) -> PyResult<&PyAny>
where
K: ToBorrowedObject;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Sets a collection item value.
///
/// This is equivalent to the Python expression `self[key] = value`.
2017-06-22 08:04:37 +00:00
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
where
K: ToBorrowedObject,
V: ToBorrowedObject;
2017-05-28 15:57:34 +00:00
2020-03-17 14:16:15 +00:00
/// Deletes an item from the collection.
///
/// This is equivalent to the Python expression `del self[key]`.
fn del_item<K>(&self, key: K) -> PyResult<()>
where
K: ToBorrowedObject;
2017-05-28 15:57:34 +00:00
2017-05-30 05:59:03 +00:00
/// Takes an object and returns an iterator for it.
2020-03-17 14:16:15 +00:00
///
/// This is typically a new iterator but if the argument is an iterator,
/// this returns itself.
2017-07-18 11:28:49 +00:00
fn iter(&self) -> PyResult<PyIterator>;
2017-05-30 01:36:44 +00:00
2020-03-17 14:16:15 +00:00
/// Returns the Python type object for this object's type.
2017-06-22 08:04:37 +00:00
fn get_type(&self) -> &PyType;
2020-03-17 14:16:15 +00:00
/// Returns the Python type pointer for this object.
2018-10-03 13:10:41 +00:00
fn get_type_ptr(&self) -> *mut ffi::PyTypeObject;
2017-06-22 08:04:37 +00:00
/// Casts the PyObject to a concrete Python object type.
2020-03-17 14:16:15 +00:00
///
/// This can cast only to native Python types, not types implemented in Rust.
2018-08-11 15:35:03 +00:00
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
where
2019-02-07 05:27:13 +00:00
D: PyTryFrom<'a>,
2019-03-04 04:50:43 +00:00
&'a PyAny: std::convert::From<&'a Self>;
2017-06-22 08:04:37 +00:00
/// Extracts some type from the Python object.
2020-03-17 14:16:15 +00:00
///
2017-06-22 08:04:37 +00:00
/// This is a wrapper function around `FromPyObject::extract()`.
fn extract<'a, D>(&'a self) -> PyResult<D>
where
D: FromPyObject<'a>,
2019-03-04 04:50:43 +00:00
&'a PyAny: std::convert::From<&'a Self>;
2017-06-06 03:25:00 +00:00
2020-03-17 14:16:15 +00:00
/// Returns the reference count for the Python object.
2017-05-30 01:36:44 +00:00
fn get_refcnt(&self) -> isize;
2017-06-22 08:04:37 +00:00
2017-06-23 03:56:09 +00:00
/// Gets the Python builtin value `None`.
#[allow(non_snake_case)] // the Python keyword starts with uppercase
fn None(&self) -> PyObject;
2017-05-28 15:57:34 +00:00
}
impl<T> ObjectProtocol for T
where
2019-02-24 07:17:44 +00:00
T: PyNativeType + AsPyPointer,
{
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>
where
N: ToPyObject,
{
2017-07-14 02:04:00 +00:00
attr_name.with_borrowed_ptr(self.py(), |attr_name| unsafe {
Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name) != 0)
2015-01-05 20:14:01 +00:00
})
2015-01-04 20:37:43 +00:00
}
2019-03-04 04:50:43 +00:00
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyAny>
where
N: ToPyObject,
2017-05-25 03:31:51 +00:00
{
2017-07-14 02:04:00 +00:00
attr_name.with_borrowed_ptr(self.py(), |attr_name| unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
2015-01-05 20:14:01 +00:00
})
2015-01-04 20:37:43 +00:00
}
2017-06-22 08:04:37 +00:00
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
where
N: ToBorrowedObject,
V: ToBorrowedObject,
2015-01-05 20:14:01 +00:00
{
attr_name.with_borrowed_ptr(self.py(), move |attr_name| {
2017-07-14 02:04:00 +00:00
value.with_borrowed_ptr(self.py(), |value| unsafe {
2017-05-25 03:31:51 +00:00
err::error_on_minusone(
self.py(),
ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value),
)
})
})
2015-01-04 20:37:43 +00:00
}
fn delattr<N>(&self, attr_name: N) -> PyResult<()>
where
N: ToPyObject,
{
2017-07-14 02:04:00 +00:00
attr_name.with_borrowed_ptr(self.py(), |attr_name| unsafe {
err::error_on_minusone(self.py(), ffi::PyObject_DelAttr(self.as_ptr(), attr_name))
2015-01-05 20:14:01 +00:00
})
2015-01-04 20:37:43 +00:00
}
fn compare<O>(&self, other: O) -> PyResult<Ordering>
where
O: ToPyObject,
{
unsafe fn do_compare(
py: Python,
a: *mut ffi::PyObject,
b: *mut ffi::PyObject,
) -> PyResult<Ordering> {
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_EQ);
if result == 1 {
return Ok(Ordering::Equal);
} else if result < 0 {
return Err(PyErr::fetch(py));
}
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_LT);
if result == 1 {
return Ok(Ordering::Less);
} else if result < 0 {
return Err(PyErr::fetch(py));
}
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_GT);
if result == 1 {
return Ok(Ordering::Greater);
} else if result < 0 {
return Err(PyErr::fetch(py));
}
2018-11-12 20:36:08 +00:00
Err(TypeError::py_err(
"ObjectProtocol::compare(): All comparisons returned false",
))
}
2017-07-14 02:04:00 +00:00
other.with_borrowed_ptr(self.py(), |other| unsafe {
do_compare(self.py(), self.as_ptr(), other)
})
2017-05-28 15:57:34 +00:00
}
2019-02-23 17:01:22 +00:00
fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<PyObject>
where
O: ToPyObject,
{
2017-05-25 03:31:51 +00:00
unsafe {
2017-07-14 02:04:00 +00:00
other.with_borrowed_ptr(self.py(), |other| {
2017-06-23 03:56:09 +00:00
PyObject::from_owned_ptr_or_err(
self.py(),
ffi::PyObject_RichCompare(self.as_ptr(), other, compare_op as c_int),
)
2017-05-25 03:31:51 +00:00
})
}
2017-05-28 15:57:34 +00:00
}
2015-01-04 20:37:43 +00:00
2017-06-22 08:04:37 +00:00
fn repr(&self) -> PyResult<&PyString> {
unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_Repr(self.as_ptr()))
2017-06-22 08:04:37 +00:00
}
2015-01-04 20:37:43 +00:00
}
2017-06-22 08:04:37 +00:00
fn str(&self) -> PyResult<&PyString> {
unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_Str(self.as_ptr()))
2017-06-22 08:04:37 +00:00
}
2015-01-04 20:37:43 +00:00
}
2017-06-22 08:04:37 +00:00
fn is_callable(&self) -> bool {
unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 }
2015-01-04 20:37:43 +00:00
}
2019-03-04 04:50:43 +00:00
fn call(&self, args: impl IntoPy<Py<PyTuple>>, kwargs: Option<&PyDict>) -> PyResult<&PyAny> {
let args = args.into_py(self.py()).into_ptr();
2018-08-26 19:35:53 +00:00
let kwargs = kwargs.into_ptr();
2017-06-06 03:25:00 +00:00
let result = unsafe {
2018-08-26 19:35:53 +00:00
let return_value = ffi::PyObject_Call(self.as_ptr(), args, kwargs);
self.py().from_owned_ptr_or_err(return_value)
2017-06-06 03:25:00 +00:00
};
2018-08-26 19:35:53 +00:00
unsafe {
ffi::Py_XDECREF(args);
ffi::Py_XDECREF(kwargs);
}
2017-06-06 03:25:00 +00:00
result
2015-01-04 20:37:43 +00:00
}
2019-03-04 04:50:43 +00:00
fn call0(&self) -> PyResult<&PyAny> {
2019-02-23 17:01:22 +00:00
self.call((), None)
}
2019-03-04 04:50:43 +00:00
fn call1(&self, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
2018-08-26 19:35:53 +00:00
self.call(args, None)
}
fn call_method(
&self,
name: &str,
args: impl IntoPy<Py<PyTuple>>,
kwargs: Option<&PyDict>,
2019-03-04 04:50:43 +00:00
) -> PyResult<&PyAny> {
2017-07-14 02:04:00 +00:00
name.with_borrowed_ptr(self.py(), |name| unsafe {
let py = self.py();
2017-05-28 15:57:34 +00:00
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
if ptr.is_null() {
return Err(PyErr::fetch(py));
}
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);
2017-07-19 13:35:59 +00:00
ffi::Py_DECREF(ptr);
2018-08-26 19:35:53 +00:00
ffi::Py_XDECREF(args);
ffi::Py_XDECREF(kwargs);
2017-06-06 03:25:00 +00:00
result
2017-05-28 15:57:34 +00:00
})
}
2019-03-04 04:50:43 +00:00
fn call_method0(&self, name: &str) -> PyResult<&PyAny> {
2019-02-23 17:01:22 +00:00
self.call_method(name, (), None)
}
2019-03-04 04:50:43 +00:00
fn call_method1(&self, name: &str, args: impl IntoPy<Py<PyTuple>>) -> PyResult<&PyAny> {
2018-08-26 19:35:53 +00:00
self.call_method(name, args, None)
}
2017-06-24 15:42:13 +00:00
fn hash(&self) -> PyResult<isize> {
2015-01-04 20:37:43 +00:00
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
if v == -1 {
2017-07-14 02:04:00 +00:00
Err(PyErr::fetch(self.py()))
2015-01-04 20:37:43 +00:00
} else {
Ok(v)
}
}
2017-06-22 08:04:37 +00:00
fn is_true(&self) -> PyResult<bool> {
2015-01-04 20:37:43 +00:00
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
if v == -1 {
2017-07-14 02:04:00 +00:00
Err(PyErr::fetch(self.py()))
2015-01-04 20:37:43 +00:00
} else {
Ok(v != 0)
}
}
2017-06-22 08:04:37 +00:00
fn is_none(&self) -> bool {
unsafe { ffi::Py_None() == self.as_ptr() }
}
2017-06-22 08:04:37 +00:00
fn len(&self) -> PyResult<usize> {
2015-01-04 20:37:43 +00:00
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
if v == -1 {
2017-07-14 02:04:00 +00:00
Err(PyErr::fetch(self.py()))
2015-01-04 20:37:43 +00:00
} else {
2015-05-24 20:45:43 +00:00
Ok(v as usize)
2015-01-04 20:37:43 +00:00
}
}
fn is_empty(&self) -> PyResult<bool> {
self.len().map(|l| l == 0)
}
2019-03-04 04:50:43 +00:00
fn get_item<K>(&self, key: K) -> PyResult<&PyAny>
where
K: ToBorrowedObject,
{
2017-07-14 02:04:00 +00:00
key.with_borrowed_ptr(self.py(), |key| unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_GetItem(self.as_ptr(), key))
2015-01-05 20:14:01 +00:00
})
2015-01-04 20:37:43 +00:00
}
2017-06-22 08:04:37 +00:00
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
where
K: ToBorrowedObject,
V: ToBorrowedObject,
2017-05-25 03:31:51 +00:00
{
key.with_borrowed_ptr(self.py(), move |key| {
2017-07-14 02:04:00 +00:00
value.with_borrowed_ptr(self.py(), |value| unsafe {
err::error_on_minusone(self.py(), ffi::PyObject_SetItem(self.as_ptr(), key, value))
})
})
2015-01-04 20:37:43 +00:00
}
fn del_item<K>(&self, key: K) -> PyResult<()>
where
K: ToBorrowedObject,
{
2017-07-14 02:04:00 +00:00
key.with_borrowed_ptr(self.py(), |key| unsafe {
err::error_on_minusone(self.py(), ffi::PyObject_DelItem(self.as_ptr(), key))
2015-01-05 20:14:01 +00:00
})
2015-01-04 20:37:43 +00:00
}
2018-01-19 18:02:36 +00:00
fn iter(&self) -> PyResult<PyIterator> {
Ok(PyIterator::from_object(self.py(), self)?)
2017-05-30 05:59:03 +00:00
}
2017-05-30 01:36:44 +00:00
2017-06-22 08:04:37 +00:00
fn get_type(&self) -> &PyType {
unsafe { PyType::from_type_ptr(self.py(), (*self.as_ptr()).ob_type) }
2017-06-06 03:25:00 +00:00
}
2018-10-03 13:10:41 +00:00
#[inline]
fn get_type_ptr(&self) -> *mut ffi::PyTypeObject {
unsafe { (*self.as_ptr()).ob_type }
}
2018-08-11 15:35:03 +00:00
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
where
2019-02-07 05:27:13 +00:00
D: PyTryFrom<'a>,
2019-03-04 04:50:43 +00:00
&'a PyAny: std::convert::From<&'a Self>,
2017-06-22 08:04:37 +00:00
{
2019-02-07 05:27:13 +00:00
D::try_from(self)
2017-06-22 08:04:37 +00:00
}
fn extract<'a, D>(&'a self) -> PyResult<D>
where
D: FromPyObject<'a>,
2019-03-04 04:50:43 +00:00
&'a PyAny: std::convert::From<&'a T>,
2017-06-22 08:04:37 +00:00
{
FromPyObject::extract(self.into())
}
2018-08-04 17:55:15 +00:00
fn get_refcnt(&self) -> isize {
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
}
2017-06-23 03:56:09 +00:00
#[allow(non_snake_case)] // the Python keyword starts with uppercase
fn None(&self) -> PyObject {
2017-07-14 02:04:00 +00:00
unsafe { PyObject::from_borrowed_ptr(self.py(), ffi::Py_None()) }
2017-06-23 03:56:09 +00:00
}
2015-01-05 15:34:12 +00:00
}
#[cfg(test)]
mod test {
use super::*;
2018-10-31 10:43:21 +00:00
use crate::instance::AsPyRef;
use crate::types::{IntoPyDict, PyString};
2019-02-23 17:01:22 +00:00
use crate::Python;
use crate::{PyTryFrom, ToPyObject};
#[test]
fn test_debug_string() {
let gil = Python::acquire_gil();
let py = gil.python();
2017-05-29 20:30:38 +00:00
let v = "Hello\n".to_object(py);
2018-03-29 14:35:35 +00:00
let s = <PyString as PyTryFrom>::try_from(v.as_ref(py)).unwrap();
2017-06-22 08:04:37 +00:00
assert_eq!(format!("{:?}", s), "'Hello\\n'");
}
#[test]
fn test_display_string() {
let gil = Python::acquire_gil();
let py = gil.python();
2017-05-29 20:30:38 +00:00
let v = "Hello\n".to_object(py);
2018-03-29 14:35:35 +00:00
let s = <PyString as PyTryFrom>::try_from(v.as_ref(py)).unwrap();
2017-06-22 08:04:37 +00:00
assert_eq!(format!("{}", s), "Hello\n");
}
#[test]
fn test_call_for_non_existing_method() {
let gil = Python::acquire_gil();
let py = gil.python();
let a = py.eval("42", None, None).unwrap();
a.call_method0("__str__").unwrap(); // ok
assert!(a.call_method("nonexistent_method", (1,), None).is_err());
assert!(a.call_method0("nonexistent_method").is_err());
assert!(a.call_method1("nonexistent_method", (1,)).is_err());
}
2018-10-03 13:10:41 +00:00
#[test]
fn test_call_with_kwargs() {
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]);
}
2018-10-03 13:10:41 +00:00
#[test]
fn test_type() {
let gil = Python::acquire_gil();
let py = gil.python();
let obj = py.eval("42", None, None).unwrap();
assert_eq!(unsafe { obj.get_type().as_type_ptr() }, obj.get_type_ptr())
}
}