From 9408d3c7cc66588339cd0eb9382144eb6f29336c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 22 Apr 2016 17:32:15 -0700 Subject: [PATCH 1/4] Skip arg count checks for dynamic functions. --- mypy/checkexpr.py | 5 +++-- mypy/test/data/check-dynamic-typing.test | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index f1b8ebcaf54c..be2a464a3ee3 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -238,8 +238,9 @@ def check_call(self, callee: Type, args: List[Node], arg_types = self.infer_arg_types_in_context2( callee, args, arg_kinds, formal_to_actual) - self.check_argument_count(callee, arg_types, arg_kinds, - arg_names, formal_to_actual, context, self.msg) + if self.chk.typing_mode_full(): + self.check_argument_count(callee, arg_types, arg_kinds, + arg_names, formal_to_actual, context, self.msg) self.check_argument_types(arg_types, arg_kinds, callee, formal_to_actual, context, diff --git a/mypy/test/data/check-dynamic-typing.test b/mypy/test/data/check-dynamic-typing.test index 4c65fc912bb9..c58e1d57306c 100644 --- a/mypy/test/data/check-dynamic-typing.test +++ b/mypy/test/data/check-dynamic-typing.test @@ -655,3 +655,25 @@ class A(B): x() [out] main: note: In class "A": + + +-- Don't complain about too few/many arguments in dynamic functions +-- ---------------------------------------------------------------- + +[case testTooManyArgsInDynamic] +def f() -> None: pass +def g(): + f(1) # Silent +[out] + +[case testTooFewArgsInDynamic] +def f(a: int) -> None: pass +def g(): + f() # Silent +[out] + +[case testJustRightInDynamic] +def f(a: int) -> None: pass +def g(): + f('') # Silent +[out] From 1ddb04aa3aff6f0214d5571f6bf79cb79c857e76 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 22 Apr 2016 17:46:23 -0700 Subject: [PATCH 2/4] Also check arg count in weak mode. --- mypy/checkexpr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index be2a464a3ee3..5686cf087d08 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -238,7 +238,7 @@ def check_call(self, callee: Type, args: List[Node], arg_types = self.infer_arg_types_in_context2( callee, args, arg_kinds, formal_to_actual) - if self.chk.typing_mode_full(): + if not self.chk.typing_mode_none(): self.check_argument_count(callee, arg_types, arg_kinds, arg_names, formal_to_actual, context, self.msg) From 55ba0ed78f6236ccd96cfebde58b934d70510b24 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 25 Apr 2016 09:46:51 -0700 Subject: [PATCH 3/4] Do it differently, per Jukka's suggestion. --- mypy/checkexpr.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 5686cf087d08..d630f4d76620 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -132,11 +132,7 @@ def visit_call_expr(self, e: CallExpr) -> Type: # It's really a special form that only looks like a call. return self.accept(e.analyzed, self.chk.type_context[-1]) self.try_infer_partial_type(e) - self.accept(e.callee) - # Access callee type directly, since accept may return the Any type - # even if the type is known (in a dynamically typed function). This - # way we get a more precise callee in dynamically typed functions. - callee_type = self.chk.type_map[e.callee] + callee_type = self.accept(e.callee) if (self.chk.disallow_untyped_calls and self.chk.typing_mode_full() and isinstance(callee_type, CallableType) @@ -238,9 +234,8 @@ def check_call(self, callee: Type, args: List[Node], arg_types = self.infer_arg_types_in_context2( callee, args, arg_kinds, formal_to_actual) - if not self.chk.typing_mode_none(): - self.check_argument_count(callee, arg_types, arg_kinds, - arg_names, formal_to_actual, context, self.msg) + self.check_argument_count(callee, arg_types, arg_kinds, + arg_names, formal_to_actual, context, self.msg) self.check_argument_types(arg_types, arg_kinds, callee, formal_to_actual, context, From 1d4ac92a91c202a119b807919dd07ba52205c894 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 25 Apr 2016 10:02:58 -0700 Subject: [PATCH 4/4] Fix tests run by testtypegen (less checking means different types). --- mypy/test/data/typexport-basic.test | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mypy/test/data/typexport-basic.test b/mypy/test/data/typexport-basic.test index 643fc2dab47d..b284a35cdc1e 100644 --- a/mypy/test/data/typexport-basic.test +++ b/mypy/test/data/typexport-basic.test @@ -510,7 +510,7 @@ def f(): def g(a: object) -> object: pass o = None # type: object [out] -CallExpr(3) : builtins.object +CallExpr(3) : Any NameExpr(3) : def (a: builtins.object) -> builtins.object NameExpr(3) : builtins.object @@ -549,8 +549,8 @@ def f(): A() class A(Generic[T]): pass [out] -CallExpr(4) : A[Any] -NameExpr(4) : def () -> A[Any] +CallExpr(4) : Any +NameExpr(4) : def [T] () -> A[T`-1] [case testGenericCallInDynamicallyTypedFunction2] from typing import TypeVar, Generic @@ -560,8 +560,8 @@ def f(): class A(Generic[T]): def __init__(self, x: T) -> None: pass [out] -CallExpr(4) : A[Any] -NameExpr(4) : def (x: Any) -> A[Any] +CallExpr(4) : Any +NameExpr(4) : def [T] (x: T`-1) -> A[T`-1] NameExpr(4) : def () -> Any [case testGenericCallInDynamicallyTypedFunction3] @@ -572,7 +572,7 @@ def f(): def g(x: t) -> t: pass [out] CallExpr(4) : Any -NameExpr(4) : def (x: Any) -> Any +NameExpr(4) : def [t] (x: t`-1) -> t`-1 -- Generic types and type inference