-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Summary
I noticed this while messing around on the playground, but it looks like formatting adds an extra \r to multiline f-string debug replacements. In combination with another software/editor that normalizes \r to \r\n, this causes the file to grow on every formatting.
The code I've been using to test this is
f"{
1=
}"Where the line endings are \r\n
One example of this is on the playground. If you keep copying the output to the input, it keeps growing.
first step
second step
third step
Another example is inside VSCode, if you have line endings set to CRLF. After file modification and save inside VSC it normalizes the newlines, so by running ruff format -> do a edit like adding a 1 to the end of the file and save in VSC -> run ruff format -> repeat, the code grows every time.
I also made a powershell script to demonstrate this, where it replaces \r with \r\n to show the growth. (I tried to make a bash script, but I'm both not familiar enough with bash and it feels like every built in tool/command nukes/normalizes newlines).
PS script
Set-Content "issue.py" -Value "f`"{`r`n1=`r`n}`""
echo "issue.py content"
Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\n", "\n"} | ForEach-Object { $_ -replace "\r", "\r"}
echo "Running ruff format"
uvx ruff format issue.py
echo "issue.py content"
Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\n", "\n"} | ForEach-Object { $_ -replace "\r", "\r"}
echo "Newline normalization"
$edited = Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\r(?!\n)", "`r`n" }
Set-Content "issue.py" $edited
echo "issue.py content"
Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\n", "\n"} | ForEach-Object { $_ -replace "\r", "\r"}
echo "Running ruff format"
uvx ruff format issue.py
echo "issue.py content"
Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\n", "\n"} | ForEach-Object { $_ -replace "\r", "\r"}
echo "Newline normalization"
$edited = Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\r(?!\n)", "`r`n" }
Set-Content "issue.py" $edited
echo "issue.py content"
Get-Content issue.py -Raw | ForEach-Object { $_ -replace "\n", "\n"} | ForEach-Object { $_ -replace "\r", "\r"}Output of script:
PS > ./issue.ps1
issue.py content
f"{\r\n1=\r\n}"\r\n
Running ruff format
1 file reformatted
issue.py content
f"{\r\r\n1=\r\r\n}"\r\n
Newline normalization
issue.py content
f"{\r\n\r\n1=\r\n\r\n}"\r\n\r\n
Running ruff format
1 file reformatted
issue.py content
f"{\r\r\n\r\r\n1=\r\r\n\r\r\n}"\r\n
Newline normalization
issue.py content
f"{\r\n\r\n\r\n\r\n1=\r\n\r\n\r\n\r\n}"\r\n\r\n
This only seems to happen when the f-string has a debug expression.
This also happens with t-strings
Version
ruff 0.11.13 (5faf72a 2025-06-05) + playground