Black: Black should add parentheses to long values in dict literals

Created on 26 Nov 2018  路  9Comments  路  Source: psf/black

Operating system: Linux CentOS 7
Python version: 3.6.6
Black version: 18.9b0
Does also happen on master: Yes (Example on master)

I have this code (line length is greater than allowed)

my_dict = {
    'a key in my dict': deformation_rupture_mean * constraint_rupture_mean / 100.0
}

So Black wrap the line, but without indent :

my_dict = {
    "a key in my dict": deformation_rupture_mean
    * constraint_rupture_mean
    / 100.0
}

I find this indent not very readable.

If I add paranthesis, I get the code below, nice formatted in my opinion.

my_dict = {
    "a key in my dict": (
        deformation_rupture_mean * constraint_rupture_mean / 100.0
    )
}

Should not Black add paranthesis in this case?

enhancement parentheses

Most helpful comment

I've found this issue shows up in Django projects that chain a lot of queryset methods together. For example, black was found to produce the following:

class MyView:
    def get_context_data(self, *args, **kwargs):
        context = {
            "filtered_users": User.objects.all()
            .archived()
            .filter(groups__in=get_groups())
        }

I think this would be more readable if the chained methods were indented.

All 9 comments

Going one step further we can observe that with even longer lines, black will propose the following formatting:

my_dict = {
    "a very very long key in my dict": (
        another_long_operand
        + deformation_rupture_mean * constraint_rupture_mean / 100.0
    )
}

Even if black did not add parenthesis, it would be nice if it added that little bit of extra indent.
It provides more readability in my opinion.

I've found this issue shows up in Django projects that chain a lot of queryset methods together. For example, black was found to produce the following:

class MyView:
    def get_context_data(self, *args, **kwargs):
        context = {
            "filtered_users": User.objects.all()
            .archived()
            .filter(groups__in=get_groups())
        }

I think this would be more readable if the chained methods were indented.

Black should totally add parenthesis in all these cases

There is probably similar problem with string lines in dictionary. Example:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100,
}

When I set line-length = 79, black does not try to fix this line, while parenthesis could help to fit line-length restriction. In cases of more long lines, splitting string to more parts is required too.

@zsol Not sure if this should be separate issue, or just part of this one.

Is there any update or fix planned for this issue? A lot of issues were created, closed and referenced to this one at this point. And manually fixing the lines still causes black to undo those fixes and violate its line-length rule.

AFAIK nobody is actively working on this right now, but I'm happy to review a pr if you're interested in contributing

Another annoying case when black decreases readability is this.

Original code:

my_function(
    my_kwarg=1 if True else 2
)

Blackified code (at first glance it looks like function takes 3 args!):

my_function(
    my_kwarg=1
    if True
    else 2,
)

What I would expect it to look like:

my_function(
    my_kwarg=(
        1
        if True
        else 2,
    ),
)

It happens with black==19.3b0 when function call is indented enough so lines start to wrap.

This also happens without string literals or even complex operations. This simple example is not split on multiple lines by black:

a = {
    SomeLongEnumeration.SOME_LONG_ENUM_NAME: another_pkg.subpkg.another_enum.another_enum_name
}

Another example

max_prediction_rank_to_save = self.metadata['additional_params'][
    'max_prediction_rank_to_save'
]

which would look better if parentheses were used

max_prediction_rank_to_save = (
    self.metadata['additional_params']['max_prediction_rank_to_save']
)

If there are too many keys, each could go on a separate line

max_prediction_rank_to_save = (
    self.metadata['additional_params']
    ['max_prediction_rank_to_save']
    ['another']
    ['looooooooooong_key']
)
Was this page helpful?
0 / 5 - 0 ratings