mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 12:58:20 +00:00
Call chain formatting in fluent style (#6151)
Implement fluent style/call chains. See the `call_chains.py` formatting for examples. This isn't fully like black because in `raise A from B` they allow `A` breaking can influence the formatting of `B` even if it is already multiline. Similarity index: | project | main | PR | |--------------|-------|-------| | build | ??? | 0.753 | | django | 0.991 | 0.998 | | transformers | 0.993 | 0.994 | | typeshed | 0.723 | 0.723 | | warehouse | 0.978 | 0.994 | | zulip | 0.992 | 0.994 | Call chain formatting is affected by https://github.com/astral-sh/ruff/issues/627, but i'm cutting scope here. Closes #5343 **Test Plan**: * Added a dedicated call chains test file * The ecosystem checks found some bugs * I manually check django and zulip formatting --------- Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
35bdbe43a8
commit
99baad12d8
16 changed files with 917 additions and 517 deletions
157
crates/ruff_python_formatter/resources/test/fixtures/ruff/call_chains.py
vendored
Normal file
157
crates/ruff_python_formatter/resources/test/fixtures/ruff/call_chains.py
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# Test cases for call chains and optional parentheses, with and without fluent style
|
||||
|
||||
raise OsError("") from a.aaaaa(
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
).a(aaaa)
|
||||
|
||||
raise OsError(
|
||||
"sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll"
|
||||
) from a.aaaaa(
|
||||
aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa
|
||||
).a(
|
||||
aaaa
|
||||
)
|
||||
|
||||
a1 = Blog.objects.filter(entry__headline__contains="Lennon").filter(
|
||||
entry__pub_date__year=2008
|
||||
)
|
||||
|
||||
a2 = Blog.objects.filter(
|
||||
entry__headline__contains="Lennon",
|
||||
).filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
|
||||
raise OsError("") from (
|
||||
Blog.objects.filter(
|
||||
entry__headline__contains="Lennon",
|
||||
)
|
||||
.filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
.filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
)
|
||||
|
||||
raise OsError("sökdjffffsldkfjlhsakfjhalsökafhsöfdahsödfjösaaksjdllllllllllllll") from (
|
||||
Blog.objects.filter(
|
||||
entry__headline__contains="Lennon",
|
||||
)
|
||||
.filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
.filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
)
|
||||
|
||||
# Break only after calls and indexing
|
||||
b1 = (
|
||||
session.query(models.Customer.id)
|
||||
.filter(
|
||||
models.Customer.account_id == account_id, models.Customer.email == email_address
|
||||
)
|
||||
.count()
|
||||
)
|
||||
|
||||
b2 = (
|
||||
Blog.objects.filter(
|
||||
entry__headline__contains="Lennon",
|
||||
)
|
||||
.limit_results[:10]
|
||||
.filter(
|
||||
entry__pub_date__month=10,
|
||||
)
|
||||
)
|
||||
|
||||
# Nested call chains
|
||||
c1 = (
|
||||
Blog.objects.filter(
|
||||
entry__headline__contains="Lennon",
|
||||
).filter(
|
||||
entry__pub_date__year=2008,
|
||||
)
|
||||
+ Blog.objects.filter(
|
||||
entry__headline__contains="McCartney",
|
||||
)
|
||||
.limit_results[:10]
|
||||
.filter(
|
||||
entry__pub_date__year=2010,
|
||||
)
|
||||
).all()
|
||||
|
||||
# Test different cases with trailing end of line comments:
|
||||
# * fluent style, fits: no parentheses -> ignore the expand_parent
|
||||
# * fluent style, doesn't fit: break all soft line breaks
|
||||
# * default, fits: no parentheses
|
||||
# * default, doesn't fit: parentheses but no soft line breaks
|
||||
|
||||
# Fits, either style
|
||||
d11 = x.e().e().e() #
|
||||
d12 = (x.e().e().e()) #
|
||||
d13 = (
|
||||
x.e() #
|
||||
.e()
|
||||
.e()
|
||||
)
|
||||
|
||||
# Doesn't fit, default
|
||||
d2 = (
|
||||
x.e().esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdddd() #
|
||||
)
|
||||
|
||||
# Doesn't fit, fluent style
|
||||
d3 = (
|
||||
x.e() #
|
||||
.esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk()
|
||||
.esadjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk()
|
||||
)
|
||||
|
||||
# Don't drop the bin op parentheses
|
||||
e1 = (1 + 2).w().t()
|
||||
e2 = (1 + 2)().w().t()
|
||||
e3 = (1 + 2)[1].w().t()
|
||||
|
||||
# Treat preserved parentheses correctly
|
||||
f1 = (b().c()).d(1,)
|
||||
f2 = b().c().d(1,)
|
||||
f3 = (b).c().d(1,)
|
||||
f4 = (a)(b).c(1,)
|
||||
f5 = (a.b()).c(1,)
|
||||
|
||||
# Indent in the parentheses without breaking
|
||||
g1 = (
|
||||
queryset.distinct().order_by(field.name).values_list(field_name_flat_long_long=True)
|
||||
)
|
||||
|
||||
# Fluent style in subexpressions
|
||||
if (
|
||||
not a()
|
||||
.b()
|
||||
.cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc()
|
||||
):
|
||||
pass
|
||||
h2 = (
|
||||
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
+ ccccccccccccccccccccccccc()
|
||||
.dddddddddddddddddddddd()
|
||||
.eeeeeeeeee()
|
||||
.ffffffffffffffffffffff()
|
||||
)
|
||||
|
||||
# Parentheses aren't allowed on statement level, don't use fluent style here
|
||||
if True:
|
||||
(alias).filter(content_typeold_content_type).update(
|
||||
content_typenew_contesadfasfdant_type
|
||||
)
|
||||
|
||||
zero(
|
||||
one,
|
||||
).two(
|
||||
three,
|
||||
).four(
|
||||
five,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ f(
|
|||
hey_this_is_a_very_long_call=1, it_has_funny_attributes_asdf_asdf=1, too_long_for_the_line=1, really=True
|
||||
)
|
||||
|
||||
# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains)
|
||||
# Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains)
|
||||
result = (
|
||||
session.query(models.Customer.id)
|
||||
.filter(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue