mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Make 'x in y' and 'x not in y' (PySequence_Contains) play nice w/ iterators.
NEEDS DOC CHANGES A few more AttributeErrors turned into TypeErrors, but in test_contains this time. The full story for instance objects is pretty much unexplainable, because instance_contains() tries its own flavor of iteration-based containment testing first, and PySequence_Contains doesn't get a chance at it unless instance_contains() blows up. A consequence is that some_complex_number in some_instance dies with a TypeError unless some_instance.__class__ defines __iter__ but does not define __getitem__.
This commit is contained in:
parent
2cfe368283
commit
de9725f135
5 changed files with 93 additions and 32 deletions
|
@ -472,4 +472,59 @@ class TestCase(unittest.TestCase):
|
|||
except OSError:
|
||||
pass
|
||||
|
||||
# Test iterators with 'x in y' and 'x not in y'.
|
||||
def test_in_and_not_in(self):
|
||||
sc5 = IteratingSequenceClass(5)
|
||||
for i in range(5):
|
||||
self.assert_(i in sc5)
|
||||
# CAUTION: This test fails on 3-12j if sc5 is SequenceClass(5)
|
||||
# instead, with:
|
||||
# TypeError: cannot compare complex numbers using <, <=, >, >=
|
||||
# The trail leads back to instance_contains() in classobject.c,
|
||||
# under comment:
|
||||
# /* fall back to previous behavior */
|
||||
# IteratingSequenceClass(5) avoids the same problem only because
|
||||
# it lacks __getitem__: instance_contains *tries* to do a wrong
|
||||
# thing with it too, but aborts with an AttributeError the first
|
||||
# time it calls instance_item(); PySequence_Contains() then catches
|
||||
# that and clears it, and tries the iterator-based "contains"
|
||||
# instead. But this is hanging together by a thread.
|
||||
for i in "abc", -1, 5, 42.42, (3, 4), [], {1: 1}, 3-12j, sc5:
|
||||
self.assert_(i not in sc5)
|
||||
del sc5
|
||||
|
||||
self.assertRaises(TypeError, lambda: 3 in 12)
|
||||
self.assertRaises(TypeError, lambda: 3 not in map)
|
||||
|
||||
d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
|
||||
for k in d:
|
||||
self.assert_(k in d)
|
||||
self.assert_(k not in d.itervalues())
|
||||
for v in d.values():
|
||||
self.assert_(v in d.itervalues())
|
||||
self.assert_(v not in d)
|
||||
for k, v in d.iteritems():
|
||||
self.assert_((k, v) in d.iteritems())
|
||||
self.assert_((v, k) not in d.iteritems())
|
||||
del d
|
||||
|
||||
f = open(TESTFN, "w")
|
||||
try:
|
||||
f.write("a\n" "b\n" "c\n")
|
||||
finally:
|
||||
f.close()
|
||||
f = open(TESTFN, "r")
|
||||
try:
|
||||
for chunk in "abc":
|
||||
f.seek(0, 0)
|
||||
self.assert_(chunk not in f)
|
||||
f.seek(0, 0)
|
||||
self.assert_((chunk + "\n") in f)
|
||||
finally:
|
||||
f.close()
|
||||
try:
|
||||
unlink(TESTFN)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
run_unittest(TestCase)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue