diff --git a/pyupgrade/_plugins/fstrings.py b/pyupgrade/_plugins/fstrings.py index 3abf1fe6..01a07b25 100644 --- a/pyupgrade/_plugins/fstrings.py +++ b/pyupgrade/_plugins/fstrings.py @@ -4,6 +4,7 @@ from typing import Iterable from tokenize_rt import Offset +from tokenize_rt import parse_string_literal from tokenize_rt import Token from tokenize_rt import tokens_to_src @@ -43,7 +44,12 @@ def _to_fstring( parts = [] i = 0 - for s, name, spec, conv in parse_format('f' + src): + + # need to remove `u` prefix so it isn't invalid syntax + prefix, rest = parse_string_literal(src) + new_src = 'f' + prefix.translate({ord('u'): None, ord('U'): None}) + rest + + for s, name, spec, conv in parse_format(new_src): if name is not None: k, dot, rest = name.partition('.') name = ''.join((params[k or str(i)], dot, rest)) diff --git a/tests/features/fstrings_test.py b/tests/features/fstrings_test.py index 6c1212c2..51e9179c 100644 --- a/tests/features/fstrings_test.py +++ b/tests/features/fstrings_test.py @@ -64,6 +64,11 @@ def test_fix_fstrings_noop(s): r'f"\N{snowman} {a}"', id='named escape sequences', ), + pytest.param( + 'u"foo{}".format(1)', + 'f"foo{1}"', + id='u-prefixed format', + ), ), ) def test_fix_fstrings(s, expected):