17db96d56Sopenharmony_ciimport unittest
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciGLOBAL_VAR = None
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciclass NamedExpressionInvalidTest(unittest.TestCase):
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci    def test_named_expression_invalid_01(self):
87db96d56Sopenharmony_ci        code = """x := 0"""
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
117db96d56Sopenharmony_ci            exec(code, {}, {})
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ci    def test_named_expression_invalid_02(self):
147db96d56Sopenharmony_ci        code = """x = y := 0"""
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
177db96d56Sopenharmony_ci            exec(code, {}, {})
187db96d56Sopenharmony_ci
197db96d56Sopenharmony_ci    def test_named_expression_invalid_03(self):
207db96d56Sopenharmony_ci        code = """y := f(x)"""
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
237db96d56Sopenharmony_ci            exec(code, {}, {})
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci    def test_named_expression_invalid_04(self):
267db96d56Sopenharmony_ci        code = """y0 = y1 := f(x)"""
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
297db96d56Sopenharmony_ci            exec(code, {}, {})
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci    def test_named_expression_invalid_06(self):
327db96d56Sopenharmony_ci        code = """((a, b) := (1, 2))"""
337db96d56Sopenharmony_ci
347db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "cannot use assignment expressions with tuple"):
357db96d56Sopenharmony_ci            exec(code, {}, {})
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci    def test_named_expression_invalid_07(self):
387db96d56Sopenharmony_ci        code = """def spam(a = b := 42): pass"""
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
417db96d56Sopenharmony_ci            exec(code, {}, {})
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci    def test_named_expression_invalid_08(self):
447db96d56Sopenharmony_ci        code = """def spam(a: b := 42 = 5): pass"""
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
477db96d56Sopenharmony_ci            exec(code, {}, {})
487db96d56Sopenharmony_ci
497db96d56Sopenharmony_ci    def test_named_expression_invalid_09(self):
507db96d56Sopenharmony_ci        code = """spam(a=b := 'c')"""
517db96d56Sopenharmony_ci
527db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
537db96d56Sopenharmony_ci            exec(code, {}, {})
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci    def test_named_expression_invalid_10(self):
567db96d56Sopenharmony_ci        code = """spam(x = y := f(x))"""
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
597db96d56Sopenharmony_ci            exec(code, {}, {})
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci    def test_named_expression_invalid_11(self):
627db96d56Sopenharmony_ci        code = """spam(a=1, b := 2)"""
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
657db96d56Sopenharmony_ci            "positional argument follows keyword argument"):
667db96d56Sopenharmony_ci            exec(code, {}, {})
677db96d56Sopenharmony_ci
687db96d56Sopenharmony_ci    def test_named_expression_invalid_12(self):
697db96d56Sopenharmony_ci        code = """spam(a=1, (b := 2))"""
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
727db96d56Sopenharmony_ci            "positional argument follows keyword argument"):
737db96d56Sopenharmony_ci            exec(code, {}, {})
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci    def test_named_expression_invalid_13(self):
767db96d56Sopenharmony_ci        code = """spam(a=1, (b := 2))"""
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
797db96d56Sopenharmony_ci            "positional argument follows keyword argument"):
807db96d56Sopenharmony_ci            exec(code, {}, {})
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci    def test_named_expression_invalid_14(self):
837db96d56Sopenharmony_ci        code = """(x := lambda: y := 1)"""
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
867db96d56Sopenharmony_ci            exec(code, {}, {})
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci    def test_named_expression_invalid_15(self):
897db96d56Sopenharmony_ci        code = """(lambda: x := 1)"""
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
927db96d56Sopenharmony_ci            "cannot use assignment expressions with lambda"):
937db96d56Sopenharmony_ci            exec(code, {}, {})
947db96d56Sopenharmony_ci
957db96d56Sopenharmony_ci    def test_named_expression_invalid_16(self):
967db96d56Sopenharmony_ci        code = "[i + 1 for i in i := [1,2]]"
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError, "invalid syntax"):
997db96d56Sopenharmony_ci            exec(code, {}, {})
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci    def test_named_expression_invalid_17(self):
1027db96d56Sopenharmony_ci        code = "[i := 0, j := 1 for i, j in [(1, 2), (3, 4)]]"
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
1057db96d56Sopenharmony_ci                "did you forget parentheses around the comprehension target?"):
1067db96d56Sopenharmony_ci            exec(code, {}, {})
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci    def test_named_expression_invalid_in_class_body(self):
1097db96d56Sopenharmony_ci        code = """class Foo():
1107db96d56Sopenharmony_ci            [(42, 1 + ((( j := i )))) for i in range(5)]
1117db96d56Sopenharmony_ci        """
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ci        with self.assertRaisesRegex(SyntaxError,
1147db96d56Sopenharmony_ci            "assignment expression within a comprehension cannot be used in a class body"):
1157db96d56Sopenharmony_ci            exec(code, {}, {})
1167db96d56Sopenharmony_ci
1177db96d56Sopenharmony_ci    def test_named_expression_invalid_rebinding_list_comprehension_iteration_variable(self):
1187db96d56Sopenharmony_ci        cases = [
1197db96d56Sopenharmony_ci            ("Local reuse", 'i', "[i := 0 for i in range(5)]"),
1207db96d56Sopenharmony_ci            ("Nested reuse", 'j', "[[(j := 0) for i in range(5)] for j in range(5)]"),
1217db96d56Sopenharmony_ci            ("Reuse inner loop target", 'j', "[(j := 0) for i in range(5) for j in range(5)]"),
1227db96d56Sopenharmony_ci            ("Unpacking reuse", 'i', "[i := 0 for i, j in [(0, 1)]]"),
1237db96d56Sopenharmony_ci            ("Reuse in loop condition", 'i', "[i+1 for i in range(5) if (i := 0)]"),
1247db96d56Sopenharmony_ci            ("Unreachable reuse", 'i', "[False or (i:=0) for i in range(5)]"),
1257db96d56Sopenharmony_ci            ("Unreachable nested reuse", 'i',
1267db96d56Sopenharmony_ci                "[(i, j) for i in range(5) for j in range(5) if True or (i:=10)]"),
1277db96d56Sopenharmony_ci        ]
1287db96d56Sopenharmony_ci        for case, target, code in cases:
1297db96d56Sopenharmony_ci            msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
1307db96d56Sopenharmony_ci            with self.subTest(case=case):
1317db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1327db96d56Sopenharmony_ci                    exec(code, {}, {})
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci    def test_named_expression_invalid_rebinding_list_comprehension_inner_loop(self):
1357db96d56Sopenharmony_ci        cases = [
1367db96d56Sopenharmony_ci            ("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"),
1377db96d56Sopenharmony_ci            ("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"),
1387db96d56Sopenharmony_ci        ]
1397db96d56Sopenharmony_ci        for case, target, code in cases:
1407db96d56Sopenharmony_ci            msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
1417db96d56Sopenharmony_ci            with self.subTest(case=case):
1427db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1437db96d56Sopenharmony_ci                    exec(code, {}) # Module scope
1447db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1457db96d56Sopenharmony_ci                    exec(code, {}, {}) # Class scope
1467db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1477db96d56Sopenharmony_ci                    exec(f"lambda: {code}", {}) # Function scope
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci    def test_named_expression_invalid_list_comprehension_iterable_expression(self):
1507db96d56Sopenharmony_ci        cases = [
1517db96d56Sopenharmony_ci            ("Top level", "[i for i in (i := range(5))]"),
1527db96d56Sopenharmony_ci            ("Inside tuple", "[i for i in (2, 3, i := range(5))]"),
1537db96d56Sopenharmony_ci            ("Inside list", "[i for i in [2, 3, i := range(5)]]"),
1547db96d56Sopenharmony_ci            ("Different name", "[i for i in (j := range(5))]"),
1557db96d56Sopenharmony_ci            ("Lambda expression", "[i for i in (lambda:(j := range(5)))()]"),
1567db96d56Sopenharmony_ci            ("Inner loop", "[i for i in range(5) for j in (i := range(5))]"),
1577db96d56Sopenharmony_ci            ("Nested comprehension", "[i for i in [j for j in (k := range(5))]]"),
1587db96d56Sopenharmony_ci            ("Nested comprehension condition", "[i for i in [j for j in range(5) if (j := True)]]"),
1597db96d56Sopenharmony_ci            ("Nested comprehension body", "[i for i in [(j := True) for j in range(5)]]"),
1607db96d56Sopenharmony_ci        ]
1617db96d56Sopenharmony_ci        msg = "assignment expression cannot be used in a comprehension iterable expression"
1627db96d56Sopenharmony_ci        for case, code in cases:
1637db96d56Sopenharmony_ci            with self.subTest(case=case):
1647db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1657db96d56Sopenharmony_ci                    exec(code, {}) # Module scope
1667db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1677db96d56Sopenharmony_ci                    exec(code, {}, {}) # Class scope
1687db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1697db96d56Sopenharmony_ci                    exec(f"lambda: {code}", {}) # Function scope
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci    def test_named_expression_invalid_rebinding_set_comprehension_iteration_variable(self):
1727db96d56Sopenharmony_ci        cases = [
1737db96d56Sopenharmony_ci            ("Local reuse", 'i', "{i := 0 for i in range(5)}"),
1747db96d56Sopenharmony_ci            ("Nested reuse", 'j', "{{(j := 0) for i in range(5)} for j in range(5)}"),
1757db96d56Sopenharmony_ci            ("Reuse inner loop target", 'j', "{(j := 0) for i in range(5) for j in range(5)}"),
1767db96d56Sopenharmony_ci            ("Unpacking reuse", 'i', "{i := 0 for i, j in {(0, 1)}}"),
1777db96d56Sopenharmony_ci            ("Reuse in loop condition", 'i', "{i+1 for i in range(5) if (i := 0)}"),
1787db96d56Sopenharmony_ci            ("Unreachable reuse", 'i', "{False or (i:=0) for i in range(5)}"),
1797db96d56Sopenharmony_ci            ("Unreachable nested reuse", 'i',
1807db96d56Sopenharmony_ci                "{(i, j) for i in range(5) for j in range(5) if True or (i:=10)}"),
1817db96d56Sopenharmony_ci        ]
1827db96d56Sopenharmony_ci        for case, target, code in cases:
1837db96d56Sopenharmony_ci            msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
1847db96d56Sopenharmony_ci            with self.subTest(case=case):
1857db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1867db96d56Sopenharmony_ci                    exec(code, {}, {})
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci    def test_named_expression_invalid_rebinding_set_comprehension_inner_loop(self):
1897db96d56Sopenharmony_ci        cases = [
1907db96d56Sopenharmony_ci            ("Inner reuse", 'j', "{i for i in range(5) if (j := 0) for j in range(5)}"),
1917db96d56Sopenharmony_ci            ("Inner unpacking reuse", 'j', "{i for i in range(5) if (j := 0) for j, k in {(0, 1)}}"),
1927db96d56Sopenharmony_ci        ]
1937db96d56Sopenharmony_ci        for case, target, code in cases:
1947db96d56Sopenharmony_ci            msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
1957db96d56Sopenharmony_ci            with self.subTest(case=case):
1967db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1977db96d56Sopenharmony_ci                    exec(code, {}) # Module scope
1987db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
1997db96d56Sopenharmony_ci                    exec(code, {}, {}) # Class scope
2007db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
2017db96d56Sopenharmony_ci                    exec(f"lambda: {code}", {}) # Function scope
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci    def test_named_expression_invalid_set_comprehension_iterable_expression(self):
2047db96d56Sopenharmony_ci        cases = [
2057db96d56Sopenharmony_ci            ("Top level", "{i for i in (i := range(5))}"),
2067db96d56Sopenharmony_ci            ("Inside tuple", "{i for i in (2, 3, i := range(5))}"),
2077db96d56Sopenharmony_ci            ("Inside list", "{i for i in {2, 3, i := range(5)}}"),
2087db96d56Sopenharmony_ci            ("Different name", "{i for i in (j := range(5))}"),
2097db96d56Sopenharmony_ci            ("Lambda expression", "{i for i in (lambda:(j := range(5)))()}"),
2107db96d56Sopenharmony_ci            ("Inner loop", "{i for i in range(5) for j in (i := range(5))}"),
2117db96d56Sopenharmony_ci            ("Nested comprehension", "{i for i in {j for j in (k := range(5))}}"),
2127db96d56Sopenharmony_ci            ("Nested comprehension condition", "{i for i in {j for j in range(5) if (j := True)}}"),
2137db96d56Sopenharmony_ci            ("Nested comprehension body", "{i for i in {(j := True) for j in range(5)}}"),
2147db96d56Sopenharmony_ci        ]
2157db96d56Sopenharmony_ci        msg = "assignment expression cannot be used in a comprehension iterable expression"
2167db96d56Sopenharmony_ci        for case, code in cases:
2177db96d56Sopenharmony_ci            with self.subTest(case=case):
2187db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
2197db96d56Sopenharmony_ci                    exec(code, {}) # Module scope
2207db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
2217db96d56Sopenharmony_ci                    exec(code, {}, {}) # Class scope
2227db96d56Sopenharmony_ci                with self.assertRaisesRegex(SyntaxError, msg):
2237db96d56Sopenharmony_ci                    exec(f"lambda: {code}", {}) # Function scope
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ciclass NamedExpressionAssignmentTest(unittest.TestCase):
2277db96d56Sopenharmony_ci
2287db96d56Sopenharmony_ci    def test_named_expression_assignment_01(self):
2297db96d56Sopenharmony_ci        (a := 10)
2307db96d56Sopenharmony_ci
2317db96d56Sopenharmony_ci        self.assertEqual(a, 10)
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci    def test_named_expression_assignment_02(self):
2347db96d56Sopenharmony_ci        a = 20
2357db96d56Sopenharmony_ci        (a := a)
2367db96d56Sopenharmony_ci
2377db96d56Sopenharmony_ci        self.assertEqual(a, 20)
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci    def test_named_expression_assignment_03(self):
2407db96d56Sopenharmony_ci        (total := 1 + 2)
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci        self.assertEqual(total, 3)
2437db96d56Sopenharmony_ci
2447db96d56Sopenharmony_ci    def test_named_expression_assignment_04(self):
2457db96d56Sopenharmony_ci        (info := (1, 2, 3))
2467db96d56Sopenharmony_ci
2477db96d56Sopenharmony_ci        self.assertEqual(info, (1, 2, 3))
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci    def test_named_expression_assignment_05(self):
2507db96d56Sopenharmony_ci        (x := 1, 2)
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci        self.assertEqual(x, 1)
2537db96d56Sopenharmony_ci
2547db96d56Sopenharmony_ci    def test_named_expression_assignment_06(self):
2557db96d56Sopenharmony_ci        (z := (y := (x := 0)))
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci        self.assertEqual(x, 0)
2587db96d56Sopenharmony_ci        self.assertEqual(y, 0)
2597db96d56Sopenharmony_ci        self.assertEqual(z, 0)
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ci    def test_named_expression_assignment_07(self):
2627db96d56Sopenharmony_ci        (loc := (1, 2))
2637db96d56Sopenharmony_ci
2647db96d56Sopenharmony_ci        self.assertEqual(loc, (1, 2))
2657db96d56Sopenharmony_ci
2667db96d56Sopenharmony_ci    def test_named_expression_assignment_08(self):
2677db96d56Sopenharmony_ci        if spam := "eggs":
2687db96d56Sopenharmony_ci            self.assertEqual(spam, "eggs")
2697db96d56Sopenharmony_ci        else: self.fail("variable was not assigned using named expression")
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci    def test_named_expression_assignment_09(self):
2727db96d56Sopenharmony_ci        if True and (spam := True):
2737db96d56Sopenharmony_ci            self.assertTrue(spam)
2747db96d56Sopenharmony_ci        else: self.fail("variable was not assigned using named expression")
2757db96d56Sopenharmony_ci
2767db96d56Sopenharmony_ci    def test_named_expression_assignment_10(self):
2777db96d56Sopenharmony_ci        if (match := 10) == 10:
2787db96d56Sopenharmony_ci            pass
2797db96d56Sopenharmony_ci        else: self.fail("variable was not assigned using named expression")
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_ci    def test_named_expression_assignment_11(self):
2827db96d56Sopenharmony_ci        def spam(a):
2837db96d56Sopenharmony_ci            return a
2847db96d56Sopenharmony_ci        input_data = [1, 2, 3]
2857db96d56Sopenharmony_ci        res = [(x, y, x/y) for x in input_data if (y := spam(x)) > 0]
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci        self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci    def test_named_expression_assignment_12(self):
2907db96d56Sopenharmony_ci        def spam(a):
2917db96d56Sopenharmony_ci            return a
2927db96d56Sopenharmony_ci        res = [[y := spam(x), x/y] for x in range(1, 5)]
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci        self.assertEqual(res, [[1, 1.0], [2, 1.0], [3, 1.0], [4, 1.0]])
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci    def test_named_expression_assignment_13(self):
2977db96d56Sopenharmony_ci        length = len(lines := [1, 2])
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci        self.assertEqual(length, 2)
3007db96d56Sopenharmony_ci        self.assertEqual(lines, [1,2])
3017db96d56Sopenharmony_ci
3027db96d56Sopenharmony_ci    def test_named_expression_assignment_14(self):
3037db96d56Sopenharmony_ci        """
3047db96d56Sopenharmony_ci        Where all variables are positive integers, and a is at least as large
3057db96d56Sopenharmony_ci        as the n'th root of x, this algorithm returns the floor of the n'th
3067db96d56Sopenharmony_ci        root of x (and roughly doubling the number of accurate bits per
3077db96d56Sopenharmony_ci        iteration):
3087db96d56Sopenharmony_ci        """
3097db96d56Sopenharmony_ci        a = 9
3107db96d56Sopenharmony_ci        n = 2
3117db96d56Sopenharmony_ci        x = 3
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci        while a > (d := x // a**(n-1)):
3147db96d56Sopenharmony_ci            a = ((n-1)*a + d) // n
3157db96d56Sopenharmony_ci
3167db96d56Sopenharmony_ci        self.assertEqual(a, 1)
3177db96d56Sopenharmony_ci
3187db96d56Sopenharmony_ci    def test_named_expression_assignment_15(self):
3197db96d56Sopenharmony_ci        while a := False:
3207db96d56Sopenharmony_ci            pass  # This will not run
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ci        self.assertEqual(a, False)
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_ci    def test_named_expression_assignment_16(self):
3257db96d56Sopenharmony_ci        a, b = 1, 2
3267db96d56Sopenharmony_ci        fib = {(c := a): (a := b) + (b := a + c) - b for __ in range(6)}
3277db96d56Sopenharmony_ci        self.assertEqual(fib, {1: 2, 2: 3, 3: 5, 5: 8, 8: 13, 13: 21})
3287db96d56Sopenharmony_ci
3297db96d56Sopenharmony_ci    def test_named_expression_assignment_17(self):
3307db96d56Sopenharmony_ci        a = [1]
3317db96d56Sopenharmony_ci        element = a[b:=0]
3327db96d56Sopenharmony_ci        self.assertEqual(b, 0)
3337db96d56Sopenharmony_ci        self.assertEqual(element, a[0])
3347db96d56Sopenharmony_ci
3357db96d56Sopenharmony_ci    def test_named_expression_assignment_18(self):
3367db96d56Sopenharmony_ci        class TwoDimensionalList:
3377db96d56Sopenharmony_ci            def __init__(self, two_dimensional_list):
3387db96d56Sopenharmony_ci                self.two_dimensional_list = two_dimensional_list
3397db96d56Sopenharmony_ci
3407db96d56Sopenharmony_ci            def __getitem__(self, index):
3417db96d56Sopenharmony_ci                return self.two_dimensional_list[index[0]][index[1]]
3427db96d56Sopenharmony_ci
3437db96d56Sopenharmony_ci        a = TwoDimensionalList([[1], [2]])
3447db96d56Sopenharmony_ci        element = a[b:=0, c:=0]
3457db96d56Sopenharmony_ci        self.assertEqual(b, 0)
3467db96d56Sopenharmony_ci        self.assertEqual(c, 0)
3477db96d56Sopenharmony_ci        self.assertEqual(element, a.two_dimensional_list[b][c])
3487db96d56Sopenharmony_ci
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ci
3517db96d56Sopenharmony_ciclass NamedExpressionScopeTest(unittest.TestCase):
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci    def test_named_expression_scope_01(self):
3547db96d56Sopenharmony_ci        code = """def spam():
3557db96d56Sopenharmony_ci    (a := 5)
3567db96d56Sopenharmony_ciprint(a)"""
3577db96d56Sopenharmony_ci
3587db96d56Sopenharmony_ci        with self.assertRaisesRegex(NameError, "name 'a' is not defined"):
3597db96d56Sopenharmony_ci            exec(code, {}, {})
3607db96d56Sopenharmony_ci
3617db96d56Sopenharmony_ci    def test_named_expression_scope_02(self):
3627db96d56Sopenharmony_ci        total = 0
3637db96d56Sopenharmony_ci        partial_sums = [total := total + v for v in range(5)]
3647db96d56Sopenharmony_ci
3657db96d56Sopenharmony_ci        self.assertEqual(partial_sums, [0, 1, 3, 6, 10])
3667db96d56Sopenharmony_ci        self.assertEqual(total, 10)
3677db96d56Sopenharmony_ci
3687db96d56Sopenharmony_ci    def test_named_expression_scope_03(self):
3697db96d56Sopenharmony_ci        containsOne = any((lastNum := num) == 1 for num in [1, 2, 3])
3707db96d56Sopenharmony_ci
3717db96d56Sopenharmony_ci        self.assertTrue(containsOne)
3727db96d56Sopenharmony_ci        self.assertEqual(lastNum, 1)
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci    def test_named_expression_scope_04(self):
3757db96d56Sopenharmony_ci        def spam(a):
3767db96d56Sopenharmony_ci            return a
3777db96d56Sopenharmony_ci        res = [[y := spam(x), x/y] for x in range(1, 5)]
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci        self.assertEqual(y, 4)
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ci    def test_named_expression_scope_05(self):
3827db96d56Sopenharmony_ci        def spam(a):
3837db96d56Sopenharmony_ci            return a
3847db96d56Sopenharmony_ci        input_data = [1, 2, 3]
3857db96d56Sopenharmony_ci        res = [(x, y, x/y) for x in input_data if (y := spam(x)) > 0]
3867db96d56Sopenharmony_ci
3877db96d56Sopenharmony_ci        self.assertEqual(res, [(1, 1, 1.0), (2, 2, 1.0), (3, 3, 1.0)])
3887db96d56Sopenharmony_ci        self.assertEqual(y, 3)
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci    def test_named_expression_scope_06(self):
3917db96d56Sopenharmony_ci        res = [[spam := i for i in range(3)] for j in range(2)]
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_ci        self.assertEqual(res, [[0, 1, 2], [0, 1, 2]])
3947db96d56Sopenharmony_ci        self.assertEqual(spam, 2)
3957db96d56Sopenharmony_ci
3967db96d56Sopenharmony_ci    def test_named_expression_scope_07(self):
3977db96d56Sopenharmony_ci        len(lines := [1, 2])
3987db96d56Sopenharmony_ci
3997db96d56Sopenharmony_ci        self.assertEqual(lines, [1, 2])
4007db96d56Sopenharmony_ci
4017db96d56Sopenharmony_ci    def test_named_expression_scope_08(self):
4027db96d56Sopenharmony_ci        def spam(a):
4037db96d56Sopenharmony_ci            return a
4047db96d56Sopenharmony_ci
4057db96d56Sopenharmony_ci        def eggs(b):
4067db96d56Sopenharmony_ci            return b * 2
4077db96d56Sopenharmony_ci
4087db96d56Sopenharmony_ci        res = [spam(a := eggs(b := h)) for h in range(2)]
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_ci        self.assertEqual(res, [0, 2])
4117db96d56Sopenharmony_ci        self.assertEqual(a, 2)
4127db96d56Sopenharmony_ci        self.assertEqual(b, 1)
4137db96d56Sopenharmony_ci
4147db96d56Sopenharmony_ci    def test_named_expression_scope_09(self):
4157db96d56Sopenharmony_ci        def spam(a):
4167db96d56Sopenharmony_ci            return a
4177db96d56Sopenharmony_ci
4187db96d56Sopenharmony_ci        def eggs(b):
4197db96d56Sopenharmony_ci            return b * 2
4207db96d56Sopenharmony_ci
4217db96d56Sopenharmony_ci        res = [spam(a := eggs(a := h)) for h in range(2)]
4227db96d56Sopenharmony_ci
4237db96d56Sopenharmony_ci        self.assertEqual(res, [0, 2])
4247db96d56Sopenharmony_ci        self.assertEqual(a, 2)
4257db96d56Sopenharmony_ci
4267db96d56Sopenharmony_ci    def test_named_expression_scope_10(self):
4277db96d56Sopenharmony_ci        res = [b := [a := 1 for i in range(2)] for j in range(2)]
4287db96d56Sopenharmony_ci
4297db96d56Sopenharmony_ci        self.assertEqual(res, [[1, 1], [1, 1]])
4307db96d56Sopenharmony_ci        self.assertEqual(a, 1)
4317db96d56Sopenharmony_ci        self.assertEqual(b, [1, 1])
4327db96d56Sopenharmony_ci
4337db96d56Sopenharmony_ci    def test_named_expression_scope_11(self):
4347db96d56Sopenharmony_ci        res = [j := i for i in range(5)]
4357db96d56Sopenharmony_ci
4367db96d56Sopenharmony_ci        self.assertEqual(res, [0, 1, 2, 3, 4])
4377db96d56Sopenharmony_ci        self.assertEqual(j, 4)
4387db96d56Sopenharmony_ci
4397db96d56Sopenharmony_ci    def test_named_expression_scope_17(self):
4407db96d56Sopenharmony_ci        b = 0
4417db96d56Sopenharmony_ci        res = [b := i + b for i in range(5)]
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ci        self.assertEqual(res, [0, 1, 3, 6, 10])
4447db96d56Sopenharmony_ci        self.assertEqual(b, 10)
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ci    def test_named_expression_scope_18(self):
4477db96d56Sopenharmony_ci        def spam(a):
4487db96d56Sopenharmony_ci            return a
4497db96d56Sopenharmony_ci
4507db96d56Sopenharmony_ci        res = spam(b := 2)
4517db96d56Sopenharmony_ci
4527db96d56Sopenharmony_ci        self.assertEqual(res, 2)
4537db96d56Sopenharmony_ci        self.assertEqual(b, 2)
4547db96d56Sopenharmony_ci
4557db96d56Sopenharmony_ci    def test_named_expression_scope_19(self):
4567db96d56Sopenharmony_ci        def spam(a):
4577db96d56Sopenharmony_ci            return a
4587db96d56Sopenharmony_ci
4597db96d56Sopenharmony_ci        res = spam((b := 2))
4607db96d56Sopenharmony_ci
4617db96d56Sopenharmony_ci        self.assertEqual(res, 2)
4627db96d56Sopenharmony_ci        self.assertEqual(b, 2)
4637db96d56Sopenharmony_ci
4647db96d56Sopenharmony_ci    def test_named_expression_scope_20(self):
4657db96d56Sopenharmony_ci        def spam(a):
4667db96d56Sopenharmony_ci            return a
4677db96d56Sopenharmony_ci
4687db96d56Sopenharmony_ci        res = spam(a=(b := 2))
4697db96d56Sopenharmony_ci
4707db96d56Sopenharmony_ci        self.assertEqual(res, 2)
4717db96d56Sopenharmony_ci        self.assertEqual(b, 2)
4727db96d56Sopenharmony_ci
4737db96d56Sopenharmony_ci    def test_named_expression_scope_21(self):
4747db96d56Sopenharmony_ci        def spam(a, b):
4757db96d56Sopenharmony_ci            return a + b
4767db96d56Sopenharmony_ci
4777db96d56Sopenharmony_ci        res = spam(c := 2, b=1)
4787db96d56Sopenharmony_ci
4797db96d56Sopenharmony_ci        self.assertEqual(res, 3)
4807db96d56Sopenharmony_ci        self.assertEqual(c, 2)
4817db96d56Sopenharmony_ci
4827db96d56Sopenharmony_ci    def test_named_expression_scope_22(self):
4837db96d56Sopenharmony_ci        def spam(a, b):
4847db96d56Sopenharmony_ci            return a + b
4857db96d56Sopenharmony_ci
4867db96d56Sopenharmony_ci        res = spam((c := 2), b=1)
4877db96d56Sopenharmony_ci
4887db96d56Sopenharmony_ci        self.assertEqual(res, 3)
4897db96d56Sopenharmony_ci        self.assertEqual(c, 2)
4907db96d56Sopenharmony_ci
4917db96d56Sopenharmony_ci    def test_named_expression_scope_23(self):
4927db96d56Sopenharmony_ci        def spam(a, b):
4937db96d56Sopenharmony_ci            return a + b
4947db96d56Sopenharmony_ci
4957db96d56Sopenharmony_ci        res = spam(b=(c := 2), a=1)
4967db96d56Sopenharmony_ci
4977db96d56Sopenharmony_ci        self.assertEqual(res, 3)
4987db96d56Sopenharmony_ci        self.assertEqual(c, 2)
4997db96d56Sopenharmony_ci
5007db96d56Sopenharmony_ci    def test_named_expression_scope_24(self):
5017db96d56Sopenharmony_ci        a = 10
5027db96d56Sopenharmony_ci        def spam():
5037db96d56Sopenharmony_ci            nonlocal a
5047db96d56Sopenharmony_ci            (a := 20)
5057db96d56Sopenharmony_ci        spam()
5067db96d56Sopenharmony_ci
5077db96d56Sopenharmony_ci        self.assertEqual(a, 20)
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ci    def test_named_expression_scope_25(self):
5107db96d56Sopenharmony_ci        ns = {}
5117db96d56Sopenharmony_ci        code = """a = 10
5127db96d56Sopenharmony_cidef spam():
5137db96d56Sopenharmony_ci    global a
5147db96d56Sopenharmony_ci    (a := 20)
5157db96d56Sopenharmony_cispam()"""
5167db96d56Sopenharmony_ci
5177db96d56Sopenharmony_ci        exec(code, ns, {})
5187db96d56Sopenharmony_ci
5197db96d56Sopenharmony_ci        self.assertEqual(ns["a"], 20)
5207db96d56Sopenharmony_ci
5217db96d56Sopenharmony_ci    def test_named_expression_variable_reuse_in_comprehensions(self):
5227db96d56Sopenharmony_ci        # The compiler is expected to raise syntax error for comprehension
5237db96d56Sopenharmony_ci        # iteration variables, but should be fine with rebinding of other
5247db96d56Sopenharmony_ci        # names (e.g. globals, nonlocals, other assignment expressions)
5257db96d56Sopenharmony_ci
5267db96d56Sopenharmony_ci        # The cases are all defined to produce the same expected result
5277db96d56Sopenharmony_ci        # Each comprehension is checked at both function scope and module scope
5287db96d56Sopenharmony_ci        rebinding = "[x := i for i in range(3) if (x := i) or not x]"
5297db96d56Sopenharmony_ci        filter_ref = "[x := i for i in range(3) if x or not x]"
5307db96d56Sopenharmony_ci        body_ref = "[x for i in range(3) if (x := i) or not x]"
5317db96d56Sopenharmony_ci        nested_ref = "[j for i in range(3) if x or not x for j in range(3) if (x := i)][:-3]"
5327db96d56Sopenharmony_ci        cases = [
5337db96d56Sopenharmony_ci            ("Rebind global", f"x = 1; result = {rebinding}"),
5347db96d56Sopenharmony_ci            ("Rebind nonlocal", f"result, x = (lambda x=1: ({rebinding}, x))()"),
5357db96d56Sopenharmony_ci            ("Filter global", f"x = 1; result = {filter_ref}"),
5367db96d56Sopenharmony_ci            ("Filter nonlocal", f"result, x = (lambda x=1: ({filter_ref}, x))()"),
5377db96d56Sopenharmony_ci            ("Body global", f"x = 1; result = {body_ref}"),
5387db96d56Sopenharmony_ci            ("Body nonlocal", f"result, x = (lambda x=1: ({body_ref}, x))()"),
5397db96d56Sopenharmony_ci            ("Nested global", f"x = 1; result = {nested_ref}"),
5407db96d56Sopenharmony_ci            ("Nested nonlocal", f"result, x = (lambda x=1: ({nested_ref}, x))()"),
5417db96d56Sopenharmony_ci        ]
5427db96d56Sopenharmony_ci        for case, code in cases:
5437db96d56Sopenharmony_ci            with self.subTest(case=case):
5447db96d56Sopenharmony_ci                ns = {}
5457db96d56Sopenharmony_ci                exec(code, ns)
5467db96d56Sopenharmony_ci                self.assertEqual(ns["x"], 2)
5477db96d56Sopenharmony_ci                self.assertEqual(ns["result"], [0, 1, 2])
5487db96d56Sopenharmony_ci
5497db96d56Sopenharmony_ci    def test_named_expression_global_scope(self):
5507db96d56Sopenharmony_ci        sentinel = object()
5517db96d56Sopenharmony_ci        global GLOBAL_VAR
5527db96d56Sopenharmony_ci        def f():
5537db96d56Sopenharmony_ci            global GLOBAL_VAR
5547db96d56Sopenharmony_ci            [GLOBAL_VAR := sentinel for _ in range(1)]
5557db96d56Sopenharmony_ci            self.assertEqual(GLOBAL_VAR, sentinel)
5567db96d56Sopenharmony_ci        try:
5577db96d56Sopenharmony_ci            f()
5587db96d56Sopenharmony_ci            self.assertEqual(GLOBAL_VAR, sentinel)
5597db96d56Sopenharmony_ci        finally:
5607db96d56Sopenharmony_ci            GLOBAL_VAR = None
5617db96d56Sopenharmony_ci
5627db96d56Sopenharmony_ci    def test_named_expression_global_scope_no_global_keyword(self):
5637db96d56Sopenharmony_ci        sentinel = object()
5647db96d56Sopenharmony_ci        def f():
5657db96d56Sopenharmony_ci            GLOBAL_VAR = None
5667db96d56Sopenharmony_ci            [GLOBAL_VAR := sentinel for _ in range(1)]
5677db96d56Sopenharmony_ci            self.assertEqual(GLOBAL_VAR, sentinel)
5687db96d56Sopenharmony_ci        f()
5697db96d56Sopenharmony_ci        self.assertEqual(GLOBAL_VAR, None)
5707db96d56Sopenharmony_ci
5717db96d56Sopenharmony_ci    def test_named_expression_nonlocal_scope(self):
5727db96d56Sopenharmony_ci        sentinel = object()
5737db96d56Sopenharmony_ci        def f():
5747db96d56Sopenharmony_ci            nonlocal_var = None
5757db96d56Sopenharmony_ci            def g():
5767db96d56Sopenharmony_ci                nonlocal nonlocal_var
5777db96d56Sopenharmony_ci                [nonlocal_var := sentinel for _ in range(1)]
5787db96d56Sopenharmony_ci            g()
5797db96d56Sopenharmony_ci            self.assertEqual(nonlocal_var, sentinel)
5807db96d56Sopenharmony_ci        f()
5817db96d56Sopenharmony_ci
5827db96d56Sopenharmony_ci    def test_named_expression_nonlocal_scope_no_nonlocal_keyword(self):
5837db96d56Sopenharmony_ci        sentinel = object()
5847db96d56Sopenharmony_ci        def f():
5857db96d56Sopenharmony_ci            nonlocal_var = None
5867db96d56Sopenharmony_ci            def g():
5877db96d56Sopenharmony_ci                [nonlocal_var := sentinel for _ in range(1)]
5887db96d56Sopenharmony_ci            g()
5897db96d56Sopenharmony_ci            self.assertEqual(nonlocal_var, None)
5907db96d56Sopenharmony_ci        f()
5917db96d56Sopenharmony_ci
5927db96d56Sopenharmony_ci    def test_named_expression_scope_in_genexp(self):
5937db96d56Sopenharmony_ci        a = 1
5947db96d56Sopenharmony_ci        b = [1, 2, 3, 4]
5957db96d56Sopenharmony_ci        genexp = (c := i + a for i in b)
5967db96d56Sopenharmony_ci
5977db96d56Sopenharmony_ci        self.assertNotIn("c", locals())
5987db96d56Sopenharmony_ci        for idx, elem in enumerate(genexp):
5997db96d56Sopenharmony_ci            self.assertEqual(elem, b[idx] + a)
6007db96d56Sopenharmony_ci
6017db96d56Sopenharmony_ci
6027db96d56Sopenharmony_ciif __name__ == "__main__":
6037db96d56Sopenharmony_ci    unittest.main()
604