#[macro_use] extern crate pyo3; use pyo3::{PyResult, Python, NoArgs, ObjectProtocol, PyDict}; use std::sync::atomic; use std::sync::atomic::Ordering::Relaxed; #[test] fn no_args() { static CALL_COUNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; fn f(_py: Python) -> PyResult { Ok(CALL_COUNT.fetch_add(1, Relaxed)) } let gil = Python::acquire_gil(); let py = gil.python(); let obj = py_fn!(py, f()); assert_eq!(CALL_COUNT.load(Relaxed), 0); assert_eq!(obj.call(NoArgs, None).unwrap().extract::().unwrap(), 0); assert_eq!(obj.call(NoArgs, None).unwrap().extract::().unwrap(), 1); assert_eq!(CALL_COUNT.load(Relaxed), 2); assert!(obj.call((1,), None).is_err()); assert_eq!(CALL_COUNT.load(Relaxed), 2); assert_eq!(obj.call(NoArgs, Some(&PyDict::new(py))).unwrap().extract::().unwrap(), 2); assert_eq!(CALL_COUNT.load(Relaxed), 3); let dict = PyDict::new(py); dict.set_item("param", 42).unwrap(); assert!(obj.call(NoArgs, Some(&dict)).is_err()); assert_eq!(CALL_COUNT.load(Relaxed), 3); } #[test] fn one_arg() { fn f(_py: Python, i: usize) -> PyResult { Ok(i * 2) } let gil = Python::acquire_gil(); let py = gil.python(); let obj = py_fn!(py, f(i: usize)); assert!(obj.call(NoArgs, None).is_err()); assert_eq!(obj.call((1,), None).unwrap().extract::().unwrap(), 2); assert!(obj.call((1, 2), None).is_err()); let dict = PyDict::new(py); dict.set_item("i", 42).unwrap(); assert_eq!(obj.call(NoArgs, Some(&dict)).unwrap().extract::().unwrap(), 84); assert!(obj.call((1,), Some(&dict)).is_err()); dict.set_item("j", 10).unwrap(); assert!(obj.call(NoArgs, Some(&dict)).is_err()); } #[test] fn inline_two_args() { let gil = Python::acquire_gil(); let py = gil.python(); let obj = py_fn!(py, f(a: i32, b: i32) -> PyResult { drop(py); // avoid unused variable warning Ok(a * b) }); assert!(obj.call(NoArgs, None).is_err()); assert_eq!(obj.call((6, 7), None).unwrap().extract::().unwrap(), 42); } /* TODO: reimplement flexible sig support #[test] fn flexible_sig() { fn f(py: Python, args: &PyTuple, kwargs: &PyDict) -> PyResult { Ok(args.len(py) + 100 * kwargs.map_or(0, |kwargs| kwargs.len(py))) } let gil = Python::acquire_gil(); let py = gil.python(); let obj = py_fn!(f(*args, **kwargs)).to_py_object(py); assert_eq!(obj.call(py, NoArgs, None).unwrap().extract::(py).unwrap(), 0); assert_eq!(obj.call(py, (1,), None).unwrap().extract::(py).unwrap(), 1); assert_eq!(obj.call(py, (1,2), None).unwrap().extract::(py).unwrap(), 2); let dict = PyDict::new(py); dict.set_item(py, "i", 42).unwrap(); assert_eq!(obj.call(py, NoArgs, Some(&dict)).unwrap().extract::(py).unwrap(), 100); assert_eq!(obj.call(py, (1,2), Some(&dict)).unwrap().extract::(py).unwrap(), 102); dict.set_item(py, "j", 10).unwrap(); assert_eq!(obj.call(py, (1,2,3), Some(&dict)).unwrap().extract::(py).unwrap(), 203); } */