@@ -1943,6 +1943,75 @@ def test_keyword_replay_respects_feature_version(self):
19431943 ast .parse (source , feature_version = (3 , 9 ))
19441944 self .assertIsNone (caught .exception ._metadata )
19451945
1946+ @cpython_only
1947+ def test_keyword_trials_reject_invalid_literals (self ):
1948+ for literal in ("b'é'" , r"'\xzz'" , r"'\U00110000'" ):
1949+ for mode in ("exec" , "eval" , "single" ):
1950+ source = "npt " + literal
1951+ with self .subTest (source = source , mode = mode ):
1952+ with self .assertRaises (SyntaxError ) as caught :
1953+ compile (source , "<test>" , mode )
1954+ self .assertIsNone (caught .exception ._metadata )
1955+
1956+ @cpython_only
1957+ @requires_subprocess ()
1958+ def test_keyword_trials_do_not_call_literal_hooks (self ):
1959+ assert_python_ok ('-c' , textwrap .dedent (r'''
1960+ import codecs, sys, _pylong
1961+ calls = []
1962+
1963+ def forbidden(*args):
1964+ calls.append(args)
1965+ raise AssertionError("literal callback")
1966+
1967+ class WatchImports:
1968+ def find_spec(self, fullname, path=None, target=None):
1969+ if fullname == "unicodedata":
1970+ forbidden(fullname)
1971+
1972+ sys.meta_path.insert(0, WatchImports())
1973+ codecs.register_error("strict", forbidden)
1974+ _pylong.int_from_string = forbidden
1975+ sys.set_int_max_str_digits(0)
1976+ literals = [(r"'\N{SNOWMAN}'", False), (r"'\xzz'", False),
1977+ (r"'\U00110000'", False), (r"f'\xzz'", False),
1978+ (r"t'\xzz'", False), ("1" * 6001, False),
1979+ (r"'\x61\u0062\U00000063'", True),
1980+ (r"r'\N{SNOWMAN}'", True), (r"'\\N{SNOWMAN}'", True),
1981+ (r"f'\x61{1}'", True), (r"t'\x61{1}'", True)]
1982+ for literal, expected in literals:
1983+ try:
1984+ compile("impor math\nx = " + literal, "<test>", "exec")
1985+ except SyntaxError as error:
1986+ assert (error._metadata is not None) == expected, literal
1987+ else:
1988+ raise AssertionError(literal)
1989+ assert calls == [], calls
1990+ # A cached Unicode name table must not change the trial policy.
1991+ sys.meta_path.pop(0)
1992+ compile(r"x = '\N{SNOWMAN}'", "<test>", "exec")
1993+ try:
1994+ compile("impor math\nx = " + literals[0][0], "<test>", "exec")
1995+ except SyntaxError as error:
1996+ assert error._metadata is None
1997+ # The normal decoder must still honor registered error handlers.
1998+ try:
1999+ br"\xzz".decode("unicode_escape")
2000+ except AssertionError:
2001+ pass
2002+ assert len(calls) == 1, calls
2003+ ''' ))
2004+
2005+ @cpython_only
2006+ def test_keyword_trials_numeric_limit (self ):
2007+ for digits , expected in ((640 , True ), (641 , False )):
2008+ with self .subTest (digits = digits ):
2009+ source = "x = " + "1" * digits
2010+ compile (source , "<test>" , "exec" )
2011+ with self .assertRaises (SyntaxError ) as caught :
2012+ compile ("impor math\n " + source , "<test>" , "exec" )
2013+ self .assertEqual (caught .exception ._metadata is not None , expected )
2014+
19462015 @cpython_only
19472016 def test_keyword_trials_do_not_call_normalizer (self ):
19482017 with unittest .mock .patch ("unicodedata.normalize" ) as normalize :
0 commit comments