Skip to content

Update test_{binop,contains}.py from 3.14.3#7038

Merged
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:update-test-0
Feb 8, 2026
Merged

Update test_{binop,contains}.py from 3.14.3#7038
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:update-test-0

Conversation

@ShaharNaveh
Copy link
Contributor

@ShaharNaveh ShaharNaveh commented Feb 7, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error messages when attempting to iterate over non-iterable objects to provide clearer feedback on what types of values can be iterated.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 7, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • Lib/test/test_binop.py is excluded by !Lib/**
  • Lib/test/test_contains.py is excluded by !Lib/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

Updates 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

Cohort / File(s) Summary
Iterator Error Message
crates/vm/src/protocol/iter.rs
Updated TypeError message text to reflect broader semantics, now mentioning both container and iterable types.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Suggested reviewers

  • youknowone

Poem

🐰 When iter paths don't quite align,
A message now more crisp and fine,
"Not a container—that's the sign!"
We hop through errors, more divine,
✨ Truth in every error line!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions updating test files from version 3.14.3, but the actual changes are to error messages in iter.rs, which is unrelated to test file updates. Update the title to accurately reflect the actual changes, such as 'Update PyIter error message for non-iterable objects' or similar.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 142 to 145
Err(vm.new_type_error(format!(
"'{}' object is not iterable",
"argument of type '{}' is not a container or iterable",
iter_target.class().name()
)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 -50

Repository: 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.rs

Repository: 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 (and y isn’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 the PY_ITERSEARCH_CONTAINS path 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) (and y isn’t iterable)
    Still raises a TypeError whose message matches is 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 5 will 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.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

📦 Library Dependencies

The 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:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@youknowone youknowone merged commit bbe5412 into RustPython:main Feb 8, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants