Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 25684e7

Browse filesBrowse files
authored
gh-100746: Improve test_named_expressions.py (#116713)
1 parent 7f418fb commit 25684e7
Copy full SHA for 25684e7

File tree

Expand file treeCollapse file tree

1 file changed

+68
-2
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+68
-2
lines changed

‎Lib/test/test_named_expressions.py

Copy file name to clipboardExpand all lines: Lib/test/test_named_expressions.py
+68-2Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,72 @@ def test_named_expression_invalid_set_comprehension_iterable_expression(self):
298298
with self.assertRaisesRegex(SyntaxError, msg):
299299
exec(f"lambda: {code}", {}) # Function scope
300300

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+
301367
def test_named_expression_invalid_mangled_class_variables(self):
302368
code = """class Foo:
303369
def bar(self):
@@ -361,7 +427,7 @@ def test_named_expression_assignment_09(self):
361427

362428
def test_named_expression_assignment_10(self):
363429
if (match := 10) == 10:
364-
pass
430+
self.assertEqual(match, 10)
365431
else: self.fail("variable was not assigned using named expression")
366432

367433
def test_named_expression_assignment_11(self):
@@ -403,7 +469,7 @@ def test_named_expression_assignment_14(self):
403469

404470
def test_named_expression_assignment_15(self):
405471
while a := False:
406-
pass # This will not run
472+
self.fail("While body executed") # This will not run
407473

408474
self.assertEqual(a, False)
409475

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.