Skip to content

Commit

Permalink
Fixed bug that results in false negative when a format string with a …
Browse files Browse the repository at this point in the history
…single quote has a newline character within it. This results in a syntax error at runtime. This addresses #9789.
  • Loading branch information
erictraut committed Feb 8, 2025
1 parent ccdf547 commit d221201
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 12 deletions.
9 changes: 6 additions & 3 deletions packages/pyright-internal/src/parser/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4945,9 +4945,12 @@ export class Parser {
continue;
}

// We've hit an error. Consume tokens until we find the end.
if (this._consumeTokensUntilType([TokenType.FStringEnd])) {
this._getNextToken();
// We've hit an error. Try to recover as gracefully as possible.
if (nextToken.type !== TokenType.NewLine) {
// Consume tokens until we find the end.
if (this._consumeTokensUntilType([TokenType.FStringEnd])) {
this._getNextToken();
}
}

this._addSyntaxError(
Expand Down
16 changes: 9 additions & 7 deletions packages/pyright-internal/src/parser/tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1649,13 +1649,15 @@ export class Tokenizer {
}
}
} else if (this._cs.currentChar === Char.LineFeed || this._cs.currentChar === Char.CarriageReturn) {
if (!isTriplicate && !isFString) {
// Unterminated single-line string
flags |= StringTokenFlags.Unterminated;
return {
escapedValue: getEscapedValue(),
flags,
};
if (!isTriplicate) {
if (!isFString || !this._activeFString?.activeReplacementField) {
// Unterminated single-line string
flags |= StringTokenFlags.Unterminated;
return {
escapedValue: getEscapedValue(),
flags,
};
}
}

// Skip over the new line (either one or two characters).
Expand Down
5 changes: 5 additions & 0 deletions packages/pyright-internal/src/tests/samples/fstring1.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,8 @@ def func1(x):
w2 = f"__{
w1:d
}__"


# This should generate an error because it's unterminated.
w3 = f"test

4 changes: 2 additions & 2 deletions packages/pyright-internal/src/tests/typeEvaluator4.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ test('FString1', () => {

configOptions.defaultPythonVersion = pythonVersion3_11;
const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['fstring1.py'], configOptions);
TestUtils.validateResults(analysisResults1, 14, 1);
TestUtils.validateResults(analysisResults1, 15, 1);

configOptions.defaultPythonVersion = pythonVersion3_12;
const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['fstring1.py'], configOptions);
TestUtils.validateResults(analysisResults2, 10, 1);
TestUtils.validateResults(analysisResults2, 11, 1);
});

test('FString2', () => {
Expand Down

0 comments on commit d221201

Please sign in to comment.