diff --git a/pyo3-derive-backend/src/method.rs b/pyo3-derive-backend/src/method.rs index 6d06c377945..e138924b868 100644 --- a/pyo3-derive-backend/src/method.rs +++ b/pyo3-derive-backend/src/method.rs @@ -206,17 +206,6 @@ impl<'a> FnSpec<'a> { false } - pub fn accept_args(&self) -> bool { - for s in self.attrs.iter() { - match *s { - Argument::VarArgs(_) => return true, - Argument::VarArgsSeparator => return true, - _ => (), - } - } - false - } - pub fn is_kwargs(&self, name: &syn::Ident) -> bool { for s in self.attrs.iter() { if let Argument::KeywordArgs(ref path) = s { @@ -226,15 +215,6 @@ impl<'a> FnSpec<'a> { false } - pub fn accept_kwargs(&self) -> bool { - for s in self.attrs.iter() { - if let Argument::KeywordArgs(_) = s { - return true; - } - } - false - } - pub fn default_value(&self, name: &syn::Ident) -> Option { for s in self.attrs.iter() { match *s { diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs index 7149d9c7a27..d590d2b2752 100644 --- a/pyo3-derive-backend/src/pymethod.rs +++ b/pyo3-derive-backend/src/pymethod.rs @@ -406,15 +406,6 @@ fn impl_call(_cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream { quote! { _slf.#fname(#(#names),*) } } -/// Converts a bool to "true" or "false" -fn bool_to_ident(condition: bool) -> syn::Ident { - if condition { - syn::Ident::new("true", Span::call_site()) - } else { - syn::Ident::new("false", Span::call_site()) - } -} - fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStream) -> TokenStream { if spec.args.is_empty() { return quote! { @@ -431,8 +422,8 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre continue; } let name = arg.name; - let kwonly = bool_to_ident(spec.is_kw_only(&arg.name)); - let opt = bool_to_ident(arg.optional.is_some() || spec.default_value(&arg.name).is_some()); + let kwonly = spec.is_kw_only(&arg.name); + let opt = arg.optional.is_some() || spec.default_value(&arg.name).is_some(); params.push(quote! { pyo3::derive_utils::ParamDescription { @@ -449,8 +440,16 @@ fn impl_arg_params_(spec: &FnSpec<'_>, body: TokenStream, into_result: TokenStre param_conversion.push(impl_arg_param(&arg, &spec, idx, &mut option_pos)); } - let accept_args = bool_to_ident(spec.accept_args()); - let accept_kwargs = bool_to_ident(spec.accept_kwargs()); + let (mut accept_args, mut accept_kwargs) = (false, false); + + for s in spec.attrs.iter() { + use crate::pyfunction::Argument; + match s { + Argument::VarArgs(_) => accept_args = true, + Argument::KeywordArgs(_) => accept_kwargs = true, + _ => continue, + } + } let num_normal_params = params.len(); // create array of arguments, and then parse quote! { diff --git a/src/derive_utils.rs b/src/derive_utils.rs index baa134f6e8a..019b49c5df9 100644 --- a/src/derive_utils.rs +++ b/src/derive_utils.rs @@ -61,7 +61,7 @@ pub fn parse_fn_args<'p>( if i < nargs { raise_error!("got multiple values for argument: {}", p.name) } - kwargs.as_ref().unwrap().del_item(p.name).unwrap(); + kwargs.as_ref().unwrap().del_item(p.name)?; Some(kwarg) } None => { diff --git a/tests/test_methods.rs b/tests/test_methods.rs index e1b2546b66b..35906d8183f 100644 --- a/tests/test_methods.rs +++ b/tests/test_methods.rs @@ -231,11 +231,15 @@ impl MethArgs { [a.to_object(py), args.into(), kwargs.to_object(py)].to_object(py) } + #[args("*", c = 10)] + fn get_pos_arg_kw_sep(&self, a: i32, b: i32, c: i32) -> PyResult { + Ok(a + b + c) + } + #[args(kwargs = "**")] fn get_pos_kw(&self, py: Python, a: i32, kwargs: Option<&PyDict>) -> PyObject { [a.to_object(py), kwargs.to_object(py)].to_object(py) } - // "args" can be anything that can be extracted from PyTuple #[args(args = "*")] fn args_as_vec(&self, args: Vec) -> i32 { @@ -264,7 +268,7 @@ fn meth_args() { py_run!(py, inst, "assert inst.get_default() == 10"); py_run!(py, inst, "assert inst.get_default(100) == 100"); py_run!(py, inst, "assert inst.get_kwarg() == 10"); - py_run!(py, inst, "assert inst.get_kwarg(100) == 10"); + py_expect_exception!(py, inst, "inst.get_kwarg(100)", TypeError); py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); @@ -295,6 +299,16 @@ fn meth_args() { py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", TypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", TypeError); + py_run!(py, inst, "assert inst.get_pos_arg_kw_sep(1, 2, c=3) == 6"); + py_run!(py, inst, "assert inst.get_pos_arg_kw_sep(1, 2) == 13"); + py_expect_exception!(py, inst, "assert inst.get_pos_arg_kw_sep(1)", TypeError); + py_expect_exception!( + py, + inst, + "assert inst.get_pos_arg_kw_sep(1, 2, 3)", + TypeError + ); + py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", TypeError);