Changed behavior of constructor call evaluation when __new__ evaluation results in type evaluation errors. Previously, pyright skipped the __init__ evaluation in this case. It now proceeds to evaluate __init__, potentially generating redundant errors. This addresses #8026. (#8029)

This commit is contained in:
Eric Traut 2024-05-30 12:49:11 -07:00 committed by GitHub
parent 2e397e9a0a
commit 32fa85e3ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 18 additions and 7 deletions

View File

@ -292,9 +292,17 @@ function validateNewAndInitMethods(
let initMethodTypeResult: TypeResult | undefined;
// Validate __init__ if it's present. Skip if the __new__ method produced errors.
// If there were errors evaluating the __new__ method, assume that __new__
// returns the class instance and proceed accordingly. This may produce
// false positives in some cases, but it will prevent false negatives
// if the __init__ method also produces type errors (perhaps unrelated
// to the errors in the __new__ method).
if (argumentErrors) {
initMethodTypeResult = { type: convertToInstance(type) };
}
// Validate __init__ if it's present.
if (
!argumentErrors &&
!isNever(newMethodReturnType) &&
!shouldSkipInitEvaluation(evaluator, type, newMethodReturnType) &&
isClassInstance(newMethodReturnType)

View File

@ -13177,7 +13177,7 @@ export function createTypeEvaluator(
if (isEffectivelyInstantiable(specializedType)) {
classType.details.baseClasses.push(specializedType);
} else {
addExpectedClassDiagnostic(typeArg.type, argList[1].valueExpression || errorNode);
classType.details.baseClasses.push(UnknownType.create());
}
});

View File

@ -13,13 +13,16 @@ class A(X1): ...
class B(X2, A): ...
# This should generate an error because the first arg is not a string.
# This should generate two errors (one for `__new__` and one for `__init__`)
# because the first arg is not a string.
X3 = type(34, (object,))
# This should generate an error because the second arg is not a tuple of class types.
# This should generate two errors (one for `__new__` and one for `__init__`)
# because the second arg is not a tuple of class types.
X4 = type("X4", 34)
# This should generate an error because the second arg is not a tuple of class types.
# This should generate two errors (one for `__new__` and one for `__init__`)
# because the second arg is not a tuple of class types.
X5 = type("X5", (3,))

View File

@ -266,7 +266,7 @@ test('NewType1', () => {
test('NewType2', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['newType2.py']);
TestUtils.validateResults(analysisResults, 4);
TestUtils.validateResults(analysisResults, 6);
});
test('NewType3', () => {