From d53c1d6eae50d073ced295276d5de946bf7c64d8 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Sun, 5 Jan 2020 11:21:14 -0700 Subject: [PATCH] Changed validateConstructorArguments to honor new SkipConstructorCheck flag, and set it for the __init__ method of NamedTuple. --- server/src/analyzer/typeEvaluator.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/server/src/analyzer/typeEvaluator.ts b/server/src/analyzer/typeEvaluator.ts index f70635f7f..42a2f5e10 100644 --- a/server/src/analyzer/typeEvaluator.ts +++ b/server/src/analyzer/typeEvaluator.ts @@ -3271,6 +3271,16 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { let returnType: Type | undefined; let reportedErrorsForInitCall = false; + // Create a helper function that determines whether we should skip argument + // validation for either __init__ or __new__. This is required for certain + // synthesized constructor types, namely NamedTuples. + const skipConstructorCheck = (type: Type) => { + if (type.category !== TypeCategory.Function) { + return false; + } + return FunctionType.isSkipConstructorCheck(type); + }; + // Validate __init__ // We validate __init__ before __new__ because the former typically has // more specific type annotations, and we want to evaluate the arguments @@ -3280,7 +3290,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { ObjectType.create(type), '__init__', { method: 'get' }, new DiagnosticAddendum(), MemberAccessFlags.SkipForMethodLookup | MemberAccessFlags.SkipObjectBaseClass); - if (initMethodType) { + if (initMethodType && !skipConstructorCheck(initMethodType)) { const typeVarMap = new Map(); if (validateCallArguments(errorNode, argList, initMethodType, typeVarMap)) { let specializedClassType = type; @@ -3305,7 +3315,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { type, '__new__', { method: 'get' }, new DiagnosticAddendum(), MemberAccessFlags.SkipForMethodLookup | MemberAccessFlags.SkipObjectBaseClass); - if (constructorMethodInfo) { + if (constructorMethodInfo && !skipConstructorCheck(constructorMethodInfo.type)) { const constructorMethodType = bindFunctionToClassOrObject( type, constructorMethodInfo.type, true); const typeVarMap = new Map(); @@ -4229,9 +4239,10 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator { // Always use generic parameters for __init__. The __new__ method // will handle property type checking. We may need to disable default - // parameter processing for __new__ (see setDefaultParameterCheckDisabled), + // parameter processing for __new__ (see isAssignmentToDefaultsFollowingNamedTuple), // and we don't want to do it for __init__ as well. - const initType = FunctionType.create(FunctionTypeFlags.SynthesizedMethod); + const initType = FunctionType.create(FunctionTypeFlags.SynthesizedMethod | + FunctionTypeFlags.SkipConstructorCheck); FunctionType.addParameter(initType, selfParameter); addDefaultFunctionParameters(initType); initType.details.declaredReturnType = NoneType.create();