Blame tests/run/test_fstring.pyx

Packit 562c7a
# cython: language_level=3
Packit 562c7a
# mode: run
Packit 562c7a
# tag: allow_unknown_names, f_strings, pep498
Packit 562c7a
Packit 562c7a
import ast
Packit 562c7a
import types
Packit 562c7a
import decimal
Packit 562c7a
import unittest
Packit 562c7a
import contextlib
Packit 562c7a
Packit 562c7a
import sys
Packit 562c7a
IS_PY2 = sys.version_info[0] < 3
Packit 562c7a
IS_PY26 = sys.version_info[:2] < (2, 7)
Packit 562c7a
Packit 562c7a
from Cython.Build.Inline import cython_inline
Packit 562c7a
from Cython.TestUtils import CythonTest
Packit 562c7a
from Cython.Compiler.Errors import CompileError, hold_errors, release_errors, error_stack, held_errors
Packit 562c7a
Packit 562c7a
def cy_eval(s, **kwargs):
Packit 562c7a
    return cython_inline('return ' + s, force=True, **kwargs)
Packit 562c7a
Packit 562c7a
a_global = 'global variable'
Packit 562c7a
Packit 562c7a
# You could argue that I'm too strict in looking for specific error
Packit 562c7a
#  values with assertRaisesRegex, but without it it's way too easy to
Packit 562c7a
#  make a syntax error in the test strings. Especially with all of the
Packit 562c7a
#  triple quotes, raw strings, backslashes, etc. I think it's a
Packit 562c7a
#  worthwhile tradeoff. When I switched to this method, I found many
Packit 562c7a
#  examples where I wasn't testing what I thought I was.
Packit 562c7a
Packit 562c7a
class TestCase(CythonTest):
Packit 562c7a
    def assertAllRaise(self, exception_type, regex, error_strings):
Packit 562c7a
        for str in error_strings:
Packit 562c7a
            hold_errors()
Packit 562c7a
            if exception_type is SyntaxError:
Packit 562c7a
                try:
Packit 562c7a
                    self.fragment(str)
Packit 562c7a
                except CompileError:
Packit 562c7a
                    assert True
Packit 562c7a
                else:
Packit 562c7a
                    assert held_errors(), "Invalid Cython code failed to raise SyntaxError: %r" % str
Packit 562c7a
                finally:
Packit 562c7a
                    release_errors(ignore=True)
Packit 562c7a
            else:
Packit 562c7a
                try:
Packit 562c7a
                    cython_inline(str, quiet=True)
Packit 562c7a
                except exception_type:
Packit 562c7a
                    assert True
Packit 562c7a
                else:
Packit 562c7a
                    assert False, "Invalid Cython code failed to raise %s: %r" % (exception_type, str)
Packit 562c7a
                finally:
Packit 562c7a
                    if error_stack:
Packit 562c7a
                        release_errors(ignore=True)
Packit 562c7a
Packit 562c7a
    if IS_PY2:
Packit 562c7a
        def assertEqual(self, first, second, msg=None):
Packit 562c7a
            # strip u'' string prefixes in Py2
Packit 562c7a
            if first != second and isinstance(first, unicode):
Packit 562c7a
                stripped_first = first.replace("u'", "'").replace('u"', '"')
Packit 562c7a
                if stripped_first == second:
Packit 562c7a
                    first = stripped_first
Packit 562c7a
                elif stripped_first.decode('unicode_escape') == second:
Packit 562c7a
                    first = stripped_first.decode('unicode_escape')
Packit 562c7a
            super(TestCase, self).assertEqual(first, second, msg)
Packit 562c7a
Packit 562c7a
        if IS_PY26:
Packit 562c7a
            @contextlib.contextmanager
Packit 562c7a
            def assertRaises(self, exc):
Packit 562c7a
                try:
Packit 562c7a
                    yield
Packit 562c7a
                except exc:
Packit 562c7a
                    pass
Packit 562c7a
                else:
Packit 562c7a
                    assert False, "exception '%s' not raised" % exc
Packit 562c7a
Packit 562c7a
            def assertIn(self, value, collection):
Packit 562c7a
                self.assertTrue(value in collection)
Packit 562c7a
Packit 562c7a
    def test__format__lookup(self):
Packit 562c7a
        if IS_PY26:
Packit 562c7a
            return
Packit 562c7a
        elif IS_PY2:
Packit 562c7a
            raise unittest.SkipTest("Py3-only")
Packit 562c7a
Packit 562c7a
        # Make sure __format__ is looked up on the type, not the instance.
Packit 562c7a
        class X:
Packit 562c7a
            def __format__(self, spec):
Packit 562c7a
                return 'class'
Packit 562c7a
Packit 562c7a
        x = X()
Packit 562c7a
Packit 562c7a
        # Add a bound __format__ method to the 'y' instance, but not
Packit 562c7a
        #  the 'x' instance.
Packit 562c7a
        y = X()
Packit 562c7a
        y.__format__ = types.MethodType(lambda self, spec: 'instance', y)
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{y}', format(y))
Packit 562c7a
        self.assertEqual(f'{y}', 'class')
Packit 562c7a
        self.assertEqual(format(x), format(y))
Packit 562c7a
Packit 562c7a
        # __format__ is not called this way, but still make sure it
Packit 562c7a
        #  returns what we expect (so we can make sure we're bypassing
Packit 562c7a
        #  it).
Packit 562c7a
        self.assertEqual(x.__format__(''), 'class')
Packit 562c7a
        self.assertEqual(y.__format__(''), 'instance')
Packit 562c7a
Packit 562c7a
        # This is how __format__ is actually called.
Packit 562c7a
        self.assertEqual(type(x).__format__(x, ''), 'class')
Packit 562c7a
        self.assertEqual(type(y).__format__(y, ''), 'class')
Packit 562c7a
Packit 562c7a
    def __test_ast(self):
Packit 562c7a
        # Inspired by http://bugs.python.org/issue24975
Packit 562c7a
        class X:
Packit 562c7a
            def __init__(self):
Packit 562c7a
                self.called = False
Packit 562c7a
            def __call__(self):
Packit 562c7a
                self.called = True
Packit 562c7a
                return 4
Packit 562c7a
        x = X()
Packit 562c7a
        expr = """
Packit 562c7a
a = 10
Packit 562c7a
f'{a * x()}'"""
Packit 562c7a
        t = ast.parse(expr)
Packit 562c7a
        c = compile(t, '', 'exec')
Packit 562c7a
Packit 562c7a
        # Make sure x was not called.
Packit 562c7a
        self.assertFalse(x.called)
Packit 562c7a
Packit 562c7a
        # Actually run the code.
Packit 562c7a
        exec(c)
Packit 562c7a
Packit 562c7a
        # Make sure x was called.
Packit 562c7a
        self.assertTrue(x.called)
Packit 562c7a
Packit 562c7a
    def test_docstring(self):
Packit 562c7a
        def f():
Packit 562c7a
            f'''Not a docstring'''
Packit 562c7a
        self.assertTrue(f.__doc__ is None)
Packit 562c7a
        def g():
Packit 562c7a
            '''Not a docstring''' \
Packit 562c7a
            f''
Packit 562c7a
        self.assertTrue(g.__doc__ is None)
Packit 562c7a
Packit 562c7a
    def __test_literal_eval(self):
Packit 562c7a
        with self.assertRaisesRegex(ValueError, 'malformed node or string'):
Packit 562c7a
            ast.literal_eval("f'x'")
Packit 562c7a
Packit 562c7a
    def __test_ast_compile_time_concat(self):
Packit 562c7a
        x = ['']
Packit 562c7a
Packit 562c7a
        expr = """x[0] = 'foo' f'{3}'"""
Packit 562c7a
        t = ast.parse(expr)
Packit 562c7a
        c = compile(t, '', 'exec')
Packit 562c7a
        exec(c)
Packit 562c7a
        self.assertEqual(x[0], 'foo3')
Packit 562c7a
Packit 562c7a
    def test_compile_time_concat_errors(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError,
Packit 562c7a
                            'cannot mix bytes and nonbytes literals',
Packit 562c7a
                            [r"""f'' b''""",
Packit 562c7a
                             r"""b'' f''""",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_literal(self):
Packit 562c7a
        self.assertEqual(f'', '')
Packit 562c7a
        self.assertEqual(f'a', 'a')
Packit 562c7a
        self.assertEqual(f' ', ' ')
Packit 562c7a
Packit 562c7a
    def test_unterminated_string(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string: unterminated string',
Packit 562c7a
                            [r"""f'{"x'""",
Packit 562c7a
                             r"""f'{"x}'""",
Packit 562c7a
                             r"""f'{("x'""",
Packit 562c7a
                             r"""f'{("x}'""",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_mismatched_parens(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string: mismatched',
Packit 562c7a
                            ["f'{((}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_double_braces(self):
Packit 562c7a
        self.assertEqual(f'{{', '{')
Packit 562c7a
        self.assertEqual(f'a{{', 'a{')
Packit 562c7a
        self.assertEqual(f'{{b', '{b')
Packit 562c7a
        self.assertEqual(f'a{{b', 'a{b')
Packit 562c7a
        self.assertEqual(f'}}', '}')
Packit 562c7a
        self.assertEqual(f'a}}', 'a}')
Packit 562c7a
        self.assertEqual(f'}}b', '}b')
Packit 562c7a
        self.assertEqual(f'a}}b', 'a}b')
Packit 562c7a
        self.assertEqual(f'{{}}', '{}')
Packit 562c7a
        self.assertEqual(f'a{{}}', 'a{}')
Packit 562c7a
        self.assertEqual(f'{{b}}', '{b}')
Packit 562c7a
        self.assertEqual(f'{{}}c', '{}c')
Packit 562c7a
        self.assertEqual(f'a{{b}}', 'a{b}')
Packit 562c7a
        self.assertEqual(f'a{{}}c', 'a{}c')
Packit 562c7a
        self.assertEqual(f'{{b}}c', '{b}c')
Packit 562c7a
        self.assertEqual(f'a{{b}}c', 'a{b}c')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{{{10}', '{10')
Packit 562c7a
        self.assertEqual(f'}}{10}', '}10')
Packit 562c7a
        self.assertEqual(f'}}{{{10}', '}{10')
Packit 562c7a
        self.assertEqual(f'}}a{{{10}', '}a{10')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{10}{{', '10{')
Packit 562c7a
        self.assertEqual(f'{10}}}', '10}')
Packit 562c7a
        self.assertEqual(f'{10}}}{{', '10}{')
Packit 562c7a
        self.assertEqual(f'{10}}}a{{' '}', '10}a{}')
Packit 562c7a
Packit 562c7a
        # Inside of strings, don't interpret doubled brackets.
Packit 562c7a
        self.assertEqual(f'{"{{}}"}', '{{}}')
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(TypeError, 'unhashable type',
Packit 562c7a
                            ["f'{ {{}} }'", # dict in a set
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_compile_time_concat(self):
Packit 562c7a
        x = 'def'
Packit 562c7a
        self.assertEqual('abc' f'## {x}ghi', 'abc## defghi')
Packit 562c7a
        self.assertEqual('abc' f'{x}' 'ghi', 'abcdefghi')
Packit 562c7a
        self.assertEqual('abc' f'{x}' 'gh' f'i{x:4}', 'abcdefghidef ')
Packit 562c7a
        self.assertEqual('{x}' f'{x}', '{x}def')
Packit 562c7a
        self.assertEqual('{x' f'{x}', '{xdef')
Packit 562c7a
        self.assertEqual('{x}' f'{x}', '{x}def')
Packit 562c7a
        self.assertEqual('{{x}}' f'{x}', '{{x}}def')
Packit 562c7a
        self.assertEqual('{{x' f'{x}', '{{xdef')
Packit 562c7a
        self.assertEqual('x}}' f'{x}', 'x}}def')
Packit 562c7a
        self.assertEqual(f'{x}' 'x}}', 'defx}}')
Packit 562c7a
        self.assertEqual(f'{x}' '', 'def')
Packit 562c7a
        self.assertEqual('' f'{x}' '', 'def')
Packit 562c7a
        self.assertEqual('' f'{x}', 'def')
Packit 562c7a
        self.assertEqual(f'{x}' '2', 'def2')
Packit 562c7a
        self.assertEqual('1' f'{x}' '2', '1def2')
Packit 562c7a
        self.assertEqual('1' f'{x}', '1def')
Packit 562c7a
        self.assertEqual(f'{x}' f'-{x}', 'def-def')
Packit 562c7a
        self.assertEqual('' f'', '')
Packit 562c7a
        self.assertEqual('' f'' '', '')
Packit 562c7a
        self.assertEqual('' f'' '' f'', '')
Packit 562c7a
        self.assertEqual(f'', '')
Packit 562c7a
        self.assertEqual(f'' '', '')
Packit 562c7a
        self.assertEqual(f'' '' f'', '')
Packit 562c7a
        self.assertEqual(f'' '' f'' '', '')
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
Packit 562c7a
                            ["f'{3' f'}'",  # can't concat to get a valid f-string
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_comments(self):
Packit 562c7a
        # These aren't comments, since they're in strings.
Packit 562c7a
        d = {'#': 'hash'}
Packit 562c7a
        self.assertEqual(f'{"#"}', '#')
Packit 562c7a
        self.assertEqual(f'{d["#"]}', 'hash')
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string expression part cannot include '#'",
Packit 562c7a
                            ["f'{1#}'",   # error because the expression becomes "(1#)"
Packit 562c7a
                             "f'{3(#)}'",
Packit 562c7a
                             "f'{#}'",
Packit 562c7a
                             "f'{)#}'",   # When wrapped in parens, this becomes
Packit 562c7a
                                          #  '()#)'.  Make sure that doesn't compile.
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_many_expressions(self):
Packit 562c7a
        # Create a string with many expressions in it. Note that
Packit 562c7a
        #  because we have a space in here as a literal, we're actually
Packit 562c7a
        #  going to use twice as many ast nodes: one for each literal
Packit 562c7a
        #  plus one for each expression.
Packit 562c7a
        def build_fstr(n, extra=''):
Packit 562c7a
            return "f'" + ('{x} ' * n) + extra + "'"
Packit 562c7a
Packit 562c7a
        x = 'X'
Packit 562c7a
        width = 1
Packit 562c7a
Packit 562c7a
        # Test around 256.
Packit 562c7a
        for i in range(250, 260):
Packit 562c7a
            self.assertEqual(cy_eval(build_fstr(i), x=x, width=width), (x+' ')*i)
Packit 562c7a
Packit 562c7a
        # Test concatenating 2 largs fstrings.
Packit 562c7a
        self.assertEqual(cy_eval(build_fstr(255)*3, x=x, width=width), (x+' ')*(255*3))  # CPython uses 255*256
Packit 562c7a
Packit 562c7a
        s = build_fstr(253, '{x:{width}} ')
Packit 562c7a
        self.assertEqual(cy_eval(s, x=x, width=width), (x+' ')*254)
Packit 562c7a
Packit 562c7a
        # Test lots of expressions and constants, concatenated.
Packit 562c7a
        s = "f'{1}' 'x' 'y'" * 1024
Packit 562c7a
        self.assertEqual(cy_eval(s, x=x, width=width), '1xy' * 1024)
Packit 562c7a
Packit 562c7a
    def test_format_specifier_expressions(self):
Packit 562c7a
        width = 10
Packit 562c7a
        precision = 4
Packit 562c7a
        value = decimal.Decimal('12.34567')
Packit 562c7a
        if not IS_PY26:
Packit 562c7a
            self.assertEqual(f'result: {value:{width}.{precision}}', 'result:      12.35')
Packit 562c7a
            self.assertEqual(f'result: {value:{width!r}.{precision}}', 'result:      12.35')
Packit 562c7a
            self.assertEqual(f'result: {value:{width:0}.{precision:1}}', 'result:      12.35')
Packit 562c7a
            self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}', 'result:      12.35')
Packit 562c7a
            self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}', 'result:      12.35')
Packit 562c7a
        self.assertEqual(f'{10:#{1}0x}', '       0xa')
Packit 562c7a
        self.assertEqual(f'{10:{"#"}1{0}{"x"}}', '       0xa')
Packit 562c7a
        self.assertEqual(f'{-10:-{"#"}1{0}x}', '      -0xa')
Packit 562c7a
        self.assertEqual(f'{-10:{"-"}#{1}0{"x"}}', '      -0xa')
Packit 562c7a
        self.assertEqual(f'{10:#{3 != {4:5} and width}x}', '       0xa')
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
Packit 562c7a
                            ["""f'{"s"!r{":10"}}'""",
Packit 562c7a
Packit 562c7a
                             # This looks like a nested format spec.
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "invalid syntax",
Packit 562c7a
                            [# Invalid syntax inside a nested spec.
Packit 562c7a
                             "f'{4:{/5}}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        # CYTHON: The nesting restriction seems rather arbitrary. Ignoring it for now and instead test that it works.
Packit 562c7a
        if not IS_PY26:
Packit 562c7a
            self.assertEqual(f'result: {value:{width:{0}}.{precision:1}}', 'result:      12.35')
Packit 562c7a
        #self.assertAllRaise(SyntaxError, "f-string: expressions nested too deeply",
Packit 562c7a
        #                    [# Can't nest format specifiers.
Packit 562c7a
        #                     "f'result: {value:{width:{0}}.{precision:1}}'",
Packit 562c7a
        #                     ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
Packit 562c7a
                            [# No expansion inside conversion or for
Packit 562c7a
                             #  the : or ! itself.
Packit 562c7a
                             """f'{"s"!{"r"}}'""",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_side_effect_order(self):
Packit 562c7a
        class X:
Packit 562c7a
            def __init__(self):
Packit 562c7a
                self.i = 0
Packit 562c7a
            def __format__(self, spec):
Packit 562c7a
                self.i += 1
Packit 562c7a
                return str(self.i)
Packit 562c7a
Packit 562c7a
        x = X()
Packit 562c7a
        self.assertEqual(f'{x} {x}', '1 2')
Packit 562c7a
Packit 562c7a
    def test_missing_expression(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string: empty expression not allowed',
Packit 562c7a
                            ["f'{}'",
Packit 562c7a
                             "f'{ }'"
Packit 562c7a
                             "f' {} '",
Packit 562c7a
                             "f'{!r}'",
Packit 562c7a
                             "f'{ !r}'",
Packit 562c7a
                             "f'{10:{ }}'",
Packit 562c7a
                             "f' { } '",
Packit 562c7a
Packit 562c7a
                             # The Python parser ignores also the following
Packit 562c7a
                             # whitespace characters in additional to a space.
Packit 562c7a
                             "f'''{\t\f\r\n}'''",
Packit 562c7a
Packit 562c7a
                             # Catch the empty expression before the
Packit 562c7a
                             #  invalid conversion.
Packit 562c7a
                             "f'{!x}'",
Packit 562c7a
                             "f'{ !xr}'",
Packit 562c7a
                             "f'{!x:}'",
Packit 562c7a
                             "f'{!x:a}'",
Packit 562c7a
                             "f'{ !xr:}'",
Packit 562c7a
                             "f'{ !xr:a}'",
Packit 562c7a
Packit 562c7a
                             "f'{!}'",
Packit 562c7a
                             "f'{:}'",
Packit 562c7a
Packit 562c7a
                             # We find the empty expression before the
Packit 562c7a
                             #  missing closing brace.
Packit 562c7a
                             "f'{!'",
Packit 562c7a
                             "f'{!s:'",
Packit 562c7a
                             "f'{:'",
Packit 562c7a
                             "f'{:x'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        # Different error message is raised for other whitespace characters.
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'invalid character in identifier',
Packit 562c7a
                            ["f'''{\xa0}'''",
Packit 562c7a
                             #"\xa0",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_parens_in_expressions(self):
Packit 562c7a
        self.assertEqual(f'{3,}', '(3,)')
Packit 562c7a
Packit 562c7a
        # Add these because when an expression is evaluated, parens
Packit 562c7a
        #  are added around it. But we shouldn't go from an invalid
Packit 562c7a
        #  expression to a valid one. The added parens are just
Packit 562c7a
        #  supposed to allow whitespace (including newlines).
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'invalid syntax',
Packit 562c7a
                            ["f'{,}'",
Packit 562c7a
                             "f'{,}'",  # this is (,), which is an error
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
Packit 562c7a
                            ["f'{3)+(4}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'EOL while scanning string literal',
Packit 562c7a
                            ["f'{\n}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_backslashes_in_string_part(self):
Packit 562c7a
        self.assertEqual(f'\t', '\t')
Packit 562c7a
        self.assertEqual(r'\t', '\\t')
Packit 562c7a
        self.assertEqual(rf'\t', '\\t')
Packit 562c7a
        self.assertEqual(f'{2}\t', '2\t')
Packit 562c7a
        self.assertEqual(f'{2}\t{3}', '2\t3')
Packit 562c7a
        self.assertEqual(f'\t{3}', '\t3')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'\u0394', '\u0394')
Packit 562c7a
        self.assertEqual(r'\u0394', '\\u0394')
Packit 562c7a
        self.assertEqual(rf'\u0394', '\\u0394')
Packit 562c7a
        self.assertEqual(f'{2}\u0394', '2\u0394')
Packit 562c7a
        self.assertEqual(f'{2}\u0394{3}', '2\u03943')
Packit 562c7a
        self.assertEqual(f'\u0394{3}', '\u03943')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'\U00000394', '\u0394')
Packit 562c7a
        self.assertEqual(r'\U00000394', '\\U00000394')
Packit 562c7a
        self.assertEqual(rf'\U00000394', '\\U00000394')
Packit 562c7a
        self.assertEqual(f'{2}\U00000394', '2\u0394')
Packit 562c7a
        self.assertEqual(f'{2}\U00000394{3}', '2\u03943')
Packit 562c7a
        self.assertEqual(f'\U00000394{3}', '\u03943')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}', '\u0394')
Packit 562c7a
        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
Packit 562c7a
        self.assertEqual(f'{2}\N{GREEK CAPITAL LETTER DELTA}{3}', '2\u03943')
Packit 562c7a
        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}{3}', '\u03943')
Packit 562c7a
        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}', '2\u0394')
Packit 562c7a
        self.assertEqual(f'2\N{GREEK CAPITAL LETTER DELTA}3', '2\u03943')
Packit 562c7a
        self.assertEqual(f'\N{GREEK CAPITAL LETTER DELTA}3', '\u03943')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'\x20', ' ')
Packit 562c7a
        self.assertEqual(r'\x20', '\\x20')
Packit 562c7a
        self.assertEqual(rf'\x20', '\\x20')
Packit 562c7a
        self.assertEqual(f'{2}\x20', '2 ')
Packit 562c7a
        self.assertEqual(f'{2}\x20{3}', '2 3')
Packit 562c7a
        self.assertEqual(f'\x20{3}', ' 3')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'2\x20', '2 ')
Packit 562c7a
        self.assertEqual(f'2\x203', '2 3')
Packit 562c7a
        self.assertEqual(f'\x203', ' 3')
Packit 562c7a
Packit 562c7a
        #with self.assertWarns(DeprecationWarning):  # invalid escape sequence
Packit 562c7a
        #    value = cy_eval(r"f'\{6*7}'")
Packit 562c7a
        #self.assertEqual(value, '\\42')
Packit 562c7a
        self.assertEqual(f'\\{6*7}', '\\42')
Packit 562c7a
        self.assertEqual(fr'\{6*7}', '\\42')
Packit 562c7a
Packit 562c7a
        AMPERSAND = 'spam'
Packit 562c7a
        # Get the right unicode character (&), or pick up local variable
Packit 562c7a
        # depending on the number of backslashes.
Packit 562c7a
        self.assertEqual(f'\N{AMPERSAND}', '&')
Packit 562c7a
        self.assertEqual(f'\\N{AMPERSAND}', '\\Nspam')
Packit 562c7a
        self.assertEqual(fr'\N{AMPERSAND}', '\\Nspam')
Packit 562c7a
        self.assertEqual(f'\\\N{AMPERSAND}', '\\&')
Packit 562c7a
Packit 562c7a
    def test_misformed_unicode_character_name(self):
Packit 562c7a
        # These test are needed because unicode names are parsed
Packit 562c7a
        # differently inside f-strings.
Packit 562c7a
        self.assertAllRaise(SyntaxError, r"\(unicode error\) 'unicodeescape' codec can't decode bytes in position .*: malformed \\N character escape",
Packit 562c7a
                            [r"f'\N'",
Packit 562c7a
                             r"f'\N{'",
Packit 562c7a
                             r"f'\N{GREEK CAPITAL LETTER DELTA'",
Packit 562c7a
Packit 562c7a
                             # Here are the non-f-string versions,
Packit 562c7a
                             #  which should give the same errors.
Packit 562c7a
                             r"'\N'",
Packit 562c7a
                             r"'\N{'",
Packit 562c7a
                             r"'\N{GREEK CAPITAL LETTER DELTA'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_no_backslashes_in_expression_part(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string expression part cannot include a backslash',
Packit 562c7a
                            [r"f'{\'a\'}'",
Packit 562c7a
                             r"f'{\t3}'",
Packit 562c7a
                             r"f'{\}'",
Packit 562c7a
                             r"rf'{\'a\'}'",
Packit 562c7a
                             r"rf'{\t3}'",
Packit 562c7a
                             r"rf'{\}'",
Packit 562c7a
                             r"""rf'{"\N{LEFT CURLY BRACKET}"}'""",
Packit 562c7a
                             r"f'{\n}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_no_escapes_for_braces(self):
Packit 562c7a
        """
Packit 562c7a
        Only literal curly braces begin an expression.
Packit 562c7a
        """
Packit 562c7a
        # \x7b is '{'.
Packit 562c7a
        self.assertEqual(f'\x7b1+1}}', '{1+1}')
Packit 562c7a
        self.assertEqual(f'\x7b1+1', '{1+1')
Packit 562c7a
        self.assertEqual(f'\u007b1+1', '{1+1')
Packit 562c7a
        self.assertEqual(f'\N{LEFT CURLY BRACKET}1+1\N{RIGHT CURLY BRACKET}', '{1+1}')
Packit 562c7a
Packit 562c7a
    def test_newlines_in_expressions(self):
Packit 562c7a
        self.assertEqual(f'{0}', '0')
Packit 562c7a
        self.assertEqual(rf'''{3+
Packit 562c7a
4}''', '7')
Packit 562c7a
Packit 562c7a
    def test_lambda(self):
Packit 562c7a
        x = 5
Packit 562c7a
        self.assertEqual(f'{(lambda y:x*y)("8")!r}', "'88888'")
Packit 562c7a
        if not IS_PY2:
Packit 562c7a
            self.assertEqual(f'{(lambda y:x*y)("8")!r:10}', "'88888'   ")
Packit 562c7a
        self.assertEqual(f'{(lambda y:x*y)("8"):10}', "88888     ")
Packit 562c7a
Packit 562c7a
        # lambda doesn't work without parens, because the colon
Packit 562c7a
        #  makes the parser think it's a format_spec
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing',
Packit 562c7a
                            ["f'{lambda x:x}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_yield(self):
Packit 562c7a
        # Not terribly useful, but make sure the yield turns
Packit 562c7a
        #  a function into a generator
Packit 562c7a
        def fn(y):
Packit 562c7a
            f'y:{yield y*2}'
Packit 562c7a
Packit 562c7a
        g = fn(4)
Packit 562c7a
        self.assertEqual(next(g), 8)
Packit 562c7a
Packit 562c7a
    def test_yield_send(self):
Packit 562c7a
        def fn(x):
Packit 562c7a
            yield f'x:{yield (lambda i: x * i)}'
Packit 562c7a
Packit 562c7a
        g = fn(10)
Packit 562c7a
        the_lambda = next(g)
Packit 562c7a
        self.assertEqual(the_lambda(4), 40)
Packit 562c7a
        self.assertEqual(g.send('string'), 'x:string')
Packit 562c7a
Packit 562c7a
    def test_expressions_with_triple_quoted_strings(self):
Packit 562c7a
        self.assertEqual(f"{'''x'''}", 'x')
Packit 562c7a
        self.assertEqual(f"{'''eric's'''}", "eric's")
Packit 562c7a
Packit 562c7a
        # Test concatenation within an expression
Packit 562c7a
        self.assertEqual(f'{"x" """eric"s""" "y"}', 'xeric"sy')
Packit 562c7a
        self.assertEqual(f'{"x" """eric"s"""}', 'xeric"s')
Packit 562c7a
        self.assertEqual(f'{"""eric"s""" "y"}', 'eric"sy')
Packit 562c7a
        self.assertEqual(f'{"""x""" """eric"s""" "y"}', 'xeric"sy')
Packit 562c7a
        self.assertEqual(f'{"""x""" """eric"s""" """y"""}', 'xeric"sy')
Packit 562c7a
        self.assertEqual(f'{r"""x""" """eric"s""" """y"""}', 'xeric"sy')
Packit 562c7a
Packit 562c7a
    def test_multiple_vars(self):
Packit 562c7a
        x = 98
Packit 562c7a
        y = 'abc'
Packit 562c7a
        self.assertEqual(f'{x}{y}', '98abc')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'X{x}{y}', 'X98abc')
Packit 562c7a
        self.assertEqual(f'{x}X{y}', '98Xabc')
Packit 562c7a
        self.assertEqual(f'{x}{y}X', '98abcX')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'X{x}Y{y}', 'X98Yabc')
Packit 562c7a
        self.assertEqual(f'X{x}{y}Y', 'X98abcY')
Packit 562c7a
        self.assertEqual(f'{x}X{y}Y', '98XabcY')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'X{x}Y{y}Z', 'X98YabcZ')
Packit 562c7a
Packit 562c7a
    def test_closure(self):
Packit 562c7a
        def outer(x):
Packit 562c7a
            def inner():
Packit 562c7a
                return f'x:{x}'
Packit 562c7a
            return inner
Packit 562c7a
Packit 562c7a
        self.assertEqual(outer('987')(), 'x:987')
Packit 562c7a
        self.assertEqual(outer(7)(), 'x:7')
Packit 562c7a
Packit 562c7a
    def test_arguments(self):
Packit 562c7a
        y = 2
Packit 562c7a
        def f(x, width):
Packit 562c7a
            return f'x={x*y:{width}}'
Packit 562c7a
Packit 562c7a
        self.assertEqual(f('foo', 10), 'x=foofoo    ')
Packit 562c7a
        x = 'bar'
Packit 562c7a
        self.assertEqual(f(10, 10), 'x=        20')
Packit 562c7a
Packit 562c7a
    def test_locals(self):
Packit 562c7a
        value = 123
Packit 562c7a
        self.assertEqual(f'v:{value}', 'v:123')
Packit 562c7a
Packit 562c7a
    def test_missing_variable(self):
Packit 562c7a
        with self.assertRaises(NameError):
Packit 562c7a
            f'v:{value}'
Packit 562c7a
Packit 562c7a
    def test_missing_format_spec(self):
Packit 562c7a
        class O:
Packit 562c7a
            def __format__(self, spec):
Packit 562c7a
                if not spec:
Packit 562c7a
                    return '*'
Packit 562c7a
                return spec
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{O():x}', 'x')
Packit 562c7a
        self.assertEqual(f'{O()}', '*')
Packit 562c7a
        self.assertEqual(f'{O():}', '*')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{3:}', '3')
Packit 562c7a
        self.assertEqual(f'{3!s:}', '3')
Packit 562c7a
Packit 562c7a
    def test_global(self):
Packit 562c7a
        self.assertEqual(f'g:{a_global}', 'g:global variable')
Packit 562c7a
        self.assertEqual(f'g:{a_global!r}', "g:'global variable'")
Packit 562c7a
Packit 562c7a
        a_local = 'local variable'
Packit 562c7a
        self.assertEqual(f'g:{a_global} l:{a_local}',
Packit 562c7a
                         'g:global variable l:local variable')
Packit 562c7a
        self.assertEqual(f'g:{a_global!r}',
Packit 562c7a
                         "g:'global variable'")
Packit 562c7a
        self.assertEqual(f'g:{a_global} l:{a_local!r}',
Packit 562c7a
                         "g:global variable l:'local variable'")
Packit 562c7a
Packit 562c7a
        self.assertIn("module 'unittest' from", f'{unittest}')
Packit 562c7a
Packit 562c7a
    def test_shadowed_global(self):
Packit 562c7a
        a_global = 'really a local'
Packit 562c7a
        self.assertEqual(f'g:{a_global}', 'g:really a local')
Packit 562c7a
        self.assertEqual(f'g:{a_global!r}', "g:'really a local'")
Packit 562c7a
Packit 562c7a
        a_local = 'local variable'
Packit 562c7a
        self.assertEqual(f'g:{a_global} l:{a_local}',
Packit 562c7a
                         'g:really a local l:local variable')
Packit 562c7a
        self.assertEqual(f'g:{a_global!r}',
Packit 562c7a
                         "g:'really a local'")
Packit 562c7a
        self.assertEqual(f'g:{a_global} l:{a_local!r}',
Packit 562c7a
                         "g:really a local l:'local variable'")
Packit 562c7a
Packit 562c7a
    def test_call(self):
Packit 562c7a
        def foo(x):
Packit 562c7a
            return 'x=' + str(x)
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{foo(10)}', 'x=10')
Packit 562c7a
Packit 562c7a
    def test_nested_fstrings(self):
Packit 562c7a
        y = 5
Packit 562c7a
        self.assertEqual(f'{f"{0}"*3}', '000')
Packit 562c7a
        self.assertEqual(f'{f"{y}"*3}', '555')
Packit 562c7a
Packit 562c7a
    def test_invalid_string_prefixes(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'unexpected EOF while parsing',
Packit 562c7a
                            ["fu''",
Packit 562c7a
                             "uf''",
Packit 562c7a
                             "Fu''",
Packit 562c7a
                             "fU''",
Packit 562c7a
                             "Uf''",
Packit 562c7a
                             "uF''",
Packit 562c7a
                             "ufr''",
Packit 562c7a
                             "urf''",
Packit 562c7a
                             "fur''",
Packit 562c7a
                             "fru''",
Packit 562c7a
                             "rfu''",
Packit 562c7a
                             "ruf''",
Packit 562c7a
                             "FUR''",
Packit 562c7a
                             "Fur''",
Packit 562c7a
                             "fb''",
Packit 562c7a
                             "fB''",
Packit 562c7a
                             "Fb''",
Packit 562c7a
                             "FB''",
Packit 562c7a
                             "bf''",
Packit 562c7a
                             "bF''",
Packit 562c7a
                             "Bf''",
Packit 562c7a
                             "BF''",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_leading_trailing_spaces(self):
Packit 562c7a
        self.assertEqual(f'{ 3}', '3')
Packit 562c7a
        self.assertEqual(f'{  3}', '3')
Packit 562c7a
        self.assertEqual(f'{3 }', '3')
Packit 562c7a
        self.assertEqual(f'{3  }', '3')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]}}',
Packit 562c7a
                         'expr={1: 2}')
Packit 562c7a
        self.assertEqual(f'expr={ {x: y for x, y in [(1, 2), ]} }',
Packit 562c7a
                         'expr={1: 2}')
Packit 562c7a
Packit 562c7a
    def test_not_equal(self):
Packit 562c7a
        # There's a special test for this because there's a special
Packit 562c7a
        #  case in the f-string parser to look for != as not ending an
Packit 562c7a
        #  expression. Normally it would, while looking for !s or !r.
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{3!=4}', 'True')
Packit 562c7a
        self.assertEqual(f'{3!=4:}', 'True')
Packit 562c7a
        self.assertEqual(f'{3!=4!s}', 'True')
Packit 562c7a
        self.assertEqual(f'{3!=4!s:.3}', 'Tru')
Packit 562c7a
Packit 562c7a
    def test_conversions(self):
Packit 562c7a
        self.assertEqual(f'{3.14:10.10}', '      3.14')
Packit 562c7a
        if not IS_PY26:
Packit 562c7a
            self.assertEqual(f'{3.14!s:10.10}', '3.14      ')
Packit 562c7a
            self.assertEqual(f'{3.14!r:10.10}', '3.14      ')
Packit 562c7a
            self.assertEqual(f'{3.14!a:10.10}', '3.14      ')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{"a"}', 'a')
Packit 562c7a
        self.assertEqual(f'{"a"!r}', "'a'")
Packit 562c7a
        self.assertEqual(f'{"a"!a}', "'a'")
Packit 562c7a
Packit 562c7a
        # Not a conversion.
Packit 562c7a
        self.assertEqual(f'{"a!r"}', "a!r")
Packit 562c7a
Packit 562c7a
        # Not a conversion, but show that ! is allowed in a format spec.
Packit 562c7a
        self.assertEqual(f'{3.14:!<10.10}', '3.14!!!!!!')
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'f-string: invalid conversion character',
Packit 562c7a
                            ["f'{3!g}'",
Packit 562c7a
                             "f'{3!A}'",
Packit 562c7a
                             "f'{3!3}'",
Packit 562c7a
                             "f'{3!G}'",
Packit 562c7a
                             "f'{3!!}'",
Packit 562c7a
                             "f'{3!:}'",
Packit 562c7a
                             "f'{3! s}'",  # no space before conversion char
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
Packit 562c7a
                            ["f'{x!s{y}}'",
Packit 562c7a
                             "f'{3!ss}'",
Packit 562c7a
                             "f'{3!ss:}'",
Packit 562c7a
                             "f'{3!ss:s}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_assignment(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'invalid syntax',
Packit 562c7a
                            ["f'' = 3",
Packit 562c7a
                             "f'{0}' = x",
Packit 562c7a
                             "f'{x}' = x",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_del(self):
Packit 562c7a
        self.assertAllRaise(CompileError, 'invalid syntax',   # CPython raises SyntaxError
Packit 562c7a
                            ["del f''",
Packit 562c7a
                             "del '' f''",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
    def test_mismatched_braces(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: single '}' is not allowed",
Packit 562c7a
                            ["f'{{}'",
Packit 562c7a
                             "f'{{}}}'",
Packit 562c7a
                             "f'}'",
Packit 562c7a
                             "f'x}'",
Packit 562c7a
                             "f'x}x'",
Packit 562c7a
                             r"f'\u007b}'",
Packit 562c7a
Packit 562c7a
                             # Can't have { or } in a format spec.
Packit 562c7a
                             "f'{3:}>10}'",
Packit 562c7a
                             "f'{3:}}>10}'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        self.assertAllRaise(SyntaxError, "f-string: expecting '}'",
Packit 562c7a
                            ["f'{3:{{>10}'",
Packit 562c7a
                             "f'{3'",
Packit 562c7a
                             "f'{3!'",
Packit 562c7a
                             "f'{3:'",
Packit 562c7a
                             "f'{3!s'",
Packit 562c7a
                             "f'{3!s:'",
Packit 562c7a
                             "f'{3!s:3'",
Packit 562c7a
                             "f'x{'",
Packit 562c7a
                             "f'x{x'",
Packit 562c7a
                             "f'{x'",
Packit 562c7a
                             "f'{3:s'",
Packit 562c7a
                             "f'{{{'",
Packit 562c7a
                             "f'{{}}{'",
Packit 562c7a
                             "f'{'",
Packit 562c7a
                             ])
Packit 562c7a
Packit 562c7a
        # But these are just normal strings.
Packit 562c7a
        self.assertEqual(f'{"{"}', '{')
Packit 562c7a
        self.assertEqual(f'{"}"}', '}')
Packit 562c7a
        self.assertEqual(f'{3:{"}"}>10}', '}}}}}}}}}3')
Packit 562c7a
        self.assertEqual(f'{2:{"{"}>10}', '{{{{{{{{{2')
Packit 562c7a
Packit 562c7a
    def test_if_conditional(self):
Packit 562c7a
        # There's special logic in compile.c to test if the
Packit 562c7a
        #  conditional for an if (and while) are constants. Exercise
Packit 562c7a
        #  that code.
Packit 562c7a
Packit 562c7a
        def test_fstring(x, expected):
Packit 562c7a
            flag = 0
Packit 562c7a
            if f'{x}':
Packit 562c7a
                flag = 1
Packit 562c7a
            else:
Packit 562c7a
                flag = 2
Packit 562c7a
            self.assertEqual(flag, expected)
Packit 562c7a
Packit 562c7a
        def test_concat_empty(x, expected):
Packit 562c7a
            flag = 0
Packit 562c7a
            if '' f'{x}':
Packit 562c7a
                flag = 1
Packit 562c7a
            else:
Packit 562c7a
                flag = 2
Packit 562c7a
            self.assertEqual(flag, expected)
Packit 562c7a
Packit 562c7a
        def test_concat_non_empty(x, expected):
Packit 562c7a
            flag = 0
Packit 562c7a
            if ' ' f'{x}':
Packit 562c7a
                flag = 1
Packit 562c7a
            else:
Packit 562c7a
                flag = 2
Packit 562c7a
            self.assertEqual(flag, expected)
Packit 562c7a
Packit 562c7a
        test_fstring('', 2)
Packit 562c7a
        test_fstring(' ', 1)
Packit 562c7a
Packit 562c7a
        test_concat_empty('', 2)
Packit 562c7a
        test_concat_empty(' ', 1)
Packit 562c7a
Packit 562c7a
        test_concat_non_empty('', 1)
Packit 562c7a
        test_concat_non_empty(' ', 1)
Packit 562c7a
Packit 562c7a
    def test_empty_format_specifier(self):
Packit 562c7a
        x = 'test'
Packit 562c7a
        self.assertEqual(f'{x}', 'test')
Packit 562c7a
        self.assertEqual(f'{x:}', 'test')
Packit 562c7a
        self.assertEqual(f'{x!s:}', 'test')
Packit 562c7a
        self.assertEqual(f'{x!r:}', "'test'")
Packit 562c7a
Packit 562c7a
    def test_str_format_differences(self):
Packit 562c7a
        d = {'a': 'string',
Packit 562c7a
             0: 'integer',
Packit 562c7a
             }
Packit 562c7a
        a = 0
Packit 562c7a
        self.assertEqual(f'{d[0]}', 'integer')
Packit 562c7a
        self.assertEqual(f'{d["a"]}', 'string')
Packit 562c7a
        self.assertEqual(f'{d[a]}', 'integer')
Packit 562c7a
        self.assertEqual('{d[a]}'.format(d=d), 'string')
Packit 562c7a
        self.assertEqual('{d[0]}'.format(d=d), 'integer')
Packit 562c7a
Packit 562c7a
    def test_invalid_expressions(self):
Packit 562c7a
        self.assertAllRaise(SyntaxError, 'invalid syntax',
Packit 562c7a
                            [r"f'{a[4)}'",
Packit 562c7a
                             r"f'{a(4]}'",
Packit 562c7a
                            ])
Packit 562c7a
Packit 562c7a
    def test_errors(self):
Packit 562c7a
        # see issue 26287
Packit 562c7a
        exc = ValueError if sys.version_info < (3, 4) else TypeError
Packit 562c7a
        self.assertAllRaise(exc, 'unsupported',
Packit 562c7a
                            [r"f'{(lambda: 0):x}'",
Packit 562c7a
                             r"f'{(0,):x}'",
Packit 562c7a
                             ])
Packit 562c7a
        self.assertAllRaise(ValueError, 'Unknown format code',
Packit 562c7a
                            [r"f'{1000:j}'",
Packit 562c7a
                             r"f'{1000:j}'",
Packit 562c7a
                            ])
Packit 562c7a
Packit 562c7a
    def test_loop(self):
Packit 562c7a
        for i in range(1000):
Packit 562c7a
            self.assertEqual(f'i:{i}', 'i:' + str(i))
Packit 562c7a
Packit 562c7a
    def test_dict(self):
Packit 562c7a
        d = {'"': 'dquote',
Packit 562c7a
             "'": 'squote',
Packit 562c7a
             'foo': 'bar',
Packit 562c7a
             }
Packit 562c7a
        self.assertEqual(f'''{d["'"]}''', 'squote')
Packit 562c7a
        self.assertEqual(f"""{d['"']}""", 'dquote')
Packit 562c7a
Packit 562c7a
        self.assertEqual(f'{d["foo"]}', 'bar')
Packit 562c7a
        self.assertEqual(f"{d['foo']}", 'bar')
Packit 562c7a
Packit 562c7a
    def __test_backslash_char(self):
Packit 562c7a
        # Check eval of a backslash followed by a control char.
Packit 562c7a
        # See bpo-30682: this used to raise an assert in pydebug mode.
Packit 562c7a
        self.assertEqual(cy_eval('f"\\\n"'), '')
Packit 562c7a
        self.assertEqual(cy_eval('f"\\\r"'), '')
Packit 562c7a
Packit 562c7a
if __name__ == '__main__':
Packit 562c7a
    unittest.main()