diff --git a/Lib/test/test_contains.py b/Lib/test/test_contains.py index 7339f16ac..259c954aa 100644 --- a/Lib/test/test_contains.py +++ b/Lib/test/test_contains.py @@ -16,7 +16,6 @@ class seq(base_set): return [self.el][n] class TestContains(unittest.TestCase): - @unittest.expectedFailure # TODO: RUSTPYTHON; Wrong error message def test_common_tests(self): a = base_set(1) b = myset(1) diff --git a/crates/vm/src/protocol/sequence.rs b/crates/vm/src/protocol/sequence.rs index cee46a290..b142e6300 100644 --- a/crates/vm/src/protocol/sequence.rs +++ b/crates/vm/src/protocol/sequence.rs @@ -1,5 +1,5 @@ use crate::{ - PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine, + AsObject, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine, builtins::{PyList, PyListRef, PySlice, PyTuple, PyTupleRef}, convert::ToPyObject, function::PyArithmeticValue, @@ -398,7 +398,19 @@ impl PySequence<'_> { return f(self, target, vm); } - let iter = self.obj.to_owned().get_iter(vm)?; + // CPython parity: when neither __contains__ nor __iter__ is available, + // `PySequence_Contains` rewords the get_iter TypeError into the + // membership-test wording. Other exception types propagate unchanged. + let iter = self.obj.to_owned().get_iter(vm).map_err(|e| { + if e.fast_isinstance(vm.ctx.exceptions.type_error) { + vm.new_type_error(format!( + "argument of type '{}' is not a container or iterable", + self.obj.class().name() + )) + } else { + e + } + })?; let iter = iter.iter::(vm)?; for elem in iter {