google / yapf

A formatter for Python files
Apache License 2.0
13.73k stars 886 forks source link

yapf 0.24.0 breaks formatting of nested data structures. #623

Open ghost opened 5 years ago

ghost commented 5 years ago

The code in question is:

CHARGE_SCHEMA = {
    "name":
    "Charge",
    "type":
    "record",
    "fields": [{
        "name": "Name",
        "type": "string"
    }, {
        "name": "Aggregators",
        "type": ["null", {
            "type": "array",
            "items": "string"
        }],
        "default": None
    }, {
        "name": "IDTypeArray",
        "type": {
            "type": "array",
            "items": "string"
        }
    }]
    }

In v0.24.0 this becomes:

CHARGE_SCHEMA = {
    "name":
    "Charge",
    "type":
    "record",
    "fields": [{
        "name": "Name",
        "type": "string"
    },
               {
                   "name": "Aggregators",
                   "type": ["null", {
                       "type": "array",
                       "items": "string"
                   }],
                   "default": None
               }, {
                   "name": "IDTypeArray",
                   "type": {
                       "type": "array",
                       "items": "string"
                   }
               }]
}
iquintero commented 5 years ago

Was giving yapf a try and I faced a very similar issue. Not sure if there is any knob combination that will fix this?

ajbeach2 commented 5 years ago

I am also having issues with this:

foo = [{
    "id": 3,
    "human_id": 1,
    "bit": 1,
    "other": [{
        "id": 1,
        "start_date": "2018-08-12 0:00:00-04:00",
        "end_date": "2100-08-12 0:00:00-04:00",
    }]
}]

becomes:

foo = [{
    "id":
    3,
    "human_id":
    1,
    "bit":
    1,
    "other": [{
        "id": 1,
        "start_date": "2018-08-12 0:00:00-04:00",
        "end_date": "2100-08-12 0:00:00-04:00",
    }]
}]
felixc commented 5 years ago

@ajbeach2 Might that one be related to the ALLOW_SPLIT_BEFORE_DICT_VALUE setting? I think it looks a bit different from the original issue in the thread (but I don't know either way; I'm just a YAPF user with the same bug as the original report!)

ajbeach2 commented 5 years ago

yeah actually I was able to resolve my issues with these settings:

[style]
based_on_style = pep8
split_before_logical_operator = true
allow_multiline_lambdas = true
ALLOW_SPLIT_BEFORE_DICT_VALUE = false
EACH_DICT_ENTRY_ON_SEPARATE_LINE = true
INDENT_WIDTH = 4
DEDENT_CLOSING_BRACKETS = true
SPLIT_BEFORE_DOT = false
CONTINUATION_INDENT_WIDTH = 4
INDENT_DICTIONARY_VALUE = true
SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET = false
agrieve commented 5 years ago

Also note that changing the final }] to a },] fixes the formatting

Larandar commented 5 years ago

After some experimentation it seem to affect not only nested structures :

No formating :

call_func_that_takes_a_dict({'key1': 'value1',
                             'key2': 'value2',
                             'key3': 'value3',
                             'key4': 'value4',},
                             kwarg=other_function())

Default style :

call_func_that_takes_a_dict({
    'key1': 'value1',
    'key2': 'value2',
    'key3': 'value3',
    'key4': 'value4',
},
                            kwarg=other_function())

With dedent_closing_brackets = true

call_func_that_takes_a_dict(
    {
        'key1': 'value1',
        'key2': 'value2',
        'key3': 'value3',
        'key4': 'value4',
    },
    kwarg=other_function()
)

With both dedent_closing_brackets & coalesce_brackets

call_func_that_takes_a_dict({
    'key1': 'value1',
    'key2': 'value2',
    'key3': 'value3',
    'key4': 'value4',
},
                            kwarg=other_function())
apbard commented 5 years ago

The source seems to be commit: ea904bd7f55fcea88e7ef3008dc5d23ac95758e0

LECbg commented 3 years ago

I just faced a similar issue with a nested dictionary structure and I don'k know why it is happening, maybe I am missing some setting? Please, any help will be appreciated.

My dictionary looks like this:

my_dict = {
    "key1": {
        "key11": 3,
        "key12": {"key121": some_value},
    },
    "key2": another_value,
    "key3": True,
}

I wouldn't expect this to be reformatted, but Yapf output is:

my_dict = {
    "key1":
        {
            "key11": 3,
            "key12": {"key121": some_value},
        },
    "key2": another_value,
    "key3": True,
}

My config at pyproject.toml

[tool.yapf]
based_on_style = 'google'
align_closing_bracket_with_visual_indent = true
allow_split_before_dict_value = false
arithmetic_precedence_indication = true
column_limit = 90
dedent_closing_brackets = true
each_dict_entry_on_separate_line = false
join_multiple_lines = true
split_before_arithmetic_operator = true
split_before_named_assigns = false
split_before_bitwise_operator = true
split_before_expression_after_opening_paren = true
split_before_logical_operator = true
# -- Penalties --
split_penalty_comprehension = 80