@@ -298,6 +298,72 @@ def test_named_expression_invalid_set_comprehension_iterable_expression(self):
298
298
with self .assertRaisesRegex (SyntaxError , msg ):
299
299
exec (f"lambda: { code } " , {}) # Function scope
300
300
301
+ def test_named_expression_invalid_rebinding_dict_comprehension_iteration_variable (self ):
302
+ cases = [
303
+ ("Key reuse" , 'i' , "{(i := 0): 1 for i in range(5)}" ),
304
+ ("Value reuse" , 'i' , "{1: (i := 0) for i in range(5)}" ),
305
+ ("Both reuse" , 'i' , "{(i := 0): (i := 0) for i in range(5)}" ),
306
+ ("Nested reuse" , 'j' , "{{(j := 0): 1 for i in range(5)} for j in range(5)}" ),
307
+ ("Reuse inner loop target" , 'j' , "{(j := 0): 1 for i in range(5) for j in range(5)}" ),
308
+ ("Unpacking key reuse" , 'i' , "{(i := 0): 1 for i, j in {(0, 1)}}" ),
309
+ ("Unpacking value reuse" , 'i' , "{1: (i := 0) for i, j in {(0, 1)}}" ),
310
+ ("Reuse in loop condition" , 'i' , "{i+1: 1 for i in range(5) if (i := 0)}" ),
311
+ ("Unreachable reuse" , 'i' , "{(False or (i:=0)): 1 for i in range(5)}" ),
312
+ ("Unreachable nested reuse" , 'i' ,
313
+ "{i: j for i in range(5) for j in range(5) if True or (i:=10)}" ),
314
+ # Regression tests from https://github.com/python/cpython/issues/87447
315
+ ("Complex expression: a" , "a" ,
316
+ "{(a := 1): 1 for a, (*b, c[d+e::f(g)], h.i) in j}" ),
317
+ ("Complex expression: b" , "b" ,
318
+ "{(b := 1): 1 for a, (*b, c[d+e::f(g)], h.i) in j}" ),
319
+ ]
320
+ for case , target , code in cases :
321
+ msg = f"assignment expression cannot rebind comprehension iteration variable '{ target } '"
322
+ with self .subTest (case = case ):
323
+ with self .assertRaisesRegex (SyntaxError , msg ):
324
+ exec (code , {}) # Module scope
325
+ with self .assertRaisesRegex (SyntaxError , msg ):
326
+ exec (code , {}, {}) # Class scope
327
+ with self .assertRaisesRegex (SyntaxError , msg ):
328
+ exec (f"lambda: { code } " , {}) # Function scope
329
+
330
+ def test_named_expression_invalid_rebinding_dict_comprehension_inner_loop (self ):
331
+ cases = [
332
+ ("Inner reuse" , 'j' , "{i: 1 for i in range(5) if (j := 0) for j in range(5)}" ),
333
+ ("Inner unpacking reuse" , 'j' , "{i: 1 for i in range(5) if (j := 0) for j, k in {(0, 1)}}" ),
334
+ ]
335
+ for case , target , code in cases :
336
+ msg = f"comprehension inner loop cannot rebind assignment expression target '{ target } '"
337
+ with self .subTest (case = case ):
338
+ with self .assertRaisesRegex (SyntaxError , msg ):
339
+ exec (code , {}) # Module scope
340
+ with self .assertRaisesRegex (SyntaxError , msg ):
341
+ exec (code , {}, {}) # Class scope
342
+ with self .assertRaisesRegex (SyntaxError , msg ):
343
+ exec (f"lambda: { code } " , {}) # Function scope
344
+
345
+ def test_named_expression_invalid_dict_comprehension_iterable_expression (self ):
346
+ cases = [
347
+ ("Top level" , "{i: 1 for i in (i := range(5))}" ),
348
+ ("Inside tuple" , "{i: 1 for i in (2, 3, i := range(5))}" ),
349
+ ("Inside list" , "{i: 1 for i in [2, 3, i := range(5)]}" ),
350
+ ("Different name" , "{i: 1 for i in (j := range(5))}" ),
351
+ ("Lambda expression" , "{i: 1 for i in (lambda:(j := range(5)))()}" ),
352
+ ("Inner loop" , "{i: 1 for i in range(5) for j in (i := range(5))}" ),
353
+ ("Nested comprehension" , "{i: 1 for i in {j: 2 for j in (k := range(5))}}" ),
354
+ ("Nested comprehension condition" , "{i: 1 for i in {j: 2 for j in range(5) if (j := True)}}" ),
355
+ ("Nested comprehension body" , "{i: 1 for i in {(j := True) for j in range(5)}}" ),
356
+ ]
357
+ msg = "assignment expression cannot be used in a comprehension iterable expression"
358
+ for case , code in cases :
359
+ with self .subTest (case = case ):
360
+ with self .assertRaisesRegex (SyntaxError , msg ):
361
+ exec (code , {}) # Module scope
362
+ with self .assertRaisesRegex (SyntaxError , msg ):
363
+ exec (code , {}, {}) # Class scope
364
+ with self .assertRaisesRegex (SyntaxError , msg ):
365
+ exec (f"lambda: { code } " , {}) # Function scope
366
+
301
367
def test_named_expression_invalid_mangled_class_variables (self ):
302
368
code = """class Foo:
303
369
def bar(self):
@@ -361,7 +427,7 @@ def test_named_expression_assignment_09(self):
361
427
362
428
def test_named_expression_assignment_10 (self ):
363
429
if (match := 10 ) == 10 :
364
- pass
430
+ self . assertEqual ( match , 10 )
365
431
else : self .fail ("variable was not assigned using named expression" )
366
432
367
433
def test_named_expression_assignment_11 (self ):
@@ -403,7 +469,7 @@ def test_named_expression_assignment_14(self):
403
469
404
470
def test_named_expression_assignment_15 (self ):
405
471
while a := False :
406
- pass # This will not run
472
+ self . fail ( "While body executed" ) # This will not run
407
473
408
474
self .assertEqual (a , False )
409
475
0 commit comments