diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyNamedTupleInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyNamedTupleInspection.kt index 0a23fd845101..d61332119fa6 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyNamedTupleInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyNamedTupleInspection.kt @@ -37,23 +37,29 @@ class PyNamedTupleInspection : PyInspection() { if ((fieldsProcessor == null || fieldsProcessor.fieldsWithoutDefaultValue.isEmpty()) && !checkInheritedOrder) return val ancestors = cls.getAncestorClasses(context) - val ancestorKinds = ancestors.map { - if (!classFieldsFilter(it)) { + val attributeNames = mutableSetOf() + val ancestorKinds = mutableListOf() + for (ancestor in ancestors.reversed()) { + val kind = if (!classFieldsFilter(ancestor)) { Ancestor.FILTERED } else { - val processor = processFields(it, fieldsFilter, hasAssignedValue, context) + val processor = processFields(ancestor, fieldsFilter, hasAssignedValue, context) if (processor.fieldsWithDefaultValue.isNotEmpty()) { Ancestor.HAS_FIELD_WITH_DEFAULT_VALUE } - else if (processor.fieldsWithoutDefaultValue.isNotEmpty()) { + else if (processor.fieldsWithoutDefaultValue.isNotEmpty() && !attributeNames.containsAll(processor.fieldsWithoutDefaultValue.map { field -> field.name })) { Ancestor.HAS_FIELD_WITHOUT_DEFAULT_VALUE } else { Ancestor.FILTERED } } + + ancestorKinds.add(kind) + attributeNames.addAll(ancestor.classAttributes.mapNotNull { attribute -> attribute.name }) } + ancestorKinds.reverse() if (checkInheritedOrder) { var seenAncestorHavingFieldWithDefaultValue: PyClass? = null diff --git a/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java index e12372829c89..c0758b6a367c 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyDataclassInspectionTest.java @@ -420,6 +420,31 @@ public class PyDataclassInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-60352 + public void testDataclassMultipleInheritanceAttributeWithDefault() { + doTestByText(""" + from dataclasses import dataclass + + + @dataclass + class Parent1: + number: int + default: int = 0 + + + @dataclass + class Parent2: + number: float + + + @dataclass + class Child(Parent2, Parent1): + pass + + + Child(number=1)"""); + } + @Override protected void doTest() { myFixture.copyDirectoryToProject("packages/attr", "attr");