@@ -96,30 +96,6 @@ def test_literal(self):
9696 self .assertEqual (f'' , '' )
9797 self .assertEqual (f'a' , 'a' )
9898 self .assertEqual (f' ' , ' ' )
99- self .assertEqual (f'\N{GREEK CAPITAL LETTER DELTA} ' ,
100- '\N{GREEK CAPITAL LETTER DELTA} ' )
101- self .assertEqual (f'\N{GREEK CAPITAL LETTER DELTA} ' ,
102- '\u0394 ' )
103- self .assertEqual (f'\N{True} ' , '\u22a8 ' )
104- self .assertEqual (rf'\N{ True } ' , r'\NTrue' )
105-
106- def test_escape_order (self ):
107- # note that hex(ord('{')) == 0x7b, so this
108- # string becomes f'a{4*10}b'
109- self .assertEqual (f'a\u007b 4*10}b', ' a40b ')
110- self .assertEqual (f'a\x7b 4*10}b', ' a40b ')
111- self .assertEqual (f'a\x7b 4*10\N{RIGHT CURLY BRACKET} b' , 'a40b' )
112- self .assertEqual (f'{ "a" !\N{LATIN SMALL LETTER R} } ' , "'a'" )
113- self .assertEqual (f'{ 10 \x3a 02X}', ' 0 A ')
114- self .assertEqual (f'{ 10 :02\N{LATIN CAPITAL LETTER X }} ' , '0A' )
115-
116- self .assertAllRaise (SyntaxError , "f-string: single '}' is not allowed" ,
117- [r"""f'a{\u007b4*10}b'""" , # mis-matched brackets
118- ])
119- self .assertAllRaise (SyntaxError , 'unexpected character after line continuation character' ,
120- [r"""f'{"a"\!r}'""" ,
121- r"""f'{a\!r}'""" ,
122- ])
12399
124100 def test_unterminated_string (self ):
125101 self .assertAllRaise (SyntaxError , 'f-string: unterminated string' ,
@@ -285,8 +261,6 @@ def test_missing_expression(self):
285261 "f'{ !r}'" ,
286262 "f'{10:{ }}'" ,
287263 "f' { } '" ,
288- r"f'{\n}'" ,
289- r"f'{\n \n}'" ,
290264
291265 # Catch the empty expression before the
292266 # invalid conversion.
@@ -328,24 +302,61 @@ def test_parens_in_expressions(self):
328302 ["f'{\n }'" ,
329303 ])
330304
305+ def test_no_backslashes (self ):
306+ # See issue 27921
307+
308+ # These should work, but currently don't
309+ self .assertAllRaise (SyntaxError , 'backslashes not allowed' ,
310+ [r"f'\t'" ,
311+ r"f'{2}\t'" ,
312+ r"f'{2}\t{3}'" ,
313+ r"f'\t{3}'" ,
314+
315+ r"f'\N{GREEK CAPITAL LETTER DELTA}'" ,
316+ r"f'{2}\N{GREEK CAPITAL LETTER DELTA}'" ,
317+ r"f'{2}\N{GREEK CAPITAL LETTER DELTA}{3}'" ,
318+ r"f'\N{GREEK CAPITAL LETTER DELTA}{3}'" ,
319+
320+ r"f'\u0394'" ,
321+ r"f'{2}\u0394'" ,
322+ r"f'{2}\u0394{3}'" ,
323+ r"f'\u0394{3}'" ,
324+
325+ r"f'\U00000394'" ,
326+ r"f'{2}\U00000394'" ,
327+ r"f'{2}\U00000394{3}'" ,
328+ r"f'\U00000394{3}'" ,
329+
330+ r"f'\x20'" ,
331+ r"f'{2}\x20'" ,
332+ r"f'{2}\x20{3}'" ,
333+ r"f'\x20{3}'" ,
334+
335+ r"f'2\x20'" ,
336+ r"f'2\x203'" ,
337+ r"f'2\x203'" ,
338+ ])
339+
340+ # And these don't work now, and shouldn't work in the future.
341+ self .assertAllRaise (SyntaxError , 'backslashes not allowed' ,
342+ [r"f'{\'a\'}'" ,
343+ r"f'{\t3}'" ,
344+ ])
345+
346+ # add this when backslashes are allowed again. see issue 27921
347+ # these test will be needed because unicode names will be parsed
348+ # differently once backslashes are allowed inside expressions
349+ ## def test_misformed_unicode_character_name(self):
350+ ## self.assertAllRaise(SyntaxError, 'xx',
351+ ## [r"f'\N'",
352+ ## [r"f'\N{'",
353+ ## [r"f'\N{GREEK CAPITAL LETTER DELTA'",
354+ ## ])
355+
331356 def test_newlines_in_expressions (self ):
332357 self .assertEqual (f'{ 0 } ' , '0' )
333- self .assertEqual (f'{ 0 \n } ' , '0' )
334- self .assertEqual (f'{ 0 \r } ' , '0' )
335- self .assertEqual (f'{\n 0\n }', ' 0 ')
336- self .assertEqual (f'{\r 0\r }', ' 0 ')
337- self .assertEqual (f'{\n 0\r }', ' 0 ')
338- self .assertEqual (f'{ \n 0 } ' , '0' )
339- self .assertEqual (f'{ 3 + \n 4 } ' , '7' )
340- self .assertEqual (f'{ 3 + \\ \n 4 } ' , '7' )
341358 self .assertEqual (rf'''{ 3 +
3423594 } ''' , '7' )
343- self .assertEqual (f'''{ 3 + \
344- 4 } ''' , '7' )
345-
346- self .assertAllRaise (SyntaxError , 'f-string: empty expression not allowed' ,
347- [r"f'{\n}'" ,
348- ])
349360
350361 def test_lambda (self ):
351362 x = 5
@@ -380,9 +391,6 @@ def fn(x):
380391 def test_expressions_with_triple_quoted_strings (self ):
381392 self .assertEqual (f"{ '''x''' } " , 'x' )
382393 self .assertEqual (f"{ '''eric's''' } " , "eric's" )
383- self .assertEqual (f'{ """eric\' s""" } ' , "eric's" )
384- self .assertEqual (f"{ '''eric\" s''' } " , 'eric"s' )
385- self .assertEqual (f'{ """eric"s""" } ' , 'eric"s' )
386394
387395 # Test concatenation within an expression
388396 self .assertEqual (f'{ "x" """eric"s""" "y" } ' , 'xeric"sy' )
@@ -484,10 +492,6 @@ def test_nested_fstrings(self):
484492 y = 5
485493 self .assertEqual (f'{ f"{ 0 } " * 3 } ' , '000' )
486494 self .assertEqual (f'{ f"{ y } " * 3 } ' , '555' )
487- self .assertEqual (f'{ f"{\' x\' } " * 3 }', ' xxx ')
488-
489- self .assertEqual (f"{ r'x' f'{\" s\" } ' }", 'xs' )
490- self .assertEqual (f"{r'x' rf'{\"s\"}'}", ' xs ')
491495
492496 def test_invalid_string_prefixes (self ):
493497 self .assertAllRaise (SyntaxError , 'unexpected EOF while parsing' ,
@@ -510,24 +514,14 @@ def test_invalid_string_prefixes(self):
510514 def test_leading_trailing_spaces (self ):
511515 self .assertEqual (f'{ 3 } ' , '3' )
512516 self .assertEqual (f'{ 3 } ' , '3' )
513- self .assertEqual (f'{ \t 3 } ' , '3' )
514- self .assertEqual (f'{\t \t 3}', ' 3 ')
515517 self .assertEqual (f'{ 3 } ' , '3' )
516518 self .assertEqual (f'{ 3 } ' , '3' )
517- self .assertEqual (f'{ 3 \t } ' , '3' )
518- self .assertEqual (f'{ 3 \t \t }', ' 3 ')
519519
520520 self .assertEqual (f'expr={ {x : y for x , y in [(1 , 2 ), ]}} ' ,
521521 'expr={1: 2}' )
522522 self .assertEqual (f'expr={ {x : y for x , y in [(1 , 2 ), ]} } ' ,
523523 'expr={1: 2}' )
524524
525- def test_character_name (self ):
526- self .assertEqual (f'{ 4 } \N{GREEK CAPITAL LETTER DELTA} { 3 } ' ,
527- '4\N{GREEK CAPITAL LETTER DELTA} 3' )
528- self .assertEqual (f'{{}}\N{GREEK CAPITAL LETTER DELTA} { 3 } ' ,
529- '{}\N{GREEK CAPITAL LETTER DELTA} 3' )
530-
531525 def test_not_equal (self ):
532526 # There's a special test for this because there's a special
533527 # case in the f-string parser to look for != as not ending an
@@ -554,20 +548,14 @@ def test_conversions(self):
554548 # Not a conversion, but show that ! is allowed in a format spec.
555549 self .assertEqual (f'{ 3.14 :!<10.10} ' , '3.14!!!!!!' )
556550
557- self .assertEqual (f'{ "\N{GREEK CAPITAL LETTER DELTA} " } ' , '\u0394 ' )
558- self .assertEqual (f'{ "\N{GREEK CAPITAL LETTER DELTA} " !r} ' , "'\u0394 '" )
559- self .assertEqual (f'{ "\N{GREEK CAPITAL LETTER DELTA} " !a} ' , "'\\ u0394'" )
560-
561551 self .assertAllRaise (SyntaxError , 'f-string: invalid conversion character' ,
562552 ["f'{3!g}'" ,
563553 "f'{3!A}'" ,
564554 "f'{3!A}'" ,
565555 "f'{3!A}'" ,
566556 "f'{3!!}'" ,
567557 "f'{3!:}'" ,
568- "f'{3!\N{GREEK CAPITAL LETTER DELTA} }'" ,
569558 "f'{3! s}'" , # no space before conversion char
570- "f'{x!\\ x00:.<10}'" ,
571559 ])
572560
573561 self .assertAllRaise (SyntaxError , "f-string: expecting '}'" ,
@@ -600,7 +588,6 @@ def test_mismatched_braces(self):
600588
601589 # Can't have { or } in a format spec.
602590 "f'{3:}>10}'" ,
603- r"f'{3:\\}>10}'" ,
604591 "f'{3:}}>10}'" ,
605592 ])
606593
@@ -620,10 +607,6 @@ def test_mismatched_braces(self):
620607 "f'{'" ,
621608 ])
622609
623- self .assertAllRaise (SyntaxError , 'invalid syntax' ,
624- [r"f'{3:\\{>10}'" ,
625- ])
626-
627610 # But these are just normal strings.
628611 self .assertEqual (f'{ "{" } ' , '{' )
629612 self .assertEqual (f'{ "}" } ' , '}' )
@@ -712,34 +695,11 @@ def test_dict(self):
712695 "'" : 'squote' ,
713696 'foo' : 'bar' ,
714697 }
715- self .assertEqual (f'{ d ["\' " ]} ' , 'squote' )
716- self .assertEqual (f"{ d ['\" ' ]} " , 'dquote' )
717-
718698 self .assertEqual (f'''{ d ["'" ]} ''' , 'squote' )
719699 self .assertEqual (f"""{ d ['"' ]} """ , 'dquote' )
720700
721701 self .assertEqual (f'{ d ["foo" ]} ' , 'bar' )
722702 self .assertEqual (f"{ d ['foo' ]} " , 'bar' )
723- self .assertEqual (f'{d [\' foo\' ]}', ' bar ')
724- self .assertEqual (f"{d [\" foo\" ]}", 'bar' )
725-
726- def test_escaped_quotes (self ):
727- d = {'"' : 'a' ,
728- "'" : 'b' }
729-
730- self .assertEqual (fr"{ d ['\" ' ]} " , 'a' )
731- self .assertEqual (fr'{ d ["\' " ]} ' , 'b' )
732- self .assertEqual (fr"{ '\" ' } " , '"' )
733- self .assertEqual (fr'{ "\' " } ' , "'" )
734- self .assertEqual (f'{"\\ " 3 "}', '" 3 ')
735-
736- self .assertAllRaise (SyntaxError , 'f-string: unterminated string' ,
737- [r'''f'{"""\\}' ''' , # Backslash at end of expression
738- ])
739- self .assertAllRaise (SyntaxError , 'unexpected character after line continuation' ,
740- [r"rf'{3\}'" ,
741- ])
742-
743703
744704if __name__ == '__main__' :
745705 unittest .main ()
0 commit comments