psf / black

The uncompromising Python code formatter
https://black.readthedocs.io/en/stable/
MIT License
37.8k stars 2.4k forks source link

`# fmt: skip` ignored in fluent interface #3364

Open metov opened 1 year ago

metov commented 1 year ago

Say I'd like to format my code like so:

v = (
    foo_dict
    .setdefault("a", {})
    .setdefault("b", {})
    .setdefault("c", {})
    .setdefault("d", {})
    .setdefault("e", {})
)

Black will of course reformat this to put foo_dict.setdefault("a", {}) on the first line.

Luckily, there are directives to not auto-format some lines:

[black] doesn’t reformat lines that end with # fmt: skip

Yet this doesn't work:

v = (
    foo_dict  # fmt: skip
    .setdefault("a", {})
    .setdefault("b", {})
    .setdefault("c", {})
    .setdefault("d", {})
    .setdefault("e", {})
)

becomes:

v = (
    foo_dict.setdefault("a", {})  # fmt: skip
    .setdefault("b", {})
    .setdefault("c", {})
    .setdefault("d", {})
    .setdefault("e", {})
)

Since the line foo_dict # fmt: skip ends with # fmt: skip, I would expect black to leave it alone.

Playground link

FSpanhel commented 1 year ago

I also have this issue (see #3443).

What's the motivation that foo_dict.setdefault("a", {}) is put on the first line? The docs only refer to https://en.wikipedia.org/wiki/Fluent_interface.

I had a look on this page. I seems that the majority of languages use

v = (
    foo_dict
    .setdefault("a", {})
    .setdefault("b", {})
    .setdefault("c", {})
    .setdefault("d", {})
    .setdefault("e", {})
)

instead of

v = (
    foo_dict.setdefault("a", {})
    .setdefault("b", {})
    .setdefault("c", {})
    .setdefault("d", {})
    .setdefault("e", {})
)

In my point of view, the former formatting is by far more readable because I see the object and then its methods that are applied. In the second formatting I have to move my eyes to the right to see what the first method is and then again to the left to see the remaining methods.

Alternatively, one could also use

v = (
    foo_dict.setdefault("a", {})
            .setdefault("b", {})
            .setdefault("c", {})
            .setdefault("d", {})
            .setdefault("e", {})
)

but I would still strongly prefer option 1.

JelleZijlstra commented 1 year ago

Please open a new issue if you want Black's normal formatting to change. This issue should be only about # fmt: skip in this context.

FSpanhel commented 1 year ago

@JelleZijlstra You are right. My apologies. I have opened #3449.