Search code examples
pythonpep8

Python black style discrepancy


I am using black to format my python code. I observed the following behavior. I admit that it is a very specific case but it goes on my nerves.

Let's suppose I have the following code:

@pytest.mark.parametrize(
"first",
["second"],
)

black does not change that. But, if I remove the trailing comma after ["second"]:

@pytest.mark.parametrize(
"first",
["second"]
)

black makes a nice reordering:

@pytest.mark.parametrize("first", ["second"])

On the other hand, let us see the following:

@pytest.mark.parametrize(
"This is a very long line. Black will not be able to to a linebreak here.",
["second"],
)

In this case, again, black does not change anything. So far, so good. Now, I remove the trailing comma after ["second"] again:

@pytest.mark.parametrize(
"This is a very long line and black will not be able to do a line break here.",
["second"]
)

As the line is too long, black does not do a nice reordering into one line as before. But instead, black adds a trailing comma after the ["second"]:

@pytest.mark.parametrize(
"This is a very long line and black will not be able to do a line break here.",
["second"],
)

I do not like that. When I am confronted with such lists in my code, I always tend to remove the trailing comma to enforce one line reordering. But then, in most of the cases, black adds it again ...


Solution

  • The black behavior is expected from my understanding, because one of the purpose is to limit the number of changes inside a git diff.

    If the line is too long, you already are in a multiline writing. And if you are in a multiline writing, then it should end with a comma.

    That way if you add elements in the tuple, list, … or arguments in method or function, it will not generate a diff for the line where you add the comma.

    If a contrario you are in a mono-line writing that is not too long, black will consider if you have added a trailing comma. If trailing comma, it will go to multi-line, if not it will encourage mono-line.

    a = [1, 2,]
    # goes to
    a = [
        1,
        2,
    ]
    
    # and
    
    a = [1, 2]
    # remains:
    a = [1, 2]