Skip to content

[3.13] GH-127682: Backport GH-132351 #132384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
9 changes: 0 additions & 9 deletions Lib/test/test_genexps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 1 addition & 3 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading