Skip to content

Unsupported syntax error false positive for escapes in f-string format specifier #20844

@ntBre

Description

@ntBre

This string from our formatter test suite:

# FIXME(brent) This should not be a syntax error on output. The escaped quotes are in the format
# spec, which is valid even before 3.12.
f'{x:a{z:hy "user"}} \'\'\''

gets formatted to

f"{x:a{z:hy \"user\"}} '''"

which is reported as invalid by Ruff. However, this is allowed even before Python 3.12:

Python 3.7.9 (default, Aug 23 2020, 00:57:53)
[Clang 10.0.1 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f"{x:a{z:hy \"user\"}} '''"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

even if GitHub's syntax highlighting doesn't like it. The NameError means this parsed successfully, unlike escapes in the expression part:

>>> f"{'\x123'}"
  File "<stdin>", line 1
SyntaxError: f-string expression part cannot include a backslash

It seems that my logic for detecting these was too naive after all:

for slash_position in memchr::memchr_iter(b'\\', self.source[expr.range].as_bytes())
{
let slash_position = TextSize::try_from(slash_position).unwrap();
self.add_unsupported_syntax_error(
UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::Backslash),
TextRange::at(expr.range.start() + slash_position, '\\'.text_len()),
);
}
if let Some(quote_position) =
memchr::memmem::find(self.source[expr.range].as_bytes(), quote_bytes)
{
let quote_position = TextSize::try_from(quote_position).unwrap();
self.add_unsupported_syntax_error(
UnsupportedSyntaxErrorKind::Pep701FString(FStringKind::NestedQuote),
TextRange::at(expr.range.start() + quote_position, quote_len),
);
}

This example from the formatter emits both the backslash and reused quote character diagnostics. We should double-check the comment semantics too, but I think that part may still be correct.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingparserRelated to the parser

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions