Disallow newlines in format specifiers of single quoted f- or t-strings (#18708)

This commit is contained in:
Micha Reiser 2025-06-18 14:56:15 +02:00 committed by GitHub
parent 23261a38a0
commit 1188ffccc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 521 additions and 513 deletions

View file

@ -826,19 +826,17 @@ impl<'src> Lexer<'src> {
)));
}
'\n' | '\r' if !interpolated_string.is_triple_quoted() => {
// If we encounter a newline while we're in a format spec, then
// we stop here and let the lexer emit the newline token.
//
// Relevant discussion: https://github.com/python/cpython/issues/110259
if in_format_spec {
break;
}
// https://github.com/astral-sh/ruff/issues/18632
self.interpolated_strings.pop();
let error_type = if in_format_spec {
InterpolatedStringErrorType::NewlineInFormatSpec
} else {
InterpolatedStringErrorType::UnterminatedString
};
return Some(self.push_error(LexicalError::new(
LexicalErrorType::from_interpolated_string_error(
InterpolatedStringErrorType::UnterminatedString,
string_kind,
),
LexicalErrorType::from_interpolated_string_error(error_type, string_kind),
self.token_range(),
)));
}
@ -1768,6 +1766,7 @@ mod tests {
}
}
#[track_caller]
fn lex_valid(source: &str, mode: Mode, start_offset: TextSize) -> LexerOutput {
let output = lex(source, mode, start_offset);
@ -1783,6 +1782,7 @@ mod tests {
output
}
#[track_caller]
fn lex_invalid(source: &str, mode: Mode) -> LexerOutput {
let output = lex(source, mode, TextSize::default());
@ -1794,14 +1794,17 @@ mod tests {
output
}
#[track_caller]
fn lex_source(source: &str) -> LexerOutput {
lex_valid(source, Mode::Module, TextSize::default())
}
#[track_caller]
fn lex_source_with_offset(source: &str, start_offset: TextSize) -> LexerOutput {
lex_valid(source, Mode::Module, start_offset)
}
#[track_caller]
fn lex_jupyter_source(source: &str) -> LexerOutput {
lex_valid(source, Mode::Ipython, TextSize::default())
}
@ -2394,6 +2397,13 @@ f'''__{
b
c
}__'''
";
assert_snapshot!(lex_source(source));
}
#[test]
fn test_fstring_newline_format_spec() {
let source = r"
f'__{
x:d
}__'
@ -2402,7 +2412,7 @@ f'__{
b
}__'
";
assert_snapshot!(lex_source(source));
assert_snapshot!(lex_invalid(source, Mode::Module));
}
#[test]
@ -2572,6 +2582,13 @@ t'''__{
b
c
}__'''
";
assert_snapshot!(lex_source(source));
}
#[test]
fn test_tstring_newline_format_spec() {
let source = r"
t'__{
x:d
}__'
@ -2580,7 +2597,7 @@ t'__{
b
}__'
";
assert_snapshot!(lex_source(source));
assert_snapshot!(lex_invalid(source, Mode::Module));
}
#[test]