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
Multiple inheritance triggers issues that cannot be resolved #4335
When using multiple inheritance, the mixing of arguments to different base classes triggers warnings that cannot be resolved.
from typing import Any, Dict, Optional, Sequence, Tuple
class BaseClass(object):
def __init__(self, foo: str, *args: Sequence[Any], **kwargs: Dict[str, Any]) -> None:
self.foo = foo
super().__init__(*args, **kwargs)
class Mixin(object):
def __init__(self, bar: str, baz: Optional[str]=None, *args: Sequence[Any], **kwargs: Dict[str, Any]) -> None:
self.bar = bar
self.baz = baz or 'baz2'
super().__init__(*args, **kwargs)
class Derived(BaseClass, Mixin):
def __init__(self, foo: str, bar: str, other: str, *args: Sequence[Any], **kwargs: Dict[str, Any]) -> None:
self.other = other
super().__init__(foo=foo, bar=bar, *args, **kwargs)
d = Derived('foo', 'bar', 'other')
print(d.foo)
print(d.bar)
print(d.other)
print(d.baz)
% python3.6 test.py
foo
bar
other
baz2
% mypy test.py
test.py:7: error: Too many arguments for "__init__" of "object"
test.py:13: error: Too many arguments for "__init__" of "object"
test.py:18: error: "__init__" of "BaseClass" gets multiple values for keyword argument "foo"
test.py:18: error: Argument 1 to "__init__" of "BaseClass" has incompatible type *Tuple[Sequence[Any], ...]; expected "str"
test.py:18: error: Argument 4 to "__init__" of "BaseClass" has incompatible type **Dict[str, Dict[str, Any]]; expected "str"
test.py:18: error: Argument 4 to "__init__" of "BaseClass" has incompatible type **Dict[str, Dict[str, Any]]; expected Sequence[Any]
test.py:18: error: Argument 3 to "__init__" of "BaseClass" has incompatible type "str"; expected Dict[str, Any]
Running on 0.560 and fixing the *arg and **kwarg types gives
classtest.py:6: error: Too many arguments for "__init__" of "object"
classtest.py:12: error: Too many arguments for "__init__" of "object"
classtest.py:17: error: "__init__" of "BaseClass" gets multiple values for keyword argument "foo"
It appears mypy is passing all of the arguments to BaseClass and some arguments to Mixin?
It's not specific to classes; the super call arguments are just passed to the first base class (which statically is the best thing to do, though not sound). The first two errors are because object() doesn't take arguments. The latter seems a bug that I can repro like this:
deff(foo: str, bar: str) ->None:
passdefg() ->None:
args: tuplef(foo='', *args) # E: "f" gets multiple values for keyword argument "foo"
I think I've seen this before; there's something wrong with the way *args is checked in a call.
In fact, it's just the usual error from following a keyword arg with a positional arg. As f requires a second argument, invoking g will always cause an error, so mypy's behavior is correct. Do I understand?
Similarly, the error above is indicating that passing a fourth argument to the Derived constructor results in a TypeError. The way to resolve the error is to not pass *args to super in Derived (demonstration).
Any workaround we can use while waiting for a fix?
I think # type: ignore is your best bet here. (You can also mention an issue number to remember why you need it, like this ... # type: ignore # mypy issue 4335.)
Activity
gvanrossum commentedon Dec 7, 2017
Please start by changing the type of all your
**kwdsto**kwds: Any; that's your first mistake.emmatyping commentedon Dec 17, 2017
Running on 0.560 and fixing the
*argand**kwargtypes givesIt appears mypy is passing all of the arguments to
BaseClassand some arguments to Mixin?gvanrossum commentedon Dec 17, 2017
It's not specific to classes; the super call arguments are just passed to the first base class (which statically is the best thing to do, though not sound). The first two errors are because object() doesn't take arguments. The latter seems a bug that I can repro like this:
I think I've seen this before; there's something wrong with the way
*argsis checked in a call.ilevkivskyi commentedon Dec 18, 2017
@gvanrossum Yes, I also have seen this. I think this may be a bug in
map_actuals_to_formals, but I didn't investigate it in depth.elliott-beach commentedon Dec 30, 2017
@gvanrossum's repro gives the same error on
python3 test.py, if you actually callg.This is my test.py:
In fact, it's just the usual error from following a keyword arg with a positional arg. As
frequires a second argument, invokinggwill always cause an error, so mypy's behavior is correct. Do I understand?Similarly, the error above is indicating that passing a fourth argument to the
Derivedconstructor results in a TypeError. The way to resolve the error is to not pass*argsto super in Derived (demonstration).As such I don't think there's a real issue here.
gvanrossum commentedon Dec 30, 2017
Ah, yes. That example gives a similar error when executed:
ilevkivskyi commentedon Jan 3, 2018
But the original code fails in mypy while it works at runtime. Here is the repro with obvious errors fixed:
astrojuanlu commentedon Feb 8, 2018
Any workaround we can use while waiting for a fix?
ilevkivskyi commentedon Feb 8, 2018
I think
# type: ignoreis your best bet here. (You can also mention an issue number to remember why you need it, like this... # type: ignore # mypy issue 4335.)Allow super() for mixin protocols (#14082)