Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

object.__setattr__ triggering PLC2801 outside of dunder methods #11636

Open
my1e5 opened this issue May 31, 2024 · 3 comments
Open

object.__setattr__ triggering PLC2801 outside of dunder methods #11636

my1e5 opened this issue May 31, 2024 · 3 comments
Labels
rule Implementing or modifying a lint rule

Comments

@my1e5
Copy link

my1e5 commented May 31, 2024

Related to false positive on PLC2801 "unnecessary dunder... for setattr" #9584

object.__setattr__ is the recommended way to set attributes on frozen dataclasses. This was addressed in #9584 but PLC2801 is triggering when object.__setattr__ is in non-dunder methods.

See - https://play.ruff.rs/1a9602da-78ce-44c9-bbfe-b17b147da04b

from dataclasses import dataclass, field


@dataclass(frozen=True)
class Foo:
    a: int
    b: int
    c: int = field(init=False)

    def __post_init__(self):
        object.__setattr__(self, "c", self.a + self.b)

    def foo(self):
        object.__setattr__(self, "c", self.a - self.b)    # <-------

    def __str__(self):
        object.__setattr__(self, "c", self.a * self.b) 
14:9: PLC2801 Unnecessary dunder call to `__setattr__`. Mutate attribute directly or use setattr built-in function.

ruff v0.4.6

@AlexWaygood
Copy link
Member

Thanks for the report!

I'm curious, what's the purpose of mutating attributes on a frozen dataclass from arbitrary non-dunder methods? Wouldn't the idiomatic thing here be to make it a regular (not frozen) dataclass?

@AlexWaygood
Copy link
Member

Having said that, we may want to consider relaxing the rules here anyway. object.__setattr__ can be useful in various other situations (though it's quite niche) where you want to make sure that you're avoiding triggering custom logic in descriptor or __setattr__ methods

@AlexWaygood AlexWaygood added the rule Implementing or modifying a lint rule label May 31, 2024
@my1e5
Copy link
Author

my1e5 commented May 31, 2024

I'm curious, what's the purpose of mutating attributes on a frozen dataclass from arbitrary non-dunder methods?

So my code looks something like this

def __post_init__(self):
    self._init_foo()
    self._init_bar()
    self._init_baz()

Basically just breaking up the __post_init__ step for readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rule Implementing or modifying a lint rule
Projects
None yet
Development

No branches or pull requests

2 participants