Update test_{binop,contains}.py from 3.14.3#7038
Conversation
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (2)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including You can disable this status message by setting the
📝 WalkthroughWalkthroughUpdates the error message produced when PyIter attempts to iterate over non-iterable objects, broadening the terminology from "'object' is not iterable" to "argument of type ... is not a container or iterable". Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@crates/vm/src/protocol/iter.rs`:
- Around line 142-145: The new error text in PyIter::try_from_object changed the
message emitted via vm.new_type_error(format!(... iter_target.class().name()))
and breaks CPython 3.14 compatibility for iter()/for; update try_from_object to
emit "'{}' object is not iterable" (using iter_target.class().name()) when the
iterator protocol path fails (the path used by iter() and for loops) and only
use "argument of type '{}' is not a container or iterable" for the
sequence/fallback path (or vice versa depending on which branch failed); you can
implement this by distinguishing the iterator-protocol failure vs.
sequence-protocol failure inside PyIter::try_from_object (or by adding a small
enum/flag param to the helper that constructs the error) and call
vm.new_type_error with the appropriate message in each branch.
| Err(vm.new_type_error(format!( | ||
| "'{}' object is not iterable", | ||
| "argument of type '{}' is not a container or iterable", | ||
| iter_target.class().name() | ||
| ))) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check where PyIter is used and how error messages are handled
echo "=== File structure around the changed line ==="
head -160 crates/vm/src/protocol/iter.rs | tail -30
echo ""
echo "=== Search for PyIter TryFromObject impl ==="
rg -A 20 'impl.*TryFromObject.*PyIter' crates/vm/src/protocol/iter.rs
echo ""
echo "=== Search for iter() builtin or for loop iteration ==="
rg -n 'pub.*iter' crates/vm/src/builtin*.rs 2>/dev/null | head -20
echo ""
echo "=== Search for contains/in operator implementation ==="
rg -n -B2 -A5 'def __contains__\|_contains\|sq_contains' crates/vm/src/ | head -50Repository: RustPython/RustPython
Length of output: 2309
🏁 Script executed:
#!/bin/bash
# Check how the in operator uses iteration in RustPython
echo "=== Search for 'in' operator / contains implementation ==="
rg -n 'BinaryOp.*In\|Op::In' crates/vm/src/ | head -20
echo ""
echo "=== Search for PySequence_Contains references ==="
rg -n 'PySequence_Contains\|sequence_contains' crates/vm/src/
echo ""
echo "=== Check the actual error message in the changed file ==="
sed -n '140,150p' crates/vm/src/protocol/iter.rsRepository: RustPython/RustPython
Length of output: 528
🌐 Web query:
CPython 3.14 TypeError error messages for iter() and in operator argument of type
💡 Result:
In CPython 3.14, the membership operator (in / not in) now uses a different TypeError message when the right-hand side can’t be treated as either a container or an iterable:
-
x in y/x not in y(andyisn’t a container or iterable)
Old (≤3.13):TypeError: argument of type 'T' is not iterable
New (3.14):TypeError: argument of type 'T' is not a container or iterable(this comes from thePY_ITERSEARCH_CONTAINSpath in_PySequence_IterSearch) [1].
This change is visible in downstream breakages that were matching the old message (e.g., pandas build logs on Python 3.14) [2]. -
iter(y)(andyisn’t iterable)
Still raises aTypeErrorwhose message matchesis not iterable(commonly"'T' object is not iterable"), i.e., it did not gain the “container” wording [3].
Practical tip for tests: if you need to match both behaviors across versions/contexts, allow both phrasings (e.g. regex like r"is not (a container or )?iterable"). [2][3]
Sources:
[1] CPython 3.14 Objects/abstract.c (_PySequence_IterSearch special-cases PY_ITERSEARCH_CONTAINS to raise “not a container or iterable”) [1]
[2] Debian build failure log showing the new runtime message “argument of type 'bool' is not a container or iterable” vs expected “not iterable” [2]
[3] CPython check-in discussion/tests asserting iter(obj) matches “is not iterable”, while obj in obj matches “is not a container or iterable” [3]
Error message change breaks iter() and for loop compatibility with CPython 3.14.
The PyIter::try_from_object implementation (documented as serving both for loops and the iter() builtin) now uses the error message "argument of type '{}' is not a container or iterable". In CPython 3.14, this message is used exclusively by the in operator fallback path (_PySequence_IterSearch), while iter() and for loops still use "'{}' object is not iterable".
Changing this shared code path's error message to match the in operator breaks compatibility:
iter(5)will now incorrectly say"argument of type 'int' is not a container or iterable"instead of CPython 3.14's"'int' object is not iterable"for x in 5will have the same incorrect message
If the in operator uses this same code path as a fallback, its message is now correct. However, iter() and for loops use this path as their primary error path and should retain the original message. Consider separating the error message based on which protocol path failed (iterator protocol vs. sequence protocol), or verify whether the in operator has a separate implementation that should be updated instead.
🤖 Prompt for AI Agents
In `@crates/vm/src/protocol/iter.rs` around lines 142 - 145, The new error text in
PyIter::try_from_object changed the message emitted via
vm.new_type_error(format!(... iter_target.class().name())) and breaks CPython
3.14 compatibility for iter()/for; update try_from_object to emit "'{}' object
is not iterable" (using iter_target.class().name()) when the iterator protocol
path fails (the path used by iter() and for loops) and only use "argument of
type '{}' is not a container or iterable" for the sequence/fallback path (or
vice versa depending on which branch failed); you can implement this by
distinguishing the iterator-protocol failure vs. sequence-protocol failure
inside PyIter::try_from_object (or by adding a small enum/flag param to the
helper that constructs the error) and call vm.new_type_error with the
appropriate message in each branch.
847c3ac to
c49f608
Compare
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_binop.py dependencies: dependent tests: (no tests depend on binop) [x] test: cpython/Lib/test/test_contains.py (TODO: 1) dependencies: dependent tests: (no tests depend on contains) Legend:
|
Summary by CodeRabbit