https://github.com/python/cpython/commit/6ae51582a1935495ce5126dbc24e319f11e2315f
commit: 6ae51582a1935495ce5126dbc24e319f11e2315f
branch: 3.13
author: T. Wouters <tho...@python.org>
committer: ambv <luk...@langa.pl>
date: 2025-06-11T16:57:35+02:00
summary:

[3.13] GH-135171: Roll back all fixes for GH-127682 as they are not suitable 
for 3.13 (#135390)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-14-09-12.gh-issue-135171.VUdivl.rst
M Lib/test/test_coroutines.py
M Lib/test/test_dis.py
M Lib/test/test_generators.py
M Lib/test/test_genexps.py
M Lib/test/test_listcomps.py
M Python/compile.c

diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index 77cdbf98067e8c..f705f4f5bfbd88 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -2252,31 +2252,6 @@ def c():
         # before fixing, visible stack from throw would be shorter than from 
send.
         self.assertEqual(len_send, len_throw)
 
-    def test_call_aiter_once_in_comprehension(self):
-
-        class Iterator:
-
-            def __init__(self):
-                self.val = 0
-
-            async def __anext__(self):
-                if self.val == 2:
-                    raise StopAsyncIteration
-                self.val += 1
-                return self.val
-
-            # No __aiter__ method
-
-        class C:
-
-            def __aiter__(self):
-                return Iterator()
-
-        async def run():
-            return [i async for i in C()]
-
-        self.assertEqual(run_async(run()), ([], [1,2]))
-
 
 @unittest.skipIf(
     support.is_emscripten or support.is_wasi,
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 51e00418165467..73807d7fa95fbd 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -184,6 +184,7 @@ 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)
@@ -764,6 +765,7 @@ 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 a6c1dd62a23cc3..515fe7407f1d80 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -246,28 +246,6 @@ 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 bb241837bd6679..4f2d3cdcc7943e 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -123,6 +123,15 @@
     >>> 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/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py
index 23fa5ef4f43810..45644d6c092782 100644
--- a/Lib/test/test_listcomps.py
+++ b/Lib/test/test_listcomps.py
@@ -750,28 +750,6 @@ def iter_raises():
                 self.assertEqual(f.line[f.colno - indent : f.end_colno - 
indent],
                                  expected)
 
-    def test_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], [i for i in C()])
-
 __test__ = {'doctests' : doctests}
 
 def load_tests(loader, tests, pattern):
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-14-09-12.gh-issue-135171.VUdivl.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-14-09-12.gh-issue-135171.VUdivl.rst
new file mode 100644
index 00000000000000..ec8a8ca39c1365
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-11-14-09-12.gh-issue-135171.VUdivl.rst
@@ -0,0 +1 @@
+Roll back changes to generator and list comprehensions that went into 3.13.4 
to fix GH-127682, but which involved semantic and bytecode changes not 
appropriate for a bugfix release.
diff --git a/Python/compile.c b/Python/compile.c
index e9506d6d978d89..bb2c2293a38c9a 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -5501,9 +5501,9 @@ compiler_async_comprehension_generator(struct compiler 
*c, location loc,
         else {
             /* Sub-iter - calculate on the fly */
             VISIT(c, expr, gen->iter);
+            ADDOP(c, LOC(gen->iter), GET_AITER);
         }
     }
-    ADDOP(c, LOC(gen->iter), GET_AITER);
 
     USE_LABEL(c, start);
     /* Runtime will push a block here, so we need to account for that */
@@ -5790,6 +5790,19 @@ pop_inlined_comprehension_state(struct compiler *c, 
location loc,
     return SUCCESS;
 }
 
+static inline int
+compiler_comprehension_iter(struct compiler *c, comprehension_ty comp)
+{
+    VISIT(c, expr, comp->iter);
+    if (comp->is_async) {
+        ADDOP(c, LOC(comp->iter), GET_AITER);
+    }
+    else {
+        ADDOP(c, LOC(comp->iter), GET_ITER);
+    }
+    return SUCCESS;
+}
+
 static int
 compiler_comprehension(struct compiler *c, expr_ty e, int type,
                        identifier name, asdl_comprehension_seq *generators, 
expr_ty elt,
@@ -5811,7 +5824,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int 
type,
 
     outermost = (comprehension_ty) asdl_seq_GET(generators, 0);
     if (is_inlined) {
-        if (compiler_visit_expr(c, outermost->iter) < 0) {
+        if (compiler_comprehension_iter(c, outermost)) {
             goto error;
         }
         if (push_inlined_comprehension_state(c, loc, entry, &inline_state)) {
@@ -5897,7 +5910,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int 
type,
     }
     Py_CLEAR(co);
 
-    VISIT(c, expr, outermost->iter);
+    if (compiler_comprehension_iter(c, outermost)) {
+        goto error;
+    }
 
     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