2018-06-15 13:59:22 +00:00
|
|
|
use pyo3::prelude::*;
|
2018-11-12 21:28:45 +00:00
|
|
|
|
|
|
|
#[cfg(Py_3)]
|
2018-09-21 21:32:48 +00:00
|
|
|
use pyo3::types::PyDict;
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-09-03 18:50:18 +00:00
|
|
|
#[macro_use]
|
|
|
|
mod common;
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-04-30 20:38:48 +00:00
|
|
|
struct EmptyClass {}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-04-30 20:38:48 +00:00
|
|
|
fn sum_as_string(a: i64, b: i64) -> String {
|
|
|
|
format!("{}", a + b).to_string()
|
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyfunction]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-07-30 20:52:22 +00:00
|
|
|
/// Doubles the given value
|
2018-04-30 21:17:09 +00:00
|
|
|
fn double(x: usize) -> usize {
|
|
|
|
x * 2
|
|
|
|
}
|
|
|
|
|
2018-04-30 20:38:48 +00:00
|
|
|
/// This module is implemented in Rust.
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
|
|
|
#[cfg(Py_3)]
|
2018-07-09 22:13:02 +00:00
|
|
|
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
|
2019-02-01 15:31:18 +00:00
|
|
|
use pyo3::wrap_pyfunction;
|
2019-02-01 14:00:41 +00:00
|
|
|
|
2018-04-30 20:38:48 +00:00
|
|
|
#[pyfn(m, "sum_as_string")]
|
|
|
|
fn sum_as_string_py(_py: Python, a: i64, b: i64) -> PyResult<String> {
|
|
|
|
let out = sum_as_string(a, b);
|
|
|
|
return Ok(out);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pyfn(m, "no_parameters")]
|
|
|
|
fn no_parameters() -> PyResult<usize> {
|
|
|
|
return Ok(42);
|
|
|
|
}
|
|
|
|
|
2018-05-05 13:50:04 +00:00
|
|
|
m.add_class::<EmptyClass>().unwrap();
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2018-05-05 13:50:04 +00:00
|
|
|
m.add("foo", "bar").unwrap();
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2019-02-01 13:01:18 +00:00
|
|
|
m.add_wrapped(wrap_pyfunction!(double)).unwrap();
|
|
|
|
m.add("also_double", wrap_pyfunction!(double)(py)).unwrap();
|
2018-04-30 21:17:09 +00:00
|
|
|
|
2018-04-30 20:38:48 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-04-30 20:38:48 +00:00
|
|
|
fn test_module_with_functions() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2018-04-30 20:38:48 +00:00
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
|
|
|
let d = PyDict::new(py);
|
2018-11-12 21:25:45 +00:00
|
|
|
d.set_item(
|
|
|
|
"module_with_functions",
|
2019-02-01 13:01:18 +00:00
|
|
|
wrap_pymodule!(module_with_functions)(py),
|
2018-11-12 21:25:45 +00:00
|
|
|
)
|
2018-09-28 21:34:57 +00:00
|
|
|
.unwrap();
|
2018-06-15 19:21:12 +00:00
|
|
|
|
|
|
|
let run = |code| py.run(code, None, Some(d)).unwrap();
|
|
|
|
|
|
|
|
run("assert module_with_functions.__doc__ == 'This module is implemented in Rust.'");
|
|
|
|
run("assert module_with_functions.sum_as_string(1, 2) == '3'");
|
|
|
|
run("assert module_with_functions.no_parameters() == 42");
|
|
|
|
run("assert module_with_functions.foo == 'bar'");
|
|
|
|
run("assert module_with_functions.EmptyClass != None");
|
|
|
|
run("assert module_with_functions.double(3) == 6");
|
2018-07-30 20:52:22 +00:00
|
|
|
run("assert module_with_functions.double.__doc__ == 'Doubles the given value'");
|
2018-06-15 19:21:12 +00:00
|
|
|
run("assert module_with_functions.also_double(3) == 6");
|
2018-07-30 20:52:22 +00:00
|
|
|
run("assert module_with_functions.also_double.__doc__ == 'Doubles the given value'");
|
2018-04-30 20:38:48 +00:00
|
|
|
}
|
2018-05-21 08:21:02 +00:00
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule(other_name)]
|
2018-07-09 22:13:02 +00:00
|
|
|
fn some_name(_: Python, _: &PyModule) -> PyResult<()> {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(Py_3)]
|
|
|
|
fn test_module_renaming() {
|
2019-02-23 17:01:22 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2018-07-09 22:13:02 +00:00
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
|
|
|
let d = PyDict::new(py);
|
2019-02-23 17:01:22 +00:00
|
|
|
d.set_item("different_name", wrap_pymodule!(other_name)(py))
|
|
|
|
.unwrap();
|
2018-07-09 22:13:02 +00:00
|
|
|
|
2018-07-18 11:08:05 +00:00
|
|
|
py.run(
|
|
|
|
"assert different_name.__name__ == 'other_name'",
|
|
|
|
None,
|
|
|
|
Some(d),
|
2018-09-28 21:34:57 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
2018-07-09 22:13:02 +00:00
|
|
|
}
|
|
|
|
|
2018-05-21 08:21:02 +00:00
|
|
|
#[test]
|
|
|
|
#[cfg(Py_3)]
|
|
|
|
fn test_module_from_code() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
2018-06-15 19:21:12 +00:00
|
|
|
let adder_mod = PyModule::from_code(
|
|
|
|
py,
|
|
|
|
"def add(a,b):\n\treturn a+b",
|
|
|
|
"adder_mod.py",
|
|
|
|
"adder_mod",
|
2018-09-28 21:34:57 +00:00
|
|
|
)
|
|
|
|
.expect("Module code should be loaded");
|
2018-05-21 08:21:02 +00:00
|
|
|
|
|
|
|
let add_func = adder_mod
|
|
|
|
.get("add")
|
|
|
|
.expect("Add fucntion should be in the module")
|
|
|
|
.to_object(py);
|
|
|
|
|
|
|
|
let ret_value: i32 = add_func
|
|
|
|
.call1(py, (1, 2))
|
|
|
|
.expect("A value should be returned")
|
|
|
|
.extract(py)
|
|
|
|
.expect("The value should be able to be converted to an i32");
|
|
|
|
|
|
|
|
assert_eq!(ret_value, 3);
|
2018-07-18 11:08:05 +00:00
|
|
|
}
|
2018-09-03 18:50:18 +00:00
|
|
|
|
|
|
|
#[pyfunction]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-09-03 18:50:18 +00:00
|
|
|
fn r#move() -> usize {
|
|
|
|
42
|
|
|
|
}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
|
|
|
#[cfg(Py_3)]
|
2018-09-03 18:50:18 +00:00
|
|
|
fn raw_ident_module(_py: Python, module: &PyModule) -> PyResult<()> {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pyfunction;
|
|
|
|
|
2019-02-01 13:01:18 +00:00
|
|
|
module.add_wrapped(wrap_pyfunction!(r#move))
|
2018-09-03 18:50:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[cfg(Py_3)]
|
2018-09-03 18:50:18 +00:00
|
|
|
fn test_raw_idents() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2018-09-03 18:50:18 +00:00
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
2019-02-01 13:01:18 +00:00
|
|
|
let module = wrap_pymodule!(raw_ident_module)(py);
|
2018-09-03 18:50:18 +00:00
|
|
|
|
|
|
|
py_assert!(py, module, "module.move() == 42");
|
|
|
|
}
|
2018-11-12 21:25:45 +00:00
|
|
|
|
|
|
|
#[pyfunction]
|
|
|
|
#[cfg(Py_3)]
|
|
|
|
fn subfunction() -> String {
|
|
|
|
"Subfunction".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(Py_3)]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
2018-11-12 21:25:45 +00:00
|
|
|
fn submodule(_py: Python, module: &PyModule) -> PyResult<()> {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pyfunction;
|
|
|
|
|
2019-02-01 13:01:18 +00:00
|
|
|
module.add_wrapped(wrap_pyfunction!(subfunction))?;
|
2018-11-12 21:25:45 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(Py_3)]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pyfunction]
|
2018-11-12 21:25:45 +00:00
|
|
|
fn superfunction() -> String {
|
|
|
|
"Superfunction".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(Py_3)]
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
2018-11-12 21:25:45 +00:00
|
|
|
fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::{wrap_pyfunction, wrap_pymodule};
|
|
|
|
|
2019-02-01 13:01:18 +00:00
|
|
|
module.add_wrapped(wrap_pyfunction!(superfunction))?;
|
|
|
|
module.add_wrapped(wrap_pymodule!(submodule))?;
|
2018-11-12 21:25:45 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(Py_3)]
|
|
|
|
fn test_module_nesting() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2018-11-12 21:25:45 +00:00
|
|
|
let gil = GILGuard::acquire();
|
|
|
|
let py = gil.python();
|
2019-02-01 13:01:18 +00:00
|
|
|
let supermodule = wrap_pymodule!(supermodule)(py);
|
2018-11-12 21:25:45 +00:00
|
|
|
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
supermodule,
|
|
|
|
"supermodule.superfunction() == 'Superfunction'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
supermodule,
|
|
|
|
"supermodule.submodule.subfunction() == 'Subfunction'"
|
|
|
|
);
|
|
|
|
}
|