mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-17 11:17:17 +03:00
Fixed false positive error caused by inappropriate method binding for instance methods.
This commit is contained in:
parent
fbb0d521ee
commit
bf8b5511d3
@ -5009,7 +5009,7 @@ export function createTypeEvaluator(
|
||||
memberInfo,
|
||||
classType,
|
||||
bindToType,
|
||||
/* isAccessedThroughObject */ false,
|
||||
/* isAccessedThroughObject */ !!bindToType,
|
||||
flags,
|
||||
errorNode,
|
||||
memberName,
|
||||
@ -5217,7 +5217,7 @@ export function createTypeEvaluator(
|
||||
} else if (isFunction(subtype) || isOverloadedFunction(subtype)) {
|
||||
// If this function is an instance member (e.g. a lambda that was
|
||||
// assigned to an instance variable), don't perform any binding.
|
||||
if (!isAccessedThroughObject || !memberInfo?.isInstanceMember) {
|
||||
if (!isAccessedThroughObject || (memberInfo && !memberInfo.isInstanceMember)) {
|
||||
return bindFunctionToClassOrObject(
|
||||
isAccessedThroughObject ? ClassType.cloneAsInstance(baseTypeClass) : baseTypeClass,
|
||||
subtype,
|
||||
@ -11783,7 +11783,7 @@ export function createTypeEvaluator(
|
||||
function createCallableType(typeArgs: TypeResult[] | undefined, errorNode: ParseNode): FunctionType {
|
||||
// Create a new function that is marked as "static" so there is later
|
||||
// no attempt to bind it as though it's an instance or class method.
|
||||
const functionType = FunctionType.createInstantiable('', '', '', FunctionTypeFlags.StaticMethod);
|
||||
const functionType = FunctionType.createInstantiable('', '', '', FunctionTypeFlags.None);
|
||||
TypeBase.setNonCallable(functionType);
|
||||
functionType.details.declaredReturnType = UnknownType.create();
|
||||
|
||||
@ -22807,7 +22807,7 @@ export function createTypeEvaluator(
|
||||
'__new__',
|
||||
'',
|
||||
'',
|
||||
FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ConstructorMethod | FunctionTypeFlags.SynthesizedMethod
|
||||
FunctionTypeFlags.ConstructorMethod | FunctionTypeFlags.SynthesizedMethod
|
||||
);
|
||||
constructorFunction.details.declaredReturnType = ClassType.cloneAsInstance(classType);
|
||||
FunctionType.addDefaultParameters(constructorFunction);
|
||||
|
@ -0,0 +1,37 @@
|
||||
# This sample tests that methods are bound properly regardless of
|
||||
# whether they are decorated.
|
||||
|
||||
from typing import Callable
|
||||
|
||||
UnboundMethodThatTakesIntAndReturnsStr = Callable[["MyClass", int], str]
|
||||
|
||||
|
||||
def method_decorator(
|
||||
method: UnboundMethodThatTakesIntAndReturnsStr,
|
||||
) -> UnboundMethodThatTakesIntAndReturnsStr:
|
||||
def wrapper(self: "MyClass", a: int) -> str:
|
||||
return "wrapped " + method(self, a)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class MyClass:
|
||||
def __init__(self):
|
||||
self.method4 = lambda x: x
|
||||
|
||||
@method_decorator
|
||||
def method1(self, a: int) -> str:
|
||||
return "foo"
|
||||
|
||||
def method2(self, a: int) -> str:
|
||||
return "foo"
|
||||
|
||||
method3 = method_decorator(method2)
|
||||
|
||||
|
||||
mc = MyClass()
|
||||
|
||||
mc.method1(1)
|
||||
mc.method2(1)
|
||||
mc.method3(1)
|
||||
mc.method4(1)
|
@ -8,7 +8,7 @@ class ClassA:
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def __getattr__(self) -> Callable[[str], str]:
|
||||
def __getattr__(self, key: str) -> Callable[[str], str]:
|
||||
return lambda a: a
|
||||
|
||||
|
||||
|
@ -375,6 +375,11 @@ test('MemberAccess10', () => {
|
||||
TestUtils.validateResults(analysisResults, 2);
|
||||
});
|
||||
|
||||
test('MemberAccess11', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['memberAccess11.py']);
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('DataClass1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['dataclass1.py']);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user