Skip to content

Commit

Permalink
Make any callable compatible with (*args: Any, **kwargs: Any) (#11203)
Browse files Browse the repository at this point in the history
Resolves #5876

Co-authored-by: hauntsaninja <>
Co-authored-by: Ivan Levkivskyi <levkivskyi@gmail.com>
  • Loading branch information
hauntsaninja and ilevkivskyi committed Aug 13, 2022
1 parent 52f1dd3 commit a0e2a2d
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
12 changes: 12 additions & 0 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# Circular import; done in the function instead.
# import mypy.solve
from mypy.nodes import (
ARG_STAR,
ARG_STAR2,
CONTRAVARIANT,
COVARIANT,
Decorator,
Expand Down Expand Up @@ -1291,6 +1293,16 @@ def are_parameters_compatible(
right_star = right.var_arg()
right_star2 = right.kw_arg()

# Treat "def _(*a: Any, **kw: Any) -> X" similarly to "Callable[..., X]"
if (
right.arg_kinds == [ARG_STAR, ARG_STAR2]
and right_star
and isinstance(get_proper_type(right_star.typ), AnyType)
and right_star2
and isinstance(get_proper_type(right_star2.typ), AnyType)
):
return True

# Match up corresponding arguments and check them for compatibility. In
# every pair (argL, argR) of corresponding arguments from L and R, argL must
# be "more general" than argR if L is to be a subtype of R.
Expand Down
10 changes: 10 additions & 0 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -7136,6 +7136,16 @@ class B(A): # E: Final class __main__.B has abstract attributes "foo"
class C:
class C1(XX): pass # E: Name "XX" is not defined

[case testArgsKwargsInheritance]
from typing import Any

class A(object):
def f(self, *args: Any, **kwargs: Any) -> int: ...

class B(A):
def f(self, x: int) -> int: ...
[builtins fixtures/dict.pyi]

[case testClassScopeImports]
class Foo:
from mod import plain_function # E: Unsupported class scoped import
Expand Down
6 changes: 3 additions & 3 deletions test-data/unit/check-functions.test
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ if int():
ee_var = everywhere

if int():
ee_var = specific_1 # The difference between Callable[..., blah] and one with a *args: Any, **kwargs: Any is that the ... goes loosely both ways.
ee_var = specific_1
if int():
ee_def = specific_1 # E: Incompatible types in assignment (expression has type "Callable[[int, str], None]", variable has type "Callable[[VarArg(Any), KwArg(Any)], None]")
ee_def = specific_1

[builtins fixtures/dict.pyi]

Expand Down Expand Up @@ -1787,7 +1787,7 @@ def f2(*args, **kwargs) -> int: pass
d(f1)
e(f2)
d(f2)
e(f1) # E: Argument 1 to "e" has incompatible type "Callable[[VarArg(Any)], int]"; expected "Callable[[VarArg(Any), KwArg(Any)], int]"
e(f1)

[builtins fixtures/dict.pyi]

Expand Down
6 changes: 3 additions & 3 deletions test-data/unit/check-modules.test
Original file line number Diff line number Diff line change
Expand Up @@ -3160,7 +3160,7 @@ from test1 import aaaa # E: Module "test1" has no attribute "aaaa"
import b
[file a.py]
class Foo:
def frobnicate(self, *args, **kwargs): pass
def frobnicate(self, x, *args, **kwargs): pass
[file b.py]
from a import Foo
class Bar(Foo):
Expand All @@ -3178,12 +3178,12 @@ class Bar(Foo):
[out1]
tmp/b.py:3: error: Signature of "frobnicate" incompatible with supertype "Foo"
tmp/b.py:3: note: Superclass:
tmp/b.py:3: note: def frobnicate(self, *args: Any, **kwargs: Any) -> Any
tmp/b.py:3: note: def frobnicate(self, x: Any, *args: Any, **kwargs: Any) -> Any
tmp/b.py:3: note: Subclass:
tmp/b.py:3: note: def frobnicate(self) -> None
[out2]
tmp/b.py:3: error: Signature of "frobnicate" incompatible with supertype "Foo"
tmp/b.py:3: note: Superclass:
tmp/b.py:3: note: def frobnicate(self, *args: Any, **kwargs: Any) -> Any
tmp/b.py:3: note: def frobnicate(self, x: Any, *args: Any, **kwargs: Any) -> Any
tmp/b.py:3: note: Subclass:
tmp/b.py:3: note: def frobnicate(self, *args: Any) -> None

0 comments on commit a0e2a2d

Please sign in to comment.