cleans up `PyCFunction::internal_new` (#3910)

This deduplicates some code around `PyCFunction::internal_new`
This commit is contained in:
Icxolu 2024-02-27 23:15:35 +01:00 committed by GitHub
parent a3ad28b70c
commit 6f03a5464f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 43 deletions

View File

@ -273,7 +273,7 @@ pub fn impl_wrap_pyfunction(
pub fn add_to_module(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> { pub fn add_to_module(module: &#krate::Bound<'_, #krate::types::PyModule>) -> #krate::PyResult<()> {
use #krate::prelude::PyModuleMethods; use #krate::prelude::PyModuleMethods;
use ::std::convert::Into; use ::std::convert::Into;
module.add_function(#krate::types::PyCFunction::internal_new(&DEF, module.as_gil_ref().into())?) module.add_function(#krate::types::PyCFunction::internal_new(module.py(), &DEF, module.into())?)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
types::{PyCFunction, PyModule}, types::{PyCFunction, PyModule},
Borrowed, Bound, PyResult, Python, Borrowed, Bound, PyNativeType, PyResult, Python,
}; };
pub use crate::impl_::pymethods::PyMethodDef; pub use crate::impl_::pymethods::PyMethodDef;
@ -13,25 +13,25 @@ pub trait WrapPyFunctionArg<'py, T> {
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> { impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
PyCFunction::internal_new_bound(self.py(), method_def, Some(&self)) PyCFunction::internal_new(self.py(), method_def, Some(&self))
} }
} }
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> { impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
PyCFunction::internal_new_bound(self.py(), method_def, Some(self)) PyCFunction::internal_new(self.py(), method_def, Some(self))
} }
} }
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> { impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
PyCFunction::internal_new_bound(self.py(), method_def, Some(&self)) PyCFunction::internal_new(self.py(), method_def, Some(&self))
} }
} }
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> { impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
PyCFunction::internal_new_bound(self.py(), method_def, Some(self)) PyCFunction::internal_new(self.py(), method_def, Some(self))
} }
} }
@ -39,13 +39,14 @@ impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, '
// The `wrap_pyfunction_bound!` macro is needed for the Bound form. // The `wrap_pyfunction_bound!` macro is needed for the Bound form.
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for Python<'py> { impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for Python<'py> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
PyCFunction::internal_new(method_def, self.into()).map(Bound::into_gil_ref) PyCFunction::internal_new(self, method_def, None).map(Bound::into_gil_ref)
} }
} }
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for &'py PyModule { impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for &'py PyModule {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
PyCFunction::internal_new(method_def, self.into()).map(Bound::into_gil_ref) PyCFunction::internal_new(self.py(), method_def, Some(&self.as_borrowed()))
.map(Bound::into_gil_ref)
} }
} }
@ -63,6 +64,6 @@ where
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound<Python<'py>> { impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound<Python<'py>> {
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
PyCFunction::internal_new_bound(self.0, method_def, None) PyCFunction::internal_new(self.0, method_def, None)
} }
} }

View File

@ -9,7 +9,7 @@ use crate::{
impl_::pymethods::{self, PyMethodDef}, impl_::pymethods::{self, PyMethodDef},
types::{PyCapsule, PyDict, PyModule, PyString, PyTuple}, types::{PyCapsule, PyDict, PyModule, PyString, PyTuple},
}; };
use crate::{Bound, IntoPy, Py, PyAny, PyResult, Python}; use crate::{Bound, IntoPy, Py, PyAny, PyNativeType, PyResult, Python};
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::ffi::CStr; use std::ffi::CStr;
@ -34,13 +34,15 @@ impl PyCFunction {
doc: &'static str, doc: &'static str,
py_or_module: PyFunctionArguments<'a>, py_or_module: PyFunctionArguments<'a>,
) -> PyResult<&'a Self> { ) -> PyResult<&'a Self> {
let (py, module) = py_or_module.into_py_and_maybe_module();
Self::internal_new( Self::internal_new(
py,
&PyMethodDef::cfunction_with_keywords( &PyMethodDef::cfunction_with_keywords(
name, name,
pymethods::PyCFunctionWithKeywords(fun), pymethods::PyCFunctionWithKeywords(fun),
doc, doc,
), ),
py_or_module, module.map(PyNativeType::as_borrowed).as_deref(),
) )
.map(Bound::into_gil_ref) .map(Bound::into_gil_ref)
} }
@ -53,7 +55,7 @@ impl PyCFunction {
doc: &'static str, doc: &'static str,
module: Option<&Bound<'py, PyModule>>, module: Option<&Bound<'py, PyModule>>,
) -> PyResult<Bound<'py, Self>> { ) -> PyResult<Bound<'py, Self>> {
Self::internal_new_bound( Self::internal_new(
py, py,
&PyMethodDef::cfunction_with_keywords( &PyMethodDef::cfunction_with_keywords(
name, name,
@ -78,9 +80,11 @@ impl PyCFunction {
doc: &'static str, doc: &'static str,
py_or_module: PyFunctionArguments<'a>, py_or_module: PyFunctionArguments<'a>,
) -> PyResult<&'a Self> { ) -> PyResult<&'a Self> {
let (py, module) = py_or_module.into_py_and_maybe_module();
Self::internal_new( Self::internal_new(
py,
&PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc), &PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
py_or_module, module.map(PyNativeType::as_borrowed).as_deref(),
) )
.map(Bound::into_gil_ref) .map(Bound::into_gil_ref)
} }
@ -93,7 +97,7 @@ impl PyCFunction {
doc: &'static str, doc: &'static str,
module: Option<&Bound<'py, PyModule>>, module: Option<&Bound<'py, PyModule>>,
) -> PyResult<Bound<'py, Self>> { ) -> PyResult<Bound<'py, Self>> {
Self::internal_new_bound( Self::internal_new(
py, py,
&PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc), &PyMethodDef::noargs(name, pymethods::PyCFunction(fun), doc),
module, module,
@ -180,35 +184,6 @@ impl PyCFunction {
#[doc(hidden)] #[doc(hidden)]
pub fn internal_new<'py>( pub fn internal_new<'py>(
method_def: &PyMethodDef,
py_or_module: PyFunctionArguments<'py>,
) -> PyResult<Bound<'py, Self>> {
let (py, module) = py_or_module.into_py_and_maybe_module();
let (mod_ptr, module_name): (_, Option<Py<PyString>>) = if let Some(m) = module {
let mod_ptr = m.as_ptr();
(mod_ptr, Some(m.name()?.into_py(py)))
} else {
(std::ptr::null_mut(), None)
};
let (def, destructor) = method_def.as_method_def()?;
// FIXME: stop leaking the def and destructor
let def = Box::into_raw(Box::new(def));
std::mem::forget(destructor);
let module_name_ptr = module_name
.as_ref()
.map_or(std::ptr::null_mut(), Py::as_ptr);
unsafe {
ffi::PyCFunction_NewEx(def, mod_ptr, module_name_ptr)
.assume_owned_or_err(py)
.downcast_into_unchecked()
}
}
#[doc(hidden)]
pub(crate) fn internal_new_bound<'py>(
py: Python<'py>, py: Python<'py>,
method_def: &PyMethodDef, method_def: &PyMethodDef,
module: Option<&Bound<'py, PyModule>>, module: Option<&Bound<'py, PyModule>>,