17db96d56Sopenharmony_ci"""Unit tests for the positional only argument syntax specified in PEP 570.""" 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciimport dis 47db96d56Sopenharmony_ciimport pickle 57db96d56Sopenharmony_ciimport unittest 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_cifrom test.support import check_syntax_error 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_cidef global_pos_only_f(a, b, /): 117db96d56Sopenharmony_ci return a, b 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cidef global_pos_only_and_normal(a, /, b): 147db96d56Sopenharmony_ci return a, b 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_cidef global_pos_only_defaults(a=1, /, b=2): 177db96d56Sopenharmony_ci return a, b 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ciclass PositionalOnlyTestCase(unittest.TestCase): 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci def assertRaisesSyntaxError(self, codestr, regex="invalid syntax"): 227db96d56Sopenharmony_ci with self.assertRaisesRegex(SyntaxError, regex): 237db96d56Sopenharmony_ci compile(codestr + "\n", "<test>", "single") 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci def test_invalid_syntax_errors(self): 267db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument") 277db96d56Sopenharmony_ci check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument") 287db96d56Sopenharmony_ci check_syntax_error(self, "def f(a = 5, b=1, /, c, *, d=2): pass", "non-default argument follows default argument") 297db96d56Sopenharmony_ci check_syntax_error(self, "def f(a = 5, b, /): pass", "non-default argument follows default argument") 307db96d56Sopenharmony_ci check_syntax_error(self, "def f(*args, /): pass") 317db96d56Sopenharmony_ci check_syntax_error(self, "def f(*args, a, /): pass") 327db96d56Sopenharmony_ci check_syntax_error(self, "def f(**kwargs, /): pass") 337db96d56Sopenharmony_ci check_syntax_error(self, "def f(/, a = 1): pass") 347db96d56Sopenharmony_ci check_syntax_error(self, "def f(/, a): pass") 357db96d56Sopenharmony_ci check_syntax_error(self, "def f(/): pass") 367db96d56Sopenharmony_ci check_syntax_error(self, "def f(*, a, /): pass") 377db96d56Sopenharmony_ci check_syntax_error(self, "def f(*, /, a): pass") 387db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, /, a): pass", "duplicate argument 'a' in function definition") 397db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, /, *, a): pass", "duplicate argument 'a' in function definition") 407db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, b/2, c): pass") 417db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, /, c, /): pass") 427db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, /, c, /, d): pass") 437db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, /, c, /, d, *, e): pass") 447db96d56Sopenharmony_ci check_syntax_error(self, "def f(a, *, c, /, d, e): pass") 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci def test_invalid_syntax_errors_async(self): 477db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument") 487db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument") 497db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a = 5, b=1, /, c, d=2): pass", "non-default argument follows default argument") 507db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a = 5, b, /): pass", "non-default argument follows default argument") 517db96d56Sopenharmony_ci check_syntax_error(self, "async def f(*args, /): pass") 527db96d56Sopenharmony_ci check_syntax_error(self, "async def f(*args, a, /): pass") 537db96d56Sopenharmony_ci check_syntax_error(self, "async def f(**kwargs, /): pass") 547db96d56Sopenharmony_ci check_syntax_error(self, "async def f(/, a = 1): pass") 557db96d56Sopenharmony_ci check_syntax_error(self, "async def f(/, a): pass") 567db96d56Sopenharmony_ci check_syntax_error(self, "async def f(/): pass") 577db96d56Sopenharmony_ci check_syntax_error(self, "async def f(*, a, /): pass") 587db96d56Sopenharmony_ci check_syntax_error(self, "async def f(*, /, a): pass") 597db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, /, a): pass", "duplicate argument 'a' in function definition") 607db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, /, *, a): pass", "duplicate argument 'a' in function definition") 617db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, b/2, c): pass") 627db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, /, c, /): pass") 637db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, /, c, /, d): pass") 647db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, /, c, /, d, *, e): pass") 657db96d56Sopenharmony_ci check_syntax_error(self, "async def f(a, *, c, /, d, e): pass") 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci def test_optional_positional_only_args(self): 687db96d56Sopenharmony_ci def f(a, b=10, /, c=100): 697db96d56Sopenharmony_ci return a + b + c 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci self.assertEqual(f(1, 2, 3), 6) 727db96d56Sopenharmony_ci self.assertEqual(f(1, 2, c=3), 6) 737db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): 747db96d56Sopenharmony_ci f(1, b=2, c=3) 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci self.assertEqual(f(1, 2), 103) 777db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): 787db96d56Sopenharmony_ci f(1, b=2) 797db96d56Sopenharmony_ci self.assertEqual(f(1, c=2), 13) 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci def f(a=1, b=10, /, c=100): 827db96d56Sopenharmony_ci return a + b + c 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci self.assertEqual(f(1, 2, 3), 6) 857db96d56Sopenharmony_ci self.assertEqual(f(1, 2, c=3), 6) 867db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): 877db96d56Sopenharmony_ci f(1, b=2, c=3) 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci self.assertEqual(f(1, 2), 103) 907db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'"): 917db96d56Sopenharmony_ci f(1, b=2) 927db96d56Sopenharmony_ci self.assertEqual(f(1, c=2), 13) 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci def test_syntax_for_many_positional_only(self): 957db96d56Sopenharmony_ci # more than 255 positional only arguments, should compile ok 967db96d56Sopenharmony_ci fundef = "def f(%s, /):\n pass\n" % ', '.join('i%d' % i for i in range(300)) 977db96d56Sopenharmony_ci compile(fundef, "<test>", "single") 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci def test_pos_only_definition(self): 1007db96d56Sopenharmony_ci def f(a, b, c, /, d, e=1, *, f, g=2): 1017db96d56Sopenharmony_ci pass 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci self.assertEqual(5, f.__code__.co_argcount) # 3 posonly + 2 "standard args" 1047db96d56Sopenharmony_ci self.assertEqual(3, f.__code__.co_posonlyargcount) 1057db96d56Sopenharmony_ci self.assertEqual((1,), f.__defaults__) 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci def f(a, b, c=1, /, d=2, e=3, *, f, g=4): 1087db96d56Sopenharmony_ci pass 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci self.assertEqual(5, f.__code__.co_argcount) # 3 posonly + 2 "standard args" 1117db96d56Sopenharmony_ci self.assertEqual(3, f.__code__.co_posonlyargcount) 1127db96d56Sopenharmony_ci self.assertEqual((1, 2, 3), f.__defaults__) 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci def test_pos_only_call_via_unpacking(self): 1157db96d56Sopenharmony_ci def f(a, b, /): 1167db96d56Sopenharmony_ci return a + b 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci self.assertEqual(f(*[1, 2]), 3) 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci def test_use_positional_as_keyword(self): 1217db96d56Sopenharmony_ci def f(a, /): 1227db96d56Sopenharmony_ci pass 1237db96d56Sopenharmony_ci expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'" 1247db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 1257db96d56Sopenharmony_ci f(a=1) 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci def f(a, /, b): 1287db96d56Sopenharmony_ci pass 1297db96d56Sopenharmony_ci expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'" 1307db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 1317db96d56Sopenharmony_ci f(a=1, b=2) 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci def f(a, b, /): 1347db96d56Sopenharmony_ci pass 1357db96d56Sopenharmony_ci expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'a, b'" 1367db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 1377db96d56Sopenharmony_ci f(a=1, b=2) 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci def test_positional_only_and_arg_invalid_calls(self): 1407db96d56Sopenharmony_ci def f(a, b, /, c): 1417db96d56Sopenharmony_ci pass 1427db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'c'"): 1437db96d56Sopenharmony_ci f(1, 2) 1447db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'b' and 'c'"): 1457db96d56Sopenharmony_ci f(1) 1467db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 3 required positional arguments: 'a', 'b', and 'c'"): 1477db96d56Sopenharmony_ci f() 1487db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) takes 3 positional arguments but 4 were given"): 1497db96d56Sopenharmony_ci f(1, 2, 3, 4) 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ci def test_positional_only_and_optional_arg_invalid_calls(self): 1527db96d56Sopenharmony_ci def f(a, b, /, c=3): 1537db96d56Sopenharmony_ci pass 1547db96d56Sopenharmony_ci f(1, 2) # does not raise 1557db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'b'"): 1567db96d56Sopenharmony_ci f(1) 1577db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): 1587db96d56Sopenharmony_ci f() 1597db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) takes from 2 to 3 positional arguments but 4 were given"): 1607db96d56Sopenharmony_ci f(1, 2, 3, 4) 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci def test_positional_only_and_kwonlyargs_invalid_calls(self): 1637db96d56Sopenharmony_ci def f(a, b, /, c, *, d, e): 1647db96d56Sopenharmony_ci pass 1657db96d56Sopenharmony_ci f(1, 2, 3, d=1, e=2) # does not raise 1667db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"missing 1 required keyword-only argument: 'd'"): 1677db96d56Sopenharmony_ci f(1, 2, 3, e=2) 1687db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"missing 2 required keyword-only arguments: 'd' and 'e'"): 1697db96d56Sopenharmony_ci f(1, 2, 3) 1707db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'c'"): 1717db96d56Sopenharmony_ci f(1, 2) 1727db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'b' and 'c'"): 1737db96d56Sopenharmony_ci f(1) 1747db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r" missing 3 required positional arguments: 'a', 'b', and 'c'"): 1757db96d56Sopenharmony_ci f() 1767db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) takes 3 positional arguments but 6 positional arguments " 1777db96d56Sopenharmony_ci r"\(and 2 keyword-only arguments\) were given"): 1787db96d56Sopenharmony_ci f(1, 2, 3, 4, 5, 6, d=7, e=8) 1797db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got an unexpected keyword argument 'f'"): 1807db96d56Sopenharmony_ci f(1, 2, 3, d=1, e=4, f=56) 1817db96d56Sopenharmony_ci 1827db96d56Sopenharmony_ci def test_positional_only_invalid_calls(self): 1837db96d56Sopenharmony_ci def f(a, b, /): 1847db96d56Sopenharmony_ci pass 1857db96d56Sopenharmony_ci f(1, 2) # does not raise 1867db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'b'"): 1877db96d56Sopenharmony_ci f(1) 1887db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): 1897db96d56Sopenharmony_ci f() 1907db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) takes 2 positional arguments but 3 were given"): 1917db96d56Sopenharmony_ci f(1, 2, 3) 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci def test_positional_only_with_optional_invalid_calls(self): 1947db96d56Sopenharmony_ci def f(a, b=2, /): 1957db96d56Sopenharmony_ci pass 1967db96d56Sopenharmony_ci f(1) # does not raise 1977db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'a'"): 1987db96d56Sopenharmony_ci f() 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) takes from 1 to 2 positional arguments but 3 were given"): 2017db96d56Sopenharmony_ci f(1, 2, 3) 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci def test_no_standard_args_usage(self): 2047db96d56Sopenharmony_ci def f(a, b, /, *, c): 2057db96d56Sopenharmony_ci pass 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci f(1, 2, c=3) 2087db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2097db96d56Sopenharmony_ci f(1, b=2, c=3) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci def test_change_default_pos_only(self): 2127db96d56Sopenharmony_ci def f(a, b=2, /, c=3): 2137db96d56Sopenharmony_ci return a + b + c 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci self.assertEqual((2,3), f.__defaults__) 2167db96d56Sopenharmony_ci f.__defaults__ = (1, 2, 3) 2177db96d56Sopenharmony_ci self.assertEqual(f(1, 2, 3), 6) 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ci def test_lambdas(self): 2207db96d56Sopenharmony_ci x = lambda a, /, b: a + b 2217db96d56Sopenharmony_ci self.assertEqual(x(1,2), 3) 2227db96d56Sopenharmony_ci self.assertEqual(x(1,b=2), 3) 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci x = lambda a, /, b=2: a + b 2257db96d56Sopenharmony_ci self.assertEqual(x(1), 3) 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci x = lambda a, b, /: a + b 2287db96d56Sopenharmony_ci self.assertEqual(x(1, 2), 3) 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci x = lambda a, b, /, : a + b 2317db96d56Sopenharmony_ci self.assertEqual(x(1, 2), 3) 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci def test_invalid_syntax_lambda(self): 2347db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument") 2357db96d56Sopenharmony_ci check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument") 2367db96d56Sopenharmony_ci check_syntax_error(self, "lambda a = 5, b, /: None", "non-default argument follows default argument") 2377db96d56Sopenharmony_ci check_syntax_error(self, "lambda *args, /: None") 2387db96d56Sopenharmony_ci check_syntax_error(self, "lambda *args, a, /: None") 2397db96d56Sopenharmony_ci check_syntax_error(self, "lambda **kwargs, /: None") 2407db96d56Sopenharmony_ci check_syntax_error(self, "lambda /, a = 1: None") 2417db96d56Sopenharmony_ci check_syntax_error(self, "lambda /, a: None") 2427db96d56Sopenharmony_ci check_syntax_error(self, "lambda /: None") 2437db96d56Sopenharmony_ci check_syntax_error(self, "lambda *, a, /: None") 2447db96d56Sopenharmony_ci check_syntax_error(self, "lambda *, /, a: None") 2457db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, /, a: None", "duplicate argument 'a' in function definition") 2467db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, /, *, a: None", "duplicate argument 'a' in function definition") 2477db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, /, b, /: None") 2487db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, /, b, /, c: None") 2497db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, /, b, /, c, *, d: None") 2507db96d56Sopenharmony_ci check_syntax_error(self, "lambda a, *, b, /, c: None") 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci def test_posonly_methods(self): 2537db96d56Sopenharmony_ci class Example: 2547db96d56Sopenharmony_ci def f(self, a, b, /): 2557db96d56Sopenharmony_ci return a, b 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci self.assertEqual(Example().f(1, 2), (1, 2)) 2587db96d56Sopenharmony_ci self.assertEqual(Example.f(Example(), 1, 2), (1, 2)) 2597db96d56Sopenharmony_ci self.assertRaises(TypeError, Example.f, 1, 2) 2607db96d56Sopenharmony_ci expected = r"f\(\) got some positional-only arguments passed as keyword arguments: 'b'" 2617db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 2627db96d56Sopenharmony_ci Example().f(1, b=2) 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def test_module_function(self): 2657db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 2 required positional arguments: 'a' and 'b'"): 2667db96d56Sopenharmony_ci global_pos_only_f() 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci def test_closures(self): 2707db96d56Sopenharmony_ci def f(x,y): 2717db96d56Sopenharmony_ci def g(x2,/,y2): 2727db96d56Sopenharmony_ci return x + y + x2 + y2 2737db96d56Sopenharmony_ci return g 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci self.assertEqual(f(1,2)(3,4), 10) 2767db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"g\(\) missing 1 required positional argument: 'y2'"): 2777db96d56Sopenharmony_ci f(1,2)(3) 2787db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"g\(\) takes 2 positional arguments but 3 were given"): 2797db96d56Sopenharmony_ci f(1,2)(3,4,5) 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci def f(x,/,y): 2827db96d56Sopenharmony_ci def g(x2,y2): 2837db96d56Sopenharmony_ci return x + y + x2 + y2 2847db96d56Sopenharmony_ci return g 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci self.assertEqual(f(1,2)(3,4), 10) 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci def f(x,/,y): 2897db96d56Sopenharmony_ci def g(x2,/,y2): 2907db96d56Sopenharmony_ci return x + y + x2 + y2 2917db96d56Sopenharmony_ci return g 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci self.assertEqual(f(1,2)(3,4), 10) 2947db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"g\(\) missing 1 required positional argument: 'y2'"): 2957db96d56Sopenharmony_ci f(1,2)(3) 2967db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"g\(\) takes 2 positional arguments but 3 were given"): 2977db96d56Sopenharmony_ci f(1,2)(3,4,5) 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci def test_annotations_in_closures(self): 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci def inner_has_pos_only(): 3027db96d56Sopenharmony_ci def f(x: int, /): ... 3037db96d56Sopenharmony_ci return f 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci assert inner_has_pos_only().__annotations__ == {'x': int} 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci class Something: 3087db96d56Sopenharmony_ci def method(self): 3097db96d56Sopenharmony_ci def f(x: int, /): ... 3107db96d56Sopenharmony_ci return f 3117db96d56Sopenharmony_ci 3127db96d56Sopenharmony_ci assert Something().method().__annotations__ == {'x': int} 3137db96d56Sopenharmony_ci 3147db96d56Sopenharmony_ci def multiple_levels(): 3157db96d56Sopenharmony_ci def inner_has_pos_only(): 3167db96d56Sopenharmony_ci def f(x: int, /): ... 3177db96d56Sopenharmony_ci return f 3187db96d56Sopenharmony_ci return inner_has_pos_only() 3197db96d56Sopenharmony_ci 3207db96d56Sopenharmony_ci assert multiple_levels().__annotations__ == {'x': int} 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci def test_same_keyword_as_positional_with_kwargs(self): 3237db96d56Sopenharmony_ci def f(something,/,**kwargs): 3247db96d56Sopenharmony_ci return (something, kwargs) 3257db96d56Sopenharmony_ci 3267db96d56Sopenharmony_ci self.assertEqual(f(42, something=42), (42, {'something': 42})) 3277db96d56Sopenharmony_ci 3287db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) missing 1 required positional argument: 'something'"): 3297db96d56Sopenharmony_ci f(something=42) 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci self.assertEqual(f(42), (42, {})) 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci def test_mangling(self): 3347db96d56Sopenharmony_ci class X: 3357db96d56Sopenharmony_ci def f(self, __a=42, /): 3367db96d56Sopenharmony_ci return __a 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci def f2(self, __a=42, /, __b=43): 3397db96d56Sopenharmony_ci return (__a, __b) 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def f3(self, __a=42, /, __b=43, *, __c=44): 3427db96d56Sopenharmony_ci return (__a, __b, __c) 3437db96d56Sopenharmony_ci 3447db96d56Sopenharmony_ci self.assertEqual(X().f(), 42) 3457db96d56Sopenharmony_ci self.assertEqual(X().f2(), (42, 43)) 3467db96d56Sopenharmony_ci self.assertEqual(X().f3(), (42, 43, 44)) 3477db96d56Sopenharmony_ci 3487db96d56Sopenharmony_ci def test_too_many_arguments(self): 3497db96d56Sopenharmony_ci # more than 255 positional-only arguments, should compile ok 3507db96d56Sopenharmony_ci fundef = "def f(%s, /):\n pass\n" % ', '.join('i%d' % i for i in range(300)) 3517db96d56Sopenharmony_ci compile(fundef, "<test>", "single") 3527db96d56Sopenharmony_ci 3537db96d56Sopenharmony_ci def test_serialization(self): 3547db96d56Sopenharmony_ci pickled_posonly = pickle.dumps(global_pos_only_f) 3557db96d56Sopenharmony_ci pickled_optional = pickle.dumps(global_pos_only_and_normal) 3567db96d56Sopenharmony_ci pickled_defaults = pickle.dumps(global_pos_only_defaults) 3577db96d56Sopenharmony_ci 3587db96d56Sopenharmony_ci unpickled_posonly = pickle.loads(pickled_posonly) 3597db96d56Sopenharmony_ci unpickled_optional = pickle.loads(pickled_optional) 3607db96d56Sopenharmony_ci unpickled_defaults = pickle.loads(pickled_defaults) 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci self.assertEqual(unpickled_posonly(1,2), (1,2)) 3637db96d56Sopenharmony_ci expected = r"global_pos_only_f\(\) got some positional-only arguments "\ 3647db96d56Sopenharmony_ci r"passed as keyword arguments: 'a, b'" 3657db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 3667db96d56Sopenharmony_ci unpickled_posonly(a=1,b=2) 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci self.assertEqual(unpickled_optional(1,2), (1,2)) 3697db96d56Sopenharmony_ci expected = r"global_pos_only_and_normal\(\) got some positional-only arguments "\ 3707db96d56Sopenharmony_ci r"passed as keyword arguments: 'a'" 3717db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 3727db96d56Sopenharmony_ci unpickled_optional(a=1,b=2) 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci self.assertEqual(unpickled_defaults(), (1,2)) 3757db96d56Sopenharmony_ci expected = r"global_pos_only_defaults\(\) got some positional-only arguments "\ 3767db96d56Sopenharmony_ci r"passed as keyword arguments: 'a'" 3777db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, expected): 3787db96d56Sopenharmony_ci unpickled_defaults(a=1,b=2) 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci def test_async(self): 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_ci async def f(a=1, /, b=2): 3837db96d56Sopenharmony_ci return a, b 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'"): 3867db96d56Sopenharmony_ci f(a=1, b=2) 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci def _check_call(*args, **kwargs): 3897db96d56Sopenharmony_ci try: 3907db96d56Sopenharmony_ci coro = f(*args, **kwargs) 3917db96d56Sopenharmony_ci coro.send(None) 3927db96d56Sopenharmony_ci except StopIteration as e: 3937db96d56Sopenharmony_ci result = e.value 3947db96d56Sopenharmony_ci self.assertEqual(result, (1, 2)) 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci _check_call(1, 2) 3977db96d56Sopenharmony_ci _check_call(1, b=2) 3987db96d56Sopenharmony_ci _check_call(1) 3997db96d56Sopenharmony_ci _check_call() 4007db96d56Sopenharmony_ci 4017db96d56Sopenharmony_ci def test_generator(self): 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci def f(a=1, /, b=2): 4047db96d56Sopenharmony_ci yield a, b 4057db96d56Sopenharmony_ci 4067db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, r"f\(\) got some positional-only arguments passed as keyword arguments: 'a'"): 4077db96d56Sopenharmony_ci f(a=1, b=2) 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci gen = f(1, 2) 4107db96d56Sopenharmony_ci self.assertEqual(next(gen), (1, 2)) 4117db96d56Sopenharmony_ci gen = f(1, b=2) 4127db96d56Sopenharmony_ci self.assertEqual(next(gen), (1, 2)) 4137db96d56Sopenharmony_ci gen = f(1) 4147db96d56Sopenharmony_ci self.assertEqual(next(gen), (1, 2)) 4157db96d56Sopenharmony_ci gen = f() 4167db96d56Sopenharmony_ci self.assertEqual(next(gen), (1, 2)) 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci def test_super(self): 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci sentinel = object() 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci class A: 4237db96d56Sopenharmony_ci def method(self): 4247db96d56Sopenharmony_ci return sentinel 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci class C(A): 4277db96d56Sopenharmony_ci def method(self, /): 4287db96d56Sopenharmony_ci return super().method() 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci self.assertEqual(C().method(), sentinel) 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci def test_annotations_constant_fold(self): 4337db96d56Sopenharmony_ci def g(): 4347db96d56Sopenharmony_ci def f(x: not (int is int), /): ... 4357db96d56Sopenharmony_ci 4367db96d56Sopenharmony_ci # without constant folding we end up with 4377db96d56Sopenharmony_ci # COMPARE_OP(is), IS_OP (0) 4387db96d56Sopenharmony_ci # with constant folding we should expect a IS_OP (1) 4397db96d56Sopenharmony_ci codes = [(i.opname, i.argval) for i in dis.get_instructions(g)] 4407db96d56Sopenharmony_ci self.assertNotIn(('UNARY_NOT', None), codes) 4417db96d56Sopenharmony_ci self.assertIn(('IS_OP', 1), codes) 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ciif __name__ == "__main__": 4457db96d56Sopenharmony_ci unittest.main() 446