Support passing name and doc to PyCFunction::new_closure. Fixes #2665
This commit is contained in:
parent
125af9b7de
commit
9201a7dd48
|
@ -0,0 +1 @@
|
|||
Change PyCFunction::new_closure to take name and doc arguments.
|
|
@ -102,11 +102,16 @@ impl PyCFunction {
|
|||
/// let i = args.extract::<(i64,)>()?.0;
|
||||
/// Ok(i+1)
|
||||
/// };
|
||||
/// let add_one = types::PyCFunction::new_closure(add_one, py).unwrap();
|
||||
/// let add_one = types::PyCFunction::new_closure(py, None, None, add_one).unwrap();
|
||||
/// py_run!(py, add_one, "assert add_one(42) == 43");
|
||||
/// });
|
||||
/// ```
|
||||
pub fn new_closure<F, R>(f: F, py: Python<'_>) -> PyResult<&PyCFunction>
|
||||
pub fn new_closure<'a, F, R>(
|
||||
py: Python<'a>,
|
||||
name: Option<&'static str>,
|
||||
doc: Option<&'static str>,
|
||||
f: F,
|
||||
) -> PyResult<&'a PyCFunction>
|
||||
where
|
||||
F: Fn(&types::PyTuple, Option<&types::PyDict>) -> R + Send + 'static,
|
||||
R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>,
|
||||
|
@ -123,9 +128,9 @@ impl PyCFunction {
|
|||
)?
|
||||
};
|
||||
let method_def = pymethods::PyMethodDef::cfunction_with_keywords(
|
||||
"pyo3-closure",
|
||||
name.unwrap_or("pyo3-closure\0"),
|
||||
pymethods::PyCFunctionWithKeywords(run_closure::<F, R>),
|
||||
"",
|
||||
doc.unwrap_or("\0"),
|
||||
);
|
||||
Self::internal_new_from_pointers(&method_def, py, capsule.as_ptr(), std::ptr::null_mut())
|
||||
}
|
||||
|
|
|
@ -418,9 +418,12 @@ fn test_closure() {
|
|||
Ok(res)
|
||||
})
|
||||
};
|
||||
let closure_py = PyCFunction::new_closure(f, py).unwrap();
|
||||
let closure_py =
|
||||
PyCFunction::new_closure(py, Some("test_fn"), Some("test_fn doc"), f).unwrap();
|
||||
|
||||
py_assert!(py, closure_py, "closure_py(42) == [43]");
|
||||
py_assert!(py, closure_py, "closure_py.__name__ == 'test_fn'");
|
||||
py_assert!(py, closure_py, "closure_py.__doc__ == 'test_fn doc'");
|
||||
py_assert!(
|
||||
py,
|
||||
closure_py,
|
||||
|
@ -439,7 +442,7 @@ fn test_closure_counter() {
|
|||
*counter += 1;
|
||||
Ok(*counter)
|
||||
};
|
||||
let counter_py = PyCFunction::new_closure(counter_fn, py).unwrap();
|
||||
let counter_py = PyCFunction::new_closure(py, None, None, counter_fn).unwrap();
|
||||
|
||||
py_assert!(py, counter_py, "counter_py() == 1");
|
||||
py_assert!(py, counter_py, "counter_py() == 2");
|
||||
|
|
|
@ -10,7 +10,7 @@ fn main() {
|
|||
println!("This is five: {:?}", ref_.len());
|
||||
Ok(())
|
||||
};
|
||||
PyCFunction::new_closure(closure_fn, py).unwrap().into()
|
||||
PyCFunction::new_closure(py, None, None, closure_fn).unwrap().into()
|
||||
});
|
||||
|
||||
Python::with_gil(|py| {
|
||||
|
|
|
@ -4,8 +4,8 @@ error[E0597]: `local_data` does not live long enough
|
|||
7 | let ref_: &[u8] = &local_data;
|
||||
| ^^^^^^^^^^^ borrowed value does not live long enough
|
||||
...
|
||||
13 | PyCFunction::new_closure(closure_fn, py).unwrap().into()
|
||||
| ---------------------------------------- argument requires that `local_data` is borrowed for `'static`
|
||||
13 | PyCFunction::new_closure(py, None, None, closure_fn).unwrap().into()
|
||||
| ---------------------------------------------------- argument requires that `local_data` is borrowed for `'static`
|
||||
14 | });
|
||||
| - `local_data` dropped here while still borrowed
|
||||
|
||||
|
@ -20,8 +20,8 @@ error[E0373]: closure may outlive the current function, but it borrows `ref_`, w
|
|||
note: function requires argument type to outlive `'static`
|
||||
--> tests/ui/invalid_closure.rs:13:9
|
||||
|
|
||||
13 | PyCFunction::new_closure(closure_fn, py).unwrap().into()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | PyCFunction::new_closure(py, None, None, closure_fn).unwrap().into()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to force the closure to take ownership of `ref_` (and any other referenced variables), use the `move` keyword
|
||||
|
|
||||
9 | let closure_fn = move |_args: &PyTuple, _kwargs: Option<&PyDict>| -> PyResult<()> {
|
||||
|
|
Loading…
Reference in New Issue