Introduce IntoPyDictPointer similar to IntoPyTuple #69

This commit is contained in:
Nikolay Kim 2017-08-03 15:01:52 -07:00
parent 032f2e0b3c
commit cd6558a19b
16 changed files with 243 additions and 135 deletions

View File

@ -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)
^^^^^^^^^^^^^^^^^^

View File

@ -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);

View File

@ -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]

View File

@ -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
}
}

View File

@ -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;

71
src/noargs.rs Normal file
View File

@ -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()
}
}

View File

@ -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
})
}

View File

@ -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
})
}

View File

@ -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);
}
}

View File

@ -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]

View File

@ -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;

View File

@ -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)
}

View File

@ -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 {

View File

@ -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;

View File

@ -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)};
}
}
}

View File

@ -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);