| -- Test cases for keyword arguments. |
| |
| |
| [case testTypeErrorInKeywordArgument] |
| import typing |
| def f(o: object) -> None: pass |
| f(o=None()) # E: "None" not callable |
| |
| [case testSimpleKeywordArgument] |
| import typing |
| def f(a: 'A') -> None: pass |
| f(a=A()) |
| f(a=object()) # E: Argument "a" to "f" has incompatible type "object"; expected "A" |
| class A: pass |
| |
| [case testTwoKeywordArgumentsNotInOrder] |
| import typing |
| def f(a: 'A', b: 'B') -> None: pass |
| f(b=A(), a=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "B" |
| f(b=B(), a=B()) # E: Argument "a" to "f" has incompatible type "B"; expected "A" |
| f(a=A(), b=B()) |
| f(b=B(), a=A()) |
| class A: pass |
| class B: pass |
| |
| [case testOneOfSeveralOptionalKeywordArguments] |
| import typing |
| def f(a: 'A' = None, b: 'B' = None, c: 'C' = None) -> None: pass |
| f(a=A()) |
| f(b=B()) |
| f(c=C()) |
| f(b=B(), c=C()) |
| f(a=B()) # E: Argument "a" to "f" has incompatible type "B"; expected "Optional[A]" |
| f(b=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "Optional[B]" |
| f(c=B()) # E: Argument "c" to "f" has incompatible type "B"; expected "Optional[C]" |
| f(b=B(), c=A()) # E: Argument "c" to "f" has incompatible type "A"; expected "Optional[C]" |
| class A: pass |
| class B: pass |
| class C: pass |
| |
| [case testBothPositionalAndKeywordArguments] |
| import typing |
| def f(a: 'A', b: 'B') -> None: pass |
| f(A(), b=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "B" |
| f(A(), b=B()) |
| class A: pass |
| class B: pass |
| |
| [case testContextSensitiveTypeInferenceForKeywordArg] |
| from typing import List |
| def f(a: 'A', b: 'List[A]') -> None: pass |
| f(b=[], a=A()) |
| class A: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testGivingArgumentAsPositionalAndKeywordArg] |
| import typing |
| def f(a: 'A', b: 'B' = None) -> None: pass |
| f(A(), a=A()) # E: "f" gets multiple values for keyword argument "a" |
| class A: pass |
| class B: pass |
| |
| [case testGivingArgumentAsPositionalAndKeywordArg2] |
| import typing |
| def f(a: 'A' = None, b: 'B' = None) -> None: pass |
| f(A(), a=A()) # E: "f" gets multiple values for keyword argument "a" |
| class A: pass |
| class B: pass |
| |
| [case testPositionalAndKeywordForSameArg] |
| # This used to crash in check_argument_count(). See #1095. |
| def f(a: int): pass |
| def g(): f(0, a=1) |
| [out] |
| |
| [case testInvalidKeywordArgument] |
| import typing |
| def f(a: 'A') -> None: pass # N: "f" defined here |
| f(b=object()) # E: Unexpected keyword argument "b" for "f" |
| class A: pass |
| |
| [case testKeywordMisspelling] |
| def f(other: 'A') -> None: pass # N: "f" defined here |
| f(otter=A()) # E: Unexpected keyword argument "otter" for "f"; did you mean "other"? |
| class A: pass |
| |
| [case testMultipleKeywordsForMisspelling] |
| def f(thing : 'A', other: 'A', atter: 'A', btter: 'B') -> None: pass # N: "f" defined here |
| f(otter=A()) # E: Unexpected keyword argument "otter" for "f"; did you mean "other" or "atter"? |
| class A: pass |
| class B: pass |
| |
| [case testKeywordMisspellingDifferentType] |
| def f(other: 'A') -> None: pass # N: "f" defined here |
| f(otter=B()) # E: Unexpected keyword argument "otter" for "f"; did you mean "other"? |
| class A: pass |
| class B: pass |
| |
| [case testKeywordMisspellingInheritance] |
| def f(atter: 'A', btter: 'B', ctter: 'C') -> None: pass # N: "f" defined here |
| f(otter=B()) # E: Unexpected keyword argument "otter" for "f"; did you mean "btter" or "atter"? |
| class A: pass |
| class B(A): pass |
| class C: pass |
| |
| [case testKeywordMisspellingFloatInt] |
| def f(atter: float, btter: int) -> None: pass # N: "f" defined here |
| x: int = 5 |
| f(otter=x) # E: Unexpected keyword argument "otter" for "f"; did you mean "btter" or "atter"? |
| |
| [case testKeywordMisspellingVarArgs] |
| def f(other: 'A', *atter: 'A') -> None: pass # N: "f" defined here |
| f(otter=A()) # E: Unexpected keyword argument "otter" for "f"; did you mean "other"? |
| class A: pass |
| [builtins fixtures/tuple.pyi] |
| |
| [case testKeywordMisspellingOnlyVarArgs] |
| def f(*other: 'A') -> None: pass # N: "f" defined here |
| f(otter=A()) # E: Unexpected keyword argument "otter" for "f" |
| class A: pass |
| [builtins fixtures/tuple.pyi] |
| |
| [case testKeywordMisspellingVarArgsDifferentTypes] |
| def f(other: 'B', *atter: 'A') -> None: pass # N: "f" defined here |
| f(otter=A()) # E: Unexpected keyword argument "otter" for "f"; did you mean "other"? |
| class A: pass |
| class B: pass |
| [builtins fixtures/tuple.pyi] |
| |
| [case testKeywordMisspellingVarKwargs] |
| def f(other: 'A', **atter: 'A') -> None: pass |
| f(otter=A()) # E: Missing positional argument "other" in call to "f" |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testKeywordArgumentsWithDynamicallyTypedCallable] |
| from typing import Any |
| f = None # type: Any |
| f(x=f(), z=None()) # E: "None" not callable |
| f(f, zz=None()) # E: "None" not callable |
| f(x=None) |
| |
| [case testKeywordArgumentWithFunctionObject] |
| from typing import Callable |
| f = None # type: Callable[[A, B], None] |
| f(a=A(), b=B()) |
| f(A(), b=B()) |
| class A: pass |
| class B: pass |
| [out] |
| main:3: error: Unexpected keyword argument "a" |
| main:3: error: Unexpected keyword argument "b" |
| main:4: error: Unexpected keyword argument "b" |
| |
| [case testKeywordOnlyArguments] |
| import typing |
| def f(a: 'A', *, b: 'B' = None) -> None: pass |
| def g(a: 'A', *, b: 'B') -> None: pass |
| def h(a: 'A', *, b: 'B', aa: 'A') -> None: pass |
| def i(a: 'A', *, b: 'B', aa: 'A' = None) -> None: pass |
| f(A(), b=B()) |
| f(b=B(), a=A()) |
| f(A()) |
| f(A(), B()) # E: Too many positional arguments for "f" |
| g(A(), b=B()) |
| g(b=B(), a=A()) |
| g(A()) # E: Missing named argument "b" for "g" |
| g(A(), B()) # E: Too many positional arguments for "g" |
| h(A()) # E: Missing named argument "b" for "h" # E: Missing named argument "aa" for "h" |
| h(A(), b=B()) # E: Missing named argument "aa" for "h" |
| h(A(), aa=A()) # E: Missing named argument "b" for "h" |
| h(A(), b=B(), aa=A()) |
| h(A(), aa=A(), b=B()) |
| i(A()) # E: Missing named argument "b" for "i" |
| i(A(), b=B()) |
| i(A(), aa=A()) # E: Missing named argument "b" for "i" |
| i(A(), b=B(), aa=A()) |
| i(A(), aa=A(), b=B()) |
| |
| class A: pass |
| class B: pass |
| |
| [case testKeywordOnlyArgumentsFastparse] |
| |
| import typing |
| def f(a: 'A', *, b: 'B' = None) -> None: pass |
| def g(a: 'A', *, b: 'B') -> None: pass |
| def h(a: 'A', *, b: 'B', aa: 'A') -> None: pass |
| def i(a: 'A', *, b: 'B', aa: 'A' = None) -> None: pass |
| f(A(), b=B()) |
| f(b=B(), a=A()) |
| f(A()) |
| f(A(), B()) # E: Too many positional arguments for "f" |
| g(A(), b=B()) |
| g(b=B(), a=A()) |
| g(A()) # E: Missing named argument "b" for "g" |
| g(A(), B()) # E: Too many positional arguments for "g" |
| h(A()) # E: Missing named argument "b" for "h" # E: Missing named argument "aa" for "h" |
| h(A(), b=B()) # E: Missing named argument "aa" for "h" |
| h(A(), aa=A()) # E: Missing named argument "b" for "h" |
| h(A(), b=B(), aa=A()) |
| h(A(), aa=A(), b=B()) |
| i(A()) # E: Missing named argument "b" for "i" |
| i(A(), b=B()) |
| i(A(), aa=A()) # E: Missing named argument "b" for "i" |
| i(A(), b=B(), aa=A()) |
| i(A(), aa=A(), b=B()) |
| |
| class A: pass |
| class B: pass |
| |
| [case testKwargsAfterBareArgs] |
| from typing import Tuple, Any |
| def f(a, *, b=None) -> None: pass |
| a = None # type: Any |
| b = None # type: Any |
| f(a, **b) |
| |
| [builtins fixtures/dict.pyi] |
| |
| [case testKeywordArgAfterVarArgs] |
| import typing |
| def f(*a: 'A', b: 'B' = None) -> None: pass |
| f() |
| f(A()) |
| f(A(), A()) |
| f(b=B()) |
| f(A(), b=B()) |
| f(A(), A(), b=B()) |
| f(B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A" |
| f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A" |
| f(b=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "Optional[B]" |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testKeywordArgAfterVarArgsWithBothCallerAndCalleeVarArgs] |
| from typing import List |
| def f(*a: 'A', b: 'B' = None) -> None: pass |
| a = None # type: List[A] |
| f(*a) |
| f(A(), *a) |
| f(b=B()) |
| f(*a, b=B()) |
| f(A(), *a, b=B()) |
| f(A(), B()) # E: Argument 2 to "f" has incompatible type "B"; expected "A" |
| f(A(), b=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "Optional[B]" |
| f(*a, b=A()) # E: Argument "b" to "f" has incompatible type "A"; expected "Optional[B]" |
| class A: pass |
| class B: pass |
| [builtins fixtures/list.pyi] |
| |
| [case testCallingDynamicallyTypedFunctionWithKeywordArgs] |
| import typing |
| def f(x, y=A()): pass |
| f(x=A(), y=A()) |
| f(y=A(), x=A()) |
| f(y=A()) # E: Missing positional argument "x" in call to "f" |
| f(A(), z=A()) # E: Unexpected keyword argument "z" for "f" |
| class A: pass |
| |
| [case testKwargsArgumentInFunctionBody] |
| from typing import Dict, Any |
| def f( **kwargs: 'A') -> None: |
| d1 = kwargs # type: Dict[str, A] |
| d2 = kwargs # type: Dict[A, Any] # E: Incompatible types in assignment (expression has type "Dict[str, A]", variable has type "Dict[A, Any]") |
| d3 = kwargs # type: Dict[Any, str] # E: Incompatible types in assignment (expression has type "Dict[str, A]", variable has type "Dict[Any, str]") |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testKwargsArgumentInFunctionBodyWithImplicitAny] |
| from typing import Dict, Any |
| def f(**kwargs) -> None: |
| d1 = kwargs # type: Dict[str, A] |
| d2 = kwargs # type: Dict[str, str] |
| d3 = kwargs # type: Dict[A, Any] # E: Incompatible types in assignment (expression has type "Dict[str, Any]", variable has type "Dict[A, Any]") |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| [out] |
| |
| [case testCallingFunctionThatAcceptsVarKwargs] |
| import typing |
| def f( **kwargs: 'A') -> None: pass |
| f() |
| f(x=A()) |
| f(y=A(), z=A()) |
| f(x=B()) # E: Argument "x" to "f" has incompatible type "B"; expected "A" |
| f(A()) # E: Too many arguments for "f" |
| # Perhaps a better message would be "Too many *positional* arguments..." |
| class A: pass |
| class B: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testCallingFunctionWithKeywordVarArgs] |
| from typing import Dict |
| def f( **kwargs: 'A') -> None: pass |
| d = None # type: Dict[str, A] |
| f(**d) |
| f(x=A(), **d) |
| d2 = None # type: Dict[str, B] |
| f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, B]"; expected "A" |
| f(x=A(), **d2) # E: Argument 2 to "f" has incompatible type "**Dict[str, B]"; expected "A" |
| class A: pass |
| class B: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testKwargsAllowedInDunderCall] |
| class Formatter: |
| def __call__(self, message: str, bold: bool = False) -> str: |
| pass |
| |
| formatter = Formatter() |
| formatter("test", bold=True) |
| reveal_type(formatter.__call__) # N: Revealed type is 'def (message: builtins.str, bold: builtins.bool =) -> builtins.str' |
| [builtins fixtures/bool.pyi] |
| [out] |
| |
| [case testKwargsAllowedInDunderCallKwOnly] |
| class Formatter: |
| def __call__(self, message: str, *, bold: bool = False) -> str: |
| pass |
| |
| formatter = Formatter() |
| formatter("test", bold=True) |
| reveal_type(formatter.__call__) # N: Revealed type is 'def (message: builtins.str, *, bold: builtins.bool =) -> builtins.str' |
| [builtins fixtures/bool.pyi] |
| [out] |
| |
| [case testPassingMappingForKeywordVarArg] |
| from typing import Mapping |
| def f(**kwargs: 'A') -> None: pass |
| b = None # type: Mapping |
| d = None # type: Mapping[A, A] |
| m = None # type: Mapping[str, A] |
| f(**d) # E: Keywords must be strings |
| f(**m) |
| f(**b) |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testPassingMappingSubclassForKeywordVarArg] |
| from typing import Mapping |
| class MappingSubclass(Mapping[str, str]): pass |
| def f(**kwargs: 'A') -> None: pass |
| d = None # type: MappingSubclass |
| f(**d) |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testInvalidTypeForKeywordVarArg] |
| from typing import Dict |
| def f(**kwargs: 'A') -> None: pass |
| d = None # type: Dict[A, A] |
| f(**d) # E: Keywords must be strings |
| f(**A()) # E: Argument after ** must be a mapping, not "A" |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testPassingKeywordVarArgsToNonVarArgsFunction] |
| from typing import Any, Dict |
| def f(a: 'A', b: 'B') -> None: pass |
| d = None # type: Dict[str, Any] |
| f(**d) |
| d2 = None # type: Dict[str, A] |
| f(**d2) # E: Argument 1 to "f" has incompatible type "**Dict[str, A]"; expected "B" |
| class A: pass |
| class B: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testBothKindsOfVarArgs] |
| from typing import Any, List, Dict |
| def f(a: 'A', b: 'A') -> None: pass |
| l = None # type: List[Any] |
| d = None # type: Dict[Any, Any] |
| f(*l, **d) |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testPassingMultipleKeywordVarArgs] |
| from typing import Any, Dict |
| def f1(a: 'A', b: 'A') -> None: pass |
| def f2(a: 'A') -> None: pass |
| def f3(a: 'A', **kwargs: 'A') -> None: pass |
| def f4(**kwargs: 'A') -> None: pass |
| d = None # type: Dict[Any, Any] |
| d2 = None # type: Dict[Any, Any] |
| f1(**d, **d2) |
| f2(**d, **d2) |
| f3(**d, **d2) |
| f4(**d, **d2) |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testPassingKeywordVarArgsToVarArgsOnlyFunction] |
| from typing import Any, Dict |
| def f(*args: 'A') -> None: pass |
| d = None # type: Dict[Any, Any] |
| f(**d) # E: Too many arguments for "f" |
| class A: pass |
| [builtins fixtures/dict.pyi] |
| |
| [case testKeywordArgumentAndCommentSignature] |
| import typing |
| def f(x): # type: (int) -> str # N: "f" defined here |
| pass |
| f(x='') # E: Argument "x" to "f" has incompatible type "str"; expected "int" |
| f(x=0) |
| f(y=0) # E: Unexpected keyword argument "y" for "f" |
| |
| [case testKeywordArgumentAndCommentSignature2] |
| import typing |
| class A: |
| def f(self, x): # type: (int) -> str # N: "f" of "A" defined here |
| pass |
| A().f(x='') # E: Argument "x" to "f" of "A" has incompatible type "str"; expected "int" |
| A().f(x=0) |
| A().f(y=0) # E: Unexpected keyword argument "y" for "f" of "A" |
| |
| [case testKeywordVarArgsAndCommentSignature] |
| import typing |
| def f(**kwargs): # type: (**int) -> None |
| pass |
| f(z=1) |
| f(x=1, y=1) |
| f(x='', y=1) # E: Argument "x" to "f" has incompatible type "str"; expected "int" |
| f(x=1, y='') # E: Argument "y" to "f" has incompatible type "str"; expected "int" |
| [builtins fixtures/dict.pyi] |
| |
| [case testCallsWithStars] |
| def f(a: int) -> None: |
| pass |
| |
| s = ('',) |
| f(*s) # E: Argument 1 to "f" has incompatible type "*Tuple[str]"; expected "int" |
| |
| a = {'': 0} |
| f(a) # E: Argument 1 to "f" has incompatible type "Dict[str, int]"; expected "int" |
| f(**a) # okay |
| |
| b = {'': ''} |
| f(b) # E: Argument 1 to "f" has incompatible type "Dict[str, str]"; expected "int" |
| f(**b) # E: Argument 1 to "f" has incompatible type "**Dict[str, str]"; expected "int" |
| |
| c = {0: 0} |
| f(**c) # E: Keywords must be strings |
| [builtins fixtures/dict.pyi] |
| |
| [case testCallStar2WithStar] |
| def f(**k): pass |
| f(*(1, 2)) # E: Too many arguments for "f" |
| [builtins fixtures/dict.pyi] |
| |
| [case testUnexpectedMethodKwargInNestedClass] |
| class A: |
| class B: |
| def __init__(self) -> None: # N: "B" defined here |
| pass |
| A.B(x=1) # E: Unexpected keyword argument "x" for "B" |
| |
| [case testUnexpectedMethodKwargFromOtherModule] |
| import m |
| m.A(x=1) |
| [file m.py] |
| 1+'asdf' |
| class A: |
| def __init__(self) -> None: |
| pass |
| [out] |
| -- Note that the messages appear "out of order" because the m.py:3 |
| -- message is really an attachment to the main:2 error and should be |
| -- reported with it. |
| tmp/m.py:1: error: Unsupported operand types for + ("int" and "str") |
| main:2: error: Unexpected keyword argument "x" for "A" |
| tmp/m.py:3: note: "A" defined here |
| |
| [case testStarArgsAndKwArgsSpecialCase] |
| from typing import Dict, Mapping |
| |
| def f(*vargs: int, **kwargs: object) -> None: |
| pass |
| |
| def g(arg: int = 0, **kwargs: object) -> None: |
| pass |
| |
| d = {} # type: Dict[str, object] |
| f(**d) |
| g(**d) # E: Argument 1 to "g" has incompatible type "**Dict[str, object]"; expected "int" |
| |
| m = {} # type: Mapping[str, object] |
| f(**m) |
| g(**m) # TODO: Should be an error |
| [builtins fixtures/dict.pyi] |