• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2# There are tests here with unicode string literals and
3# identifiers. There's a code in ast.c that was added because of a
4# failure with a non-ascii-only expression.  So, I have tests for
5# that.  There are workarounds that would let me run tests for that
6# code without unicode identifiers and strings, but just using them
7# directly seems like the easiest and therefore safest thing to do.
8# Unicode identifiers in tests is allowed by PEP 3131.
9
10import ast
11import os
12import re
13import types
14import decimal
15import unittest
16from test.support.os_helper import temp_cwd
17from test.support.script_helper import assert_python_failure
18
19a_global = 'global variable'
20
21# You could argue that I'm too strict in looking for specific error
22#  values with assertRaisesRegex, but without it it's way too easy to
23#  make a syntax error in the test strings. Especially with all of the
24#  triple quotes, raw strings, backslashes, etc. I think it's a
25#  worthwhile tradeoff. When I switched to this method, I found many
26#  examples where I wasn't testing what I thought I was.
27
28class TestCase(unittest.TestCase):
29    def assertAllRaise(self, exception_type, regex, error_strings):
30        for str in error_strings:
31            with self.subTest(str=str):
32                with self.assertRaisesRegex(exception_type, regex):
33                    eval(str)
34
35    def test__format__lookup(self):
36        # Make sure __format__ is looked up on the type, not the instance.
37        class X:
38            def __format__(self, spec):
39                return 'class'
40
41        x = X()
42
43        # Add a bound __format__ method to the 'y' instance, but not
44        #  the 'x' instance.
45        y = X()
46        y.__format__ = types.MethodType(lambda self, spec: 'instance', y)
47
48        self.assertEqual(f'{y}', format(y))
49        self.assertEqual(f'{y}', 'class')
50        self.assertEqual(format(x), format(y))
51
52        # __format__ is not called this way, but still make sure it
53        #  returns what we expect (so we can make sure we're bypassing
54        #  it).
55        self.assertEqual(x.__format__(''), 'class')
56        self.assertEqual(y.__format__(''), 'instance')
57
58        # This is how __format__ is actually called.
59        self.assertEqual(type(x).__format__(x, ''), 'class')
60        self.assertEqual(type(y).__format__(y, ''), 'class')
61
62    def test_ast(self):
63        # Inspired by http://bugs.python.org/issue24975
64        class X:
65            def __init__(self):
66                self.called = False
67            def __call__(self):
68                self.called = True
69                return 4
70        x = X()
71        expr = """
72a = 10
73f'{a * x()}'"""
74        t = ast.parse(expr)
75        c = compile(t, '', 'exec')
76
77        # Make sure x was not called.
78        self.assertFalse(x.called)
79
80        # Actually run the code.
81        exec(c)
82
83        # Make sure x was called.
84        self.assertTrue(x.called)
85
86    def test_ast_line_numbers(self):
87        expr = """
88a = 10
89f'{a * x()}'"""
90        t = ast.parse(expr)
91        self.assertEqual(type(t), ast.Module)
92        self.assertEqual(len(t.body), 2)
93        # check `a = 10`
94        self.assertEqual(type(t.body[0]), ast.Assign)
95        self.assertEqual(t.body[0].lineno, 2)
96        # check `f'...'`
97        self.assertEqual(type(t.body[1]), ast.Expr)
98        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
99        self.assertEqual(len(t.body[1].value.values), 1)
100        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
101        self.assertEqual(t.body[1].lineno, 3)
102        self.assertEqual(t.body[1].value.lineno, 3)
103        self.assertEqual(t.body[1].value.values[0].lineno, 3)
104        # check the binop location
105        binop = t.body[1].value.values[0].value
106        self.assertEqual(type(binop), ast.BinOp)
107        self.assertEqual(type(binop.left), ast.Name)
108        self.assertEqual(type(binop.op), ast.Mult)
109        self.assertEqual(type(binop.right), ast.Call)
110        self.assertEqual(binop.lineno, 3)
111        self.assertEqual(binop.left.lineno, 3)
112        self.assertEqual(binop.right.lineno, 3)
113        self.assertEqual(binop.col_offset, 3)
114        self.assertEqual(binop.left.col_offset, 3)
115        self.assertEqual(binop.right.col_offset, 7)
116
117    def test_ast_line_numbers_multiple_formattedvalues(self):
118        expr = """
119f'no formatted values'
120f'eggs {a * x()} spam {b + y()}'"""
121        t = ast.parse(expr)
122        self.assertEqual(type(t), ast.Module)
123        self.assertEqual(len(t.body), 2)
124        # check `f'no formatted value'`
125        self.assertEqual(type(t.body[0]), ast.Expr)
126        self.assertEqual(type(t.body[0].value), ast.JoinedStr)
127        self.assertEqual(t.body[0].lineno, 2)
128        # check `f'...'`
129        self.assertEqual(type(t.body[1]), ast.Expr)
130        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
131        self.assertEqual(len(t.body[1].value.values), 4)
132        self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
133        self.assertEqual(type(t.body[1].value.values[0].value), str)
134        self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
135        self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
136        self.assertEqual(type(t.body[1].value.values[2].value), str)
137        self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue)
138        self.assertEqual(t.body[1].lineno, 3)
139        self.assertEqual(t.body[1].value.lineno, 3)
140        self.assertEqual(t.body[1].value.values[0].lineno, 3)
141        self.assertEqual(t.body[1].value.values[1].lineno, 3)
142        self.assertEqual(t.body[1].value.values[2].lineno, 3)
143        self.assertEqual(t.body[1].value.values[3].lineno, 3)
144        # check the first binop location
145        binop1 = t.body[1].value.values[1].value
146        self.assertEqual(type(binop1), ast.BinOp)
147        self.assertEqual(type(binop1.left), ast.Name)
148        self.assertEqual(type(binop1.op), ast.Mult)
149        self.assertEqual(type(binop1.right), ast.Call)
150        self.assertEqual(binop1.lineno, 3)
151        self.assertEqual(binop1.left.lineno, 3)
152        self.assertEqual(binop1.right.lineno, 3)
153        self.assertEqual(binop1.col_offset, 8)
154        self.assertEqual(binop1.left.col_offset, 8)
155        self.assertEqual(binop1.right.col_offset, 12)
156        # check the second binop location
157        binop2 = t.body[1].value.values[3].value
158        self.assertEqual(type(binop2), ast.BinOp)
159        self.assertEqual(type(binop2.left), ast.Name)
160        self.assertEqual(type(binop2.op), ast.Add)
161        self.assertEqual(type(binop2.right), ast.Call)
162        self.assertEqual(binop2.lineno, 3)
163        self.assertEqual(binop2.left.lineno, 3)
164        self.assertEqual(binop2.right.lineno, 3)
165        self.assertEqual(binop2.col_offset, 23)
166        self.assertEqual(binop2.left.col_offset, 23)
167        self.assertEqual(binop2.right.col_offset, 27)
168
169    def test_ast_line_numbers_nested(self):
170        expr = """
171a = 10
172f'{a * f"-{x()}-"}'"""
173        t = ast.parse(expr)
174        self.assertEqual(type(t), ast.Module)
175        self.assertEqual(len(t.body), 2)
176        # check `a = 10`
177        self.assertEqual(type(t.body[0]), ast.Assign)
178        self.assertEqual(t.body[0].lineno, 2)
179        # check `f'...'`
180        self.assertEqual(type(t.body[1]), ast.Expr)
181        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
182        self.assertEqual(len(t.body[1].value.values), 1)
183        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
184        self.assertEqual(t.body[1].lineno, 3)
185        self.assertEqual(t.body[1].value.lineno, 3)
186        self.assertEqual(t.body[1].value.values[0].lineno, 3)
187        # check the binop location
188        binop = t.body[1].value.values[0].value
189        self.assertEqual(type(binop), ast.BinOp)
190        self.assertEqual(type(binop.left), ast.Name)
191        self.assertEqual(type(binop.op), ast.Mult)
192        self.assertEqual(type(binop.right), ast.JoinedStr)
193        self.assertEqual(binop.lineno, 3)
194        self.assertEqual(binop.left.lineno, 3)
195        self.assertEqual(binop.right.lineno, 3)
196        self.assertEqual(binop.col_offset, 3)
197        self.assertEqual(binop.left.col_offset, 3)
198        self.assertEqual(binop.right.col_offset, 7)
199        # check the nested call location
200        self.assertEqual(len(binop.right.values), 3)
201        self.assertEqual(type(binop.right.values[0]), ast.Constant)
202        self.assertEqual(type(binop.right.values[0].value), str)
203        self.assertEqual(type(binop.right.values[1]), ast.FormattedValue)
204        self.assertEqual(type(binop.right.values[2]), ast.Constant)
205        self.assertEqual(type(binop.right.values[2].value), str)
206        self.assertEqual(binop.right.values[0].lineno, 3)
207        self.assertEqual(binop.right.values[1].lineno, 3)
208        self.assertEqual(binop.right.values[2].lineno, 3)
209        call = binop.right.values[1].value
210        self.assertEqual(type(call), ast.Call)
211        self.assertEqual(call.lineno, 3)
212        self.assertEqual(call.col_offset, 11)
213
214    def test_ast_line_numbers_duplicate_expression(self):
215        expr = """
216a = 10
217f'{a * x()} {a * x()} {a * x()}'
218"""
219        t = ast.parse(expr)
220        self.assertEqual(type(t), ast.Module)
221        self.assertEqual(len(t.body), 2)
222        # check `a = 10`
223        self.assertEqual(type(t.body[0]), ast.Assign)
224        self.assertEqual(t.body[0].lineno, 2)
225        # check `f'...'`
226        self.assertEqual(type(t.body[1]), ast.Expr)
227        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
228        self.assertEqual(len(t.body[1].value.values), 5)
229        self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
230        self.assertEqual(type(t.body[1].value.values[1]), ast.Constant)
231        self.assertEqual(type(t.body[1].value.values[1].value), str)
232        self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue)
233        self.assertEqual(type(t.body[1].value.values[3]), ast.Constant)
234        self.assertEqual(type(t.body[1].value.values[3].value), str)
235        self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue)
236        self.assertEqual(t.body[1].lineno, 3)
237        self.assertEqual(t.body[1].value.lineno, 3)
238        self.assertEqual(t.body[1].value.values[0].lineno, 3)
239        self.assertEqual(t.body[1].value.values[1].lineno, 3)
240        self.assertEqual(t.body[1].value.values[2].lineno, 3)
241        self.assertEqual(t.body[1].value.values[3].lineno, 3)
242        self.assertEqual(t.body[1].value.values[4].lineno, 3)
243        # check the first binop location
244        binop = t.body[1].value.values[0].value
245        self.assertEqual(type(binop), ast.BinOp)
246        self.assertEqual(type(binop.left), ast.Name)
247        self.assertEqual(type(binop.op), ast.Mult)
248        self.assertEqual(type(binop.right), ast.Call)
249        self.assertEqual(binop.lineno, 3)
250        self.assertEqual(binop.left.lineno, 3)
251        self.assertEqual(binop.right.lineno, 3)
252        self.assertEqual(binop.col_offset, 3)
253        self.assertEqual(binop.left.col_offset, 3)
254        self.assertEqual(binop.right.col_offset, 7)
255        # check the second binop location
256        binop = t.body[1].value.values[2].value
257        self.assertEqual(type(binop), ast.BinOp)
258        self.assertEqual(type(binop.left), ast.Name)
259        self.assertEqual(type(binop.op), ast.Mult)
260        self.assertEqual(type(binop.right), ast.Call)
261        self.assertEqual(binop.lineno, 3)
262        self.assertEqual(binop.left.lineno, 3)
263        self.assertEqual(binop.right.lineno, 3)
264        self.assertEqual(binop.col_offset, 13)
265        self.assertEqual(binop.left.col_offset, 13)
266        self.assertEqual(binop.right.col_offset, 17)
267        # check the third binop location
268        binop = t.body[1].value.values[4].value
269        self.assertEqual(type(binop), ast.BinOp)
270        self.assertEqual(type(binop.left), ast.Name)
271        self.assertEqual(type(binop.op), ast.Mult)
272        self.assertEqual(type(binop.right), ast.Call)
273        self.assertEqual(binop.lineno, 3)
274        self.assertEqual(binop.left.lineno, 3)
275        self.assertEqual(binop.right.lineno, 3)
276        self.assertEqual(binop.col_offset, 23)
277        self.assertEqual(binop.left.col_offset, 23)
278        self.assertEqual(binop.right.col_offset, 27)
279
280    def test_ast_numbers_fstring_with_formatting(self):
281
282        t = ast.parse('f"Here is that pesky {xxx:.3f} again"')
283        self.assertEqual(len(t.body), 1)
284        self.assertEqual(t.body[0].lineno, 1)
285
286        self.assertEqual(type(t.body[0]), ast.Expr)
287        self.assertEqual(type(t.body[0].value), ast.JoinedStr)
288        self.assertEqual(len(t.body[0].value.values), 3)
289
290        self.assertEqual(type(t.body[0].value.values[0]), ast.Constant)
291        self.assertEqual(type(t.body[0].value.values[1]), ast.FormattedValue)
292        self.assertEqual(type(t.body[0].value.values[2]), ast.Constant)
293
294        _, expr, _ = t.body[0].value.values
295
296        name = expr.value
297        self.assertEqual(type(name), ast.Name)
298        self.assertEqual(name.lineno, 1)
299        self.assertEqual(name.end_lineno, 1)
300        self.assertEqual(name.col_offset, 22)
301        self.assertEqual(name.end_col_offset, 25)
302
303    def test_ast_line_numbers_multiline_fstring(self):
304        # See bpo-30465 for details.
305        expr = """
306a = 10
307f'''
308  {a
309     *
310       x()}
311non-important content
312'''
313"""
314        t = ast.parse(expr)
315        self.assertEqual(type(t), ast.Module)
316        self.assertEqual(len(t.body), 2)
317        # check `a = 10`
318        self.assertEqual(type(t.body[0]), ast.Assign)
319        self.assertEqual(t.body[0].lineno, 2)
320        # check `f'...'`
321        self.assertEqual(type(t.body[1]), ast.Expr)
322        self.assertEqual(type(t.body[1].value), ast.JoinedStr)
323        self.assertEqual(len(t.body[1].value.values), 3)
324        self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
325        self.assertEqual(type(t.body[1].value.values[0].value), str)
326        self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
327        self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
328        self.assertEqual(type(t.body[1].value.values[2].value), str)
329        self.assertEqual(t.body[1].lineno, 3)
330        self.assertEqual(t.body[1].value.lineno, 3)
331        self.assertEqual(t.body[1].value.values[0].lineno, 3)
332        self.assertEqual(t.body[1].value.values[1].lineno, 3)
333        self.assertEqual(t.body[1].value.values[2].lineno, 3)
334        self.assertEqual(t.body[1].col_offset, 0)
335        self.assertEqual(t.body[1].value.col_offset, 0)
336        self.assertEqual(t.body[1].value.values[0].col_offset, 0)
337        self.assertEqual(t.body[1].value.values[1].col_offset, 0)
338        self.assertEqual(t.body[1].value.values[2].col_offset, 0)
339        # NOTE: the following lineno information and col_offset is correct for
340        # expressions within FormattedValues.
341        binop = t.body[1].value.values[1].value
342        self.assertEqual(type(binop), ast.BinOp)
343        self.assertEqual(type(binop.left), ast.Name)
344        self.assertEqual(type(binop.op), ast.Mult)
345        self.assertEqual(type(binop.right), ast.Call)
346        self.assertEqual(binop.lineno, 4)
347        self.assertEqual(binop.left.lineno, 4)
348        self.assertEqual(binop.right.lineno, 6)
349        self.assertEqual(binop.col_offset, 4)
350        self.assertEqual(binop.left.col_offset, 4)
351        self.assertEqual(binop.right.col_offset, 7)
352
353    def test_ast_line_numbers_with_parentheses(self):
354        expr = """
355x = (
356    f" {test(t)}"
357)"""
358        t = ast.parse(expr)
359        self.assertEqual(type(t), ast.Module)
360        self.assertEqual(len(t.body), 1)
361        # check the test(t) location
362        call = t.body[0].value.values[1].value
363        self.assertEqual(type(call), ast.Call)
364        self.assertEqual(call.lineno, 3)
365        self.assertEqual(call.end_lineno, 3)
366        self.assertEqual(call.col_offset, 8)
367        self.assertEqual(call.end_col_offset, 15)
368
369        expr = """
370x = (
371        'PERL_MM_OPT', (
372            f'wat'
373            f'some_string={f(x)} '
374            f'wat'
375        ),
376)
377"""
378        t = ast.parse(expr)
379        self.assertEqual(type(t), ast.Module)
380        self.assertEqual(len(t.body), 1)
381        # check the fstring
382        fstring = t.body[0].value.elts[1]
383        self.assertEqual(type(fstring), ast.JoinedStr)
384        self.assertEqual(len(fstring.values), 3)
385        wat1, middle, wat2 = fstring.values
386        # check the first wat
387        self.assertEqual(type(wat1), ast.Constant)
388        self.assertEqual(wat1.lineno, 4)
389        self.assertEqual(wat1.end_lineno, 6)
390        self.assertEqual(wat1.col_offset, 12)
391        self.assertEqual(wat1.end_col_offset, 18)
392        # check the call
393        call = middle.value
394        self.assertEqual(type(call), ast.Call)
395        self.assertEqual(call.lineno, 5)
396        self.assertEqual(call.end_lineno, 5)
397        self.assertEqual(call.col_offset, 27)
398        self.assertEqual(call.end_col_offset, 31)
399        # check the second wat
400        self.assertEqual(type(wat2), ast.Constant)
401        self.assertEqual(wat2.lineno, 4)
402        self.assertEqual(wat2.end_lineno, 6)
403        self.assertEqual(wat2.col_offset, 12)
404        self.assertEqual(wat2.end_col_offset, 18)
405
406    def test_docstring(self):
407        def f():
408            f'''Not a docstring'''
409        self.assertIsNone(f.__doc__)
410        def g():
411            '''Not a docstring''' \
412            f''
413        self.assertIsNone(g.__doc__)
414
415    def test_literal_eval(self):
416        with self.assertRaisesRegex(ValueError, 'malformed node or string'):
417            ast.literal_eval("f'x'")
418
419    def test_ast_compile_time_concat(self):
420        x = ['']
421
422        expr = """x[0] = 'foo' f'{3}'"""
423        t = ast.parse(expr)
424        c = compile(t, '', 'exec')
425        exec(c)
426        self.assertEqual(x[0], 'foo3')
427
428    def test_compile_time_concat_errors(self):
429        self.assertAllRaise(SyntaxError,
430                            'cannot mix bytes and nonbytes literals',
431                            [r"""f'' b''""",
432                             r"""b'' f''""",
433                             ])
434
435    def test_literal(self):
436        self.assertEqual(f'', '')
437        self.assertEqual(f'a', 'a')
438        self.assertEqual(f' ', ' ')
439
440    def test_unterminated_string(self):
441        self.assertAllRaise(SyntaxError, 'f-string: unterminated string',
442                            [r"""f'{"x'""",
443                             r"""f'{"x}'""",
444                             r"""f'{("x'""",
445                             r"""f'{("x}'""",
446                             ])
447
448    def test_mismatched_parens(self):
449        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
450                            r"does not match opening parenthesis '\('",
451                            ["f'{((}'",
452                             ])
453        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\)' "
454                            r"does not match opening parenthesis '\['",
455                            ["f'{a[4)}'",
456                            ])
457        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\]' "
458                            r"does not match opening parenthesis '\('",
459                            ["f'{a(4]}'",
460                            ])
461        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
462                            r"does not match opening parenthesis '\['",
463                            ["f'{a[4}'",
464                            ])
465        self.assertAllRaise(SyntaxError, r"f-string: closing parenthesis '\}' "
466                            r"does not match opening parenthesis '\('",
467                            ["f'{a(4}'",
468                            ])
469        self.assertRaises(SyntaxError, eval, "f'{" + "("*500 + "}'")
470
471    def test_double_braces(self):
472        self.assertEqual(f'{{', '{')
473        self.assertEqual(f'a{{', 'a{')
474        self.assertEqual(f'{{b', '{b')
475        self.assertEqual(f'a{{b', 'a{b')
476        self.assertEqual(f'}}', '}')
477        self.assertEqual(f'a}}', 'a}')
478        self.assertEqual(f'}}b', '}b')
479        self.assertEqual(f'a}}b', 'a}b')
480        self.assertEqual(f'{{}}', '{}')
481        self.assertEqual(f'a{{}}', 'a{}')
482        self.assertEqual(f'{{b}}', '{b}')
483        self.assertEqual(f'{{}}c', '{}c')
484        self.assertEqual(f'a{{b}}', 'a{b}')
485        self.assertEqual(f'a{{}}c', 'a{}c')
486        self.assertEqual(f'{{b}}c', '{b}c')
487        self.assertEqual(f'a{{b}}c', 'a{b}c')
488
489        self.assertEqual(f'{{{10}', '{10')
490        self.assertEqual(f'}}{10}', '}10')
491        self.assertEqual(f'}}{{{10}', '}{10')
492        self.assertEqual(f'}}a{{{10}', '}a{10')
493
494        self.assertEqual(f'{10}{{', '10{')
495        self.assertEqual(f'{10}}}', '10}')
496        self.assertEqual(f'{10}}}{{', '10}{')
497        self.assertEqual(f'{10}}}a{{' '}', '10}a{}')
498
499        # Inside of strings, don't interpret doubled brackets.
500        self.assertEqual(f'{"{{}}"}', '{{}}')
501
502        self.assertAllRaise(TypeError, 'unhashable type',
503                            ["f'{ {{}} }'", # dict in a set
504                             ])
505
506    def test_compile_time_concat(self):
507        x = 'def'
508        self.assertEqual('abc' f'## {x}ghi', 'abc## defghi')
509        self.assertEqual('abc' f'{x}' 'ghi', 'abcdefghi')
510        self.assertEqual('abc' f'{x}' 'gh' f'i{x:4}', 'abcdefghidef ')
511        self.assertEqual('{x}' f'{x}', '{x}def')
512        self.assertEqual('{x' f'{x}', '{xdef')
513        self.assertEqual('{x}' f'{x}', '{x}def')
514        self.assertEqual('{{x}}' f'{x}', '{{x}}def')
515        self.assertEqual('{{x' f'{x}', '{{xdef')
516        self.assertEqual('x}}' f'{x}', 'x}}def')
517        self.assertEqual(f'{x}' 'x}}', 'defx}}')
518        self.assertEqual(f'{x}' '', 'def')
519        self.assertEqual('' f'{x}' '', 'def')
520        self.assertEqual('' f'{x}', 'def')
521        self.assertEqual(f'{x}' '2', 'def2')
522        self.assertEqual('1' f'{x}' '2', '1def2')
523        self.assertEqual('1' f'{x}', '1def')
524        self.assertEqual(f'{x}' f'-{x}', 'def-def')
525        self.assertEqual('' f'', '')
526        self.assertEqual('' f'' '', '')
527        self.assertEqual('' f'' '' f'', '')
528        self.assertEqual(f'', '')
529        self.assertEqual(f'' '', '')
530        self.assertEqual(f'' '' f'', '')
531        self.assertEqual(f'' '' f'' '', '')
532
533        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
534                            ["f'{3' f'}'",  # can't concat to get a valid f-string
535                             ])
536
537    def test_comments(self):
538        # These aren't comments, since they're in strings.
539        d = {'#': 'hash'}
540        self.assertEqual(f'{"#"}', '#')
541        self.assertEqual(f'{d["#"]}', 'hash')
542
543        self.assertAllRaise(SyntaxError, "f-string expression part cannot include '#'",
544                            ["f'{1#}'",   # error because the expression becomes "(1#)"
545                             "f'{3(#)}'",
546                             "f'{#}'",
547                             ])
548        self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'",
549                            ["f'{)#}'",   # When wrapped in parens, this becomes
550                                          #  '()#)'.  Make sure that doesn't compile.
551                             ])
552
553    def test_many_expressions(self):
554        # Create a string with many expressions in it. Note that
555        #  because we have a space in here as a literal, we're actually
556        #  going to use twice as many ast nodes: one for each literal
557        #  plus one for each expression.
558        def build_fstr(n, extra=''):
559            return "f'" + ('{x} ' * n) + extra + "'"
560
561        x = 'X'
562        width = 1
563
564        # Test around 256.
565        for i in range(250, 260):
566            self.assertEqual(eval(build_fstr(i)), (x+' ')*i)
567
568        # Test concatenating 2 largs fstrings.
569        self.assertEqual(eval(build_fstr(255)*256), (x+' ')*(255*256))
570
571        s = build_fstr(253, '{x:{width}} ')
572        self.assertEqual(eval(s), (x+' ')*254)
573
574        # Test lots of expressions and constants, concatenated.
575        s = "f'{1}' 'x' 'y'" * 1024
576        self.assertEqual(eval(s), '1xy' * 1024)
577
578    def test_format_specifier_expressions(self):
579        width = 10
580        precision = 4
581        value = decimal.Decimal('12.34567')
582        self.assertEqual(f'result: {value:{width}.{precision}}', 'result:      12.35')
583        self.assertEqual(f'result: {value:{width!r}.{precision}}', 'result:      12.35')
584        self.assertEqual(f'result: {value:{width:0}.{precision:1}}', 'result:      12.35')
585        self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}', 'result:      12.35')
586        self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}', 'result:      12.35')
587        self.assertEqual(f'{10:#{1}0x}', '       0xa')
588        self.assertEqual(f'{10:{"#"}1{0}{"x"}}', '       0xa')
589        self.assertEqual(f'{-10:-{"#"}1{0}x}', '      -0xa')
590        self.assertEqual(f'{-10:{"-"}#{1}0{"x"}}', '      -0xa')
591        self.assertEqual(f'{10:#{3 != {4:5} and width}x}', '       0xa')
592
593        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
594                            ["""f'{"s"!r{":10"}}'""",
595
596                             # This looks like a nested format spec.
597                             ])
598
599        self.assertAllRaise(SyntaxError, "f-string: invalid syntax",
600                            [# Invalid syntax inside a nested spec.
601                             "f'{4:{/5}}'",
602                             ])
603
604        self.assertAllRaise(SyntaxError, "f-string: expressions nested too deeply",
605                            [# Can't nest format specifiers.
606                             "f'result: {value:{width:{0}}.{precision:1}}'",
607                             ])
608
609        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
610                            [# No expansion inside conversion or for
611                             #  the : or ! itself.
612                             """f'{"s"!{"r"}}'""",
613                             ])
614
615    def test_side_effect_order(self):
616        class X:
617            def __init__(self):
618                self.i = 0
619            def __format__(self, spec):
620                self.i += 1
621                return str(self.i)
622
623        x = X()
624        self.assertEqual(f'{x} {x}', '1 2')
625
626    def test_missing_expression(self):
627        self.assertAllRaise(SyntaxError, 'f-string: empty expression not allowed',
628                            ["f'{}'",
629                             "f'{ }'"
630                             "f' {} '",
631                             "f'{!r}'",
632                             "f'{ !r}'",
633                             "f'{10:{ }}'",
634                             "f' { } '",
635
636                             # The Python parser ignores also the following
637                             # whitespace characters in additional to a space.
638                             "f'''{\t\f\r\n}'''",
639
640                             # Catch the empty expression before the
641                             #  invalid conversion.
642                             "f'{!x}'",
643                             "f'{ !xr}'",
644                             "f'{!x:}'",
645                             "f'{!x:a}'",
646                             "f'{ !xr:}'",
647                             "f'{ !xr:a}'",
648
649                             "f'{!}'",
650                             "f'{:}'",
651
652                             # We find the empty expression before the
653                             #  missing closing brace.
654                             "f'{!'",
655                             "f'{!s:'",
656                             "f'{:'",
657                             "f'{:x'",
658                             ])
659
660        # Different error message is raised for other whitespace characters.
661        self.assertAllRaise(SyntaxError, r"invalid non-printable character U\+00A0",
662                            ["f'''{\xa0}'''",
663                             "\xa0",
664                             ])
665
666    def test_parens_in_expressions(self):
667        self.assertEqual(f'{3,}', '(3,)')
668
669        # Add these because when an expression is evaluated, parens
670        #  are added around it. But we shouldn't go from an invalid
671        #  expression to a valid one. The added parens are just
672        #  supposed to allow whitespace (including newlines).
673        self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
674                            ["f'{,}'",
675                             "f'{,}'",  # this is (,), which is an error
676                             ])
677
678        self.assertAllRaise(SyntaxError, r"f-string: unmatched '\)'",
679                            ["f'{3)+(4}'",
680                             ])
681
682        self.assertAllRaise(SyntaxError, 'unterminated string literal',
683                            ["f'{\n}'",
684                             ])
685    def test_newlines_before_syntax_error(self):
686        self.assertAllRaise(SyntaxError, "invalid syntax",
687                ["f'{.}'", "\nf'{.}'", "\n\nf'{.}'"])
688
689    def test_backslashes_in_string_part(self):
690        self.assertEqual(f'\t', '\t')
691        self.assertEqual(r'\t', '\\t')
692        self.assertEqual(rf'\t', '\\t')
693        self.assertEqual(f'{2}\t', '2\t')
694        self.assertEqual(f'{2}\t{3}', '2\t3')
695        self.assertEqual(f'\t{3}', '\t3')
696
697        self.assertEqual(f'\u0394', '\u0394')
698        self.assertEqual(r'\u0394', '\\u0394')
699        self.assertEqual(rf'\u0394', '\\u0394')
700        self.assertEqual(f'{2}\u0394', '2\u0394')
701        self.assertEqual(f'{2}\u0394{3}', '2\u03943')
702        self.assertEqual(f'\u0394{3}', '\u03943')
703
704        self.assertEqual(f'\U00000394', '\u0394')
705        self.assertEqual(r'\U00000394', '\\U00000394')
706        self.assertEqual(rf'\U00000394', '\\U00000394')
707        self.assertEqual(f'{2}\U00000394', '2\u0394')
708        self.assertEqual(f'{2}\U00000394{3}', '2\u03943')
709        self.assertEqual(f'\U00000394{3}', '\u03943')
710
711        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}', '\u0394')
712        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
713        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}{3}', '2\u03943')
714        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}{3}', '\u03943')
715        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
716        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}3', '2\u03943')
717        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}3', '\u03943')
718
719        self.assertEqual(f'\x20', ' ')
720        self.assertEqual(r'\x20', '\\x20')
721        self.assertEqual(rf'\x20', '\\x20')
722        self.assertEqual(f'{2}\x20', '2 ')
723        self.assertEqual(f'{2}\x20{3}', '2 3')
724        self.assertEqual(f'\x20{3}', ' 3')
725
726        self.assertEqual(f'2\x20', '2 ')
727        self.assertEqual(f'2\x203', '2 3')
728        self.assertEqual(f'\x203', ' 3')
729
730        with self.assertWarns(DeprecationWarning):  # invalid escape sequence
731            value = eval(r"f'\{6*7}'")
732        self.assertEqual(value, '\\42')
733        self.assertEqual(f'\\{6*7}', '\\42')
734        self.assertEqual(fr'\{6*7}', '\\42')
735
736        AMPERSAND = 'spam'
737        # Get the right unicode character (&), or pick up local variable
738        # depending on the number of backslashes.
739        self.assertEqual(f'\N{AMPERSAND}', '&')
740        self.assertEqual(f'\\N{AMPERSAND}', '\\Nspam')
741        self.assertEqual(fr'\N{AMPERSAND}', '\\Nspam')
742        self.assertEqual(f'\\\N{AMPERSAND}', '\\&')
743
744    def test_misformed_unicode_character_name(self):
745        # These test are needed because unicode names are parsed
746        # differently inside f-strings.
747        self.assertAllRaise(SyntaxError, r"\(unicode error\) 'unicodeescape' codec can't decode bytes in position .*: malformed \\N character escape",
748                            [r"f'\N'",
749                             r"f'\N{'",
750                             r"f'\N{GREEK CAPITAL LETTER DELTA'",
751
752                             # Here are the non-f-string versions,
753                             #  which should give the same errors.
754                             r"'\N'",
755                             r"'\N{'",
756                             r"'\N{GREEK CAPITAL LETTER DELTA'",
757                             ])
758
759    def test_no_backslashes_in_expression_part(self):
760        self.assertAllRaise(SyntaxError, 'f-string expression part cannot include a backslash',
761                            [r"f'{\'a\'}'",
762                             r"f'{\t3}'",
763                             r"f'{\}'",
764                             r"rf'{\'a\'}'",
765                             r"rf'{\t3}'",
766                             r"rf'{\}'",
767                             r"""rf'{"\N{LEFT CURLY BRACKET}"}'""",
768                             r"f'{\n}'",
769                             ])
770
771    def test_no_escapes_for_braces(self):
772        """
773        Only literal curly braces begin an expression.
774        """
775        # \x7b is '{'.
776        self.assertEqual(f'\x7b1+1}}', '{1+1}')
777        self.assertEqual(f'\x7b1+1', '{1+1')
778        self.assertEqual(f'\u007b1+1', '{1+1')
779        self.assertEqual(f'\N{LEFT CURLY BRACKET}1+1\N{RIGHT CURLY BRACKET}', '{1+1}')
780
781    def test_newlines_in_expressions(self):
782        self.assertEqual(f'{0}', '0')
783        self.assertEqual(rf'''{3+
7844}''', '7')
785
786    def test_lambda(self):
787        x = 5
788        self.assertEqual(f'{(lambda y:x*y)("8")!r}', "'88888'")
789        self.assertEqual(f'{(lambda y:x*y)("8")!r:10}', "'88888'   ")
790        self.assertEqual(f'{(lambda y:x*y)("8"):10}', "88888     ")
791
792        # lambda doesn't work without parens, because the colon
793        #  makes the parser think it's a format_spec
794        self.assertAllRaise(SyntaxError, 'f-string: invalid syntax',
795                            ["f'{lambda x:x}'",
796                             ])
797
798    def test_yield(self):
799        # Not terribly useful, but make sure the yield turns
800        #  a function into a generator
801        def fn(y):
802            f'y:{yield y*2}'
803            f'{yield}'
804
805        g = fn(4)
806        self.assertEqual(next(g), 8)
807        self.assertEqual(next(g), None)
808
809    def test_yield_send(self):
810        def fn(x):
811            yield f'x:{yield (lambda i: x * i)}'
812
813        g = fn(10)
814        the_lambda = next(g)
815        self.assertEqual(the_lambda(4), 40)
816        self.assertEqual(g.send('string'), 'x:string')
817
818    def test_expressions_with_triple_quoted_strings(self):
819        self.assertEqual(f"{'''x'''}", 'x')
820        self.assertEqual(f"{'''eric's'''}", "eric's")
821
822        # Test concatenation within an expression
823        self.assertEqual(f'{"x" """eric"s""" "y"}', 'xeric"sy')
824        self.assertEqual(f'{"x" """eric"s"""}', 'xeric"s')
825        self.assertEqual(f'{"""eric"s""" "y"}', 'eric"sy')
826        self.assertEqual(f'{"""x""" """eric"s""" "y"}', 'xeric"sy')
827        self.assertEqual(f'{"""x""" """eric"s""" """y"""}', 'xeric"sy')
828        self.assertEqual(f'{r"""x""" """eric"s""" """y"""}', 'xeric"sy')
829
830    def test_multiple_vars(self):
831        x = 98
832        y = 'abc'
833        self.assertEqual(f'{x}{y}', '98abc')
834
835        self.assertEqual(f'X{x}{y}', 'X98abc')
836        self.assertEqual(f'{x}X{y}', '98Xabc')
837        self.assertEqual(f'{x}{y}X', '98abcX')
838
839        self.assertEqual(f'X{x}Y{y}', 'X98Yabc')
840        self.assertEqual(f'X{x}{y}Y', 'X98abcY')
841        self.assertEqual(f'{x}X{y}Y', '98XabcY')
842
843        self.assertEqual(f'X{x}Y{y}Z', 'X98YabcZ')
844
845    def test_closure(self):
846        def outer(x):
847            def inner():
848                return f'x:{x}'
849            return inner
850
851        self.assertEqual(outer('987')(), 'x:987')
852        self.assertEqual(outer(7)(), 'x:7')
853
854    def test_arguments(self):
855        y = 2
856        def f(x, width):
857            return f'x={x*y:{width}}'
858
859        self.assertEqual(f('foo', 10), 'x=foofoo    ')
860        x = 'bar'
861        self.assertEqual(f(10, 10), 'x=        20')
862
863    def test_locals(self):
864        value = 123
865        self.assertEqual(f'v:{value}', 'v:123')
866
867    def test_missing_variable(self):
868        with self.assertRaises(NameError):
869            f'v:{value}'
870
871    def test_missing_format_spec(self):
872        class O:
873            def __format__(self, spec):
874                if not spec:
875                    return '*'
876                return spec
877
878        self.assertEqual(f'{O():x}', 'x')
879        self.assertEqual(f'{O()}', '*')
880        self.assertEqual(f'{O():}', '*')
881
882        self.assertEqual(f'{3:}', '3')
883        self.assertEqual(f'{3!s:}', '3')
884
885    def test_global(self):
886        self.assertEqual(f'g:{a_global}', 'g:global variable')
887        self.assertEqual(f'g:{a_global!r}', "g:'global variable'")
888
889        a_local = 'local variable'
890        self.assertEqual(f'g:{a_global} l:{a_local}',
891                         'g:global variable l:local variable')
892        self.assertEqual(f'g:{a_global!r}',
893                         "g:'global variable'")
894        self.assertEqual(f'g:{a_global} l:{a_local!r}',
895                         "g:global variable l:'local variable'")
896
897        self.assertIn("module 'unittest' from", f'{unittest}')
898
899    def test_shadowed_global(self):
900        a_global = 'really a local'
901        self.assertEqual(f'g:{a_global}', 'g:really a local')
902        self.assertEqual(f'g:{a_global!r}', "g:'really a local'")
903
904        a_local = 'local variable'
905        self.assertEqual(f'g:{a_global} l:{a_local}',
906                         'g:really a local l:local variable')
907        self.assertEqual(f'g:{a_global!r}',
908                         "g:'really a local'")
909        self.assertEqual(f'g:{a_global} l:{a_local!r}',
910                         "g:really a local l:'local variable'")
911
912    def test_call(self):
913        def foo(x):
914            return 'x=' + str(x)
915
916        self.assertEqual(f'{foo(10)}', 'x=10')
917
918    def test_nested_fstrings(self):
919        y = 5
920        self.assertEqual(f'{f"{0}"*3}', '000')
921        self.assertEqual(f'{f"{y}"*3}', '555')
922
923    def test_invalid_string_prefixes(self):
924        single_quote_cases = ["fu''",
925                             "uf''",
926                             "Fu''",
927                             "fU''",
928                             "Uf''",
929                             "uF''",
930                             "ufr''",
931                             "urf''",
932                             "fur''",
933                             "fru''",
934                             "rfu''",
935                             "ruf''",
936                             "FUR''",
937                             "Fur''",
938                             "fb''",
939                             "fB''",
940                             "Fb''",
941                             "FB''",
942                             "bf''",
943                             "bF''",
944                             "Bf''",
945                             "BF''",]
946        double_quote_cases = [case.replace("'", '"') for case in single_quote_cases]
947        self.assertAllRaise(SyntaxError, 'invalid syntax',
948                            single_quote_cases + double_quote_cases)
949
950    def test_leading_trailing_spaces(self):
951        self.assertEqual(f'{ 3}', '3')
952        self.assertEqual(f'{  3}', '3')
953        self.assertEqual(f'{3 }', '3')
954        self.assertEqual(f'{3  }', '3')
955
956        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]}}',
957                         'expr={1: 2}')
958        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]} }',
959                         'expr={1: 2}')
960
961    def test_not_equal(self):
962        # There's a special test for this because there's a special
963        #  case in the f-string parser to look for != as not ending an
964        #  expression. Normally it would, while looking for !s or !r.
965
966        self.assertEqual(f'{3!=4}', 'True')
967        self.assertEqual(f'{3!=4:}', 'True')
968        self.assertEqual(f'{3!=4!s}', 'True')
969        self.assertEqual(f'{3!=4!s:.3}', 'Tru')
970
971    def test_equal_equal(self):
972        # Because an expression ending in = has special meaning,
973        # there's a special test for ==. Make sure it works.
974
975        self.assertEqual(f'{0==1}', 'False')
976
977    def test_conversions(self):
978        self.assertEqual(f'{3.14:10.10}', '      3.14')
979        self.assertEqual(f'{3.14!s:10.10}', '3.14      ')
980        self.assertEqual(f'{3.14!r:10.10}', '3.14      ')
981        self.assertEqual(f'{3.14!a:10.10}', '3.14      ')
982
983        self.assertEqual(f'{"a"}', 'a')
984        self.assertEqual(f'{"a"!r}', "'a'")
985        self.assertEqual(f'{"a"!a}', "'a'")
986
987        # Not a conversion.
988        self.assertEqual(f'{"a!r"}', "a!r")
989
990        # Not a conversion, but show that ! is allowed in a format spec.
991        self.assertEqual(f'{3.14:!<10.10}', '3.14!!!!!!')
992
993        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
994                            ["f'{3!g}'",
995                             "f'{3!A}'",
996                             "f'{3!3}'",
997                             "f'{3!G}'",
998                             "f'{3!!}'",
999                             "f'{3!:}'",
1000                             "f'{3! s}'",  # no space before conversion char
1001                             ])
1002
1003        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
1004                            ["f'{x!s{y}}'",
1005                             "f'{3!ss}'",
1006                             "f'{3!ss:}'",
1007                             "f'{3!ss:s}'",
1008                             ])
1009
1010    def test_assignment(self):
1011        self.assertAllRaise(SyntaxError, r'invalid syntax',
1012                            ["f'' = 3",
1013                             "f'{0}' = x",
1014                             "f'{x}' = x",
1015                             ])
1016
1017    def test_del(self):
1018        self.assertAllRaise(SyntaxError, 'invalid syntax',
1019                            ["del f''",
1020                             "del '' f''",
1021                             ])
1022
1023    def test_mismatched_braces(self):
1024        self.assertAllRaise(SyntaxError, "f-string: single '}' is not allowed",
1025                            ["f'{{}'",
1026                             "f'{{}}}'",
1027                             "f'}'",
1028                             "f'x}'",
1029                             "f'x}x'",
1030                             r"f'\u007b}'",
1031
1032                             # Can't have { or } in a format spec.
1033                             "f'{3:}>10}'",
1034                             "f'{3:}}>10}'",
1035                             ])
1036
1037        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
1038                            ["f'{3:{{>10}'",
1039                             "f'{3'",
1040                             "f'{3!'",
1041                             "f'{3:'",
1042                             "f'{3!s'",
1043                             "f'{3!s:'",
1044                             "f'{3!s:3'",
1045                             "f'x{'",
1046                             "f'x{x'",
1047                             "f'{x'",
1048                             "f'{3:s'",
1049                             "f'{{{'",
1050                             "f'{{}}{'",
1051                             "f'{'",
1052                             ])
1053
1054        # But these are just normal strings.
1055        self.assertEqual(f'{"{"}', '{')
1056        self.assertEqual(f'{"}"}', '}')
1057        self.assertEqual(f'{3:{"}"}>10}', '}}}}}}}}}3')
1058        self.assertEqual(f'{2:{"{"}>10}', '{{{{{{{{{2')
1059
1060    def test_if_conditional(self):
1061        # There's special logic in compile.c to test if the
1062        #  conditional for an if (and while) are constants. Exercise
1063        #  that code.
1064
1065        def test_fstring(x, expected):
1066            flag = 0
1067            if f'{x}':
1068                flag = 1
1069            else:
1070                flag = 2
1071            self.assertEqual(flag, expected)
1072
1073        def test_concat_empty(x, expected):
1074            flag = 0
1075            if '' f'{x}':
1076                flag = 1
1077            else:
1078                flag = 2
1079            self.assertEqual(flag, expected)
1080
1081        def test_concat_non_empty(x, expected):
1082            flag = 0
1083            if ' ' f'{x}':
1084                flag = 1
1085            else:
1086                flag = 2
1087            self.assertEqual(flag, expected)
1088
1089        test_fstring('', 2)
1090        test_fstring(' ', 1)
1091
1092        test_concat_empty('', 2)
1093        test_concat_empty(' ', 1)
1094
1095        test_concat_non_empty('', 1)
1096        test_concat_non_empty(' ', 1)
1097
1098    def test_empty_format_specifier(self):
1099        x = 'test'
1100        self.assertEqual(f'{x}', 'test')
1101        self.assertEqual(f'{x:}', 'test')
1102        self.assertEqual(f'{x!s:}', 'test')
1103        self.assertEqual(f'{x!r:}', "'test'")
1104
1105    def test_str_format_differences(self):
1106        d = {'a': 'string',
1107             0: 'integer',
1108             }
1109        a = 0
1110        self.assertEqual(f'{d[0]}', 'integer')
1111        self.assertEqual(f'{d["a"]}', 'string')
1112        self.assertEqual(f'{d[a]}', 'integer')
1113        self.assertEqual('{d[a]}'.format(d=d), 'string')
1114        self.assertEqual('{d[0]}'.format(d=d), 'integer')
1115
1116    def test_errors(self):
1117        # see issue 26287
1118        self.assertAllRaise(TypeError, 'unsupported',
1119                            [r"f'{(lambda: 0):x}'",
1120                             r"f'{(0,):x}'",
1121                             ])
1122        self.assertAllRaise(ValueError, 'Unknown format code',
1123                            [r"f'{1000:j}'",
1124                             r"f'{1000:j}'",
1125                            ])
1126
1127    def test_filename_in_syntaxerror(self):
1128        # see issue 38964
1129        with temp_cwd() as cwd:
1130            file_path = os.path.join(cwd, 't.py')
1131            with open(file_path, 'w', encoding="utf-8") as f:
1132                f.write('f"{a b}"') # This generates a SyntaxError
1133            _, _, stderr = assert_python_failure(file_path,
1134                                                 PYTHONIOENCODING='ascii')
1135        self.assertIn(file_path.encode('ascii', 'backslashreplace'), stderr)
1136
1137    def test_loop(self):
1138        for i in range(1000):
1139            self.assertEqual(f'i:{i}', 'i:' + str(i))
1140
1141    def test_dict(self):
1142        d = {'"': 'dquote',
1143             "'": 'squote',
1144             'foo': 'bar',
1145             }
1146        self.assertEqual(f'''{d["'"]}''', 'squote')
1147        self.assertEqual(f"""{d['"']}""", 'dquote')
1148
1149        self.assertEqual(f'{d["foo"]}', 'bar')
1150        self.assertEqual(f"{d['foo']}", 'bar')
1151
1152    def test_backslash_char(self):
1153        # Check eval of a backslash followed by a control char.
1154        # See bpo-30682: this used to raise an assert in pydebug mode.
1155        self.assertEqual(eval('f"\\\n"'), '')
1156        self.assertEqual(eval('f"\\\r"'), '')
1157
1158    def test_debug_conversion(self):
1159        x = 'A string'
1160        self.assertEqual(f'{x=}', 'x=' + repr(x))
1161        self.assertEqual(f'{x =}', 'x =' + repr(x))
1162        self.assertEqual(f'{x=!s}', 'x=' + str(x))
1163        self.assertEqual(f'{x=!r}', 'x=' + repr(x))
1164        self.assertEqual(f'{x=!a}', 'x=' + ascii(x))
1165
1166        x = 2.71828
1167        self.assertEqual(f'{x=:.2f}', 'x=' + format(x, '.2f'))
1168        self.assertEqual(f'{x=:}', 'x=' + format(x, ''))
1169        self.assertEqual(f'{x=!r:^20}', 'x=' + format(repr(x), '^20'))
1170        self.assertEqual(f'{x=!s:^20}', 'x=' + format(str(x), '^20'))
1171        self.assertEqual(f'{x=!a:^20}', 'x=' + format(ascii(x), '^20'))
1172
1173        x = 9
1174        self.assertEqual(f'{3*x+15=}', '3*x+15=42')
1175
1176        # There is code in ast.c that deals with non-ascii expression values.  So,
1177        # use a unicode identifier to trigger that.
1178        tenπ = 31.4
1179        self.assertEqual(f'{tenπ=:.2f}', 'tenπ=31.40')
1180
1181        # Also test with Unicode in non-identifiers.
1182        self.assertEqual(f'{"Σ"=}', '"Σ"=\'Σ\'')
1183
1184        # Make sure nested fstrings still work.
1185        self.assertEqual(f'{f"{3.1415=:.1f}":*^20}', '*****3.1415=3.1*****')
1186
1187        # Make sure text before and after an expression with = works
1188        # correctly.
1189        pi = 'π'
1190        self.assertEqual(f'alpha α {pi=} ω omega', "alpha α pi='π' ω omega")
1191
1192        # Check multi-line expressions.
1193        self.assertEqual(f'''{
11943
1195=}''', '\n3\n=3')
1196
1197        # Since = is handled specially, make sure all existing uses of
1198        # it still work.
1199
1200        self.assertEqual(f'{0==1}', 'False')
1201        self.assertEqual(f'{0!=1}', 'True')
1202        self.assertEqual(f'{0<=1}', 'True')
1203        self.assertEqual(f'{0>=1}', 'False')
1204        self.assertEqual(f'{(x:="5")}', '5')
1205        self.assertEqual(x, '5')
1206        self.assertEqual(f'{(x:=5)}', '5')
1207        self.assertEqual(x, 5)
1208        self.assertEqual(f'{"="}', '=')
1209
1210        x = 20
1211        # This isn't an assignment expression, it's 'x', with a format
1212        # spec of '=10'.  See test_walrus: you need to use parens.
1213        self.assertEqual(f'{x:=10}', '        20')
1214
1215        # Test named function parameters, to make sure '=' parsing works
1216        # there.
1217        def f(a):
1218            nonlocal x
1219            oldx = x
1220            x = a
1221            return oldx
1222        x = 0
1223        self.assertEqual(f'{f(a="3=")}', '0')
1224        self.assertEqual(x, '3=')
1225        self.assertEqual(f'{f(a=4)}', '3=')
1226        self.assertEqual(x, 4)
1227
1228        # Make sure __format__ is being called.
1229        class C:
1230            def __format__(self, s):
1231                return f'FORMAT-{s}'
1232            def __repr__(self):
1233                return 'REPR'
1234
1235        self.assertEqual(f'{C()=}', 'C()=REPR')
1236        self.assertEqual(f'{C()=!r}', 'C()=REPR')
1237        self.assertEqual(f'{C()=:}', 'C()=FORMAT-')
1238        self.assertEqual(f'{C()=: }', 'C()=FORMAT- ')
1239        self.assertEqual(f'{C()=:x}', 'C()=FORMAT-x')
1240        self.assertEqual(f'{C()=!r:*^20}', 'C()=********REPR********')
1241
1242        self.assertRaises(SyntaxError, eval, "f'{C=]'")
1243
1244        # Make sure leading and following text works.
1245        x = 'foo'
1246        self.assertEqual(f'X{x=}Y', 'Xx='+repr(x)+'Y')
1247
1248        # Make sure whitespace around the = works.
1249        self.assertEqual(f'X{x  =}Y', 'Xx  ='+repr(x)+'Y')
1250        self.assertEqual(f'X{x=  }Y', 'Xx=  '+repr(x)+'Y')
1251        self.assertEqual(f'X{x  =  }Y', 'Xx  =  '+repr(x)+'Y')
1252
1253        # These next lines contains tabs.  Backslash escapes don't
1254        # work in f-strings.
1255        # patchcheck doesn't like these tabs.  So the only way to test
1256        # this will be to dynamically created and exec the f-strings.  But
1257        # that's such a hassle I'll save it for another day.  For now, convert
1258        # the tabs to spaces just to shut up patchcheck.
1259        #self.assertEqual(f'X{x =}Y', 'Xx\t='+repr(x)+'Y')
1260        #self.assertEqual(f'X{x =       }Y', 'Xx\t=\t'+repr(x)+'Y')
1261
1262    def test_walrus(self):
1263        x = 20
1264        # This isn't an assignment expression, it's 'x', with a format
1265        # spec of '=10'.
1266        self.assertEqual(f'{x:=10}', '        20')
1267
1268        # This is an assignment expression, which requires parens.
1269        self.assertEqual(f'{(x:=10)}', '10')
1270        self.assertEqual(x, 10)
1271
1272    def test_invalid_syntax_error_message(self):
1273        with self.assertRaisesRegex(SyntaxError, "f-string: invalid syntax"):
1274            compile("f'{a $ b}'", "?", "exec")
1275
1276    def test_with_two_commas_in_format_specifier(self):
1277        error_msg = re.escape("Cannot specify ',' with ','.")
1278        with self.assertRaisesRegex(ValueError, error_msg):
1279            f'{1:,,}'
1280
1281    def test_with_two_underscore_in_format_specifier(self):
1282        error_msg = re.escape("Cannot specify '_' with '_'.")
1283        with self.assertRaisesRegex(ValueError, error_msg):
1284            f'{1:__}'
1285
1286    def test_with_a_commas_and_an_underscore_in_format_specifier(self):
1287        error_msg = re.escape("Cannot specify both ',' and '_'.")
1288        with self.assertRaisesRegex(ValueError, error_msg):
1289            f'{1:,_}'
1290
1291    def test_with_an_underscore_and_a_comma_in_format_specifier(self):
1292        error_msg = re.escape("Cannot specify both ',' and '_'.")
1293        with self.assertRaisesRegex(ValueError, error_msg):
1294            f'{1:_,}'
1295
1296    def test_syntax_error_for_starred_expressions(self):
1297        error_msg = re.escape("cannot use starred expression here")
1298        with self.assertRaisesRegex(SyntaxError, error_msg):
1299            compile("f'{*a}'", "?", "exec")
1300
1301        error_msg = re.escape("cannot use double starred expression here")
1302        with self.assertRaisesRegex(SyntaxError, error_msg):
1303            compile("f'{**a}'", "?", "exec")
1304
1305if __name__ == '__main__':
1306    unittest.main()
1307