ExplicitFrozenDataclassRule

Encourages the use of frozen dataclass objects by telling users to specify the kwarg.

Without this lint rule, most users of dataclass won’t know to use the kwarg, and may unintentionally end up with mutable objects.

Message

When using dataclasses, explicitly specify a frozen keyword argument. Example: @dataclass(frozen=True) or @dataclass(frozen=False). Docs: https://docs.python.org/3/library/dataclasses.html

Has Autofix: Yes

VALID Code Examples

# 1:

@some_other_decorator
class Cls: pass

# 2:

from dataclasses import dataclass
@dataclass(frozen=False)
class Cls: pass

# 3:

import dataclasses
@dataclasses.dataclass(frozen=False)
class Cls: pass

# 4:

import dataclasses as dc
@dc.dataclass(frozen=False)
class Cls: pass

# 5:

from dataclasses import dataclass as dc
@dc(frozen=False)
class Cls: pass

INVALID Code Examples

# 1:

from dataclasses import dataclass
@some_unrelated_decorator
@dataclass  # not called as a function
@another_unrelated_decorator
class Cls: pass

Autofix:

---
+++
@@ -1,6 +1,6 @@

 from dataclasses import dataclass
 @some_unrelated_decorator
-@dataclass  # not called as a function
+@dataclass(frozen=True)  # not called as a function
 @another_unrelated_decorator
 class Cls: pass

# 2:

from dataclasses import dataclass
@dataclass()  # called as a function, no kwargs
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 from dataclasses import dataclass
-@dataclass()  # called as a function, no kwargs
+@dataclass(frozen=True)  # called as a function, no kwargs
 class Cls: pass

# 3:

from dataclasses import dataclass
@dataclass(other_kwarg=False)
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 from dataclasses import dataclass
-@dataclass(other_kwarg=False)
+@dataclass(other_kwarg=False, frozen=True)
 class Cls: pass

# 4:

import dataclasses
@dataclasses.dataclass
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses
-@dataclasses.dataclass
+@dataclasses.dataclass(frozen=True)
 class Cls: pass

# 5:

import dataclasses
@dataclasses.dataclass()
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses
-@dataclasses.dataclass()
+@dataclasses.dataclass(frozen=True)
 class Cls: pass

# 6:

import dataclasses
@dataclasses.dataclass(other_kwarg=False)
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses
-@dataclasses.dataclass(other_kwarg=False)
+@dataclasses.dataclass(other_kwarg=False, frozen=True)
 class Cls: pass

# 7:

from dataclasses import dataclass as dc
@dc
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 from dataclasses import dataclass as dc
-@dc
+@dc(frozen=True)
 class Cls: pass

# 8:

from dataclasses import dataclass as dc
@dc()
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 from dataclasses import dataclass as dc
-@dc()
+@dc(frozen=True)
 class Cls: pass

# 9:

from dataclasses import dataclass as dc
@dc(other_kwarg=False)
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 from dataclasses import dataclass as dc
-@dc(other_kwarg=False)
+@dc(other_kwarg=False, frozen=True)
 class Cls: pass

# 10:

import dataclasses as dc
@dc.dataclass
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses as dc
-@dc.dataclass
+@dc.dataclass(frozen=True)
 class Cls: pass

# 11:

import dataclasses as dc
@dc.dataclass()
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses as dc
-@dc.dataclass()
+@dc.dataclass(frozen=True)
 class Cls: pass

# 12:

import dataclasses as dc
@dc.dataclass(other_kwarg=False)
class Cls: pass

Autofix:

---
+++
@@ -1,4 +1,4 @@

 import dataclasses as dc
-@dc.dataclass(other_kwarg=False)
+@dc.dataclass(other_kwarg=False, frozen=True)
 class Cls: pass