Merge pull request #2686 from dalcde/closure-name-doc

Support passing name and doc to new_closure.
This commit is contained in:
Bruno Kolenbrander 2022-11-06 17:35:20 +01:00 committed by GitHub
commit 6766d9f93b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 11 deletions

View file

@ -0,0 +1 @@
Change PyCFunction::new_closure to take name and doc arguments.

View file

@ -108,11 +108,16 @@ impl PyCFunction {
/// let i = args.extract::<(i64,)>()?.0; /// let i = args.extract::<(i64,)>()?.0;
/// Ok(i+1) /// 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"); /// 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 where
F: Fn(&types::PyTuple, Option<&types::PyDict>) -> R + Send + 'static, F: Fn(&types::PyTuple, Option<&types::PyDict>) -> R + Send + 'static,
R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>, R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>,
@ -129,9 +134,9 @@ impl PyCFunction {
)? )?
}; };
let method_def = pymethods::PyMethodDef::cfunction_with_keywords( let method_def = pymethods::PyMethodDef::cfunction_with_keywords(
"pyo3-closure", name.unwrap_or("pyo3-closure\0"),
pymethods::PyCFunctionWithKeywords(run_closure::<F, R>), 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()) Self::internal_new_from_pointers(&method_def, py, capsule.as_ptr(), std::ptr::null_mut())
} }

View file

@ -418,9 +418,12 @@ fn test_closure() {
Ok(res) 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(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_assert!(
py, py,
closure_py, closure_py,
@ -439,7 +442,7 @@ fn test_closure_counter() {
*counter += 1; *counter += 1;
Ok(*counter) 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() == 1");
py_assert!(py, counter_py, "counter_py() == 2"); py_assert!(py, counter_py, "counter_py() == 2");

View file

@ -10,7 +10,7 @@ fn main() {
println!("This is five: {:?}", ref_.len()); println!("This is five: {:?}", ref_.len());
Ok(()) Ok(())
}; };
PyCFunction::new_closure(closure_fn, py).unwrap().into() PyCFunction::new_closure(py, None, None, closure_fn).unwrap().into()
}); });
Python::with_gil(|py| { Python::with_gil(|py| {

View file

@ -4,8 +4,8 @@ error[E0597]: `local_data` does not live long enough
7 | let ref_: &[u8] = &local_data; 7 | let ref_: &[u8] = &local_data;
| ^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^ borrowed value does not live long enough
... ...
13 | PyCFunction::new_closure(closure_fn, py).unwrap().into() 13 | PyCFunction::new_closure(py, None, None, closure_fn).unwrap().into()
| ---------------------------------------- argument requires that `local_data` is borrowed for `'static` | ---------------------------------------------------- argument requires that `local_data` is borrowed for `'static`
14 | }); 14 | });
| - `local_data` dropped here while still borrowed | - `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` note: function requires argument type to outlive `'static`
--> tests/ui/invalid_closure.rs:13:9 --> 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 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<()> { 9 | let closure_fn = move |_args: &PyTuple, _kwargs: Option<&PyDict>| -> PyResult<()> {