Fixed handling of __new__ magic method. Its parameter signature changes based on whether it's called as a constructor or by name directly.

This commit is contained in:
Eric Traut 2019-03-29 23:36:26 -07:00
Родитель 24b7af34f1
Коммит bf46a52c97
2 изменённых файлов: 11 добавлений и 7 удалений

Просмотреть файл

@ -429,9 +429,12 @@ export class ExpressionEvaluator {
// If the memberType is an instance or class method, creates a new
// version of the function that has the "self" or "cls" parameter bound
// to it.
// to it. If treatAsClassMember is true, the function is treated like a
// class member even if it's not marked as such. That's needed to
// special-case the __new__ magic method when it's invoked as a
// constructor (as opposed to by name).
private _bindFunctionToClassOrObject(baseType: ClassType | ObjectType | undefined,
memberType: Type): Type {
memberType: Type, treatAsClassMember = false): Type {
if (memberType instanceof FunctionType) {
// If the caller specified no base type, always strip the
@ -443,7 +446,7 @@ export class ExpressionEvaluator {
return this._partiallySpecializeFunctionForBoundClassOrObject(
baseType, memberType);
}
} else if (memberType.isClassMethod()) {
} else if (memberType.isClassMethod() || treatAsClassMember) {
if (baseType instanceof ClassType) {
return this._partiallySpecializeFunctionForBoundClassOrObject(
baseType, memberType);
@ -456,7 +459,8 @@ export class ExpressionEvaluator {
let newOverloadType = new OverloadedFunctionType();
memberType.getOverloads().forEach(overload => {
newOverloadType.addOverload(overload.typeSourceId,
this._bindFunctionToClassOrObject(baseType, overload.type) as FunctionType);
this._bindFunctionToClassOrObject(baseType, overload.type,
treatAsClassMember) as FunctionType);
});
return newOverloadType;
@ -786,7 +790,7 @@ export class ExpressionEvaluator {
MemberAccessFlags.SkipBaseClasses);
if (constructorMethodType) {
constructorMethodType = this._bindFunctionToClassOrObject(
type, constructorMethodType);
type, constructorMethodType, true);
returnType = this._validateCallArguments(node, constructorMethodType);
if (returnType instanceof UnknownType) {
returnType = new ObjectType(type);

Просмотреть файл

@ -228,9 +228,9 @@ export abstract class SemanticAnalyzer extends ParseTreeWalker {
}
// The "__new__" magic method is not an instance method.
// It acts as a class method instead.
// It acts as a static method instead.
if (node.name.nameToken.value === '__new__') {
functionFlags |= FunctionTypeFlags.ClassMethod;
functionFlags |= FunctionTypeFlags.StaticMethod;
functionFlags &= ~FunctionTypeFlags.InstanceMethod;
}