-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Confusing behavior when subclassing a generic type #4148
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I think that |
IIUC the problem is that the actual implementation is not generic (because of the metaclass conflict). @marienz There are two possible solutions, one is the one you found with if TYPE_CHECKING:
class _WrappedText(urwid.WidgetWrap[urwid.Text]):
pass
else:
_WrappedText = urwid.WidgetWrap
class WrappedText(_WrappedText):
# actual implementation
... The second option is to somehow play with metaclasses: from typing import GenericMeta
class AdvWrapperMeta(GenericMeta, WrapperMeta):
pass and then use explicit @gvanrossum I am going to post the updated version of PEP 560 (implementing suggestions form python-ideas) very soon. Everyone seems to be supportive, so I hope that PEP 560 can be accepted and merged soon, and we can move forward with corresponding changes to |
I am supportive of PEP 560 too!
|
Thanks! I'll stick to a variant of the |
I'm trying to use mypy with Urwid, and ran into something I can't quite get to work. I'm not sure if this is a bug, a missing feature, or me expecting too much magic.
Urwid provides a hierarchy of Widget classes. One of them is WidgetWrap: it wraps a widget, exposes the wrapped widget as
self._w
, and forwards the methods of the Widget base class to the wrapped widget. It is intended to be subclassed, with the subclass methods accessing the wrapped widget but keeping it hidden from other code.I'm writing an application that uses Urwid, so I can't change Urwid itself.
With an
urwid.pyi
of:and some example code:
I want mypy to catch the two calls to
no_such_method
.Mypy 0.540 catches the first one, but not the second one:
So when instantiating WidgetWrap directly, mypy correctly infers the type of
_w
, and catches the call to a nonexistent method. But when subclassing WidgetWrap, the type for_w
is Any (this surprises me: I was at least expecting the bound of Widget to apply), so it cannot detect the subclass doing something wrong.I tried to work around this by explicit use of Generic in my code, not just in the .pyi stub:
This works great with mypy, but runs afoul of python/typing#449 (Urwid uses metaclasses internally, so mixing in Generic triggers a metaclass conflict).
I found a workaround for that, but it's a bit ugly:
This works at runtime and seems to work with mypy.
Is there a neat way of dealing with this class I'm overlooking? And is the different behaviour from mypy when a subclass passes fixed arguments to the superclass
__init__
versus directly instantiating the class expected?The text was updated successfully, but these errors were encountered: