remove type_is_pymodule

This commit is contained in:
David Hewitt 2023-11-22 21:30:10 +00:00
parent 3d17f7442a
commit 25b8a37521
5 changed files with 40 additions and 62 deletions

View File

@ -81,7 +81,7 @@ pub enum FnType {
FnNewClass, FnNewClass,
FnClass, FnClass,
FnStatic, FnStatic,
FnModule, FnModule(Span),
ClassAttribute, ClassAttribute,
} }
@ -93,7 +93,7 @@ impl FnType {
| FnType::Fn(_) | FnType::Fn(_)
| FnType::FnClass | FnType::FnClass
| FnType::FnNewClass | FnType::FnNewClass
| FnType::FnModule => true, | FnType::FnModule(_) => true,
FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => false, FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => false,
} }
} }
@ -117,8 +117,8 @@ impl FnType {
::std::convert::Into::into(_pyo3::types::PyType::from_type_ptr(py, _slf as *mut _pyo3::ffi::PyTypeObject)), ::std::convert::Into::into(_pyo3::types::PyType::from_type_ptr(py, _slf as *mut _pyo3::ffi::PyTypeObject)),
} }
} }
FnType::FnModule => { FnType::FnModule(span) => {
quote! { quote_spanned! { *span =>
#[allow(clippy::useless_conversion)] #[allow(clippy::useless_conversion)]
::std::convert::Into::into(py.from_borrowed_ptr::<_pyo3::types::PyModule>(_slf)), ::std::convert::Into::into(py.from_borrowed_ptr::<_pyo3::types::PyModule>(_slf)),
} }
@ -627,7 +627,7 @@ impl<'a> FnSpec<'a> {
// Getters / Setters / ClassAttribute are not callables on the Python side // Getters / Setters / ClassAttribute are not callables on the Python side
FnType::Getter(_) | FnType::Setter(_) | FnType::ClassAttribute => return None, FnType::Getter(_) | FnType::Setter(_) | FnType::ClassAttribute => return None,
FnType::Fn(_) => Some("self"), FnType::Fn(_) => Some("self"),
FnType::FnModule => Some("module"), FnType::FnModule(_) => Some("module"),
FnType::FnClass | FnType::FnNewClass => Some("cls"), FnType::FnClass | FnType::FnNewClass => Some("cls"),
FnType::FnStatic | FnType::FnNew => None, FnType::FnStatic | FnType::FnNew => None,
}; };

View File

@ -191,30 +191,30 @@ pub fn impl_wrap_pyfunction(
let python_name = name.map_or_else(|| func.sig.ident.unraw(), |name| name.value.0); let python_name = name.map_or_else(|| func.sig.ident.unraw(), |name| name.value.0);
let mut arguments = func
.sig
.inputs
.iter_mut()
.map(FnArg::parse)
.collect::<syn::Result<Vec<_>>>()?;
let tp = if pass_module.is_some() { let tp = if pass_module.is_some() {
const PASS_MODULE_ERR: &str = let span = match func.sig.inputs.first() {
"expected &PyModule or Py<PyModule> as first argument with `pass_module`"; Some(syn::FnArg::Typed(first_arg)) => first_arg.ty.span(),
ensure_spanned!( Some(syn::FnArg::Receiver(_)) | None => bail_spanned!(
!arguments.is_empty(), func.span() => "expected `&PyModule` or `Py<PyModule>` as first argument with `pass_module`"
func.span() => PASS_MODULE_ERR ),
); };
let arg = arguments.remove(0); method::FnType::FnModule(span)
ensure_spanned!(
type_is_pymodule(arg.ty),
arg.ty.span() => PASS_MODULE_ERR
);
method::FnType::FnModule
} else { } else {
method::FnType::FnStatic method::FnType::FnStatic
}; };
let arguments = func
.sig
.inputs
.iter_mut()
.skip(if tp.skip_first_rust_argument_in_python_signature() {
1
} else {
0
})
.map(FnArg::parse)
.collect::<syn::Result<Vec<_>>>()?;
let signature = if let Some(signature) = signature { let signature = if let Some(signature) = signature {
FunctionSignature::from_arguments_and_attribute(arguments, signature)? FunctionSignature::from_arguments_and_attribute(arguments, signature)?
} else { } else {
@ -270,34 +270,3 @@ pub fn impl_wrap_pyfunction(
}; };
Ok(wrapped_pyfunction) Ok(wrapped_pyfunction)
} }
fn type_is_pymodule(ty: &syn::Type) -> bool {
let is_pymodule = |typath: &syn::TypePath| {
typath
.path
.segments
.last()
.map_or(false, |seg| seg.ident == "PyModule")
};
match ty {
syn::Type::Reference(tyref) => {
if let syn::Type::Path(typath) = tyref.elem.as_ref() {
return is_pymodule(typath);
}
}
syn::Type::Path(typath) => {
if let Some(syn::PathSegment {
arguments: syn::PathArguments::AngleBracketed(args),
..
}) = typath.path.segments.last()
{
if args.args.len() != 1 {
return false;
}
return matches!(args.args.first().unwrap(), syn::GenericArgument::Type(syn::Type::Path(typath)) if is_pymodule(typath));
}
}
_ => {}
}
false
}

View File

@ -258,7 +258,7 @@ pub fn gen_py_method(
doc: spec.get_doc(meth_attrs), doc: spec.get_doc(meth_attrs),
}, },
)?), )?),
(_, FnType::FnModule) => { (_, FnType::FnModule(_)) => {
unreachable!("methods cannot be FnModule") unreachable!("methods cannot be FnModule")
} }
}) })

View File

@ -3,10 +3,10 @@ use pyo3::prelude::*;
#[pymodule] #[pymodule]
fn module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { fn module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
#[pyfn(m, pass_module)] #[pyfn(m, pass_module)]
fn fail(string: &str, module: &PyModule) -> PyResult<&str> { fn fail<'py>(string: &str, module: &'py PyModule) -> PyResult<&'py str> {
module.name() module.name()
} }
Ok(()) Ok(())
} }
fn main(){} fn main() {}

View File

@ -1,5 +1,14 @@
error: expected &PyModule or Py<PyModule> as first argument with `pass_module` error[E0277]: the trait bound `&str: From<&pyo3::prelude::PyModule>` is not satisfied
--> tests/ui/invalid_need_module_arg_position.rs:6:21 --> tests/ui/invalid_need_module_arg_position.rs:6:26
| |
6 | fn fail(string: &str, module: &PyModule) -> PyResult<&str> { 6 | fn fail<'py>(string: &str, module: &'py PyModule) -> PyResult<&'py str> {
| ^ | ^ the trait `From<&pyo3::prelude::PyModule>` is not implemented for `&str`
|
= help: the following other types implement trait `From<T>`:
<String as From<char>>
<String as From<Box<str>>>
<String as From<Cow<'a, str>>>
<String as From<&str>>
<String as From<&mut str>>
<String as From<&String>>
= note: required for `&pyo3::prelude::PyModule` to implement `Into<&str>`