You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
mypy fails to consider the case where *args or **kwds contains zero elements #4001
Too many arguments for "object"
Too many arguments for "object"
I think this is valid code and should pass the type check.
Context: I encountered this when I tried to write a multiple inheritance model where each class is passing arguments to the next parent (in terms of MRO):
classA(object):
def__init__(self, a_arg: int, **kwds: Any) ->None:
super().__init__(**kwds)
classB(object):
def__init__(self, b_arg: int, **kwds: Any) ->None:
super().__init__(**kwds)
classC(A, B):
def__init__(self, c_arg: int, **kwds: Any) ->None:
super().__init__(**kwds)
C(a_arg=1, b_arg=2, c_arg=3)
# This code runs fine but gives three type errors saying:# Too many arguments for "__init__" of "object"
You cannot expect a static derivation order due to the dynamic nature of MRO, so it's hard to avoid this error from happening.
While your minimal repro indeed gives those errors (and probably shouldn't), in your actual example things are not so simple -- mypy only looks at your source code, it doesn't execute your code, so when it type-checks the line super().__init__(**kwds) in your full example it can't actually assume that the argument list for object() is empty -- this depends on the call site, and while you show a call that would indeed result in an empty argument list, there may be other calls to C() that end up passing a non-empty kwds to object(). Mypy type-checks calls purely on the basis of the given signature, and the signature for C() says that any keyword arguments are accepted.
Hi, I'd like to work on this as my first issue and I have a question.
Current implementation requires the type of kwargs in **kwargs to be a subtype of dict[str, <any>].
However, an empty dictionary {} is currently typed as dict[<nothing>, <nothing>] and fails this check, presumably because dictionary types are contravariant at the key position. Would it be better to type {} as dict[<any>, <nothing>] ?
I think it's difficult to judge whether a given dictionary is empty or not, so we cannot help but give up the "Too many arguments" check whenever there are arguments like **kwds (i.e. the third line of the following should not raise error)
def f(): pass
f(**{}) # ok
f(**{'a':0}) # this should also be okay (false-negative)
This is consistent with the case of lists and variable-length tuples:
def f(): pass
f(*[]) # ok
f(*[1]) # also ok
x: Tuple[int, ...] = ()
f(*x) # ok
At first I thought we can take advantage of the fact that an empty dictionary is typed as dict[<nothing>, <nothing>], but that will contradict with this solution (#5580 (comment)) on fixing the incorrect type checking on ** arguments...
Activity
gvanrossum commentedon Sep 25, 2017
While your minimal repro indeed gives those errors (and probably shouldn't), in your actual example things are not so simple -- mypy only looks at your source code, it doesn't execute your code, so when it type-checks the line
super().__init__(**kwds)in your full example it can't actually assume that the argument list forobject()is empty -- this depends on the call site, and while you show a call that would indeed result in an empty argument list, there may be other calls toC()that end up passing a non-emptykwdstoobject(). Mypy type-checks calls purely on the basis of the given signature, and the signature forC()says that any keyword arguments are accepted.astrojuanlu commentedon Feb 8, 2018
Is this related to #4335?
gvanrossum commentedon Feb 9, 2018
@Juanlu001
I don't see how. Maybe you mistyped the issue number? #4335 is about multiple inheritance. This issue is about varargs function calls.
astrojuanlu commentedon Feb 9, 2018
I was confused because the original example in this issue used multiple inheritance as well.
ilevkivskyi commentedon Sep 27, 2019
The first example
object(*[])now works correctly, second one still fails. Should be probably not hard to fix.momohatt commentedon Mar 22, 2020
Hi, I'd like to work on this as my first issue and I have a question.
Current implementation requires the type of
kwargsin**kwargsto be a subtype ofdict[str, <any>].mypy/mypy/checkexpr.py
Lines 3790 to 3795 in 1677efd
However, an empty dictionary
{}is currently typed asdict[<nothing>, <nothing>]and fails this check, presumably because dictionary types are contravariant at the key position. Would it be better to type{}asdict[<any>, <nothing>]?EDIT: I think #5580 is the same problem as this
NeilGirdhar commentedon May 4, 2020
This issue is explained with
__init__, but the same problem happens when calling super in other methods like__init_subclass__.momohatt commentedon Oct 22, 2020
I think it's difficult to judge whether a given dictionary is empty or not, so we cannot help but give up the "Too many arguments" check whenever there are arguments like
**kwds(i.e. the third line of the following should not raise error)This is consistent with the case of lists and variable-length tuples:
At first I thought we can take advantage of the fact that an empty dictionary is typed as
dict[<nothing>, <nothing>], but that will contradict with this solution (#5580 (comment)) on fixing the incorrect type checking on**arguments...Fix argument checking on empty dict with double stars (#9629)