[cppyy] Only alias size() to __len__ for container-like classes#21905
Conversation
5815907 to
7a2ba49
Compare
guitargeek
left a comment
There was a problem hiding this comment.
Thank you very much for stepping up to fix this, that's very much appreciated!
My main request is to make the integer check a part of the backend library, and a few other small things.
|
@chrisburr, how far do you need this packported? We need to cut somewhere, since the problem existed forever. I also commited another fix related to this a few months ago, by the way: |
Test Results 22 files 22 suites 3d 1h 41m 39s ⏱️ For more details on these failures, see this check. Results for commit 18ad0e0. ♻️ This comment has been updated with latest results. |
7a2ba49 to
18ad0e0
Compare
I don't know much about the issue this caused so @sponce is probably better positioned to answer. |
bindings/pyroot/cppyy/cppyy-backend/clingwrapper/src/clingwrapper.cxx
Outdated
Show resolved
Hide resolved
|
No need to backport further that LCG108b, aka ROOT 6.36.08 for us |
Guard the automatic size() -> __len__ pythonization to require that size() returns an integer type and the class has begin()/end() methods or operator[]. This prevents bool() returning False for valid objects whose size() returns non-integer types like std::optional<std::size_t>. Use Cppyy::IsIntegerType (backed by Clang's QualType) to check the return type, which correctly resolves typedefs like size_type. Walk the MRO when checking for size/begin/end/getitem attributes, since HasAttrDirect only checks the class's own __dict__. Skip pythonization if size() has multiple overloads. Update tests for stl_like_class2/3 which have incomplete container interfaces (missing iterators or returning non-iterator types from begin/end).
18ad0e0 to
002caaf
Compare
guitargeek
left a comment
There was a problem hiding this comment.
Thank you very much for improving the heuristics for the size()-to-__len__ Pythonization and addressing the review comments!
|
Fix was backported to 6.36 and 6.38 |
Summary
If a C++ class has a
size()method that returns a non-integer type cppyy adds a__len__method but it always crashes. This can then affect the result of__bool__in unexpected ways.This PR fixes it by only pythonising
size()->__len__if the return type is valid and it also appears to be iterable (hasbegin()+end()oroperator[]).Feel free to close this if you think there is a better solution.
This Pull request:
This was triggered by this issue in LHCb and Gaudi:
I debugged this to find:
Changes or fixes:
Guard the automatic
size()->__len__pythonization to require thatsize()returns an integer type and the class has eitherbegin()/end()methods or acceptsoperator[]. This preventsbool()returningFalsefor valid objects whosesize()returns non-integer types likestd::optional<std::size_t>.Checklist: