https://github.com/python/cpython/commit/132bdf6990003df61d30c379a12c041010d00245
commit: 132bdf6990003df61d30c379a12c041010d00245
branch: 3.13
author: Mark Shannon <m...@hotpy.org>
committer: markshannon <m...@hotpy.org>
date: 2025-04-29T09:35:29+01:00
summary:

[3.13] GH-127682: Backport GH-132351 (GH-132384)

Only call `__iter__` once in generator expressions

files:
A Misc/NEWS.d/next/Core and 
Builtins/2025-04-10-10-29-45.gh-issue-127682.X0HoGz.rst
M Lib/test/test_dis.py
M Lib/test/test_generators.py
M Lib/test/test_genexps.py
M Python/compile.c

diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 73807d7fa95fbd..51e00418165467 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -184,7 +184,6 @@ def bug1333982(x=[]):
               LOAD_CONST               1 (<code object <genexpr> at 0x..., 
file "%s", line %d>)
               MAKE_FUNCTION
               LOAD_FAST                0 (x)
-              GET_ITER
               CALL                     0
 
 %3d           LOAD_CONST               2 (1)
@@ -765,7 +764,6 @@ def foo(x):
                MAKE_FUNCTION
                SET_FUNCTION_ATTRIBUTE   8 (closure)
                LOAD_DEREF               1 (y)
-               GET_ITER
                CALL                     0
                CALL                     1
                RETURN_VALUE
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 515fe7407f1d80..a6c1dd62a23cc3 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -246,6 +246,28 @@ def loop():
         #This should not raise
         loop()
 
+    def test_genexpr_only_calls_dunder_iter_once(self):
+
+        class Iterator:
+
+            def __init__(self):
+                self.val = 0
+
+            def __next__(self):
+                if self.val == 2:
+                    raise StopIteration
+                self.val += 1
+                return self.val
+
+            # No __iter__ method
+
+        class C:
+
+            def __iter__(self):
+                return Iterator()
+
+        self.assertEqual([1,2], list(i for i in C()))
+
 
 class ModifyUnderlyingIterableTest(unittest.TestCase):
     iterables = [
diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py
index 4f2d3cdcc7943e..bb241837bd6679 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -123,15 +123,6 @@
     >>> list(g)
     [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
 
-Verify that the outermost for-expression makes an immediate check
-for iterability
-
-    >>> (i for i in 6)
-    Traceback (most recent call last):
-      File "<pyshell#4>", line 1, in -toplevel-
-        (i for i in 6)
-    TypeError: 'int' object is not iterable
-
 Verify late binding for the outermost if-expression
 
     >>> include = (2,4,6,8)
diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2025-04-10-10-29-45.gh-issue-127682.X0HoGz.rst b/Misc/NEWS.d/next/Core 
and Builtins/2025-04-10-10-29-45.gh-issue-127682.X0HoGz.rst
new file mode 100644
index 00000000000000..b87750eb516e7a
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2025-04-10-10-29-45.gh-issue-127682.X0HoGz.rst 
@@ -0,0 +1,4 @@
+No longer call ``__iter__`` twice when creating and executing a generator 
expression.
+Creating a generator expression from a non-interable will raise only when the
+generator expression is executed.
+This brings the behavior of generator expressions in line with other 
generators.
diff --git a/Python/compile.c b/Python/compile.c
index bb2c2293a38c9a..e8d19d2dc42744 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -5910,9 +5910,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int 
type,
     }
     Py_CLEAR(co);
 
-    if (compiler_comprehension_iter(c, outermost)) {
-        goto error;
-    }
+    VISIT(c, expr, outermost->iter);
 
     ADDOP_I(c, loc, CALL, 0);
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to