Skip to content

Match CPython's "argument of type ... is not a container or iterable" wording#7714

Merged
youknowone merged 1 commit intoRustPython:mainfrom
changjoon-park:fix-contains-error-message
Apr 29, 2026
Merged

Match CPython's "argument of type ... is not a container or iterable" wording#7714
youknowone merged 1 commit intoRustPython:mainfrom
changjoon-park:fix-contains-error-message

Conversation

@changjoon-park
Copy link
Copy Markdown
Contributor

@changjoon-park changjoon-park commented Apr 28, 2026

Background

CPython's PySequence_Contains (Objects/abstract.c::_PySequence_IterSearch) catches the TypeError from PyObject_GetIter when neither __contains__ nor __iter__ is available, and re-raises with membership-test wording:

TypeError: argument of type 'X' is not a container or iterable

RustPython's PySequence::contains propagated the get_iter error verbatim, so 1 in obj produced 'X' object is not iterable — a literal but less specific message.

Repro

class X: pass
1 in X()
# CPython 3.14:    TypeError: argument of type 'X' is not a container or iterable
# RustPython:      TypeError: 'X' object is not iterable    (before this PR)

Fix

Wrap the get_iter(vm) call inside PySequence::contains in map_err. When the failure is a TypeError (the "not iterable" case), re-raise with the byte-identical CPython membership-test wording. Other exception types (e.g. propagated from a user __iter__) pass through unchanged.

Tests unmasked

  • test_contains.TestContains.test_common_tests

Verification

  • CPython 3.14.4 byte-identical for the bare-class case
  • Types with __contains__ (str/tuple/dict/set/list/...): unchanged — they go through the slots().contains path before reaching this site
  • Types with only __iter__: unchanged — get_iter succeeds
  • No regressions across 8 modules (~1,349 tests): test_contains, test_iter, test_dict, test_set, test_list, test_tuple, test_str, test_bytes

Summary by CodeRabbit

Bug Fixes

  • Improved error messages for membership testing: TypeError messages when testing membership on non-container or non-iterable objects now align with CPython's standard wording for better consistency.

… wording

CPython's PySequence_Contains (Objects/abstract.c::_PySequence_IterSearch)
catches the TypeError from PyObject_GetIter when neither __contains__ nor
__iter__ is available, and re-raises with membership-test wording.

RustPython's PySequence::contains propagated the get_iter error verbatim,
so '1 in obj' produced 'X' object is not iterable — a literal but less
specific message.

Wrap the get_iter call in map_err: when the failure is a TypeError,
re-raise with byte-identical CPython wording. Other exception types pass
through unchanged.

Unmasks test_contains.TestContains.test_common_tests.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 769ad4e3-40bb-4141-91f7-262854b6d9f6

📥 Commits

Reviewing files that changed from the base of the PR and between 3f718f9 and aab298f.

⛔ Files ignored due to path filters (1)
  • Lib/test/test_contains.py is excluded by !Lib/**
📒 Files selected for processing (1)
  • crates/vm/src/protocol/sequence.rs

📝 Walkthrough

Walkthrough

PySequence::contains method now intercepts TypeError exceptions from get_iter(vm) and rewrites them to match CPython's membership-test error message. Other exception types are propagated unchanged. The module imports AsObject from the crate.

Changes

Cohort / File(s) Summary
Error Message Standardization
crates/vm/src/protocol/sequence.rs
Updated PySequence::contains to intercept and rewrite TypeError from get_iter(vm) to match CPython's membership-test error wording ("not a container or iterable"). Added AsObject import from crate.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • youknowone
  • ShaharNaveh

Poem

🐰 A tiny fix, so clean and bright,
Where error messages now align just right—
CPython's words now echo here,
In containers and iterables, crystal clear! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: matching CPython's error message wording for membership tests. It accurately reflects the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions
Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] test: cpython/Lib/test/test_contains.py

dependencies:

dependent tests: (no tests depend on contains)

Legend:

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

Copy link
Copy Markdown
Contributor

@ShaharNaveh ShaharNaveh left a comment

Choose a reason for hiding this comment

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

great! tysm:)

@changjoon-park
Copy link
Copy Markdown
Contributor Author

great! tysm:)

thanks for the review !

@youknowone youknowone merged commit 04ffa38 into RustPython:main Apr 29, 2026
21 of 22 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.

3 participants