[Python-checkins] bpo-40824: Do not mask errors in __iter__ in "in" and the operator module. (GH-20537)

Serhiy Storchaka webhook-mailer at python.org
Mon Jun 22 03:43:40 EDT 2020


https://github.com/python/cpython/commit/cafe1b6e9d3594a34aba50e872d4198296ffaadf
commit: cafe1b6e9d3594a34aba50e872d4198296ffaadf
branch: master
author: Serhiy Storchaka <storchaka at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-06-22T10:43:35+03:00
summary:

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().

files:
A Misc/NEWS.d/next/Core and Builtins/2020-05-30-14-37-18.bpo-40824.XR3V5s.rst
M Lib/test/test_iter.py
M Lib/test/test_operator.py
M Objects/abstract.c

diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py
index 6aceda23e9bd8..524346939886d 100644
--- a/Lib/test/test_iter.py
+++ b/Lib/test/test_iter.py
@@ -76,6 +76,10 @@ def __getitem__(self, i):
         return i
     __iter__ = None
 
+class BadIterableClass:
+    def __iter__(self):
+        raise ZeroDivisionError
+
 # Main test suite
 
 class TestCase(unittest.TestCase):
@@ -658,6 +662,7 @@ def test_in_and_not_in(self):
 
         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:
@@ -740,6 +745,7 @@ def test_indexOf(self):
 
         self.assertRaises(TypeError, indexOf, 42, 1)
         self.assertRaises(TypeError, indexOf, indexOf, indexOf)
+        self.assertRaises(ZeroDivisionError, indexOf, BadIterableClass(), 1)
 
         f = open(TESTFN, "w")
         try:
@@ -1027,6 +1033,7 @@ def test_free_after_iterating(self):
     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 f46d94a226717..29f5e4275c55e 100644
--- a/Lib/test/test_operator.py
+++ b/Lib/test/test_operator.py
@@ -35,6 +35,10 @@ def __mul__(self, other):
     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 @@ def test_countOf(self):
         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 @@ def test_indexOf(self):
         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 @@ def test_contains(self):
         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 0000000000000..73c593c04a0da
--- /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 973c43fe7fda9..aac42c2898cdf 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2083,7 +2083,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;
     }
 



More information about the Python-checkins mailing list