sourcery icon indicating copy to clipboard operation
sourcery copied to clipboard

Dictionary update operator mutates input

Open danhje opened this issue 2 years ago • 2 comments

Sourcery wants to refactor d = d | {"add": "this"} into d |= {"add": "this"}, but the two are not equivalent. The latter actually mutates d, while the first creates a new dict and assigns it to the same variable.

def add_b(d: dict) -> dict:
    d = d | {"b": 2}
    return d

def add_c(d: dict) -> dict:
    d |= {"c": 3}
    return d

original = {"a": 1}

updated = add_b(original)
assert original == {"a": 1}  # All good

updated = add_c(original)
assert original == {"a": 1}  # Error, original is now {"a": 1, "c": 3}

I suggest removing the refactoring.

danhje avatar Apr 11 '23 19:04 danhje

Thanks for raising this!

Hellebore avatar Apr 12 '23 18:04 Hellebore

Due to this I've downgraded this rule from a refactoring to a suggestion (meaning it doesn't get combined with other rules and needs individual consideration). This change will be in our next release.

Hellebore avatar Sep 19 '23 09:09 Hellebore