From 42217da9cda619fa0a22e11a5f3d6bd28cccafa5 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 15:00:33 +0530 Subject: [PATCH 1/7] Add f-string formatting to the docs --- docs/formatter.md | 75 +++++++++++++++++++++++++++++++++++++++++ docs/formatter/black.md | 5 ++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/docs/formatter.md b/docs/formatter.md index 443d2712aa1797..e76ba7475e2854 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -225,6 +225,81 @@ def f(x): [literal blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#literal-blocks [`code-block` and `sourcecode` directives]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block +## F-string formatting + +_Stabilized in 2025 style with Ruff 0.9.0_ + +By default, Ruff formats f-string expressions. This is a [known deviation](formatter/black.md#f-strings) +from Black, which does not format f-strings. + +Ruff employs several heuristics to determine how an f-string should be formatted, including the +following considerations: + +* The quote style for both outer and nested f-strings +* Whether to break the f-string into multiple lines +* When to skip formatting the f-string altogether + +### Quotes + +Ruff will use the configured quote style for the f-string expression unless doing so would result in +invalid syntax for the target Python version. In such cases, Ruff will avoid changing the +quote style. + +For example, if a self-documenting f-string contains a string literal with the configured quote +style, Ruff cannot use the same quote style for the f-string itself when targeting Python versions +earlier than 3.12: + +```python +f'{10 + len("hello")=}' +# This f-string cannot be formatted as follows when targeting Python < 3.12 +f"{10 + len("hello")=}" +``` + +For nested f-strings, Ruff alternates quote styles, starting with the configured style for the +outermost f-string. If this would result in an invalid syntax, Ruff avoids changing the quote style. +For example, consider the following f-string: + +```python +f"outer f-string {f"nested f-string {f"another nested f-string"} end"} end" +``` + +Ruff formats it as: + +```python +f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" +``` + +### Line breaks + +Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), f-string expressions can +span multiple lines. Ruff adopts a similar heuristic as [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals) +for when to introduce a line break in an f-string expression: it introduces line breaks only +if the original f-string expression already contains them. + +For example, the following code: + +```python +f"this f-string has a multiline expression { + ['red', 'green', 'blue', 'yellow',]} and does not fit within the line length" +``` + +... is formatted as: + +```python +# The list expression is split across multiple lines because of the trailing comma +f"this f-string has a multiline expression { + [ + 'red', + 'green', + 'blue', + 'yellow', + ] +} and does not fit within the line length" +``` + +If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak within the +`{...}` expression. + ## Format suppression Like Black, Ruff supports `# fmt: on`, `# fmt: off`, and `# fmt: skip` pragma comments, which can diff --git a/docs/formatter/black.md b/docs/formatter/black.md index e696f68cfe49c8..d560f1706b13da 100644 --- a/docs/formatter/black.md +++ b/docs/formatter/black.md @@ -253,6 +253,9 @@ f'test{inner + "nested_string"} including math {5 ** 3 + 10}' f"test{inner + 'nested_string'} including math {5**3 + 10}" ``` +For more details on the formatting style, refer to the [f-string +formatting](../formatter.md#f-string-formatting) section. + ### Implicit concatenated strings Ruff merges implicitly concatenated strings if the entire string fits on a single line: @@ -348,7 +351,7 @@ match some_variable: ) or last_condition: pass - + # Ruff match some_variable: case "short-guard" if other_condition: From 21db9c5e5b4613ec8072f154ed748c0c2243649c Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 19:25:45 +0530 Subject: [PATCH 2/7] Address review feedback (1) Remaining bits after dinner --- docs/formatter.md | 58 +++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/docs/formatter.md b/docs/formatter.md index e76ba7475e2854..98de0b9329b243 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -227,27 +227,22 @@ def f(x): ## F-string formatting -_Stabilized in 2025 style with Ruff 0.9.0_ +_Stabilized in Ruff 0.9.0_ -By default, Ruff formats f-string expressions. This is a [known deviation](formatter/black.md#f-strings) -from Black, which does not format f-strings. +Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly +braces `{...}`. This is a [known deviation](formatter/black.md#f-strings) from Black. -Ruff employs several heuristics to determine how an f-string should be formatted, including the -following considerations: - -* The quote style for both outer and nested f-strings -* Whether to break the f-string into multiple lines -* When to skip formatting the f-string altogether +Ruff employs several heuristics to determine how an f-string should be formatted which are detailed +below. ### Quotes Ruff will use the configured quote style for the f-string expression unless doing so would result in -invalid syntax for the target Python version. In such cases, Ruff will avoid changing the -quote style. +invalid syntax for the target Python version or it results in more backslashes than the original +expression. Specifically, Ruff will preserve the original quote style for the following cases: -For example, if a self-documenting f-string contains a string literal with the configured quote -style, Ruff cannot use the same quote style for the f-string itself when targeting Python versions -earlier than 3.12: +When the target Python version is < 3.12 and a [self-documenting f-string expressions] contains a string +literal with the configured quote style: ```python f'{10 + len("hello")=}' @@ -255,9 +250,26 @@ f'{10 + len("hello")=}' f"{10 + len("hello")=}" ``` +When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte +or f-string literal that contains the configured quote style: + +```python +f'{"""nested " """}'` +# This f-string cannot be formatted as follows when targeting Python < 3.12 +f"{'''nested " '''}`` +``` + +For all target Python versions, when a [self-documenting f-string expressions] contains any expression between +the curly braces (`{...}`) with a format specifier that contains the configured quote style: + +```python +f'{1=:"foo}' +# This f-string cannot be formatted as follows for all target Python versions +f"{1=:"foo}" +``` + For nested f-strings, Ruff alternates quote styles, starting with the configured style for the -outermost f-string. If this would result in an invalid syntax, Ruff avoids changing the quote style. -For example, consider the following f-string: +outermost f-string. For example, consider the following f-string: ```python f"outer f-string {f"nested f-string {f"another nested f-string"} end"} end" @@ -271,10 +283,10 @@ f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" ### Line breaks -Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), f-string expressions can +Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), expression parts of an f-string can span multiple lines. Ruff adopts a similar heuristic as [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals) for when to introduce a line break in an f-string expression: it introduces line breaks only -if the original f-string expression already contains them. +if there was already a line break within any of the expression parts of an f-string. For example, the following code: @@ -297,9 +309,17 @@ f"this f-string has a multiline expression { } and does not fit within the line length" ``` -If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak within the +But, the following will not be split across multiple lines even though it exceeds the line length: + +```python +f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length" +``` + +If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the `{...}` expression. +[self-documenting f-string expressions]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging + ## Format suppression Like Black, Ruff supports `# fmt: on`, `# fmt: off`, and `# fmt: skip` pragma comments, which can From 1b4d996c615cf807ac1ba50ce69a3d5aa728d87b Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 21:25:37 +0530 Subject: [PATCH 3/7] Re-arrange section to use "Style Guide" --- docs/formatter.md | 209 ++++++++++++++++++++++------------------------ 1 file changed, 100 insertions(+), 109 deletions(-) diff --git a/docs/formatter.md b/docs/formatter.md index 98de0b9329b243..6c393c3b9135a3 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -225,101 +225,6 @@ def f(x): [literal blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#literal-blocks [`code-block` and `sourcecode` directives]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block -## F-string formatting - -_Stabilized in Ruff 0.9.0_ - -Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly -braces `{...}`. This is a [known deviation](formatter/black.md#f-strings) from Black. - -Ruff employs several heuristics to determine how an f-string should be formatted which are detailed -below. - -### Quotes - -Ruff will use the configured quote style for the f-string expression unless doing so would result in -invalid syntax for the target Python version or it results in more backslashes than the original -expression. Specifically, Ruff will preserve the original quote style for the following cases: - -When the target Python version is < 3.12 and a [self-documenting f-string expressions] contains a string -literal with the configured quote style: - -```python -f'{10 + len("hello")=}' -# This f-string cannot be formatted as follows when targeting Python < 3.12 -f"{10 + len("hello")=}" -``` - -When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte -or f-string literal that contains the configured quote style: - -```python -f'{"""nested " """}'` -# This f-string cannot be formatted as follows when targeting Python < 3.12 -f"{'''nested " '''}`` -``` - -For all target Python versions, when a [self-documenting f-string expressions] contains any expression between -the curly braces (`{...}`) with a format specifier that contains the configured quote style: - -```python -f'{1=:"foo}' -# This f-string cannot be formatted as follows for all target Python versions -f"{1=:"foo}" -``` - -For nested f-strings, Ruff alternates quote styles, starting with the configured style for the -outermost f-string. For example, consider the following f-string: - -```python -f"outer f-string {f"nested f-string {f"another nested f-string"} end"} end" -``` - -Ruff formats it as: - -```python -f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" -``` - -### Line breaks - -Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), expression parts of an f-string can -span multiple lines. Ruff adopts a similar heuristic as [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals) -for when to introduce a line break in an f-string expression: it introduces line breaks only -if there was already a line break within any of the expression parts of an f-string. - -For example, the following code: - -```python -f"this f-string has a multiline expression { - ['red', 'green', 'blue', 'yellow',]} and does not fit within the line length" -``` - -... is formatted as: - -```python -# The list expression is split across multiple lines because of the trailing comma -f"this f-string has a multiline expression { - [ - 'red', - 'green', - 'blue', - 'yellow', - ] -} and does not fit within the line length" -``` - -But, the following will not be split across multiple lines even though it exceeds the line length: - -```python -f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length" -``` - -If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the -`{...}` expression. - -[self-documenting f-string expressions]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging - ## Format suppression Like Black, Ruff supports `# fmt: on`, `# fmt: off`, and `# fmt: skip` pragma comments, which can @@ -468,21 +373,10 @@ Meanwhile, `ruff format --check` exits with the following status codes: - `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error. -## Black compatibility +## Style Guide The formatter is designed to be a drop-in replacement for [Black](https://github.com/psf/black). - -Specifically, the formatter is intended to emit near-identical output when run over Black-formatted -code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines -are formatted identically. When migrating an existing project from Black to Ruff, you should expect -to see a few differences on the margins, but the vast majority of your code should be unchanged. - -When run over _non_-Black-formatted code, the formatter makes some different decisions than Black, -and so more deviations should be expected, especially around the treatment of end-of-line comments. - -If you identify deviations in your project, spot-check them against the [known deviations](formatter/black.md), -as well as the [unintentional deviations](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter) -filed in the issue tracker. If you've identified a new deviation, please [file an issue](https://github.com/astral-sh/ruff/issues/new). +This section documents the areas where the Ruff formatter goes beyond Black in terms of code style. ### Intentional deviations @@ -493,11 +387,108 @@ Black's code style, while others fall out of differences in the underlying imple For a complete enumeration of these intentional deviations, see [_Known deviations_](formatter/black.md). Unintentional deviations from Black are tracked in the [issue tracker](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter). +If you've identified a new deviation, please [file an issue](https://github.com/astral-sh/ruff/issues/new). ### Preview style -Similar to [Black](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style), Ruff implements formatting changes + +Similar to [Black](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style), Ruff implements formatting changes 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). +### F-string formatting + +_Stabilized in Ruff 0.9.0_ + +Unlike Black, Ruff formats the expression parts of f-strings which are the parts inside the curly +braces `{...}`. This is a [known deviation](formatter/black.md#f-strings) from Black. + +Ruff employs several heuristics to determine how an f-string should be formatted which are detailed +below. + +#### Quotes + +Ruff will use the configured quote style for the f-string expression unless doing so would result in +invalid syntax for the target Python version or it results in more backslashes than the original +expression. Specifically, Ruff will preserve the original quote style for the following cases: + +When the target Python version is < 3.12 and a [self-documenting f-string expressions] contains a string +literal with the configured quote style: + +```python +f'{10 + len("hello")=}' +# This f-string cannot be formatted as follows when targeting Python < 3.12 +f"{10 + len("hello")=}" +``` + +When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte +or f-string literal that contains the configured quote style: + +```python +f'{"""nested " """}'` +# This f-string cannot be formatted as follows when targeting Python < 3.12 +f"{'''nested " '''}`` +``` + +For all target Python versions, when a [self-documenting f-string expressions] contains any expression between +the curly braces (`{...}`) with a format specifier that contains the configured quote style: + +```python +f'{1=:"foo}' +# This f-string cannot be formatted as follows for all target Python versions +f"{1=:"foo}" +``` + +For nested f-strings, Ruff alternates quote styles, starting with the configured style for the +outermost f-string. For example, consider the following f-string: + +```python +f"outer f-string {f"nested f-string {f"another nested f-string"} end"} end" +``` + +Ruff formats it as: + +```python +f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" +``` + +#### Line breaks + +Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), expression parts of an f-string can +span multiple lines. Ruff adopts a similar heuristic as [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals) +for when to introduce a line break in an f-string expression: it introduces line breaks only +if there was already a line break within any of the expression parts of an f-string. + +For example, the following code: + +```python +f"this f-string has a multiline expression { + ['red', 'green', 'blue', 'yellow',]} and does not fit within the line length" +``` + +... is formatted as: + +```python +# The list expression is split across multiple lines because of the trailing comma +f"this f-string has a multiline expression { + [ + 'red', + 'green', + 'blue', + 'yellow', + ] +} and does not fit within the line length" +``` + +But, the following will not be split across multiple lines even though it exceeds the line length: + +```python +f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} and does not fit within the line length" +``` + +If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the +`{...}` expression. + +[self-documenting f-string expressions]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging + ## Sorting imports Currently, the Ruff formatter does not sort imports. In order to both sort imports and format, From 4031d3c81d4c23cccef4a9952dde233e986b6517 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 21:37:38 +0530 Subject: [PATCH 4/7] Update references --- crates/ruff_python_formatter/README.md | 2 +- docs/faq.md | 2 +- docs/formatter.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ruff_python_formatter/README.md b/crates/ruff_python_formatter/README.md index 19f0c0065159e5..d6ed9a96d8e264 100644 --- a/crates/ruff_python_formatter/README.md +++ b/crates/ruff_python_formatter/README.md @@ -19,7 +19,7 @@ filed in the issue tracker. If you've identified a new deviation, please [file a When run over _non_-Black-formatted code, the formatter makes some different decisions than Black, and so more deviations should be expected, especially around the treatment of end-of-line comments. -For details, see [Black compatibility](https://docs.astral.sh/ruff/formatter/#black-compatibility). +For details, see [Style Guide](https://docs.astral.sh/ruff/formatter/#style-guide). ## Getting started diff --git a/docs/faq.md b/docs/faq.md index 5e15dc63f19c87..431ada6329be2a 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -28,7 +28,7 @@ to see a few differences on the margins, but the vast majority of your code shou When run over _non_-Black-formatted code, the formatter makes some different decisions than Black, and so more deviations should be expected, especially around the treatment of end-of-line comments. -See [_Black compatibility_](formatter.md#black-compatibility) for more. +See [_Style Guide_](formatter.md#style-guide) for more. ## How does Ruff's linter compare to Flake8? diff --git a/docs/formatter.md b/docs/formatter.md index 6c393c3b9135a3..5a97f03c396eec 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -33,7 +33,7 @@ adoption is minimally disruptive for the vast majority of projects. Specifically, the formatter is intended to emit near-identical output when run over existing Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% -of lines are formatted identically. (See: [_Black compatibility_](#black-compatibility).) +of lines are formatted identically. (See: [_Style Guide](#style-guide).) 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), which aims for "consistency, generality, readability and reducing git diffs". To give you a sense From 5b60afdf90c86ecd7b447a5a865b5affce35a4b7 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 22:31:18 +0530 Subject: [PATCH 5/7] Expand line breaks section --- docs/formatter.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/formatter.md b/docs/formatter.md index 5a97f03c396eec..cc870e290a46cf 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -407,7 +407,7 @@ below. #### Quotes Ruff will use the configured quote style for the f-string expression unless doing so would result in -invalid syntax for the target Python version or it results in more backslashes than the original +invalid syntax for the target Python version or requires more backslash escapes than the original expression. Specifically, Ruff will preserve the original quote style for the following cases: When the target Python version is < 3.12 and a [self-documenting f-string expressions] contains a string @@ -453,9 +453,12 @@ f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" #### Line breaks Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), expression parts of an f-string can -span multiple lines. Ruff adopts a similar heuristic as [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals) -for when to introduce a line break in an f-string expression: it introduces line breaks only -if there was already a line break within any of the expression parts of an f-string. +span multiple lines. Ruff needs to decide when to introduce a line break in an f-string expression. +This depends on the semantic content of the expression parts of an f-string - for example, +introducing a line break in the middle of a natural-language sentence is undesirable. Since Ruff +doesn't have enough information to make that decision, it uses a heuristic similar to [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals): +it will only split the expression parts of an f-string across multiple lines if there was already a line break +within any of the expression parts. For example, the following code: @@ -485,7 +488,7 @@ f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} ``` If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the -`{...}` expression. +`{...}` parts of an f-string. [self-documenting f-string expressions]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging From 0c96180bf04b7240fc1a87b0732082d8cd9c23b7 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Wed, 8 Jan 2025 22:35:30 +0530 Subject: [PATCH 6/7] Improve grammar from review --- docs/formatter.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/formatter.md b/docs/formatter.md index cc870e290a46cf..a4211f34f5b68f 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -410,7 +410,7 @@ Ruff will use the configured quote style for the f-string expression unless doin invalid syntax for the target Python version or requires more backslash escapes than the original expression. Specifically, Ruff will preserve the original quote style for the following cases: -When the target Python version is < 3.12 and a [self-documenting f-string expressions] contains a string +When the target Python version is < 3.12 and a [self-documenting f-string] contains a string literal with the configured quote style: ```python @@ -428,8 +428,8 @@ f'{"""nested " """}'` f"{'''nested " '''}`` ``` -For all target Python versions, when a [self-documenting f-string expressions] contains any expression between -the curly braces (`{...}`) with a format specifier that contains the configured quote style: +For all target Python versions, when a [self-documenting f-string] contains an expression between +the curly braces (`{...}`) with a format specifier containing the configured quote style: ```python f'{1=:"foo}' @@ -452,11 +452,11 @@ f"outer f-string {f'nested f-string {f"another nested f-string"} end'} end" #### Line breaks -Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), expression parts of an f-string can +Starting with Python 3.12 ([PEP 701](https://peps.python.org/pep-0701/)), the expression parts of an f-string can span multiple lines. Ruff needs to decide when to introduce a line break in an f-string expression. This depends on the semantic content of the expression parts of an f-string - for example, introducing a line break in the middle of a natural-language sentence is undesirable. Since Ruff -doesn't have enough information to make that decision, it uses a heuristic similar to [Prettier](https://prettier.io/docs/en/next/rationale.html#template-literals): +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): it will only split the expression parts of an f-string across multiple lines if there was already a line break within any of the expression parts. @@ -490,7 +490,7 @@ f"this f-string has a multiline expression {['red', 'green', 'blue', 'yellow']} If you want Ruff to split an f-string across multiple lines, ensure there's a linebreak somewhere within the `{...}` parts of an f-string. -[self-documenting f-string expressions]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging +[self-documenting f-string]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging ## Sorting imports From 24e45aa89cb3849460ab0b9e08d00b50986dd5f4 Mon Sep 17 00:00:00 2001 From: Dhruv Manilawala Date: Thu, 9 Jan 2025 11:48:15 +0530 Subject: [PATCH 7/7] Provide link `format.quote-style` setting --- docs/formatter.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/formatter.md b/docs/formatter.md index a4211f34f5b68f..01eb4fb396ff80 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -406,41 +406,49 @@ below. #### Quotes -Ruff will use the configured quote style for the f-string expression unless doing so would result in +Ruff will use the [configured quote style] for the f-string expression unless doing so would result in invalid syntax for the target Python version or requires more backslash escapes than the original expression. Specifically, Ruff will preserve the original quote style for the following cases: When the target Python version is < 3.12 and a [self-documenting f-string] contains a string -literal with the configured quote style: +literal with the [configured quote style]: ```python +# format.quote-style = "double" + f'{10 + len("hello")=}' # This f-string cannot be formatted as follows when targeting Python < 3.12 f"{10 + len("hello")=}" ``` When the target Python version is < 3.12 and an f-string contains any triple-quoted string, byte -or f-string literal that contains the configured quote style: +or f-string literal that contains the [configured quote style]: ```python +# format.quote-style = "double" + f'{"""nested " """}'` # This f-string cannot be formatted as follows when targeting Python < 3.12 f"{'''nested " '''}`` ``` For all target Python versions, when a [self-documenting f-string] contains an expression between -the curly braces (`{...}`) with a format specifier containing the configured quote style: +the curly braces (`{...}`) with a format specifier containing the [configured quote style]: ```python +# format.quote-style = "double" + f'{1=:"foo}' # This f-string cannot be formatted as follows for all target Python versions f"{1=:"foo}" ``` -For nested f-strings, Ruff alternates quote styles, starting with the configured style for the +For nested f-strings, Ruff alternates quote styles, starting with the [configured quote style] for the outermost f-string. For example, consider the following f-string: ```python +# format.quote-style = "double" + f"outer f-string {f"nested f-string {f"another nested f-string"} end"} end" ``` @@ -491,6 +499,7 @@ If you want Ruff to split an f-string across multiple lines, ensure there's a li `{...}` parts of an f-string. [self-documenting f-string]: https://realpython.com/python-f-strings/#self-documenting-expressions-for-debugging +[configured quote style]: settings.md/#format_quote-style ## Sorting imports