-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Description
Context
We have some code along the lines of:
result = (
(await query_the_thing(mypy_doesnt_understand)) # type: ignore[x]
.foo()
.bar()
)Switching from black to ruff format results in the comment moving:
- in a non-idempotent way, requiring two
ruff formatinvocations - to a 'strange' location
Reproducer
Formatting this code requires multiple invocations of ruff format to be "stable"/reach a fixed point:
-
Input:
( (x) # a .y() .z() ) -
Output of formatting 1 (change: comment is shifted to next line):
( (x) # a .y() .z() ) -
Output of formatting 2 (change: comment is unindented):
( (x) # a .y() .z() )
Playground links:
- Step 1 -> 2: https://play.ruff.rs/515f65e6-80ee-43b0-9131-8130dcde20a3
- Step 2 -> 3: https://play.ruff.rs/fda5a46d-519e-498c-866c-9f49133277f9
Expected behaviour
ruff format should be idempotent: the output of formatting should not have any changes if formatted again.
That is, the first format call (step 1 -> 2) should give the final result with the comment in its final position (unindented), and the second (step 2 -> 3) should not change the code.
Alternatively, the formatting for this circumstance changed to sidestep the issue. It's seems weird to me that this comment is being wrapped. It moving the comment to the next line also problems if the comment is a # type: ... or # noqa pragma.
See also "Ablations".
Ablations
This stops reproducing with these variations of the Input (1):
-
Only one extra line after the comment (no change: comment remains where it is)
( (x) # a .y() ) -
No parens around
x(becomesx.y().z() # a)( x # a .y() .z() ) -
Comment on a different line (no change):
( (x) .y() # a .z() )
Metadata
Ruff version: 0.9.6
Settings (default play.ruff.rs ones):
Details
{
"preview": false,
"builtins": [],
"target-version": "py312",
"line-length": 88,
"indent-width": 4,
"lint": {
"allowed-confusables": [],
"dummy-variable-rgx": "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$",
"extend-select": [],
"extend-fixable": [],
"external": [],
"ignore": [],
"select": [
"ALL"
]
},
"format": {
"indent-style": "space",
"quote-style": "double"
}
}Search keywords: idempotent, idempotency, reformat, repeated invocations, fixed point, stable
Thanks for ruff!