mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
Changed interpretation of function definitions with (*args: Any, **kwargs: Any) to be ...
in compliance with latest typing spec. This addresses #7848. (#7859)
This commit is contained in:
parent
0ead803de9
commit
c49af8f349
@ -17926,6 +17926,16 @@ export function createTypeEvaluator(
|
||||
}
|
||||
}
|
||||
|
||||
// If the function contains an *args and a **kwargs parameter and both
|
||||
// are annotated as Any or are unannotated, make it exempt from
|
||||
// args/kwargs compatibility checks.
|
||||
const variadicsWithAnyType = functionType.details.parameters.filter(
|
||||
(param) => param.category !== ParameterCategory.Simple && param.name && isAnyOrUnknown(param.type)
|
||||
);
|
||||
if (variadicsWithAnyType.length >= 2) {
|
||||
functionType.details.flags |= FunctionTypeFlags.SkipArgsKwargsCompatibilityCheck;
|
||||
}
|
||||
|
||||
// If there was a defined return type, analyze that first so when we
|
||||
// walk the contents of the function, return statements can be
|
||||
// validated against this type.
|
||||
|
@ -3068,6 +3068,14 @@ export function isTypeSame(type1: Type, type2: Type, options: TypeSameOptions =
|
||||
return false;
|
||||
}
|
||||
|
||||
// If one function is ... and the other is not, they are not the same.
|
||||
if (
|
||||
FunctionType.shouldSkipArgsKwargsCompatibilityCheck(type1) !==
|
||||
FunctionType.shouldSkipArgsKwargsCompatibilityCheck(functionType2)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const positionOnlyIndex1 = params1.findIndex((param) => isPositionOnlySeparator(param));
|
||||
const positionOnlyIndex2 = params2.findIndex((param) => isPositionOnlySeparator(param));
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
# This sample tests the case where a callback protocol uses
|
||||
# a (*args: Any, **kwargs: Any) signature.
|
||||
|
||||
|
||||
from typing import Any, Callable, Concatenate, ParamSpec, Protocol, TypeVar
|
||||
|
||||
P = ParamSpec("P")
|
||||
T_contra = TypeVar("T_contra", contravariant=True)
|
||||
|
||||
|
||||
class Proto1(Protocol):
|
||||
def __call__(self, *args, **kwargs) -> None: ...
|
||||
|
||||
|
||||
class Proto2(Protocol):
|
||||
def __call__(self, a: int, /, *args, **kwargs) -> None: ...
|
||||
|
||||
|
||||
class Proto3(Protocol):
|
||||
def __call__(self, a: int, *args: Any, **kwargs: Any) -> None: ...
|
||||
|
||||
|
||||
class Proto4(Protocol[P]):
|
||||
def __call__(self, a: int, *args: P.args, **kwargs: P.kwargs) -> None: ...
|
||||
|
||||
|
||||
class Proto5(Protocol[T_contra]):
|
||||
def __call__(self, *args: T_contra, **kwargs: T_contra) -> None: ...
|
||||
|
||||
|
||||
class Proto6(Protocol):
|
||||
def __call__(self, a: int, /, *args: Any, k: str, **kwargs: Any) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class Proto7(Protocol):
|
||||
def __call__(self, a: float, /, b: int, *, k: str, m: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def func(
|
||||
p1: Proto1,
|
||||
p2: Proto2,
|
||||
p3: Proto3,
|
||||
p4: Proto4[...],
|
||||
p5: Proto5[Any],
|
||||
p7: Proto7,
|
||||
c1: Callable[..., None],
|
||||
c2: Callable[Concatenate[int, ...], None],
|
||||
):
|
||||
x1: Callable[..., None] = p1
|
||||
x2: Proto1 = c1
|
||||
x3: Callable[..., None] = p5
|
||||
x4: Proto5[Any] = c1
|
||||
x5: Callable[Concatenate[int, ...], None] = p2
|
||||
x6: Proto2 = c2
|
||||
x7: Callable[..., None] = p3
|
||||
x8: Proto3 = c1
|
||||
x9: Proto4[...] = p3
|
||||
x10: Proto3 = p4
|
||||
x11: Proto6 = p7
|
@ -72,7 +72,7 @@ class Class5(metaclass=Meta1):
|
||||
|
||||
|
||||
r5 = accepts_callable(Class5)
|
||||
reveal_type(r5, expected_text="(*args: Any, **kwargs: Any) -> NoReturn")
|
||||
reveal_type(r5, expected_text="(...) -> NoReturn")
|
||||
|
||||
|
||||
class Class6Proxy: ...
|
||||
|
@ -136,7 +136,7 @@ class ParentClass:
|
||||
|
||||
my_method43: Callable[..., None]
|
||||
|
||||
def my_method44(self, *args: Any, **kwargs: Any) -> None: ...
|
||||
def my_method44(self, *args: object, **kwargs: object) -> None: ...
|
||||
|
||||
def my_method45(self, __i: int) -> None: ...
|
||||
|
||||
@ -300,7 +300,7 @@ class ChildClass(ParentClass):
|
||||
def my_method43(self, a: int, b: str, c: str) -> None: ...
|
||||
|
||||
# This should generate an error because kwargs is missing.
|
||||
def my_method44(self, *args) -> None: ...
|
||||
def my_method44(self, *object) -> None: ...
|
||||
|
||||
def my_method45(self, i: int, /) -> None: ...
|
||||
|
||||
|
@ -67,6 +67,12 @@ test('CallbackProtocol9', () => {
|
||||
TestUtils.validateResults(analysisResults, 2);
|
||||
});
|
||||
|
||||
test('CallbackProtocol10', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['callbackProtocol10.py']);
|
||||
|
||||
TestUtils.validateResults(analysisResults, 0);
|
||||
});
|
||||
|
||||
test('Assignment1', () => {
|
||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['assignment1.py']);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user