-- 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 testGivingSameKeywordArgumentTwice]
import typing
def f(a: 'A', b: 'B') -> None: pass
f(a=A(), b=B(), a=A()) # E: keyword argument repeated
class A: pass
class B: pass

[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 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__)  # E: 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__)  # E: 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 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
