You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/formatter.md
+113-15
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,7 @@ adoption is minimally disruptive for the vast majority of projects.
33
33
34
34
Specifically, the formatter is intended to emit near-identical output when run over existing
35
35
Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9%
36
-
of lines are formatted identically. (See: [_Black compatibility_](#black-compatibility).)
36
+
of lines are formatted identically. (See: [_Style Guide](#style-guide).)
37
37
38
38
Given this focus on Black compatibility, the formatter thus adheres to [Black's (stable) code style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html),
39
39
which aims for "consistency, generality, readability and reducing git diffs". To give you a sense
@@ -373,21 +373,10 @@ Meanwhile, `ruff format --check` exits with the following status codes:
373
373
-`2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an
374
374
internal error.
375
375
376
-
## Black compatibility
376
+
## Style Guide
377
377
378
378
The formatter is designed to be a drop-in replacement for [Black](https://github.com/psf/black).
379
-
380
-
Specifically, the formatter is intended to emit near-identical output when run over Black-formatted
381
-
code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines
382
-
are formatted identically. When migrating an existing project from Black to Ruff, you should expect
383
-
to see a few differences on the margins, but the vast majority of your code should be unchanged.
384
-
385
-
When run over _non_-Black-formatted code, the formatter makes some different decisions than Black,
386
-
and so more deviations should be expected, especially around the treatment of end-of-line comments.
387
-
388
-
If you identify deviations in your project, spot-check them against the [known deviations](formatter/black.md),
389
-
as well as the [unintentional deviations](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter)
390
-
filed in the issue tracker. If you've identified a new deviation, please [file an issue](https://github.com/astral-sh/ruff/issues/new).
379
+
This section documents the areas where the Ruff formatter goes beyond Black in terms of code style.
391
380
392
381
### Intentional deviations
393
382
@@ -398,11 +387,120 @@ Black's code style, while others fall out of differences in the underlying imple
398
387
For a complete enumeration of these intentional deviations, see [_Known deviations_](formatter/black.md).
399
388
400
389
Unintentional deviations from Black are tracked in the [issue tracker](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter).
390
+
If you've identified a new deviation, please [file an issue](https://github.com/astral-sh/ruff/issues/new).
401
391
402
392
### Preview style
403
-
Similar to [Black](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style), Ruff implements formatting changes
393
+
394
+
Similar to [Black](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style), Ruff implements formatting changes
404
395
under the [`preview`](https://docs.astral.sh/ruff/settings/#format_preview) flag, promoting them to stable through minor releases, in accordance with our [versioning policy](https://github.com/astral-sh/ruff/discussions/6998#discussioncomment-7016766).
405
396
397
+
### F-string formatting
398
+
399
+
_Stabilized in Ruff 0.9.0_
400
+
401
+
Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly
402
+
braces `{...}`. This is a [known deviation](formatter/black.md#f-strings) from Black.
403
+
404
+
Ruff employs several heuristics to determine how an f-string should be formatted which are detailed
405
+
below.
406
+
407
+
#### Quotes
408
+
409
+
Ruff will use the [configured quote style] for the f-string expression unless doing so would result in
410
+
invalid syntax for the target Python version or requires more backslash escapes than the original
411
+
expression. Specifically, Ruff will preserve the original quote style for the following cases:
412
+
413
+
When the target Python version is < 3.12 and a [self-documenting f-string] contains a string
414
+
literal with the [configured quote style]:
415
+
416
+
```python
417
+
# format.quote-style = "double"
418
+
419
+
f'{10+len("hello")=}'
420
+
# This f-string cannot be formatted as follows when targeting Python < 3.12
421
+
f"{10+len("hello")=}"
422
+
```
423
+
424
+
When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte
425
+
or f-string literal that contains the [configured quote style]:
426
+
427
+
```python
428
+
# format.quote-style = "double"
429
+
430
+
f'{"""nested " """}'`
431
+
# This f-string cannot be formatted as follows when targeting Python < 3.12
432
+
f"{'''nested " '''}``
433
+
```
434
+
435
+
For all target Python versions, when a [self-documenting f-string] contains an expression between
436
+
the curly braces (`{...}`) with a format specifier containing the [configured quote style]:
437
+
438
+
```python
439
+
# format.quote-style = "double"
440
+
441
+
f'{1=:"foo}'
442
+
# This f-string cannot be formatted as follows forall target Python versions
443
+
f"{1=:"foo}"
444
+
```
445
+
446
+
For nested f-strings, Ruff alternates quote styles, starting with the [configured quote style] for the
447
+
outermost f-string. For example, consider the following f-string:
Starting with Python 3.12 ([PEP701](https://peps.python.org/pep-0701/)), the expression parts of an f-string can
464
+
span multiple lines. Ruff needs to decide when to introduce a line breakin an f-string expression.
465
+
This depends on the semantic content of the expression parts of an f-string -for example,
466
+
introducing a line breakin the middle of a natural-language sentence is undesirable. Since Ruff
467
+
doesn't have enough information to make that decision, it adopts a heuristic similar to [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals):
468
+
it will only split the expression parts of an f-string across multiple lines if there was already a line break
469
+
within any of the expression parts.
470
+
471
+
For example, the following code:
472
+
473
+
```python
474
+
f"this f-string has a multiline expression {
475
+
['red', 'green', 'blue', 'yellow',]} and does not fit within the line length"
476
+
```
477
+
478
+
...is formatted as:
479
+
480
+
```python
481
+
# The list expression is split across multiple lines because of the trailing comma
482
+
f"this f-string has a multiline expression {
483
+
[
484
+
'red',
485
+
'green',
486
+
'blue',
487
+
'yellow',
488
+
]
489
+
} and does not fit within the line length"
490
+
```
491
+
492
+
But, the following will not be split across multiple lines even though it exceeds the line length:
493
+
494
+
```python
495
+
f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length"
496
+
```
497
+
498
+
If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the
0 commit comments