Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable Black formatting of dict expression within mapping comprehensions

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?

like image 330
Nitzan Avatar asked May 03 '20 17:05

Nitzan


People also ask

Can you break a black code?

Black will break a line before a binary operator when splitting a block of code over multiple lines. This is so that Black is compliant with the recent changes in the PEP 8 style guide, which emphasizes that this approach improves readability.

Is Black pep8 compliant?

Black is a PEP 8 compliant opinionated formatter. Black reformats entire files in place. Style configuration options are deliberately limited and rarely added.

What is black formatting in Python?

Black is the uncompromising Python code formatter. By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.

Why does black Add trailing commas?

Black will add trailing commas to expressions that are split by comma where each element is on its own line. This includes function signatures. Unnecessary trailing commas are removed if an expression fits in one line. This makes it 1% more likely that your line won't exceed the allotted line length limit.


2 Answers

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()
]
like image 68
Nitzan Avatar answered Sep 22 '22 08:09

Nitzan


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

like image 23
milanbalazs Avatar answered Sep 23 '22 08:09

milanbalazs