From a03eb8492e62adbf8627c175f269693090db3c17 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 14 Jun 2024 09:15:34 -0700 Subject: [PATCH] Removed recent change in `dataclass_transform` handling. Dataclass properties should not be inherited from base classes after all. See https://discuss.python.org/t/dataclass-transform-inheriting-class-doesnt-recognize-kw-only-true-from-parent-class/55734/2. --- .../src/analyzer/typeEvaluator.ts | 47 +++++-------------- .../src/tests/samples/dataclassTransform5.py | 29 ------------ .../src/tests/typeEvaluator5.test.ts | 6 --- 3 files changed, 12 insertions(+), 70 deletions(-) delete mode 100644 packages/pyright-internal/src/tests/samples/dataclassTransform5.py diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index cba58de61..a2a46759a 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -17071,42 +17071,19 @@ export function createTypeEvaluator( // Determine whether this class derives from (or has a metaclass) that imbues // it with dataclass-like behaviors. If so, we'll apply those here. let dataClassBehaviors: DataClassBehaviors | undefined; + if (isInstantiableClass(effectiveMetaclass) && effectiveMetaclass.details.classDataClassTransform) { + dataClassBehaviors = effectiveMetaclass.details.classDataClassTransform; + } else { + const baseClassDataTransform = classType.details.mro.find((mroClass) => { + return ( + isClass(mroClass) && + mroClass.details.classDataClassTransform !== undefined && + !ClassType.isSameGenericClass(mroClass, classType) + ); + }); - // If this class has not already received its dataclass behaviors from a - // decorator and is inheriting from a class that has dataclass behaviors, - // apply those inherited behaviors to this class. - if (!classType.details.dataClassBehaviors) { - for (const mroClass of classType.details.mro) { - if (!isClass(mroClass)) { - break; - } - - if (ClassType.isSameGenericClass(mroClass, classType)) { - continue; - } - - if (mroClass.details.dataClassBehaviors) { - dataClassBehaviors = mroClass.details.dataClassBehaviors; - break; - } - } - } - - if (!dataClassBehaviors) { - if (isInstantiableClass(effectiveMetaclass) && effectiveMetaclass.details.classDataClassTransform) { - dataClassBehaviors = effectiveMetaclass.details.classDataClassTransform; - } else { - const baseClassDataTransform = classType.details.mro.find((mroClass) => { - return ( - isClass(mroClass) && - mroClass.details.classDataClassTransform !== undefined && - !ClassType.isSameGenericClass(mroClass, classType) - ); - }); - - if (baseClassDataTransform) { - dataClassBehaviors = (baseClassDataTransform as ClassType).details.classDataClassTransform; - } + if (baseClassDataTransform) { + dataClassBehaviors = (baseClassDataTransform as ClassType).details.classDataClassTransform; } } diff --git a/packages/pyright-internal/src/tests/samples/dataclassTransform5.py b/packages/pyright-internal/src/tests/samples/dataclassTransform5.py deleted file mode 100644 index a1fdc66bf..000000000 --- a/packages/pyright-internal/src/tests/samples/dataclassTransform5.py +++ /dev/null @@ -1,29 +0,0 @@ -# This sample tests the case where a dataclass inherits a dataclass -# behavior (like kw_only) from its parent class. - -from typing import dataclass_transform - - -@dataclass_transform() -class ModelMeta(type): - pass - - -class ModelBase(metaclass=ModelMeta): - def __init_subclass__(cls, kw_only: bool = False) -> None: - pass - - -class Base(ModelBase, kw_only=True): - pass - - -class Model(Base): - a: str | None = None - b: int - - -Model(b=0) - -# This should generate an error because of kw_only. -Model("", 1) diff --git a/packages/pyright-internal/src/tests/typeEvaluator5.test.ts b/packages/pyright-internal/src/tests/typeEvaluator5.test.ts index bf458ba00..d4cc61be1 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator5.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator5.test.ts @@ -416,12 +416,6 @@ test('DataclassTransform4', () => { TestUtils.validateResults(analysisResults, 2); }); -test('DataclassTransform5', () => { - const analysisResults = TestUtils.typeAnalyzeSampleFiles(['dataclassTransform5.py']); - - TestUtils.validateResults(analysisResults, 1); -}); - test('Async1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['async1.py']);