-
Notifications
You must be signed in to change notification settings - Fork 1.4k
raise TypeError when __iter__ method is None
#7092
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
base: main
Are you sure you want to change the base?
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 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.
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/types/slot.rs`:
- Around line 548-551: Replace the AttributeError raised when __iter__ is
missing with a TypeError: in the block that calls vm.get_special_method(&zelf,
identifier!(vm, __iter__)), change the ok_or_else(...) from
vm.new_attribute_error(...) to vm.new_type_error(...) and construct the message
as "'<ClassName>' object is not iterable" using the object's class name (e.g.,
format!("'{}' object is not iterable", zelf.class().name())). Keep the existing
method_is_none() TypeError behavior unchanged.
🧹 Nitpick comments (2)
crates/vm/src/types/slot.rs (2)
545-551: Decorative comment separators violate coding guidelines.Lines 545–547 and 553–556 use blank
//lines as section separators. As per coding guidelines, "Do not add decorative section separators (e.g.// -----------,// ===,/* *** */). Use///doc-comments or short//comments only when they add value."Proposed fix: collapse to single-line comments
- // - // look-up '__iter__' method - // + // Look up __iter__ method let method_ident = identifier!(vm, __iter__); let method = vm .get_special_method(&zelf, method_ident)? .ok_or_else(|| vm.new_attribute_error(method_ident.as_str().to_owned()))?; - // - // setting '__iter__' method to 'None' value is used - // to mark non-iterable objects, raise TypeError - // + // __iter__ = None marks non-iterable objects if method_is_none(&method, vm) {
537-562: Consider consistency with__hash__ = Nonehandling.The
__hash__ = Nonecase (lines 758–783) is handled at slot-update time by storinghash_not_implementedas the slot function. The__iter__ = Nonecase is handled at call time inside the wrapper. Both approaches work, but the inconsistency may confuse future maintainers. If there's no strong reason to differ, consider aligning the pattern (e.g., storing a dedicatediter_not_implementedfunction during slot update, similar tohash_not_implemented).That said, CPython's
slot_tp_iteralso checks at call time, so the current approach is arguably more faithful to CPython.
| let method_ident = identifier!(vm, __iter__); | ||
| let method = vm | ||
| .get_special_method(&zelf, method_ident)? | ||
| .ok_or_else(|| vm.new_attribute_error(method_ident.as_str().to_owned()))?; |
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify what error CPython raises when __iter__ is dynamically deleted after being set
# Also check how get_special_method works and what it returns for None vs missing
echo "=== Check get_special_method implementation ==="
ast-grep --pattern 'fn get_special_method($$$) {
$$$
}'
echo ""
echo "=== Look for get_special_method definition ==="
rg -n 'fn get_special_method' crates/vm/src/ -A 20 | head -50Repository: RustPython/RustPython
Length of output: 1467
🏁 Script executed:
#!/bin/bash
echo "=== Check iter_wrapper and surrounding context in slot.rs ==="
rg -n 'iter_wrapper\|__iter__' crates/vm/src/types/slot.rs -B 5 -A 10Repository: RustPython/RustPython
Length of output: 126
🏁 Script executed:
#!/bin/bash
echo "=== Check how other slot wrappers handle missing methods ==="
rg -n 'new_attribute_error|new_type_error' crates/vm/src/types/slot.rs -B 3 -A 1 | head -100Repository: RustPython/RustPython
Length of output: 4724
🏁 Script executed:
#!/bin/bash
echo "=== Check if there are references to 'not iterable' error messages ==="
rg -n 'not iterable' crates/vm/src/ -B 2 -A 2Repository: RustPython/RustPython
Length of output: 1234
🏁 Script executed:
#!/bin/bash
echo "=== Check get_special_method behavior in the codebase ==="
rg -n 'get_special_method.*ok_or' crates/vm/src/ -B 3 -A 3 | head -60Repository: RustPython/RustPython
Length of output: 122
Change error type from AttributeError to TypeError when __iter__ is missing.
The code at line 551 currently raises AttributeError when get_special_method returns None (i.e., when __iter__ is not found). This is inconsistent with CPython, which raises TypeError: '<ClassName>' object is not iterable. This error type also aligns with how other slot wrappers in the codebase handle missing methods—len_wrapper, repr_wrapper, str_wrapper, and others all use new_type_error() for similar cases.
The method_is_none() check at line 557 handles the case where __iter__ exists but returns None, which should also raise the same TypeError (already correct).
Proposed fix
let method_ident = identifier!(vm, __iter__);
let method = vm
.get_special_method(&zelf, method_ident)?
- .ok_or_else(|| vm.new_attribute_error(method_ident.as_str().to_owned()))?;
+ .ok_or_else(|| vm.new_type_error(format!("'{}' object is not iterable", zelf.class().name())))?;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let method_ident = identifier!(vm, __iter__); | |
| let method = vm | |
| .get_special_method(&zelf, method_ident)? | |
| .ok_or_else(|| vm.new_attribute_error(method_ident.as_str().to_owned()))?; | |
| let method_ident = identifier!(vm, __iter__); | |
| let method = vm | |
| .get_special_method(&zelf, method_ident)? | |
| .ok_or_else(|| vm.new_type_error(format!("'{}' object is not iterable", zelf.class().name())))?; |
🤖 Prompt for AI Agents
In `@crates/vm/src/types/slot.rs` around lines 548 - 551, Replace the
AttributeError raised when __iter__ is missing with a TypeError: in the block
that calls vm.get_special_method(&zelf, identifier!(vm, __iter__)), change the
ok_or_else(...) from vm.new_attribute_error(...) to vm.new_type_error(...) and
construct the message as "'<ClassName>' object is not iterable" using the
object's class name (e.g., format!("'{}' object is not iterable",
zelf.class().name())). Keep the existing method_is_none() TypeError behavior
unchanged.
|
Thanks for the PR! |
|
yup: rust-lang/miri#4855 |
Thanks for investigating! |
|
@elmjag please merge main, it should pass now |
I'll look into using this approach for |
Setting special `__iter__` method to `None` is used to mark objects as non-iterable. https://docs.python.org/3/reference/datamodel.html#special-method-names Check if `__iter__` is set to `None` and raise TypeError exception.
e131b7c to
bdcc047
Compare
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] lib: cpython/Lib/typing.py dependencies:
dependent tests: (12 tests)
Legend:
|
Setting special
__iter__method toNoneis used to mark objects as non-iterable.https://docs.python.org/3/reference/datamodel.html#special-method-names
Check if
__iter__is set toNoneand raise TypeError exception.Summary by CodeRabbit