mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +00:00
Show kwargs in failed method invocation
With the previous commit, output can be very confusing because you only see positional arguments in the "invoked with" line, but you can have a failure from kwargs as well (in particular, when a value is invalidly specified via both via positional and kwargs). This commits adds kwargs to the output, and updates the associated tests to match.
This commit is contained in:
parent
caa1379e92
commit
231e167854
@ -650,11 +650,26 @@ protected:
|
|||||||
}
|
}
|
||||||
msg += "\nInvoked with: ";
|
msg += "\nInvoked with: ";
|
||||||
auto args_ = reinterpret_borrow<tuple>(args_in);
|
auto args_ = reinterpret_borrow<tuple>(args_in);
|
||||||
|
bool some_args = false;
|
||||||
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
|
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
|
||||||
|
if (!some_args) some_args = true;
|
||||||
|
else msg += ", ";
|
||||||
msg += pybind11::repr(args_[ti]);
|
msg += pybind11::repr(args_[ti]);
|
||||||
if ((ti + 1) != args_.size() )
|
|
||||||
msg += ", ";
|
|
||||||
}
|
}
|
||||||
|
if (kwargs_in) {
|
||||||
|
auto kwargs = reinterpret_borrow<dict>(kwargs_in);
|
||||||
|
if (kwargs.size() > 0) {
|
||||||
|
if (some_args) msg += "; ";
|
||||||
|
msg += "kwargs: ";
|
||||||
|
bool first = true;
|
||||||
|
for (auto kwarg : kwargs) {
|
||||||
|
if (first) first = false;
|
||||||
|
else msg += ", ";
|
||||||
|
msg += pybind11::str("{}={!r}").format(kwarg.first, kwarg.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (!result) {
|
} else if (!result) {
|
||||||
|
@ -34,12 +34,8 @@ def test_named_arguments(msg):
|
|||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
# noinspection PyArgumentList
|
# noinspection PyArgumentList
|
||||||
kw_func2(x=5, y=10, z=12)
|
kw_func2(x=5, y=10, z=12)
|
||||||
assert msg(excinfo.value) == """
|
assert excinfo.match(
|
||||||
kw_func2(): incompatible function arguments. The following argument types are supported:
|
r'(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$)){3}$')
|
||||||
1. (x: int=100, y: int=200) -> str
|
|
||||||
|
|
||||||
Invoked with:
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert kw_func4() == "{13 17}"
|
assert kw_func4() == "{13 17}"
|
||||||
assert kw_func4(myList=[1, 2, 3]) == "{1 2 3}"
|
assert kw_func4(myList=[1, 2, 3]) == "{1 2 3}"
|
||||||
@ -74,7 +70,7 @@ def test_mixed_args_and_kwargs(msg):
|
|||||||
1. (arg0: int, arg1: float, *args) -> tuple
|
1. (arg0: int, arg1: float, *args) -> tuple
|
||||||
|
|
||||||
Invoked with: 1
|
Invoked with: 1
|
||||||
""" # noqa: E501
|
""" # noqa: E501 line too long
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
assert mpa()
|
assert mpa()
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
@ -82,7 +78,7 @@ def test_mixed_args_and_kwargs(msg):
|
|||||||
1. (arg0: int, arg1: float, *args) -> tuple
|
1. (arg0: int, arg1: float, *args) -> tuple
|
||||||
|
|
||||||
Invoked with:
|
Invoked with:
|
||||||
""" # noqa: E501
|
""" # noqa: E501 line too long
|
||||||
|
|
||||||
assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (-2, 3.5, {'e': 2.71828, 'pi': 3.14159})
|
assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (-2, 3.5, {'e': 2.71828, 'pi': 3.14159})
|
||||||
assert mpak(7, 7.7, 7.77, 7.777, 7.7777, minusseven=-7) == (
|
assert mpak(7, 7.7, 7.77, 7.777, 7.7777, minusseven=-7) == (
|
||||||
@ -93,14 +89,20 @@ def test_mixed_args_and_kwargs(msg):
|
|||||||
assert mpakd(k=42) == (1, 3.14159, (), {'k': 42})
|
assert mpakd(k=42) == (1, 3.14159, (), {'k': 42})
|
||||||
assert mpakd(1, 1, 2, 3, 5, 8, then=13, followedby=21) == (
|
assert mpakd(1, 1, 2, 3, 5, 8, then=13, followedby=21) == (
|
||||||
1, 1, (2, 3, 5, 8), {'then': 13, 'followedby': 21})
|
1, 1, (2, 3, 5, 8), {'then': 13, 'followedby': 21})
|
||||||
# Arguments specified both positionally and via kwargs is an error:
|
# Arguments specified both positionally and via kwargs should fail:
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
assert mpakd(1, i=1)
|
assert mpakd(1, i=1)
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
mixed_plus_args_kwargs_defaults(): got multiple values for argument 'i'
|
mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported:
|
||||||
"""
|
1. (i: int=1, j: float=3.14159, *args, **kwargs) -> tuple
|
||||||
|
|
||||||
|
Invoked with: 1; kwargs: i=1
|
||||||
|
""" # noqa: E501 line too long
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
assert mpakd(1, 2, j=1)
|
assert mpakd(1, 2, j=1)
|
||||||
assert msg(excinfo.value) == """
|
assert msg(excinfo.value) == """
|
||||||
mixed_plus_args_kwargs_defaults(): got multiple values for argument 'j'
|
mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported:
|
||||||
"""
|
1. (i: int=1, j: float=3.14159, *args, **kwargs) -> tuple
|
||||||
|
|
||||||
|
Invoked with: 1, 2; kwargs: j=1
|
||||||
|
""" # noqa: E501 line too long
|
||||||
|
Loading…
Reference in New Issue
Block a user