12

I'm currently researching Black as our default formatter, but, I'm having some edge cases that don't format well and I want to know if there's a way to get the result I want.

Black's documentation partially explores my problem, I have a dictionary expression spread horizontally, and I want to keep it that way since I'm expecting lines to be added, e.g.:

# Black would keep this as-is because of the trailing comma
TRANSLATIONS = {
    "en_us": "English (US)",
    "pl_pl": "polski",
}

But in my case the dictionary is inside a list comprehension:

res = [
    {
        'id': item.id,
        'name': item.name,
    }
    for item in items.select()
]

Which Black collapses, regardless of the trailing comma, like so:

res = [
    {"id": item.id, "name": item.name,}
    for item in items.select()
]

Is there a way of telling Black to retain the horizontal structure in these cases?

Nitzan
  • 1,669
  • 3
  • 19
  • 33

2 Answers2

12

You can use the # fmt: off / # fmt: on feature.

As you can see below:

  • The list comprehension before the # fmt: off has been formatted by Black
  • Between the # fmt: off / # fmt: on the list comprehension hasn't been formatted by Black
  • The list comprehension after # fmt: on has been formatted by Black

Code (after formatting by Black):

res1 = [{"id": item[0], "name": item[1],} for item in [[5, "foo"], [6, "bar"]]]

# fmt: off
res2 = [
    {
        'id': item[0],
        'name': item[1],
    }
    for item in [[7, "fooo"], [8, "barr"]]
]
# fmt: on

res3 = [{"id": item[0], "name": item[1],} for item in [[9, "fooo0"], [10, "barrr"]]]

print(res1)
print(res2)
print(res3)

Output of Python balck:

/home/milanbalazs/.local/bin/black --fast -l 100 -v /home/milanbalazs/test.py
reformatted /home/milanbalazs/test.py
All done! ✨  ✨
1 file reformatted.

Output of code:

>>> python3 test.py 
[{'id': 5, 'name': 'foo'}, {'id': 6, 'name': 'bar'}]
[{'id': 7, 'name': 'fooo'}, {'id': 8, 'name': 'barr'}]
[{'id': 9, 'name': 'fooo0'}, {'id': 10, 'name': 'barrr'}]

Related part of Black documentation: https://github.com/psf/black#the-black-code-style

milanbalazs
  • 4,811
  • 4
  • 23
  • 45
  • 1
    I'm aware it's possible to disable formatting for segments of code this way but I am more interested in whether I can make Black play nice without disabling formatting of these sections. – Nitzan May 05 '20 at 08:14
  • I was wondering if there is some way without actually commenting the dict, maybe in the argument's list of black. – Nachokhan Jan 11 '21 at 14:21
8

It seems that black addressed this issue.

At the time of writing this answer, using black version 20.8b1, the formatting is done as I was hoping for.

As long as there is a magic trailing comma on the last item in the dictionary expression, black will format the code within the list comprehension.

res = [
    {
        "id": item.id, "name": item.name,
    }
    for item in items.select()
]

Will format to:

res = [
    {
        "id": item.id,
        "name": item.name,
    }
    for item in items.select()
]
Scovetta
  • 3,112
  • 1
  • 14
  • 13
Nitzan
  • 1,669
  • 3
  • 19
  • 33