#![feature(proc_macro, specialization)] extern crate pyo3; use pyo3::prelude::*; use pyo3::py::class as pyclass; use pyo3::py::methods as pymethods; #[macro_use] mod common; #[pyclass] struct InstanceMethod { member: i32, token: PyToken } #[pymethods] impl InstanceMethod { /// Test method fn method(&self) -> PyResult { Ok(self.member) } } #[test] fn instance_method() { let gil = Python::acquire_gil(); let py = gil.python(); let obj = py.init_ref(|t| InstanceMethod{member: 42, token: t}).unwrap(); assert!(obj.method().unwrap() == 42); let d = PyDict::new(py); d.set_item("obj", obj).unwrap(); py.run("assert obj.method() == 42", None, Some(d)).unwrap(); py.run("assert obj.method.__doc__ == 'Test method'", None, Some(d)).unwrap(); } #[pyclass] struct InstanceMethodWithArgs { member: i32, token: PyToken } #[pymethods] impl InstanceMethodWithArgs { fn method(&self, multiplier: i32) -> PyResult { Ok(self.member * multiplier) } } //#[test] #[allow(dead_code)] fn instance_method_with_args() { let gil = Python::acquire_gil(); let py = gil.python(); let obj = py.init_ref(|t| InstanceMethodWithArgs{member: 7, token: t}).unwrap(); assert!(obj.method(6).unwrap() == 42); let d = PyDict::new(py); d.set_item("obj", obj).unwrap(); py.run("assert obj.method(3) == 21", None, Some(d)).unwrap(); py.run("assert obj.method(multiplier=6) == 42", None, Some(d)).unwrap(); } #[pyclass] struct ClassMethod {token: PyToken} #[pymethods] impl ClassMethod { #[new] fn __new__(obj: &PyRawObject) -> PyResult<()> { obj.init(|t| ClassMethod{token: t}) } #[classmethod] fn method(cls: &PyType) -> PyResult { Ok(format!("{}.method()!", cls.name())) } } #[test] fn class_method() { let gil = Python::acquire_gil(); let py = gil.python(); let d = PyDict::new(py); d.set_item("C", py.get_type::()).unwrap(); py.run("assert C.method() == 'ClassMethod.method()!'", None, Some(d)).unwrap(); py.run("assert C().method() == 'ClassMethod.method()!'", None, Some(d)).unwrap(); } #[pyclass] struct ClassMethodWithArgs{token: PyToken} #[pymethods] impl ClassMethodWithArgs { #[classmethod] fn method(cls: &PyType, input: &PyString) -> PyResult { Ok(format!("{}.method({})", cls.name(), input)) } } #[test] fn class_method_with_args() { let gil = Python::acquire_gil(); let py = gil.python(); let d = PyDict::new(py); d.set_item("C", py.get_type::()).unwrap(); py.run("assert C.method('abc') == 'ClassMethodWithArgs.method(abc)'", None, Some(d)).unwrap(); } #[pyclass] struct StaticMethod { token: PyToken } #[pymethods] impl StaticMethod { #[new] fn __new__(obj: &PyRawObject) -> PyResult<()> { obj.init(|t| StaticMethod{token: t}) } #[staticmethod] fn method(_py: Python) -> PyResult<&'static str> { Ok("StaticMethod.method()!") } } #[test] fn static_method() { let gil = Python::acquire_gil(); let py = gil.python(); assert_eq!(StaticMethod::method(py).unwrap(), "StaticMethod.method()!"); let d = PyDict::new(py); d.set_item("C", py.get_type::()).unwrap(); py.run("assert C.method() == 'StaticMethod.method()!'", None, Some(d)).unwrap(); py.run("assert C().method() == 'StaticMethod.method()!'", None, Some(d)).unwrap(); } #[pyclass] struct StaticMethodWithArgs{token: PyToken} #[pymethods] impl StaticMethodWithArgs { #[staticmethod] fn method(_py: Python, input: i32) -> PyResult { Ok(format!("0x{:x}", input)) } } #[test] fn static_method_with_args() { let gil = Python::acquire_gil(); let py = gil.python(); assert_eq!(StaticMethodWithArgs::method(py, 1234).unwrap(), "0x4d2"); let d = PyDict::new(py); d.set_item("C", py.get_type::()).unwrap(); py.run("assert C.method(1337) == '0x539'", None, Some(d)).unwrap(); } #[pyclass] struct MethArgs { token: PyToken } #[pymethods] impl MethArgs { #[args(test)] fn get_optional(&self, test: Option) -> PyResult { Ok(test.unwrap_or(10)) } #[args(test="10")] fn get_default(&self, test: i32) -> PyResult { Ok(test) } #[args("*", test=10)] fn get_kwarg(&self, test: i32) -> PyResult { Ok(test) } #[args(args="*", kwargs="**")] fn get_kwargs(&self, args: &PyTuple, kwargs: Option<&PyDict>) -> PyResult { Ok([args.into(), kwargs.to_object(self.py())].to_object(self.py())) } } #[test] fn meth_args() { let gil = Python::acquire_gil(); let py = gil.python(); let inst = py.init(|t| MethArgs{token: t}).unwrap(); py_run!(py, inst, "assert inst.get_optional() == 10"); py_run!(py, inst, "assert inst.get_optional(100) == 100"); py_run!(py, inst, "assert inst.get_default() == 10"); py_run!(py, inst, "assert inst.get_default(100) == 100"); py_run!(py, inst, "assert inst.get_kwarg() == 10"); py_run!(py, inst, "assert inst.get_kwarg(100) == 10"); py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); py_run!(py, inst, "assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]"); // py_expect_exception!(py, inst, "inst.get_kwarg(100)", TypeError); }