Fix the interpretation of '*'

This commit is contained in:
kngwyu 2020-03-04 23:44:40 +09:00
parent 96115eaaaa
commit 25069baef4
5 changed files with 30 additions and 36 deletions

View File

@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745)
* Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760)
* `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769)
* Interpretation of `*`. #[792](https://github.com/PyO3/pyo3/pull/792)
### Removed

View File

@ -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<TokenStream> {
for s in self.attrs.iter() {
match *s {

View File

@ -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! {

View File

@ -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 => {

View File

@ -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<i32> {
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>) -> 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);