Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,7 @@ def check_call(
callee, args, arg_kinds, arg_names, callable_name, object_type, context
)
elif isinstance(callee, AnyType) or not self.chk.in_checked_function():
return self.check_any_type_call(args, callee)
return self.check_any_type_call(args, arg_kinds, callee, context)
elif isinstance(callee, UnionType):
return self.check_union_call(callee, args, arg_kinds, arg_names, context)
elif isinstance(callee, Instance):
Expand Down Expand Up @@ -2495,6 +2495,19 @@ def missing_classvar_callable_note(
context,
)

def check_var_args_kwargs(
self, arg_types: list[Type], arg_kinds: list[ArgKind], context: Context
) -> None:
for arg_type, arg_kind in zip(arg_types, arg_kinds):
arg_type = get_proper_type(arg_type)
if arg_kind == nodes.ARG_STAR and not self.is_valid_var_arg(arg_type):
self.msg.invalid_var_arg(arg_type, context)
if arg_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(arg_type):
is_mapping = is_subtype(
arg_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
)
self.msg.invalid_keyword_var_arg(arg_type, is_mapping, context)

def check_argument_types(
self,
arg_types: list[Type],
Expand All @@ -2512,20 +2525,12 @@ def check_argument_types(

The check_call docstring describes some of the arguments.
"""
self.check_var_args_kwargs(arg_types, arg_kinds, context)

check_arg = check_arg or self.check_arg
# Keep track of consumed tuple *arg items.
mapper = ArgTypeExpander(self.argument_infer_context())

for arg_type, arg_kind in zip(arg_types, arg_kinds):
arg_type = get_proper_type(arg_type)
if arg_kind == nodes.ARG_STAR and not self.is_valid_var_arg(arg_type):
self.msg.invalid_var_arg(arg_type, context)
if arg_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(arg_type):
is_mapping = is_subtype(
arg_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
)
self.msg.invalid_keyword_var_arg(arg_type, is_mapping, context)

for i, actuals in enumerate(formal_to_actual):
orig_callee_arg_type = get_proper_type(callee.arg_types[i])

Expand Down Expand Up @@ -3297,8 +3302,12 @@ def apply_generic_arguments(
skip_unsatisfied=skip_unsatisfied,
)

def check_any_type_call(self, args: list[Expression], callee: Type) -> tuple[Type, Type]:
self.infer_arg_types_in_empty_context(args)
def check_any_type_call(
self, args: list[Expression], arg_kinds: list[ArgKind], callee: Type, context: Context
) -> tuple[Type, Type]:
arg_types = self.infer_arg_types_in_empty_context(args)
self.check_var_args_kwargs(arg_types, arg_kinds, context)

callee = get_proper_type(callee)
if isinstance(callee, AnyType):
return (
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -7688,7 +7688,7 @@ class A(thing=5):
pass
[out]
main:1: error: Unexpected keyword argument "thing" for "__init_subclass__" of "object"
tmp/builtins.pyi:5: note: "__init_subclass__" of "object" defined here
tmp/builtins.pyi:6: note: "__init_subclass__" of "object" defined here
[builtins fixtures/object_with_init_subclass.pyi]

[case testInitSubclassWithImports]
Expand Down
3 changes: 3 additions & 0 deletions test-data/unit/check-kwargs.test
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,9 @@ f(**kwargs) # E: Argument after ** must be a mapping, not "Any | None"

def g(a: int) -> None: pass
g(a=1, **4) # E: Argument after ** must be a mapping, not "int"

def main(f: Any) -> None:
f(**3) # E: Argument after ** must be a mapping, not "int"
[builtins fixtures/dict.pyi]

[case testPassingKeywordVarArgsToNonVarArgsFunction]
Expand Down
6 changes: 6 additions & 0 deletions test-data/unit/check-varargs.test
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ f(a, *(b, cc))
[builtins fixtures/tuple.pyi]

[case testInvalidVarArg]
from typing import Any

def f(a: 'A') -> None:
pass

Expand All @@ -291,6 +293,10 @@ f(*(a,))

f(*4) # E: Expected iterable as variadic argument
f(a, *4) # E: Expected iterable as variadic argument

def main(f: Any) -> None:
f(*3) # E: Expected iterable as variadic argument

[builtins fixtures/tuple.pyi]


Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/object_with_init_subclass.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _typeshed
from typing import Sequence, Iterator, TypeVar, Mapping, Iterable, Optional, Union, overload, Tuple, Generic, List

class object:
Expand Down