Update test_named_expressions.py from 3.14.4 (#7629)

This commit is contained in:
Shahar Naveh
2026-04-19 15:33:51 +02:00
committed by GitHub
parent 764e4de061
commit 37707081f8

View File

@@ -4,40 +4,35 @@ GLOBAL_VAR = None
class NamedExpressionInvalidTest(unittest.TestCase):
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_01(self):
code = """x := 0"""
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_02(self):
code = """x = y := 0"""
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_03(self):
code = """y := f(x)"""
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_04(self):
code = """y0 = y1 := f(x)"""
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_06(self):
code = """((a, b) := (1, 2))"""
@@ -68,8 +63,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_11(self):
code = """spam(a=1, b := 2)"""
@@ -77,8 +71,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
"positional argument follows keyword argument"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_12(self):
code = """spam(a=1, (b := 2))"""
@@ -86,8 +79,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
"positional argument follows keyword argument"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_13(self):
code = """spam(a=1, (b := 2))"""
@@ -101,8 +93,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON: wrong error message
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_15(self):
code = """(lambda: x := 1)"""
@@ -116,8 +107,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
exec(code, {}, {})
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_named_expression_invalid_17(self):
code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"
@@ -134,8 +124,70 @@ class NamedExpressionInvalidTest(unittest.TestCase):
"assignment expression within a comprehension cannot be used in a class body"):
exec(code, {}, {})
# TODO: RUSTPYTHON
@unittest.expectedFailure # wrong error message
def test_named_expression_valid_rebinding_iteration_variable(self):
# This test covers that we can reassign variables
# that are not directly assigned in the
# iterable part of a comprehension.
cases = [
# Regression tests from https://github.com/python/cpython/issues/87447
("Complex expression: c",
"{0}(c := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: d",
"{0}(d := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: e",
"{0}(e := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: f",
"{0}(f := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: g",
"{0}(g := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: h",
"{0}(h := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: i",
"{0}(i := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: j",
"{0}(j := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
]
for test_case, code in cases:
for lpar, rpar in [('(', ')'), ('[', ']'), ('{', '}')]:
code = code.format(lpar, rpar)
with self.subTest(case=test_case, lpar=lpar, rpar=rpar):
# Names used in snippets are not defined,
# but we are fine with it: just must not be a SyntaxError.
# Names used in snippets are not defined,
# but we are fine with it: just must not be a SyntaxError.
with self.assertRaises(NameError):
exec(code, {}) # Module scope
with self.assertRaises(NameError):
exec(code, {}, {}) # Class scope
exec(f"lambda: {code}", {}) # Function scope
def test_named_expression_invalid_rebinding_iteration_variable(self):
# This test covers that we cannot reassign variables
# that are directly assigned in the iterable part of a comprehension.
cases = [
# Regression tests from https://github.com/python/cpython/issues/87447
("Complex expression: a", "a",
"{0}(a := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
("Complex expression: b", "b",
"{0}(b := 1) for a, (*b, c[d+e::f(g)], h.i) in j{1}"),
]
for test_case, target, code in cases:
msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
for lpar, rpar in [('(', ')'), ('[', ']'), ('{', '}')]:
code = code.format(lpar, rpar)
with self.subTest(case=test_case, lpar=lpar, rpar=rpar):
# Names used in snippets are not defined,
# but we are fine with it: just must not be a SyntaxError.
# Names used in snippets are not defined,
# but we are fine with it: just must not be a SyntaxError.
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_named_expression_invalid_rebinding_list_comprehension_iteration_variable(self):
cases = [
("Local reuse", 'i', "[i := 0 for i in range(5)]"),
@@ -151,7 +203,11 @@ class NamedExpressionInvalidTest(unittest.TestCase):
msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
with self.subTest(case=case):
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {})
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
def test_named_expression_invalid_rebinding_list_comprehension_inner_loop(self):
cases = [
@@ -190,8 +246,7 @@ class NamedExpressionInvalidTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
# TODO: RUSTPYTHON
@unittest.expectedFailure
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_named_expression_invalid_rebinding_set_comprehension_iteration_variable(self):
cases = [
("Local reuse", 'i', "{i := 0 for i in range(5)}"),
@@ -202,12 +257,21 @@ class NamedExpressionInvalidTest(unittest.TestCase):
("Unreachable reuse", 'i', "{False or (i:=0) for i in range(5)}"),
("Unreachable nested reuse", 'i',
"{(i, j) for i in range(5) for j in range(5) if True or (i:=10)}"),
# Regression tests from https://github.com/python/cpython/issues/87447
("Complex expression: a", "a",
"{(a := 1) for a, (*b, c[d+e::f(g)], h.i) in j}"),
("Complex expression: b", "b",
"{(b := 1) for a, (*b, c[d+e::f(g)], h.i) in j}"),
]
for case, target, code in cases:
msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
with self.subTest(case=case):
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {})
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
def test_named_expression_invalid_rebinding_set_comprehension_inner_loop(self):
cases = [
@@ -246,6 +310,84 @@ class NamedExpressionInvalidTest(unittest.TestCase):
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_rebinding_dict_comprehension_iteration_variable(self):
cases = [
("Key reuse", 'i', "{(i := 0): 1 for i in range(5)}"),
("Value reuse", 'i', "{1: (i := 0) for i in range(5)}"),
("Both reuse", 'i', "{(i := 0): (i := 0) for i in range(5)}"),
("Nested reuse", 'j', "{{(j := 0): 1 for i in range(5)} for j in range(5)}"),
("Reuse inner loop target", 'j', "{(j := 0): 1 for i in range(5) for j in range(5)}"),
("Unpacking key reuse", 'i', "{(i := 0): 1 for i, j in {(0, 1)}}"),
("Unpacking value reuse", 'i', "{1: (i := 0) for i, j in {(0, 1)}}"),
("Reuse in loop condition", 'i', "{i+1: 1 for i in range(5) if (i := 0)}"),
("Unreachable reuse", 'i', "{(False or (i:=0)): 1 for i in range(5)}"),
("Unreachable nested reuse", 'i',
"{i: j for i in range(5) for j in range(5) if True or (i:=10)}"),
# Regression tests from https://github.com/python/cpython/issues/87447
("Complex expression: a", "a",
"{(a := 1): 1 for a, (*b, c[d+e::f(g)], h.i) in j}"),
("Complex expression: b", "b",
"{(b := 1): 1 for a, (*b, c[d+e::f(g)], h.i) in j}"),
]
for case, target, code in cases:
msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
with self.subTest(case=case):
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
def test_named_expression_invalid_rebinding_dict_comprehension_inner_loop(self):
cases = [
("Inner reuse", 'j', "{i: 1 for i in range(5) if (j := 0) for j in range(5)}"),
("Inner unpacking reuse", 'j', "{i: 1 for i in range(5) if (j := 0) for j, k in {(0, 1)}}"),
]
for case, target, code in cases:
msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
with self.subTest(case=case):
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
def test_named_expression_invalid_dict_comprehension_iterable_expression(self):
cases = [
("Top level", "{i: 1 for i in (i := range(5))}"),
("Inside tuple", "{i: 1 for i in (2, 3, i := range(5))}"),
("Inside list", "{i: 1 for i in [2, 3, i := range(5)]}"),
("Different name", "{i: 1 for i in (j := range(5))}"),
("Lambda expression", "{i: 1 for i in (lambda:(j := range(5)))()}"),
("Inner loop", "{i: 1 for i in range(5) for j in (i := range(5))}"),
("Nested comprehension", "{i: 1 for i in {j: 2 for j in (k := range(5))}}"),
("Nested comprehension condition", "{i: 1 for i in {j: 2 for j in range(5) if (j := True)}}"),
("Nested comprehension body", "{i: 1 for i in {(j := True) for j in range(5)}}"),
]
msg = "assignment expression cannot be used in a comprehension iterable expression"
for case, code in cases:
with self.subTest(case=case):
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}) # Module scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {}) # Class scope
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
@unittest.expectedFailure # TODO: RUSTPYTHON; wrong error message
def test_named_expression_invalid_mangled_class_variables(self):
code = """class Foo:
def bar(self):
[[(__x:=2) for _ in range(2)] for __x in range(2)]
"""
with self.assertRaisesRegex(SyntaxError,
"assignment expression cannot rebind comprehension iteration variable '__x'"):
exec(code, {}, {})
class NamedExpressionAssignmentTest(unittest.TestCase):
@@ -299,7 +441,7 @@ class NamedExpressionAssignmentTest(unittest.TestCase):
def test_named_expression_assignment_10(self):
if (match := 10) == 10:
pass
self.assertEqual(match, 10)
else: self.fail("variable was not assigned using named expression")
def test_named_expression_assignment_11(self):
@@ -341,7 +483,7 @@ class NamedExpressionAssignmentTest(unittest.TestCase):
def test_named_expression_assignment_15(self):
while a := False:
pass # This will not run
self.fail("While body executed") # This will not run
self.assertEqual(a, False)
@@ -622,6 +764,18 @@ spam()"""
for idx, elem in enumerate(genexp):
self.assertEqual(elem, b[idx] + a)
def test_named_expression_scope_mangled_names(self):
class Foo:
def f(self_):
global __x1
__x1 = 0
[_Foo__x1 := 1 for a in [2]]
self.assertEqual(__x1, 1)
[__x1 := 2 for a in [3]]
self.assertEqual(__x1, 2)
Foo().f()
self.assertEqual(_Foo__x1, 2)
if __name__ == "__main__":
unittest.main()