Skip to content

C408 recomendations sometimes end in hard to find bugs #13039

Open
@klausmyrseth

Description

@klausmyrseth

I checked for C408 which is several issues on but not this perticular issue which the recommendation potentialy introduse grave bugs in your code.

C408 asks you to use the literal hence {} instead of dict() when creating a dict. This can work very well but for instance when using this together with attrs or as default values for method parameters this is a critical and hard to track bug.

I can describe this with some code:

import attrs


@attrs.define(kw_only=True)
class BigBug:
  struct_1: dict[str, str] | None = field(init=True, default={})
  struct_2: dict[str, str] | None = field(init=True, default={})

  def horrid_buggy_method(self, struct_3: dict = {}, struct_4: dict = {}) -> tuple[dict, dict]:
    struct_3['foo'] = 'bar'
    struct_4['bar'] = 'foo'
    # magically struct 3 and 4 will contain both keys :P
    return (struct_3, struct_4)

foo = BigBug()
foo.struct_1['bar'] = 'bas'
dict_3, dict_4 = foo.horrid_buggy_method()

In this scenarion both struct_1 and struct_2 will contain {'bar': 'bas'} as the literal will imply same class reference as default.

It's not always the case but in general you quickly learn to just use dict() instead as you avoid those edge cases, but we started using ruff in our projects now and our jrs is flooding the code with this bugs as ruff is "correcting" their code.

Edit: added the method too to illustrate the most common facepalm when it comes to this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-infoMore information is needed from the issue authorquestionAsking for support or clarification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions