17db96d56Sopenharmony_ci"""Test suite for 2to3's parser and grammar files. 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciThis is the place to add tests for changes to 2to3's grammar, such as those 47db96d56Sopenharmony_cimerging the grammars for Python 2 and 3. In addition to specific tests for 57db96d56Sopenharmony_ciparts of the grammar we've changed, we also make sure we can parse the 67db96d56Sopenharmony_citest_grammar.py files from both Python 2 and Python 3. 77db96d56Sopenharmony_ci""" 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci# Testing imports 107db96d56Sopenharmony_cifrom . import support 117db96d56Sopenharmony_cifrom .support import driver, driver_no_print_statement 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci# Python imports 147db96d56Sopenharmony_ciimport difflib 157db96d56Sopenharmony_ciimport importlib 167db96d56Sopenharmony_ciimport operator 177db96d56Sopenharmony_ciimport os 187db96d56Sopenharmony_ciimport pickle 197db96d56Sopenharmony_ciimport shutil 207db96d56Sopenharmony_ciimport subprocess 217db96d56Sopenharmony_ciimport sys 227db96d56Sopenharmony_ciimport tempfile 237db96d56Sopenharmony_ciimport test.support 247db96d56Sopenharmony_ciimport unittest 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ci# Local imports 277db96d56Sopenharmony_cifrom lib2to3.pgen2 import driver as pgen2_driver 287db96d56Sopenharmony_cifrom lib2to3.pgen2 import tokenize 297db96d56Sopenharmony_cifrom ..pgen2.parse import ParseError 307db96d56Sopenharmony_cifrom lib2to3.pygram import python_symbols as syms 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ciclass TestDriver(support.TestCase): 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci def test_formfeed(self): 367db96d56Sopenharmony_ci s = """print 1\n\x0Cprint 2\n""" 377db96d56Sopenharmony_ci t = driver.parse_string(s) 387db96d56Sopenharmony_ci self.assertEqual(t.children[0].children[0].type, syms.print_stmt) 397db96d56Sopenharmony_ci self.assertEqual(t.children[1].children[0].type, syms.print_stmt) 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ciclass TestPgen2Caching(support.TestCase): 437db96d56Sopenharmony_ci def test_load_grammar_from_txt_file(self): 447db96d56Sopenharmony_ci pgen2_driver.load_grammar(support.grammar_path, save=False, force=True) 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci def test_load_grammar_from_pickle(self): 477db96d56Sopenharmony_ci # Make a copy of the grammar file in a temp directory we are 487db96d56Sopenharmony_ci # guaranteed to be able to write to. 497db96d56Sopenharmony_ci tmpdir = tempfile.mkdtemp() 507db96d56Sopenharmony_ci try: 517db96d56Sopenharmony_ci grammar_copy = os.path.join( 527db96d56Sopenharmony_ci tmpdir, os.path.basename(support.grammar_path)) 537db96d56Sopenharmony_ci shutil.copy(support.grammar_path, grammar_copy) 547db96d56Sopenharmony_ci pickle_name = pgen2_driver._generate_pickle_name(grammar_copy) 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ci pgen2_driver.load_grammar(grammar_copy, save=True, force=True) 577db96d56Sopenharmony_ci self.assertTrue(os.path.exists(pickle_name)) 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci os.unlink(grammar_copy) # Only the pickle remains... 607db96d56Sopenharmony_ci pgen2_driver.load_grammar(grammar_copy, save=False, force=False) 617db96d56Sopenharmony_ci finally: 627db96d56Sopenharmony_ci shutil.rmtree(tmpdir) 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci @unittest.skipIf(sys.executable is None, 'sys.executable required') 657db96d56Sopenharmony_ci @unittest.skipIf( 667db96d56Sopenharmony_ci sys.platform in {'emscripten', 'wasi'}, 'requires working subprocess' 677db96d56Sopenharmony_ci ) 687db96d56Sopenharmony_ci def test_load_grammar_from_subprocess(self): 697db96d56Sopenharmony_ci tmpdir = tempfile.mkdtemp() 707db96d56Sopenharmony_ci tmpsubdir = os.path.join(tmpdir, 'subdir') 717db96d56Sopenharmony_ci try: 727db96d56Sopenharmony_ci os.mkdir(tmpsubdir) 737db96d56Sopenharmony_ci grammar_base = os.path.basename(support.grammar_path) 747db96d56Sopenharmony_ci grammar_copy = os.path.join(tmpdir, grammar_base) 757db96d56Sopenharmony_ci grammar_sub_copy = os.path.join(tmpsubdir, grammar_base) 767db96d56Sopenharmony_ci shutil.copy(support.grammar_path, grammar_copy) 777db96d56Sopenharmony_ci shutil.copy(support.grammar_path, grammar_sub_copy) 787db96d56Sopenharmony_ci pickle_name = pgen2_driver._generate_pickle_name(grammar_copy) 797db96d56Sopenharmony_ci pickle_sub_name = pgen2_driver._generate_pickle_name( 807db96d56Sopenharmony_ci grammar_sub_copy) 817db96d56Sopenharmony_ci self.assertNotEqual(pickle_name, pickle_sub_name) 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci # Generate a pickle file from this process. 847db96d56Sopenharmony_ci pgen2_driver.load_grammar(grammar_copy, save=True, force=True) 857db96d56Sopenharmony_ci self.assertTrue(os.path.exists(pickle_name)) 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci # Generate a new pickle file in a subprocess with a most likely 887db96d56Sopenharmony_ci # different hash randomization seed. 897db96d56Sopenharmony_ci sub_env = dict(os.environ) 907db96d56Sopenharmony_ci sub_env['PYTHONHASHSEED'] = 'random' 917db96d56Sopenharmony_ci code = """ 927db96d56Sopenharmony_cifrom lib2to3.pgen2 import driver as pgen2_driver 937db96d56Sopenharmony_cipgen2_driver.load_grammar(%r, save=True, force=True) 947db96d56Sopenharmony_ci """ % (grammar_sub_copy,) 957db96d56Sopenharmony_ci cmd = [sys.executable, 967db96d56Sopenharmony_ci '-Wignore:lib2to3:DeprecationWarning', 977db96d56Sopenharmony_ci '-c', code] 987db96d56Sopenharmony_ci subprocess.check_call( cmd, env=sub_env) 997db96d56Sopenharmony_ci self.assertTrue(os.path.exists(pickle_sub_name)) 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci with open(pickle_name, 'rb') as pickle_f_1, \ 1027db96d56Sopenharmony_ci open(pickle_sub_name, 'rb') as pickle_f_2: 1037db96d56Sopenharmony_ci self.assertEqual( 1047db96d56Sopenharmony_ci pickle_f_1.read(), pickle_f_2.read(), 1057db96d56Sopenharmony_ci msg='Grammar caches generated using different hash seeds' 1067db96d56Sopenharmony_ci ' were not identical.') 1077db96d56Sopenharmony_ci finally: 1087db96d56Sopenharmony_ci shutil.rmtree(tmpdir) 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci def test_load_packaged_grammar(self): 1117db96d56Sopenharmony_ci modname = __name__ + '.load_test' 1127db96d56Sopenharmony_ci class MyLoader: 1137db96d56Sopenharmony_ci def get_data(self, where): 1147db96d56Sopenharmony_ci return pickle.dumps({'elephant': 19}) 1157db96d56Sopenharmony_ci class MyModule: 1167db96d56Sopenharmony_ci __file__ = 'parsertestmodule' 1177db96d56Sopenharmony_ci __spec__ = importlib.util.spec_from_loader(modname, MyLoader()) 1187db96d56Sopenharmony_ci sys.modules[modname] = MyModule() 1197db96d56Sopenharmony_ci self.addCleanup(operator.delitem, sys.modules, modname) 1207db96d56Sopenharmony_ci g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt') 1217db96d56Sopenharmony_ci self.assertEqual(g.elephant, 19) 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ciclass GrammarTest(support.TestCase): 1257db96d56Sopenharmony_ci def validate(self, code): 1267db96d56Sopenharmony_ci support.parse_string(code) 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci def invalid_syntax(self, code): 1297db96d56Sopenharmony_ci try: 1307db96d56Sopenharmony_ci self.validate(code) 1317db96d56Sopenharmony_ci except ParseError: 1327db96d56Sopenharmony_ci pass 1337db96d56Sopenharmony_ci else: 1347db96d56Sopenharmony_ci raise AssertionError("Syntax shouldn't have been valid") 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ciclass TestMatrixMultiplication(GrammarTest): 1387db96d56Sopenharmony_ci def test_matrix_multiplication_operator(self): 1397db96d56Sopenharmony_ci self.validate("a @ b") 1407db96d56Sopenharmony_ci self.validate("a @= b") 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ciclass TestYieldFrom(GrammarTest): 1447db96d56Sopenharmony_ci def test_yield_from(self): 1457db96d56Sopenharmony_ci self.validate("yield from x") 1467db96d56Sopenharmony_ci self.validate("(yield from x) + y") 1477db96d56Sopenharmony_ci self.invalid_syntax("yield from") 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ciclass TestAsyncAwait(GrammarTest): 1517db96d56Sopenharmony_ci def test_await_expr(self): 1527db96d56Sopenharmony_ci self.validate("""async def foo(): 1537db96d56Sopenharmony_ci await x 1547db96d56Sopenharmony_ci """) 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci self.validate("""async def foo(): 1577db96d56Sopenharmony_ci [i async for i in b] 1587db96d56Sopenharmony_ci """) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci self.validate("""async def foo(): 1617db96d56Sopenharmony_ci {i for i in b 1627db96d56Sopenharmony_ci async for i in a if await i 1637db96d56Sopenharmony_ci for b in i} 1647db96d56Sopenharmony_ci """) 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci self.validate("""async def foo(): 1677db96d56Sopenharmony_ci [await i for i in b if await c] 1687db96d56Sopenharmony_ci """) 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ci self.validate("""async def foo(): 1717db96d56Sopenharmony_ci [ i for i in b if c] 1727db96d56Sopenharmony_ci """) 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci self.validate("""async def foo(): 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci def foo(): pass 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci def foo(): pass 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci await x 1817db96d56Sopenharmony_ci """) 1827db96d56Sopenharmony_ci 1837db96d56Sopenharmony_ci self.validate("""async def foo(): return await a""") 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci self.validate("""def foo(): 1867db96d56Sopenharmony_ci def foo(): pass 1877db96d56Sopenharmony_ci async def foo(): await x 1887db96d56Sopenharmony_ci """) 1897db96d56Sopenharmony_ci 1907db96d56Sopenharmony_ci self.invalid_syntax("await x") 1917db96d56Sopenharmony_ci self.invalid_syntax("""def foo(): 1927db96d56Sopenharmony_ci await x""") 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci self.invalid_syntax("""def foo(): 1957db96d56Sopenharmony_ci def foo(): pass 1967db96d56Sopenharmony_ci async def foo(): pass 1977db96d56Sopenharmony_ci await x 1987db96d56Sopenharmony_ci """) 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci def test_async_var(self): 2017db96d56Sopenharmony_ci self.validate("""async = 1""") 2027db96d56Sopenharmony_ci self.validate("""await = 1""") 2037db96d56Sopenharmony_ci self.validate("""def async(): pass""") 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci def test_async_for(self): 2067db96d56Sopenharmony_ci self.validate("""async def foo(): 2077db96d56Sopenharmony_ci async for a in b: pass""") 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci def test_async_with(self): 2107db96d56Sopenharmony_ci self.validate("""async def foo(): 2117db96d56Sopenharmony_ci async with a: pass""") 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci self.invalid_syntax("""def foo(): 2147db96d56Sopenharmony_ci async with a: pass""") 2157db96d56Sopenharmony_ci 2167db96d56Sopenharmony_ci def test_async_generator(self): 2177db96d56Sopenharmony_ci self.validate( 2187db96d56Sopenharmony_ci """async def foo(): 2197db96d56Sopenharmony_ci return (i * 2 async for i in arange(42))""" 2207db96d56Sopenharmony_ci ) 2217db96d56Sopenharmony_ci self.validate( 2227db96d56Sopenharmony_ci """def foo(): 2237db96d56Sopenharmony_ci return (i * 2 async for i in arange(42))""" 2247db96d56Sopenharmony_ci ) 2257db96d56Sopenharmony_ci 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ciclass TestRaiseChanges(GrammarTest): 2287db96d56Sopenharmony_ci def test_2x_style_1(self): 2297db96d56Sopenharmony_ci self.validate("raise") 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci def test_2x_style_2(self): 2327db96d56Sopenharmony_ci self.validate("raise E, V") 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci def test_2x_style_3(self): 2357db96d56Sopenharmony_ci self.validate("raise E, V, T") 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci def test_2x_style_invalid_1(self): 2387db96d56Sopenharmony_ci self.invalid_syntax("raise E, V, T, Z") 2397db96d56Sopenharmony_ci 2407db96d56Sopenharmony_ci def test_3x_style(self): 2417db96d56Sopenharmony_ci self.validate("raise E1 from E2") 2427db96d56Sopenharmony_ci 2437db96d56Sopenharmony_ci def test_3x_style_invalid_1(self): 2447db96d56Sopenharmony_ci self.invalid_syntax("raise E, V from E1") 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci def test_3x_style_invalid_2(self): 2477db96d56Sopenharmony_ci self.invalid_syntax("raise E from E1, E2") 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci def test_3x_style_invalid_3(self): 2507db96d56Sopenharmony_ci self.invalid_syntax("raise from E1, E2") 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci def test_3x_style_invalid_4(self): 2537db96d56Sopenharmony_ci self.invalid_syntax("raise E from") 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci# Modelled after Lib/test/test_grammar.py:TokenTests.test_funcdef issue2292 2577db96d56Sopenharmony_ci# and Lib/test/text_parser.py test_list_displays, test_set_displays, 2587db96d56Sopenharmony_ci# test_dict_displays, test_argument_unpacking, ... changes. 2597db96d56Sopenharmony_ciclass TestUnpackingGeneralizations(GrammarTest): 2607db96d56Sopenharmony_ci def test_mid_positional_star(self): 2617db96d56Sopenharmony_ci self.validate("""func(1, *(2, 3), 4)""") 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_ci def test_double_star_dict_literal(self): 2647db96d56Sopenharmony_ci self.validate("""func(**{'eggs':'scrambled', 'spam':'fried'})""") 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_ci def test_double_star_dict_literal_after_keywords(self): 2677db96d56Sopenharmony_ci self.validate("""func(spam='fried', **{'eggs':'scrambled'})""") 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci def test_double_star_expression(self): 2707db96d56Sopenharmony_ci self.validate("""func(**{'a':2} or {})""") 2717db96d56Sopenharmony_ci self.validate("""func(**() or {})""") 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci def test_star_expression(self): 2747db96d56Sopenharmony_ci self.validate("""func(*[] or [2])""") 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci def test_list_display(self): 2777db96d56Sopenharmony_ci self.validate("""[*{2}, 3, *[4]]""") 2787db96d56Sopenharmony_ci 2797db96d56Sopenharmony_ci def test_set_display(self): 2807db96d56Sopenharmony_ci self.validate("""{*{2}, 3, *[4]}""") 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci def test_dict_display_1(self): 2837db96d56Sopenharmony_ci self.validate("""{**{}}""") 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_ci def test_dict_display_2(self): 2867db96d56Sopenharmony_ci self.validate("""{**{}, 3:4, **{5:6, 7:8}}""") 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci def test_complex_star_expression(self): 2897db96d56Sopenharmony_ci self.validate("func(* [] or [1])") 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci def test_complex_double_star_expression(self): 2927db96d56Sopenharmony_ci self.validate("func(**{1: 3} if False else {x: x for x in range(3)})") 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci def test_argument_unpacking_1(self): 2957db96d56Sopenharmony_ci self.validate("""f(a, *b, *c, d)""") 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ci def test_argument_unpacking_2(self): 2987db96d56Sopenharmony_ci self.validate("""f(**a, **b)""") 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci def test_argument_unpacking_3(self): 3017db96d56Sopenharmony_ci self.validate("""f(2, *a, *b, **b, **c, **d)""") 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci def test_trailing_commas_1(self): 3047db96d56Sopenharmony_ci self.validate("def f(a, b): call(a, b)") 3057db96d56Sopenharmony_ci self.validate("def f(a, b,): call(a, b,)") 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def test_trailing_commas_2(self): 3087db96d56Sopenharmony_ci self.validate("def f(a, *b): call(a, *b)") 3097db96d56Sopenharmony_ci self.validate("def f(a, *b,): call(a, *b,)") 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci def test_trailing_commas_3(self): 3127db96d56Sopenharmony_ci self.validate("def f(a, b=1): call(a, b=1)") 3137db96d56Sopenharmony_ci self.validate("def f(a, b=1,): call(a, b=1,)") 3147db96d56Sopenharmony_ci 3157db96d56Sopenharmony_ci def test_trailing_commas_4(self): 3167db96d56Sopenharmony_ci self.validate("def f(a, **b): call(a, **b)") 3177db96d56Sopenharmony_ci self.validate("def f(a, **b,): call(a, **b,)") 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci def test_trailing_commas_5(self): 3207db96d56Sopenharmony_ci self.validate("def f(*a, b=1): call(*a, b=1)") 3217db96d56Sopenharmony_ci self.validate("def f(*a, b=1,): call(*a, b=1,)") 3227db96d56Sopenharmony_ci 3237db96d56Sopenharmony_ci def test_trailing_commas_6(self): 3247db96d56Sopenharmony_ci self.validate("def f(*a, **b): call(*a, **b)") 3257db96d56Sopenharmony_ci self.validate("def f(*a, **b,): call(*a, **b,)") 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci def test_trailing_commas_7(self): 3287db96d56Sopenharmony_ci self.validate("def f(*, b=1): call(*b)") 3297db96d56Sopenharmony_ci self.validate("def f(*, b=1,): call(*b,)") 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci def test_trailing_commas_8(self): 3327db96d56Sopenharmony_ci self.validate("def f(a=1, b=2): call(a=1, b=2)") 3337db96d56Sopenharmony_ci self.validate("def f(a=1, b=2,): call(a=1, b=2,)") 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci def test_trailing_commas_9(self): 3367db96d56Sopenharmony_ci self.validate("def f(a=1, **b): call(a=1, **b)") 3377db96d56Sopenharmony_ci self.validate("def f(a=1, **b,): call(a=1, **b,)") 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci def test_trailing_commas_lambda_1(self): 3407db96d56Sopenharmony_ci self.validate("f = lambda a, b: call(a, b)") 3417db96d56Sopenharmony_ci self.validate("f = lambda a, b,: call(a, b,)") 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci def test_trailing_commas_lambda_2(self): 3447db96d56Sopenharmony_ci self.validate("f = lambda a, *b: call(a, *b)") 3457db96d56Sopenharmony_ci self.validate("f = lambda a, *b,: call(a, *b,)") 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci def test_trailing_commas_lambda_3(self): 3487db96d56Sopenharmony_ci self.validate("f = lambda a, b=1: call(a, b=1)") 3497db96d56Sopenharmony_ci self.validate("f = lambda a, b=1,: call(a, b=1,)") 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci def test_trailing_commas_lambda_4(self): 3527db96d56Sopenharmony_ci self.validate("f = lambda a, **b: call(a, **b)") 3537db96d56Sopenharmony_ci self.validate("f = lambda a, **b,: call(a, **b,)") 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci def test_trailing_commas_lambda_5(self): 3567db96d56Sopenharmony_ci self.validate("f = lambda *a, b=1: call(*a, b=1)") 3577db96d56Sopenharmony_ci self.validate("f = lambda *a, b=1,: call(*a, b=1,)") 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci def test_trailing_commas_lambda_6(self): 3607db96d56Sopenharmony_ci self.validate("f = lambda *a, **b: call(*a, **b)") 3617db96d56Sopenharmony_ci self.validate("f = lambda *a, **b,: call(*a, **b,)") 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci def test_trailing_commas_lambda_7(self): 3647db96d56Sopenharmony_ci self.validate("f = lambda *, b=1: call(*b)") 3657db96d56Sopenharmony_ci self.validate("f = lambda *, b=1,: call(*b,)") 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci def test_trailing_commas_lambda_8(self): 3687db96d56Sopenharmony_ci self.validate("f = lambda a=1, b=2: call(a=1, b=2)") 3697db96d56Sopenharmony_ci self.validate("f = lambda a=1, b=2,: call(a=1, b=2,)") 3707db96d56Sopenharmony_ci 3717db96d56Sopenharmony_ci def test_trailing_commas_lambda_9(self): 3727db96d56Sopenharmony_ci self.validate("f = lambda a=1, **b: call(a=1, **b)") 3737db96d56Sopenharmony_ci self.validate("f = lambda a=1, **b,: call(a=1, **b,)") 3747db96d56Sopenharmony_ci 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.testFuncdef 3777db96d56Sopenharmony_ciclass TestFunctionAnnotations(GrammarTest): 3787db96d56Sopenharmony_ci def test_1(self): 3797db96d56Sopenharmony_ci self.validate("""def f(x) -> list: pass""") 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ci def test_2(self): 3827db96d56Sopenharmony_ci self.validate("""def f(x:int): pass""") 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci def test_3(self): 3857db96d56Sopenharmony_ci self.validate("""def f(*x:str): pass""") 3867db96d56Sopenharmony_ci 3877db96d56Sopenharmony_ci def test_4(self): 3887db96d56Sopenharmony_ci self.validate("""def f(**x:float): pass""") 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci def test_5(self): 3917db96d56Sopenharmony_ci self.validate("""def f(x, y:1+2): pass""") 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci def test_6(self): 3947db96d56Sopenharmony_ci self.validate("""def f(a, (b:1, c:2, d)): pass""") 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci def test_7(self): 3977db96d56Sopenharmony_ci self.validate("""def f(a, (b:1, c:2, d), e:3=4, f=5, *g:6): pass""") 3987db96d56Sopenharmony_ci 3997db96d56Sopenharmony_ci def test_8(self): 4007db96d56Sopenharmony_ci s = """def f(a, (b:1, c:2, d), e:3=4, f=5, 4017db96d56Sopenharmony_ci *g:6, h:7, i=8, j:9=10, **k:11) -> 12: pass""" 4027db96d56Sopenharmony_ci self.validate(s) 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci def test_9(self): 4057db96d56Sopenharmony_ci s = """def f( 4067db96d56Sopenharmony_ci a: str, 4077db96d56Sopenharmony_ci b: int, 4087db96d56Sopenharmony_ci *, 4097db96d56Sopenharmony_ci c: bool = False, 4107db96d56Sopenharmony_ci **kwargs, 4117db96d56Sopenharmony_ci ) -> None: 4127db96d56Sopenharmony_ci call(c=c, **kwargs,)""" 4137db96d56Sopenharmony_ci self.validate(s) 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci def test_10(self): 4167db96d56Sopenharmony_ci s = """def f( 4177db96d56Sopenharmony_ci a: str, 4187db96d56Sopenharmony_ci ) -> None: 4197db96d56Sopenharmony_ci call(a,)""" 4207db96d56Sopenharmony_ci self.validate(s) 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci def test_11(self): 4237db96d56Sopenharmony_ci s = """def f( 4247db96d56Sopenharmony_ci a: str = '', 4257db96d56Sopenharmony_ci ) -> None: 4267db96d56Sopenharmony_ci call(a=a,)""" 4277db96d56Sopenharmony_ci self.validate(s) 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci def test_12(self): 4307db96d56Sopenharmony_ci s = """def f( 4317db96d56Sopenharmony_ci *args: str, 4327db96d56Sopenharmony_ci ) -> None: 4337db96d56Sopenharmony_ci call(*args,)""" 4347db96d56Sopenharmony_ci self.validate(s) 4357db96d56Sopenharmony_ci 4367db96d56Sopenharmony_ci def test_13(self): 4377db96d56Sopenharmony_ci self.validate("def f(a: str, b: int) -> None: call(a, b)") 4387db96d56Sopenharmony_ci self.validate("def f(a: str, b: int,) -> None: call(a, b,)") 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci def test_14(self): 4417db96d56Sopenharmony_ci self.validate("def f(a: str, *b: int) -> None: call(a, *b)") 4427db96d56Sopenharmony_ci self.validate("def f(a: str, *b: int,) -> None: call(a, *b,)") 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci def test_15(self): 4457db96d56Sopenharmony_ci self.validate("def f(a: str, b: int=1) -> None: call(a, b=1)") 4467db96d56Sopenharmony_ci self.validate("def f(a: str, b: int=1,) -> None: call(a, b=1,)") 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ci def test_16(self): 4497db96d56Sopenharmony_ci self.validate("def f(a: str, **b: int) -> None: call(a, **b)") 4507db96d56Sopenharmony_ci self.validate("def f(a: str, **b: int,) -> None: call(a, **b,)") 4517db96d56Sopenharmony_ci 4527db96d56Sopenharmony_ci def test_17(self): 4537db96d56Sopenharmony_ci self.validate("def f(*a: str, b: int=1) -> None: call(*a, b=1)") 4547db96d56Sopenharmony_ci self.validate("def f(*a: str, b: int=1,) -> None: call(*a, b=1,)") 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci def test_18(self): 4577db96d56Sopenharmony_ci self.validate("def f(*a: str, **b: int) -> None: call(*a, **b)") 4587db96d56Sopenharmony_ci self.validate("def f(*a: str, **b: int,) -> None: call(*a, **b,)") 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ci def test_19(self): 4617db96d56Sopenharmony_ci self.validate("def f(*, b: int=1) -> None: call(*b)") 4627db96d56Sopenharmony_ci self.validate("def f(*, b: int=1,) -> None: call(*b,)") 4637db96d56Sopenharmony_ci 4647db96d56Sopenharmony_ci def test_20(self): 4657db96d56Sopenharmony_ci self.validate("def f(a: str='', b: int=2) -> None: call(a=a, b=2)") 4667db96d56Sopenharmony_ci self.validate("def f(a: str='', b: int=2,) -> None: call(a=a, b=2,)") 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci def test_21(self): 4697db96d56Sopenharmony_ci self.validate("def f(a: str='', **b: int) -> None: call(a=a, **b)") 4707db96d56Sopenharmony_ci self.validate("def f(a: str='', **b: int,) -> None: call(a=a, **b,)") 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci 4737db96d56Sopenharmony_ci# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.test_var_annot 4747db96d56Sopenharmony_ciclass TestVarAnnotations(GrammarTest): 4757db96d56Sopenharmony_ci def test_1(self): 4767db96d56Sopenharmony_ci self.validate("var1: int = 5") 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci def test_2(self): 4797db96d56Sopenharmony_ci self.validate("var2: [int, str]") 4807db96d56Sopenharmony_ci 4817db96d56Sopenharmony_ci def test_3(self): 4827db96d56Sopenharmony_ci self.validate("def f():\n" 4837db96d56Sopenharmony_ci " st: str = 'Hello'\n" 4847db96d56Sopenharmony_ci " a.b: int = (1, 2)\n" 4857db96d56Sopenharmony_ci " return st\n") 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_ci def test_4(self): 4887db96d56Sopenharmony_ci self.validate("def fbad():\n" 4897db96d56Sopenharmony_ci " x: int\n" 4907db96d56Sopenharmony_ci " print(x)\n") 4917db96d56Sopenharmony_ci 4927db96d56Sopenharmony_ci def test_5(self): 4937db96d56Sopenharmony_ci self.validate("class C:\n" 4947db96d56Sopenharmony_ci " x: int\n" 4957db96d56Sopenharmony_ci " s: str = 'attr'\n" 4967db96d56Sopenharmony_ci " z = 2\n" 4977db96d56Sopenharmony_ci " def __init__(self, x):\n" 4987db96d56Sopenharmony_ci " self.x: int = x\n") 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ci def test_6(self): 5017db96d56Sopenharmony_ci self.validate("lst: List[int] = []") 5027db96d56Sopenharmony_ci 5037db96d56Sopenharmony_ci 5047db96d56Sopenharmony_ciclass TestExcept(GrammarTest): 5057db96d56Sopenharmony_ci def test_new(self): 5067db96d56Sopenharmony_ci s = """ 5077db96d56Sopenharmony_ci try: 5087db96d56Sopenharmony_ci x 5097db96d56Sopenharmony_ci except E as N: 5107db96d56Sopenharmony_ci y""" 5117db96d56Sopenharmony_ci self.validate(s) 5127db96d56Sopenharmony_ci 5137db96d56Sopenharmony_ci def test_old(self): 5147db96d56Sopenharmony_ci s = """ 5157db96d56Sopenharmony_ci try: 5167db96d56Sopenharmony_ci x 5177db96d56Sopenharmony_ci except E, N: 5187db96d56Sopenharmony_ci y""" 5197db96d56Sopenharmony_ci self.validate(s) 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ciclass TestStringLiterals(GrammarTest): 5237db96d56Sopenharmony_ci prefixes = ("'", '"', 5247db96d56Sopenharmony_ci "r'", 'r"', "R'", 'R"', 5257db96d56Sopenharmony_ci "u'", 'u"', "U'", 'U"', 5267db96d56Sopenharmony_ci "b'", 'b"', "B'", 'B"', 5277db96d56Sopenharmony_ci "f'", 'f"', "F'", 'F"', 5287db96d56Sopenharmony_ci "ur'", 'ur"', "Ur'", 'Ur"', 5297db96d56Sopenharmony_ci "uR'", 'uR"', "UR'", 'UR"', 5307db96d56Sopenharmony_ci "br'", 'br"', "Br'", 'Br"', 5317db96d56Sopenharmony_ci "bR'", 'bR"', "BR'", 'BR"', 5327db96d56Sopenharmony_ci "rb'", 'rb"', "Rb'", 'Rb"', 5337db96d56Sopenharmony_ci "rB'", 'rB"', "RB'", 'RB"',) 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci def test_lit(self): 5367db96d56Sopenharmony_ci for pre in self.prefixes: 5377db96d56Sopenharmony_ci single = "{p}spamspamspam{s}".format(p=pre, s=pre[-1]) 5387db96d56Sopenharmony_ci self.validate(single) 5397db96d56Sopenharmony_ci triple = "{p}{s}{s}eggs{s}{s}{s}".format(p=pre, s=pre[-1]) 5407db96d56Sopenharmony_ci self.validate(triple) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci# Adapted from Python 3's Lib/test/test_grammar.py:GrammarTests.testAtoms 5447db96d56Sopenharmony_ciclass TestSetLiteral(GrammarTest): 5457db96d56Sopenharmony_ci def test_1(self): 5467db96d56Sopenharmony_ci self.validate("""x = {'one'}""") 5477db96d56Sopenharmony_ci 5487db96d56Sopenharmony_ci def test_2(self): 5497db96d56Sopenharmony_ci self.validate("""x = {'one', 1,}""") 5507db96d56Sopenharmony_ci 5517db96d56Sopenharmony_ci def test_3(self): 5527db96d56Sopenharmony_ci self.validate("""x = {'one', 'two', 'three'}""") 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci def test_4(self): 5557db96d56Sopenharmony_ci self.validate("""x = {2, 3, 4,}""") 5567db96d56Sopenharmony_ci 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci# Adapted from Python 3's Lib/test/test_unicode_identifiers.py and 5597db96d56Sopenharmony_ci# Lib/test/test_tokenize.py:TokenizeTest.test_non_ascii_identifiers 5607db96d56Sopenharmony_ciclass TestIdentifier(GrammarTest): 5617db96d56Sopenharmony_ci def test_non_ascii_identifiers(self): 5627db96d56Sopenharmony_ci self.validate("Örter = 'places'\ngrün = 'green'") 5637db96d56Sopenharmony_ci self.validate("蟒 = a蟒 = 锦蛇 = 1") 5647db96d56Sopenharmony_ci self.validate("µ = aµ = µµ = 1") 5657db96d56Sopenharmony_ci self.validate(" = a_ = 1") 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ciclass TestNumericLiterals(GrammarTest): 5697db96d56Sopenharmony_ci def test_new_octal_notation(self): 5707db96d56Sopenharmony_ci self.validate("""0o7777777777777""") 5717db96d56Sopenharmony_ci self.invalid_syntax("""0o7324528887""") 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci def test_new_binary_notation(self): 5747db96d56Sopenharmony_ci self.validate("""0b101010""") 5757db96d56Sopenharmony_ci self.invalid_syntax("""0b0101021""") 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_ci 5787db96d56Sopenharmony_ciclass TestClassDef(GrammarTest): 5797db96d56Sopenharmony_ci def test_new_syntax(self): 5807db96d56Sopenharmony_ci self.validate("class B(t=7): pass") 5817db96d56Sopenharmony_ci self.validate("class B(t, *args): pass") 5827db96d56Sopenharmony_ci self.validate("class B(t, **kwargs): pass") 5837db96d56Sopenharmony_ci self.validate("class B(t, *args, **kwargs): pass") 5847db96d56Sopenharmony_ci self.validate("class B(t, y=9, *args, **kwargs,): pass") 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ciclass TestParserIdempotency(support.TestCase): 5887db96d56Sopenharmony_ci 5897db96d56Sopenharmony_ci """A cut-down version of pytree_idempotency.py.""" 5907db96d56Sopenharmony_ci 5917db96d56Sopenharmony_ci def parse_file(self, filepath): 5927db96d56Sopenharmony_ci if test.support.verbose: 5937db96d56Sopenharmony_ci print(f"Parse file: {filepath}") 5947db96d56Sopenharmony_ci with open(filepath, "rb") as fp: 5957db96d56Sopenharmony_ci encoding = tokenize.detect_encoding(fp.readline)[0] 5967db96d56Sopenharmony_ci self.assertIsNotNone(encoding, 5977db96d56Sopenharmony_ci "can't detect encoding for %s" % filepath) 5987db96d56Sopenharmony_ci with open(filepath, "r", encoding=encoding) as fp: 5997db96d56Sopenharmony_ci source = fp.read() 6007db96d56Sopenharmony_ci try: 6017db96d56Sopenharmony_ci tree = driver.parse_string(source) 6027db96d56Sopenharmony_ci except ParseError: 6037db96d56Sopenharmony_ci try: 6047db96d56Sopenharmony_ci tree = driver_no_print_statement.parse_string(source) 6057db96d56Sopenharmony_ci except ParseError as err: 6067db96d56Sopenharmony_ci self.fail('ParseError on file %s (%s)' % (filepath, err)) 6077db96d56Sopenharmony_ci new = str(tree) 6087db96d56Sopenharmony_ci if new != source: 6097db96d56Sopenharmony_ci print(diff_texts(source, new, filepath)) 6107db96d56Sopenharmony_ci self.fail("Idempotency failed: %s" % filepath) 6117db96d56Sopenharmony_ci 6127db96d56Sopenharmony_ci def test_all_project_files(self): 6137db96d56Sopenharmony_ci for filepath in support.all_project_files(): 6147db96d56Sopenharmony_ci with self.subTest(filepath=filepath): 6157db96d56Sopenharmony_ci self.parse_file(filepath) 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_ci def test_extended_unpacking(self): 6187db96d56Sopenharmony_ci driver.parse_string("a, *b, c = x\n") 6197db96d56Sopenharmony_ci driver.parse_string("[*a, b] = x\n") 6207db96d56Sopenharmony_ci driver.parse_string("(z, *y, w) = m\n") 6217db96d56Sopenharmony_ci driver.parse_string("for *z, m in d: pass\n") 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ciclass TestLiterals(GrammarTest): 6257db96d56Sopenharmony_ci 6267db96d56Sopenharmony_ci def validate(self, s): 6277db96d56Sopenharmony_ci driver.parse_string(support.dedent(s) + "\n\n") 6287db96d56Sopenharmony_ci 6297db96d56Sopenharmony_ci def test_multiline_bytes_literals(self): 6307db96d56Sopenharmony_ci s = """ 6317db96d56Sopenharmony_ci md5test(b"\xaa" * 80, 6327db96d56Sopenharmony_ci (b"Test Using Larger Than Block-Size Key " 6337db96d56Sopenharmony_ci b"and Larger Than One Block-Size Data"), 6347db96d56Sopenharmony_ci "6f630fad67cda0ee1fb1f562db3aa53e") 6357db96d56Sopenharmony_ci """ 6367db96d56Sopenharmony_ci self.validate(s) 6377db96d56Sopenharmony_ci 6387db96d56Sopenharmony_ci def test_multiline_bytes_tripquote_literals(self): 6397db96d56Sopenharmony_ci s = ''' 6407db96d56Sopenharmony_ci b""" 6417db96d56Sopenharmony_ci <?xml version="1.0" encoding="UTF-8"?> 6427db96d56Sopenharmony_ci <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"> 6437db96d56Sopenharmony_ci """ 6447db96d56Sopenharmony_ci ''' 6457db96d56Sopenharmony_ci self.validate(s) 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ci def test_multiline_str_literals(self): 6487db96d56Sopenharmony_ci s = """ 6497db96d56Sopenharmony_ci md5test("\xaa" * 80, 6507db96d56Sopenharmony_ci ("Test Using Larger Than Block-Size Key " 6517db96d56Sopenharmony_ci "and Larger Than One Block-Size Data"), 6527db96d56Sopenharmony_ci "6f630fad67cda0ee1fb1f562db3aa53e") 6537db96d56Sopenharmony_ci """ 6547db96d56Sopenharmony_ci self.validate(s) 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci 6577db96d56Sopenharmony_ciclass TestNamedAssignments(GrammarTest): 6587db96d56Sopenharmony_ci """Also known as the walrus operator.""" 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci def test_named_assignment_if(self): 6617db96d56Sopenharmony_ci driver.parse_string("if f := x(): pass\n") 6627db96d56Sopenharmony_ci 6637db96d56Sopenharmony_ci def test_named_assignment_while(self): 6647db96d56Sopenharmony_ci driver.parse_string("while f := x(): pass\n") 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_ci def test_named_assignment_generator(self): 6677db96d56Sopenharmony_ci driver.parse_string("any((lastNum := num) == 1 for num in [1, 2, 3])\n") 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci def test_named_assignment_listcomp(self): 6707db96d56Sopenharmony_ci driver.parse_string("[(lastNum := num) == 1 for num in [1, 2, 3]]\n") 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ciclass TestPositionalOnlyArgs(GrammarTest): 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci def test_one_pos_only_arg(self): 6767db96d56Sopenharmony_ci driver.parse_string("def one_pos_only_arg(a, /): pass\n") 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ci def test_all_markers(self): 6797db96d56Sopenharmony_ci driver.parse_string( 6807db96d56Sopenharmony_ci "def all_markers(a, b=2, /, c, d=4, *, e=5, f): pass\n") 6817db96d56Sopenharmony_ci 6827db96d56Sopenharmony_ci def test_all_with_args_and_kwargs(self): 6837db96d56Sopenharmony_ci driver.parse_string( 6847db96d56Sopenharmony_ci """def all_markers_with_args_and_kwargs( 6857db96d56Sopenharmony_ci aa, b, /, _cc, d, *args, e, f_f, **kwargs, 6867db96d56Sopenharmony_ci ): 6877db96d56Sopenharmony_ci pass\n""") 6887db96d56Sopenharmony_ci 6897db96d56Sopenharmony_ci def test_lambda_soup(self): 6907db96d56Sopenharmony_ci driver.parse_string( 6917db96d56Sopenharmony_ci "lambda a, b, /, c, d, *args, e, f, **kw: kw\n") 6927db96d56Sopenharmony_ci 6937db96d56Sopenharmony_ci def test_only_positional_or_keyword(self): 6947db96d56Sopenharmony_ci driver.parse_string("def func(a,b,/,*,g,e=3): pass\n") 6957db96d56Sopenharmony_ci 6967db96d56Sopenharmony_ci 6977db96d56Sopenharmony_ciclass TestPickleableException(unittest.TestCase): 6987db96d56Sopenharmony_ci def test_ParseError(self): 6997db96d56Sopenharmony_ci err = ParseError('msg', 2, None, (1, 'context')) 7007db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 7017db96d56Sopenharmony_ci err2 = pickle.loads(pickle.dumps(err, protocol=proto)) 7027db96d56Sopenharmony_ci self.assertEqual(err.args, err2.args) 7037db96d56Sopenharmony_ci self.assertEqual(err.msg, err2.msg) 7047db96d56Sopenharmony_ci self.assertEqual(err.type, err2.type) 7057db96d56Sopenharmony_ci self.assertEqual(err.value, err2.value) 7067db96d56Sopenharmony_ci self.assertEqual(err.context, err2.context) 7077db96d56Sopenharmony_ci 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_cidef diff_texts(a, b, filename): 7107db96d56Sopenharmony_ci a = a.splitlines() 7117db96d56Sopenharmony_ci b = b.splitlines() 7127db96d56Sopenharmony_ci return difflib.unified_diff(a, b, filename, filename, 7137db96d56Sopenharmony_ci "(original)", "(reserialized)", 7147db96d56Sopenharmony_ci lineterm="") 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_ci 7177db96d56Sopenharmony_ciif __name__ == '__main__': 7187db96d56Sopenharmony_ci unittest.main() 719