PY-77433 Don't report mutable field defaults in dataclass_transform-based dataclasses

Some dataclass implementations, such as Pydantic, allow declaring fields with
mutable defaults, deep-copying them under the hood.

See https://docs.pydantic.dev/latest/concepts/models/#fields-with-non-hashable-default-values


(cherry picked from commit e495621858950976226731dddbb01af4012704fa)

IJ-CR-151192

GitOrigin-RevId: 7412272584a4c26e404d3d84e6150f974027eca7
This commit is contained in:
Mikhail Golubev
2024-12-09 14:51:06 +02:00
committed by intellij-monorepo-bot
parent 19d6ad45a2
commit 6e515ed9b8
2 changed files with 18 additions and 9 deletions

View File

@@ -60,8 +60,17 @@ class PyDataclassInspection : PyInspection() {
val dataclassParameters = parseDataclassParameters(node, myTypeEvalContext)
if (dataclassParameters != null) {
if (dataclassParameters.type.asPredefinedType == PyDataclassParameters.PredefinedType.STD ||
dataclassParameters.type.asPredefinedType == PyDataclassParameters.PredefinedType.DATACLASS_TRANSFORM) {
if (dataclassParameters.type.asPredefinedType == PyDataclassParameters.PredefinedType.DATACLASS_TRANSFORM) {
processDataclassParameters(node, dataclassParameters)
node.processClassLevelDeclarations { element, _ ->
if (element is PyTargetExpression) {
processFieldFunctionCall(node, dataclassParameters, element)
}
true
}
}
else if (dataclassParameters.type.asPredefinedType == PyDataclassParameters.PredefinedType.STD) {
processDataclassParameters(node, dataclassParameters)
val postInit = node.findMethodByName(Dataclasses.DUNDER_POST_INIT, false, myTypeEvalContext)

View File

@@ -6,19 +6,19 @@ from decorator import my_dataclass, field
@my_dataclass()
class A:
a: list[int] = <error descr="Mutable default '[]' is not allowed. Use 'default_factory'">[]</error>
b: list[int] = <error descr="Mutable default 'list()' is not allowed. Use 'default_factory'">list()</error>
c: set[int] = <error descr="Mutable default '{1}' is not allowed. Use 'default_factory'">{1}</error>
d: set[int] = <error descr="Mutable default 'set()' is not allowed. Use 'default_factory'">set()</error>
a: list[int] = []
b: list[int] = list()
c: set[int] = {1}
d: set[int] = set()
e: tuple[int, ...] = ()
f: tuple[int, ...] = tuple()
g: ClassVar[list[int]] = []
h: ClassVar = []
i: dict[int, int] = <error descr="Mutable default '{1: 2}' is not allowed. Use 'default_factory'">{1: 2}</error>
j: dict[int, int] = <error descr="Mutable default 'dict()' is not allowed. Use 'default_factory'">dict()</error>
i: dict[int, int] = {1: 2}
j: dict[int, int] = dict()
k = []
l = list()
m: dict[int, int] = <error descr="Mutable default 'OrderedDict()' is not allowed. Use 'default_factory'">OrderedDict()</error>
m: dict[int, int] = OrderedDict()
n: frozenset[int] = frozenset()
o: list = field(default_factory=list)
a2: type[list[int]] = list