summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2020-06-22 01:21:04 -0700
committerGitHub <noreply@github.com>2020-06-22 01:21:04 -0700
commitb99824a8e14d94c3c5c29499a08fe70deb477d0c (patch)
tree2071b90c828dccc80d65b6b280197d97b9162c9f
parentd5ee9b9940ba24120838b07061058afe931cfff1 (diff)
downloadcpython-git-b99824a8e14d94c3c5c29499a08fe70deb477d0c.tar.gz
bpo-40824: Do not mask errors in __iter__ in "in" and the operator module. (GH-20537)
Unexpected errors in calling the __iter__ method are no longer masked by TypeError in the "in" operator and functions operator.contains(), operator.indexOf() and operator.countOf(). (cherry picked from commit cafe1b6e9d3594a34aba50e872d4198296ffaadf) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Lib/test/test_iter.py7
-rw-r--r--Lib/test/test_operator.py7
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-05-30-14-37-18.bpo-40824.XR3V5s.rst4
-rw-r--r--Objects/abstract.c4
4 files changed, 21 insertions, 1 deletions
diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py
index 542b28419e..22553d5d28 100644
--- a/Lib/test/test_iter.py
+++ b/Lib/test/test_iter.py
@@ -62,6 +62,10 @@ class NoIterClass:
return i
__iter__ = None
+class BadIterableClass:
+ def __iter__(self):
+ raise ZeroDivisionError
+
# Main test suite
class TestCase(unittest.TestCase):
@@ -637,6 +641,7 @@ class TestCase(unittest.TestCase):
self.assertRaises(TypeError, lambda: 3 in 12)
self.assertRaises(TypeError, lambda: 3 not in map)
+ self.assertRaises(ZeroDivisionError, lambda: 3 in BadIterableClass())
d = {"one": 1, "two": 2, "three": 3, 1j: 2j}
for k in d:
@@ -719,6 +724,7 @@ class TestCase(unittest.TestCase):
self.assertRaises(TypeError, indexOf, 42, 1)
self.assertRaises(TypeError, indexOf, indexOf, indexOf)
+ self.assertRaises(ZeroDivisionError, indexOf, BadIterableClass(), 1)
f = open(TESTFN, "w")
try:
@@ -1006,6 +1012,7 @@ class TestCase(unittest.TestCase):
def test_error_iter(self):
for typ in (DefaultIterClass, NoIterClass):
self.assertRaises(TypeError, iter, typ())
+ self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
def test_main():
diff --git a/Lib/test/test_operator.py b/Lib/test/test_operator.py
index f46d94a226..29f5e4275c 100644
--- a/Lib/test/test_operator.py
+++ b/Lib/test/test_operator.py
@@ -35,6 +35,10 @@ class Seq2(object):
def __rmul__(self, other):
return other * self.lst
+class BadIterable:
+ def __iter__(self):
+ raise ZeroDivisionError
+
class OperatorTestCase:
def test_lt(self):
@@ -142,6 +146,7 @@ class OperatorTestCase:
operator = self.module
self.assertRaises(TypeError, operator.countOf)
self.assertRaises(TypeError, operator.countOf, None, None)
+ self.assertRaises(ZeroDivisionError, operator.countOf, BadIterable(), 1)
self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 3), 1)
self.assertEqual(operator.countOf([1, 2, 1, 3, 1, 4], 5), 0)
@@ -176,6 +181,7 @@ class OperatorTestCase:
operator = self.module
self.assertRaises(TypeError, operator.indexOf)
self.assertRaises(TypeError, operator.indexOf, None, None)
+ self.assertRaises(ZeroDivisionError, operator.indexOf, BadIterable(), 1)
self.assertEqual(operator.indexOf([4, 3, 2, 1], 3), 1)
self.assertRaises(ValueError, operator.indexOf, [4, 3, 2, 1], 0)
@@ -258,6 +264,7 @@ class OperatorTestCase:
operator = self.module
self.assertRaises(TypeError, operator.contains)
self.assertRaises(TypeError, operator.contains, None, None)
+ self.assertRaises(ZeroDivisionError, operator.contains, BadIterable(), 1)
self.assertTrue(operator.contains(range(4), 2))
self.assertFalse(operator.contains(range(4), 5))
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-05-30-14-37-18.bpo-40824.XR3V5s.rst b/Misc/NEWS.d/next/Core and Builtins/2020-05-30-14-37-18.bpo-40824.XR3V5s.rst
new file mode 100644
index 0000000000..73c593c04a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-05-30-14-37-18.bpo-40824.XR3V5s.rst
@@ -0,0 +1,4 @@
+Unexpected errors in calling the ``__iter__`` method are no longer masked by
+``TypeError`` in the :keyword:`in` operator and functions
+:func:`~operator.contains`, :func:`~operator.indexOf` and
+:func:`~operator.countOf` of the :mod:`operator` module.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 4fabfd762f..12237d570f 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1999,7 +1999,9 @@ _PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
it = PyObject_GetIter(seq);
if (it == NULL) {
- type_error("argument of type '%.200s' is not iterable", seq);
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+ type_error("argument of type '%.200s' is not iterable", seq);
+ }
return -1;
}