2021-12-03 00:03:32 +00:00
|
|
|
#![cfg(feature = "macros")]
|
|
|
|
|
2018-06-15 13:59:22 +00:00
|
|
|
use pyo3::prelude::*;
|
2018-11-12 21:28:45 +00:00
|
|
|
|
2021-06-24 14:18:48 +00:00
|
|
|
use pyo3::py_run;
|
2024-02-16 00:36:11 +00:00
|
|
|
use pyo3::types::PyString;
|
2020-09-03 15:27:24 +00:00
|
|
|
use pyo3::types::{IntoPyDict, PyDict, PyTuple};
|
2023-09-24 12:34:53 +00:00
|
|
|
|
|
|
|
#[path = "../src/tests/common.rs"]
|
2018-09-03 18:50:18 +00:00
|
|
|
mod common;
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2019-06-03 03:18:44 +00:00
|
|
|
struct AnonClass {}
|
|
|
|
|
2020-03-03 16:23:32 +00:00
|
|
|
#[pyclass]
|
|
|
|
struct ValueClass {
|
|
|
|
value: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl ValueClass {
|
|
|
|
#[new]
|
|
|
|
fn new(value: usize) -> ValueClass {
|
|
|
|
ValueClass { value }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-03 03:18:44 +00:00
|
|
|
#[pyclass(module = "module")]
|
|
|
|
struct LocatedClass {}
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyfunction]
|
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]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2021-05-16 09:41:59 +00:00
|
|
|
#[pyfn(m)]
|
|
|
|
#[pyo3(name = "no_parameters")]
|
|
|
|
fn function_with_name() -> usize {
|
2021-02-11 21:37:38 +00:00
|
|
|
42
|
2018-04-30 20:38:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyfn(m)]
|
|
|
|
#[pyo3(pass_module)]
|
2024-03-09 09:52:12 +00:00
|
|
|
fn with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module.name()
|
|
|
|
}
|
|
|
|
|
2021-05-16 09:41:59 +00:00
|
|
|
#[pyfn(m)]
|
2020-03-03 16:23:32 +00:00
|
|
|
fn double_value(v: &ValueClass) -> usize {
|
|
|
|
v.value * 2
|
|
|
|
}
|
|
|
|
|
2024-02-28 22:36:50 +00:00
|
|
|
m.add_class::<AnonClass>()?;
|
|
|
|
m.add_class::<ValueClass>()?;
|
|
|
|
m.add_class::<LocatedClass>()?;
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2024-02-28 22:36:50 +00:00
|
|
|
m.add("foo", "bar")?;
|
2018-04-30 20:38:48 +00:00
|
|
|
|
2024-02-28 22:36:50 +00:00
|
|
|
m.add_function(wrap_pyfunction!(double, m)?)?;
|
|
|
|
m.add("also_double", wrap_pyfunction!(double, m)?)?;
|
2018-04-30 21:17:09 +00:00
|
|
|
|
2018-04-30 20:38:48 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_with_functions() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let d = [(
|
|
|
|
"module_with_functions",
|
|
|
|
wrap_pymodule!(module_with_functions)(py),
|
|
|
|
)]
|
2024-02-10 12:59:55 +00:00
|
|
|
.into_py_dict_bound(py);
|
2022-07-19 17:34:23 +00:00
|
|
|
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.__doc__ == 'This module is implemented in Rust.'"
|
|
|
|
);
|
|
|
|
py_assert!(py, *d, "module_with_functions.no_parameters() == 42");
|
|
|
|
py_assert!(py, *d, "module_with_functions.foo == 'bar'");
|
|
|
|
py_assert!(py, *d, "module_with_functions.AnonClass != None");
|
|
|
|
py_assert!(py, *d, "module_with_functions.LocatedClass != None");
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.LocatedClass.__module__ == 'module'"
|
|
|
|
);
|
|
|
|
py_assert!(py, *d, "module_with_functions.double(3) == 6");
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.double.__doc__ == 'Doubles the given value'"
|
|
|
|
);
|
|
|
|
py_assert!(py, *d, "module_with_functions.also_double(3) == 6");
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.also_double.__doc__ == 'Doubles the given value'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
*d,
|
|
|
|
"module_with_functions.with_module() == 'module_with_functions'"
|
|
|
|
);
|
|
|
|
});
|
2018-04-30 20:38:48 +00:00
|
|
|
}
|
2018-05-21 08:21:02 +00:00
|
|
|
|
2024-02-28 22:36:50 +00:00
|
|
|
/// This module uses a legacy two-argument module function.
|
|
|
|
#[pymodule]
|
2024-03-08 00:28:11 +00:00
|
|
|
fn module_with_explicit_py_arg(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2024-02-28 22:36:50 +00:00
|
|
|
m.add_function(wrap_pyfunction!(double, m)?)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_with_explicit_py_arg() {
|
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
|
|
|
Python::with_gil(|py| {
|
|
|
|
let d = [(
|
|
|
|
"module_with_explicit_py_arg",
|
|
|
|
wrap_pymodule!(module_with_explicit_py_arg)(py),
|
|
|
|
)]
|
|
|
|
.into_py_dict_bound(py);
|
|
|
|
|
|
|
|
py_assert!(py, *d, "module_with_explicit_py_arg.double(3) == 6");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-05-24 06:48:22 +00:00
|
|
|
#[pymodule]
|
|
|
|
#[pyo3(name = "other_name")]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn some_name(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2021-02-11 21:37:38 +00:00
|
|
|
m.add("other_name", "other_name")?;
|
2018-07-09 22:13:02 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_renaming() {
|
2019-02-23 17:01:22 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
2024-02-10 12:59:55 +00:00
|
|
|
let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict_bound(py);
|
2018-07-09 22:13:02 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_run!(py, *d, "assert different_name.__name__ == 'other_name'");
|
|
|
|
});
|
2018-07-09 22:13:02 +00:00
|
|
|
}
|
|
|
|
|
2018-05-21 08:21:02 +00:00
|
|
|
#[test]
|
2024-02-22 09:35:47 +00:00
|
|
|
fn test_module_from_code_bound() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
2024-02-22 09:35:47 +00:00
|
|
|
let adder_mod = PyModule::from_code_bound(
|
2022-07-19 17:34:23 +00:00
|
|
|
py,
|
|
|
|
"def add(a,b):\n\treturn a+b",
|
|
|
|
"adder_mod.py",
|
|
|
|
"adder_mod",
|
|
|
|
)
|
|
|
|
.expect("Module code should be loaded");
|
|
|
|
|
|
|
|
let add_func = adder_mod
|
|
|
|
.getattr("add")
|
|
|
|
.expect("Add function 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]
|
|
|
|
fn r#move() -> usize {
|
|
|
|
42
|
|
|
|
}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn raw_ident_module(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
2020-09-09 09:53:24 +00:00
|
|
|
module.add_function(wrap_pyfunction!(r#move, module)?)
|
2018-09-03 18:50:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_raw_idents() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let module = wrap_pymodule!(raw_ident_module)(py);
|
2018-09-03 18:50:18 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, module, "module.move() == 42");
|
|
|
|
});
|
2018-09-03 18:50:18 +00:00
|
|
|
}
|
2018-11-12 21:25:45 +00:00
|
|
|
|
2019-12-17 22:14:28 +00:00
|
|
|
#[pyfunction]
|
2021-04-17 21:22:06 +00:00
|
|
|
#[pyo3(name = "foobar")]
|
2019-12-17 22:14:28 +00:00
|
|
|
fn custom_named_fn() -> usize {
|
|
|
|
42
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_custom_names() {
|
2022-07-26 18:28:03 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn custom_names(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2022-07-26 18:28:03 +00:00
|
|
|
m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
2022-07-26 18:28:03 +00:00
|
|
|
let module = pyo3::wrap_pymodule!(custom_names)(py);
|
2019-12-17 22:14:28 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, module, "not hasattr(module, 'custom_named_fn')");
|
|
|
|
py_assert!(py, module, "module.foobar() == 42");
|
|
|
|
});
|
2019-12-17 22:14:28 +00:00
|
|
|
}
|
|
|
|
|
2020-03-16 06:34:02 +00:00
|
|
|
#[test]
|
|
|
|
fn test_module_dict() {
|
2022-07-26 18:28:03 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn module_dict(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2022-07-26 18:28:03 +00:00
|
|
|
m.dict().set_item("yay", "me")?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
2022-07-26 18:28:03 +00:00
|
|
|
let module = pyo3::wrap_pymodule!(module_dict)(py);
|
2020-03-16 06:34:02 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, module, "module.yay == 'me'");
|
|
|
|
});
|
2020-03-16 06:34:02 +00:00
|
|
|
}
|
|
|
|
|
2021-03-20 03:16:52 +00:00
|
|
|
#[test]
|
|
|
|
fn test_module_dunder_all() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
2022-07-26 18:28:03 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn dunder_all(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2022-07-26 18:28:03 +00:00
|
|
|
m.dict().set_item("yay", "me")?;
|
|
|
|
m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
let module = pyo3::wrap_pymodule!(dunder_all)(py);
|
2021-03-20 03:16:52 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, module, "module.__all__ == ['foobar']");
|
|
|
|
});
|
2021-03-20 03:16:52 +00:00
|
|
|
}
|
|
|
|
|
2018-11-12 21:25:45 +00:00
|
|
|
#[pyfunction]
|
|
|
|
fn subfunction() -> String {
|
|
|
|
"Subfunction".to_string()
|
|
|
|
}
|
|
|
|
|
2024-02-22 09:35:47 +00:00
|
|
|
fn submodule(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
2024-02-27 19:19:52 +00:00
|
|
|
module.add_function(wrap_pyfunction!(subfunction, module)?)?;
|
2020-09-05 13:54:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn submodule_with_init_fn(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
2020-09-09 09:53:24 +00:00
|
|
|
module.add_function(wrap_pyfunction!(subfunction, module)?)?;
|
2018-11-12 21:25:45 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pyfunction]
|
2018-11-12 21:25:45 +00:00
|
|
|
fn superfunction() -> String {
|
|
|
|
"Superfunction".to_string()
|
|
|
|
}
|
|
|
|
|
2018-11-12 21:28:45 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn supermodule(module: &Bound<'_, PyModule>) -> PyResult<()> {
|
2020-09-09 09:53:24 +00:00
|
|
|
module.add_function(wrap_pyfunction!(superfunction, module)?)?;
|
2024-02-28 22:36:50 +00:00
|
|
|
let module_to_add = PyModule::new_bound(module.py(), "submodule")?;
|
2024-02-22 09:35:47 +00:00
|
|
|
submodule(&module_to_add)?;
|
2024-02-28 22:36:50 +00:00
|
|
|
module.add_submodule(&module_to_add)?;
|
|
|
|
let module_to_add = PyModule::new_bound(module.py(), "submodule_with_init_fn")?;
|
|
|
|
submodule_with_init_fn(&module_to_add)?;
|
|
|
|
module.add_submodule(&module_to_add)?;
|
2018-11-12 21:25:45 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_nesting() {
|
2019-02-01 14:00:41 +00:00
|
|
|
use pyo3::wrap_pymodule;
|
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let supermodule = wrap_pymodule!(supermodule)(py);
|
|
|
|
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
supermodule,
|
|
|
|
"supermodule.superfunction() == 'Superfunction'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
supermodule,
|
|
|
|
"supermodule.submodule.subfunction() == 'Subfunction'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
supermodule,
|
|
|
|
"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'"
|
|
|
|
);
|
|
|
|
});
|
2018-11-12 21:25:45 +00:00
|
|
|
}
|
2019-04-18 05:59:15 +00:00
|
|
|
|
|
|
|
// Test that argument parsing specification works for pyfunctions
|
|
|
|
|
2022-10-25 06:23:21 +00:00
|
|
|
#[pyfunction(signature = (a=5, *args))]
|
2024-02-27 19:19:52 +00:00
|
|
|
fn ext_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyObject {
|
|
|
|
[a.to_object(py), args.into_py(py)].to_object(py)
|
2019-04-18 05:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn vararg_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2022-10-25 06:23:21 +00:00
|
|
|
#[pyfn(m, signature = (a=5, *args))]
|
2024-02-27 19:19:52 +00:00
|
|
|
fn int_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyObject {
|
2022-10-25 06:23:21 +00:00
|
|
|
ext_vararg_fn(py, a, args)
|
2019-04-18 05:59:15 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 09:41:59 +00:00
|
|
|
m.add_function(wrap_pyfunction!(ext_vararg_fn, m)?).unwrap();
|
2019-04-18 05:59:15 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_vararg_module() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let m = pyo3::wrap_pymodule!(vararg_module)(py);
|
2019-04-18 05:59:15 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]");
|
|
|
|
py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]");
|
2019-04-18 05:59:15 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, m, "m.int_vararg_fn() == [5, ()]");
|
|
|
|
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
|
|
|
|
});
|
2019-04-18 05:59:15 +00:00
|
|
|
}
|
2020-08-30 15:22:41 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_with_constant() {
|
|
|
|
// Regression test for #1102
|
|
|
|
|
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn module_with_constant(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2020-08-30 15:22:41 +00:00
|
|
|
const ANON: AnonClass = AnonClass {};
|
|
|
|
|
|
|
|
m.add("ANON", ANON)?;
|
|
|
|
m.add_class::<AnonClass>()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
Python::with_gil(|py| {
|
|
|
|
let m = pyo3::wrap_pymodule!(module_with_constant)(py);
|
|
|
|
py_assert!(py, m, "isinstance(m.ANON, m.AnonClass)");
|
|
|
|
});
|
|
|
|
}
|
2020-09-03 15:27:24 +00:00
|
|
|
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module.name()
|
|
|
|
}
|
|
|
|
|
2023-11-20 08:04:06 +00:00
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module_gil_ref(module: &PyModule) -> PyResult<&str> {
|
|
|
|
module.name()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
|
|
|
fn pyfunction_with_module_owned(
|
|
|
|
module: Py<PyModule>,
|
|
|
|
py: Python<'_>,
|
|
|
|
) -> PyResult<Bound<'_, PyString>> {
|
|
|
|
module.bind(py).name()
|
2023-11-20 08:04:06 +00:00
|
|
|
}
|
|
|
|
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module_and_py<'py>(
|
|
|
|
module: &Bound<'py, PyModule>,
|
|
|
|
_python: Python<'py>,
|
|
|
|
) -> PyResult<Bound<'py, PyString>> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module.name()
|
|
|
|
}
|
|
|
|
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module_and_arg<'py>(
|
|
|
|
module: &Bound<'py, PyModule>,
|
|
|
|
string: String,
|
|
|
|
) -> PyResult<(Bound<'py, PyString>, String)> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module.name().map(|s| (s, string))
|
|
|
|
}
|
|
|
|
|
2022-10-25 06:23:21 +00:00
|
|
|
#[pyfunction(signature = (string="foo"))]
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyo3(pass_module)]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module_and_default_arg<'py>(
|
|
|
|
module: &Bound<'py, PyModule>,
|
2020-09-03 15:27:24 +00:00
|
|
|
string: &str,
|
2024-02-16 00:36:11 +00:00
|
|
|
) -> PyResult<(Bound<'py, PyString>, String)> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module.name().map(|s| (s, string.into()))
|
|
|
|
}
|
|
|
|
|
2022-10-25 06:23:21 +00:00
|
|
|
#[pyfunction(signature = (*args, **kwargs))]
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyo3(pass_module)]
|
2024-02-16 00:36:11 +00:00
|
|
|
fn pyfunction_with_module_and_args_kwargs<'py>(
|
|
|
|
module: &Bound<'py, PyModule>,
|
|
|
|
args: &Bound<'py, PyTuple>,
|
|
|
|
kwargs: Option<&Bound<'py, PyDict>>,
|
|
|
|
) -> PyResult<(Bound<'py, PyString>, usize, Option<usize>)> {
|
2020-09-03 15:27:24 +00:00
|
|
|
module
|
|
|
|
.name()
|
|
|
|
.map(|s| (s, args.len(), kwargs.map(|d| d.len())))
|
|
|
|
}
|
|
|
|
|
2021-06-05 15:39:54 +00:00
|
|
|
#[pyfunction]
|
|
|
|
#[pyo3(pass_module)]
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2021-06-05 15:39:54 +00:00
|
|
|
fn pyfunction_with_pass_module_in_attribute(module: &PyModule) -> PyResult<&str> {
|
|
|
|
module.name()
|
|
|
|
}
|
|
|
|
|
2020-09-03 15:27:24 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn module_with_functions_with_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2021-05-16 09:41:59 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?;
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2024-02-16 00:36:11 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_gil_ref, m)?)?;
|
2023-11-20 08:04:06 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_owned, m)?)?;
|
2021-05-16 09:41:59 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?;
|
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?;
|
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_default_arg, m)?)?;
|
2021-06-05 15:39:54 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module_and_args_kwargs, m)?)?;
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2021-06-05 15:39:54 +00:00
|
|
|
m.add_function(wrap_pyfunction!(
|
|
|
|
pyfunction_with_pass_module_in_attribute,
|
|
|
|
m
|
|
|
|
)?)?;
|
2023-11-20 08:04:06 +00:00
|
|
|
m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?;
|
2021-06-05 15:39:54 +00:00
|
|
|
Ok(())
|
2020-09-03 15:27:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_module_functions_with_module() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module() == 'module_with_functions_with_module'"
|
|
|
|
);
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2024-02-16 00:36:11 +00:00
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module_gil_ref() == 'module_with_functions_with_module'"
|
|
|
|
);
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(
|
|
|
|
py,
|
2023-11-20 08:04:06 +00:00
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module_owned() == 'module_with_functions_with_module'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
2022-07-19 17:34:23 +00:00
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'"
|
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module_and_default_arg() \
|
2020-09-03 15:27:24 +00:00
|
|
|
== ('module_with_functions_with_module', 'foo')"
|
2022-07-19 17:34:23 +00:00
|
|
|
);
|
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
m,
|
|
|
|
"m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \
|
2020-09-03 15:27:24 +00:00
|
|
|
== ('module_with_functions_with_module', 1, 2)"
|
2022-07-19 17:34:23 +00:00
|
|
|
);
|
2024-03-09 09:52:12 +00:00
|
|
|
#[cfg(feature = "gil-refs")]
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(
|
|
|
|
py,
|
|
|
|
m,
|
|
|
|
"m.pyfunction_with_pass_module_in_attribute() == 'module_with_functions_with_module'"
|
|
|
|
);
|
|
|
|
});
|
2020-09-03 15:27:24 +00:00
|
|
|
}
|
2021-05-24 06:48:22 +00:00
|
|
|
|
2021-07-08 22:41:24 +00:00
|
|
|
#[test]
|
|
|
|
fn test_module_doc_hidden() {
|
|
|
|
#[doc(hidden)]
|
2022-02-28 08:03:54 +00:00
|
|
|
#[allow(clippy::unnecessary_wraps)]
|
2021-07-08 22:41:24 +00:00
|
|
|
#[pymodule]
|
2024-02-28 22:36:50 +00:00
|
|
|
fn my_module(_m: &Bound<'_, PyModule>) -> PyResult<()> {
|
2021-07-08 22:41:24 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
Python::with_gil(|py| {
|
|
|
|
let m = pyo3::wrap_pymodule!(my_module)(py);
|
|
|
|
py_assert!(py, m, "m.__doc__ == ''");
|
|
|
|
})
|
|
|
|
}
|