Skip to content

Commit 54173f4

Browse files
committed
Update Black deviations
1 parent ec04f00 commit 54173f4

File tree

2 files changed

+142
-12
lines changed

2 files changed

+142
-12
lines changed

docs/formatter/black.md

Lines changed: 135 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ c = "\U0001f977"
215215
d = "\N{CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I}"
216216
```
217217

218+
TODO: Is this part of Black's 2025 style guide?
219+
218220
### Module docstrings
219221

220222
Ruff formats module docstrings similar to class or function docstrings, whereas Black does not.
@@ -234,32 +236,92 @@ Ruff formats module docstrings similar to class or function docstrings, whereas
234236
"""Module docstring"""
235237

236238
```
239+
TODO: Is this part of Black's 2025 style guide?
237240

241+
### F-string formatting
238242

239-
### Walruses in slice expressions
243+
Ruff formats expression parts in f-strings whereas Black does not:
240244

241-
Black avoids inserting space around `:=` operators within slices. For example, the following adheres
242-
to Black stable style:
245+
```python
246+
# Input
247+
f'test{inner + "nested_string"} including math {5 ** 3 + 10}'
248+
249+
# Black
250+
f'test{inner + "nested_string"} including math {5 ** 3 + 10}'
251+
252+
# Ruff
253+
f"test{inner + 'nested_string'} including math {5**3 + 10}"
254+
```
255+
256+
### Implicit concatenated string formatting
257+
258+
Ruff merges implicitly concatenated strings if the entire string fits on a single line:
243259

244260
```python
245261
# Input
246-
x[y:=1]
262+
def test(max_history):
263+
raise argparse.ArgumentTypeError(
264+
f"The value of `--max-history {max_history}` " f"is not a positive integer."
265+
)
247266

248267
# Black
249-
x[y:=1]
268+
def test(max_history):
269+
raise argparse.ArgumentTypeError(
270+
f"The value of `--max-history {max_history}` " f"is not a positive integer."
271+
)
272+
273+
# Ruff
274+
def test(max_history):
275+
raise argparse.ArgumentTypeError(
276+
f"The value of `--max-history {max_history}` is not a positive integer."
277+
)
250278
```
251279

252-
Ruff will instead add space around the `:=` operator:
280+
Black's unstable style applies the same formatting.
281+
282+
There are few rare cases where Ruff can't merge the implicitly concatenated strings automatically.
283+
In those cases, Ruff preserves if the implicit concatenated strings are formatted over multiple lines:
253284

254285
```python
255286
# Input
256-
x[y:=1]
287+
a = (
288+
r"aaaaaaa"
289+
"bbbbbbbbbbbb"
290+
)
291+
292+
# Black
293+
a = r"aaaaaaa" "bbbbbbbbbbbb"
257294

258295
# Ruff
259-
x[y := 1]
296+
a = (
297+
r"aaaaaaa"
298+
"bbbbbbbbbbbb"
299+
)
260300
```
261301

262-
This will likely be incorporated into Black's preview style ([#3823](https://github.com/psf/black/pull/3823)).
302+
This makes the formatter compatible with `ISC001` ([#8272](https://github.com/astral-sh/ruff/issues/8272)).
303+
304+
### `assert` formatting
305+
306+
Unlike Black, Ruff prefers breaking the message over breaking the assertion, similar to how both Ruff and Black prefer breaking the assignment value over breaking the assignment target:
307+
308+
```python
309+
# Input
310+
assert (
311+
len(policy_types) >= priority + num_duplicates
312+
), f"This tests needs at least {priority+num_duplicates} many types."
313+
314+
315+
# Black
316+
assert (
317+
len(policy_types) >= priority + num_duplicates
318+
), f"This tests needs at least {priority+num_duplicates} many types."
319+
320+
# Ruff
321+
assert len(policy_types) >= priority + num_duplicates, (
322+
f"This tests needs at least {priority + num_duplicates} many types."
323+
)
324+
```
263325

264326
### `global` and `nonlocal` names are broken across multiple lines by continuations
265327

@@ -309,6 +371,8 @@ class IntFromGeom(GEOSFuncFactory):
309371
errcheck = staticmethod(check_minus_one)
310372
```
311373

374+
TODO: Is this part of Black's 2025 style guide?
375+
312376
### Trailing own-line comments on imports are not moved to the next line
313377

314378
Black enforces a single empty line between an import and a trailing own-line comment. Ruff leaves
@@ -385,9 +449,7 @@ would instead format the above as:
385449

386450
```python
387451
print(
388-
"aaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaa".format(
389-
bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb
390-
)
452+
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".format(bbbbbbbbbbbbbbbbbb + bbbbbbbbbbbbbbbbbb)
391453
)
392454
```
393455

@@ -528,6 +590,8 @@ def func(
528590

529591
Ruff will instead insert a trailing comma in all such cases for consistency.
530592

593+
TODO: Is this part of Black's 2025 style guide?
594+
531595
### Parentheses around call-chain assignment values are not preserved
532596

533597
Given:
@@ -651,6 +715,65 @@ assert AAAAAAAAAAAAAAAAAAAAAA.bbbbbb.fooo(
651715
) * foooooo * len(list(foo(bar(4, foo), foo)))
652716
```
653717

718+
### Single `with` item targeting Python 3.8 or older
719+
720+
Unlike Black, Ruff uses the same layout for `with` statements with a single context manager as it does for `while`, `if` and other compound statements:
721+
722+
```python
723+
# Input
724+
def run(data_path, model_uri):
725+
with pyspark.sql.SparkSession.builder.config(
726+
key="spark.python.worker.reuse", value=True
727+
).config(key="spark.ui.enabled", value=False).master(
728+
"local-cluster[2, 1, 1024]"
729+
).getOrCreate():
730+
# ignore spark log output
731+
spark.sparkContext.setLogLevel("OFF")
732+
print(score_model(spark, data_path, model_uri))
733+
734+
# Black
735+
def run(data_path, model_uri):
736+
with pyspark.sql.SparkSession.builder.config(
737+
key="spark.python.worker.reuse", value=True
738+
).config(key="spark.ui.enabled", value=False).master(
739+
"local-cluster[2, 1, 1024]"
740+
).getOrCreate():
741+
# ignore spark log output
742+
spark.sparkContext.setLogLevel("OFF")
743+
print(score_model(spark, data_path, model_uri))
744+
745+
# Ruff
746+
def run(data_path, model_uri):
747+
with (
748+
pyspark.sql.SparkSession.builder.config(
749+
key="spark.python.worker.reuse", value=True
750+
)
751+
.config(key="spark.ui.enabled", value=False)
752+
.master("local-cluster[2, 1, 1024]")
753+
.getOrCreate()
754+
):
755+
# ignore spark log output
756+
spark.sparkContext.setLogLevel("OFF")
757+
print(score_model(spark, data_path, model_uri))
758+
```
759+
760+
Ruff's formatting matches the formatting of other compound statements:
761+
762+
```python
763+
def test():
764+
if (
765+
pyspark.sql.SparkSession.builder.config(
766+
key="spark.python.worker.reuse", value=True
767+
)
768+
.config(key="spark.ui.enabled", value=False)
769+
.master("local-cluster[2, 1, 1024]")
770+
.getOrCreate()
771+
):
772+
# ignore spark log output
773+
spark.sparkContext.setLogLevel("OFF")
774+
print(score_model(spark, data_path, model_uri))
775+
```
776+
654777
### The last context manager in a `with` statement may be collapsed onto a single line
655778

656779
When using a `with` statement with multiple unparenthesized context managers, Ruff may collapse the

uv.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)