Refactor derive_utils

This commit is contained in:
kngwyu 2019-05-25 21:52:53 +09:00
parent ab802cd829
commit a4cf09f16a
1 changed files with 25 additions and 40 deletions

View File

@ -45,78 +45,63 @@ pub fn parse_fn_args<'p>(
) -> PyResult<()> { ) -> PyResult<()> {
let nargs = args.len(); let nargs = args.len();
let mut used_args = 0; let mut used_args = 0;
macro_rules! raise_error {
($s: expr $(,$arg:expr)*) => (return Err(TypeError::py_err(format!(
concat!("{} ", $s), fname.unwrap_or("function") $(,$arg)*
))))
}
// Iterate through the parameters and assign values to output: // Iterate through the parameters and assign values to output:
for (i, (p, out)) in params.iter().zip(output).enumerate() { for (i, (p, out)) in params.iter().zip(output).enumerate() {
match kwargs.and_then(|d| d.get_item(p.name)) { *out = match kwargs.and_then(|d| d.get_item(p.name)) {
Some(kwarg) => { Some(kwarg) => {
*out = Some(kwarg);
if i < nargs { if i < nargs {
return Err(TypeError::py_err(format!( raise_error!("got multiple values for argument: {}", p.name)
"{} got multiple values for argument '{}'",
fname.unwrap_or("function"),
p.name
)));
} }
kwargs.as_ref().unwrap().del_item(p.name).unwrap(); kwargs.as_ref().unwrap().del_item(p.name).unwrap();
Some(kwarg)
} }
None => { None => {
if p.kw_only { if p.kw_only {
if !p.is_optional { if !p.is_optional {
return Err(TypeError::py_err(format!( raise_error!("missing required keyword-only argument: {}", p.name)
"{} missing required keyword-only argument '{}'",
fname.unwrap_or("function"),
p.name
)));
} }
*out = None; None
} else if i < nargs { } else if i < nargs {
*out = Some(args.get_item(i));
used_args += 1; used_args += 1;
Some(args.get_item(i))
} else { } else {
*out = None;
if !p.is_optional { if !p.is_optional {
return Err(TypeError::py_err(format!( raise_error!("missing required positional argument: {}", p.name)
"{} missing required positional argument: '{}'",
fname.unwrap_or("function"),
p.name
)));
} }
None
} }
} }
} }
} }
// check for extraneous keyword arguments let is_kwargs_empty = kwargs.as_ref().map_or(true, |dict| dict.is_empty());
if !accept_kwargs && !kwargs.as_ref().map_or(true, |d| d.is_empty()) { // Raise an error when we get an unknown key
for (key, _) in kwargs.unwrap().iter() { if !accept_kwargs && !is_kwargs_empty {
// raise an error with any of the keys let (key, _) = kwargs.unwrap().iter().next().unwrap();
return Err(TypeError::py_err(format!( raise_error!("got an unexpected keyword argument: {}", key)
"{} got an unexpected keyword argument '{}'",
fname.unwrap_or("function"),
key
)));
}
} }
// check for extraneous positional arguments // Raise an error when we get too many positional args
if !accept_args && used_args < nargs { if !accept_args && used_args < nargs {
return Err(TypeError::py_err(format!( raise_error!(
"{} takes at most {} positional argument{} ({} given)", "takes at most {} positional argument{} ({} given)",
fname.unwrap_or("function"),
used_args, used_args,
if used_args == 1 { "" } else { "s" }, if used_args == 1 { "" } else { "s" },
nargs nargs
))); )
} }
// adjust the remaining args // Adjust the remaining args
if accept_args { if accept_args {
let slice = args let slice = args
.slice(used_args as isize, nargs as isize) .slice(used_args as isize, nargs as isize)
.into_object(py); .into_object(py);
*args = py.checked_cast_as(slice).unwrap(); *args = py.checked_cast_as(slice).unwrap();
} }
if accept_kwargs { if accept_kwargs && is_kwargs_empty {
if kwargs.map_or(false, |d| d.is_empty()) { *kwargs = None;
*kwargs = None;
}
} }
Ok(()) Ok(())
} }