-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Print key in KeyError in map.__getitem__/__delitem__ #5397
Conversation
Looks useful, thanks. Could you please add tests? (Please tag me when it's ready for review with tests.) |
@rwgk Tests added, ready for review. |
include/pybind11/stl_bind.h
Outdated
@@ -785,7 +785,7 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args && | |||
[](Map &m, const KeyType &k) -> MappedType & { | |||
auto it = m.find(k); | |||
if (it == m.end()) { | |||
throw key_error(); | |||
throw key_error(str(cast(k)).cast<std::string>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this more closely, there are a bunch of things that can go wrong:
cast(k)
may fail,str(...)
may fail,.cast<std::string>()
may fail.
Any of those failures will be a secondary error, masking the desired KeyError
. This can be extremely confusing.
Making this robust is not easy.
What's needed is something like (untested; only to give the idea):
str key_as_str;
try {
key_as_str = str(cast(k));
}
catch (const std::exception&) {
throw key_error();
}
set_error(PyExc_KeyError, key_as_tr);
throw error_already_set();
This would be implemented in a helper function.
Another thought: if str() fails, try repr().
Oh, there should also be a size limit. I.e. you don't want to produce a 1M numpy array as a str.
Sorry to make this difficult, but these things sure will bite, someone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rwgk PTAL. I added a test for long keys. I don't know what kind of object would fail in str of cast - happy to add a test if you have a suggestion. What is the benefit of set_error + throw error_already_set()
over throw key_error()
?
I added commit ef17743 to reduce the amount of templated code. Waiting for GitHub Actions to finish. |
LGTM, thank you! |
Also rename variable to `cut_length`, to not get into even/odd issues with the meaning of "half".
Description
When a C++ container is bound by
bind_map
and one accesses or deletes an element that does not exist, pybind11 currently raises an empty, uninformative message:KeyError: ''
. This PR prints the key, which is the behavior of Python'sdict
.Suggested changelog entry: