Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Feature
If you have a subclass that has a method defined in the superclass, but in the subclass should never get called, you should be able to declare self to have type Never.
Pitch
Let's suppose I have a base class Base with a method foo(), and a subclass Sub that raises an Exception if foo() is called. I'd like it so that the type checker flags an error on Sub.foo(), but not Base.foo(), so I tried this:
fromtyping_extensionsimportNeverclassBase: def__init__(self): passdeffoo(self) ->None: print("foo") defgoo(self, x: int) ->None; print("goo ", x) classSub(Base): deffoo(self: Never) ->None: raiseException("never") defgoo(self, x: Never) ->None: raiseException("never") x=Sub() x.foo() x.goo(3)With mypy 1.0.0 and python 3.10, I get the following:
neversub.py:16: error: The erased type of self "<nothing>" is not a supertype of its class "neversub.Sub" [misc] neversub.py:19: error: Argument 1 of "goo" is incompatible with supertype "Base"; supertype defines the argument type as "int" [override] neversub.py:19: note: This violates the Liskov substitution principle neversub.py:19: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides neversub.py:24: error: Invalid self argument "Sub" to attribute function "foo" with type "Callable[[NoReturn], None]" [misc] neversub.py:25: error: Argument 1 to "goo" of "Sub" has incompatible type "int"; expected "NoReturn" [arg-type] The last two errors are exactly what I want. But while the first error makes sense, aside from using a # type: ignore, I'm not sure how this should be declared to avoid having to use # type: ignore. In other words, what is the right way to indicate that a method with zero parameters is not valid to call in a subclass? Secondly, shouldn't the declaration of goo be considered as not violating the Liskov substitution principle based on how typing.Never is supposed to work?
I should note that with the method goo(), since it has a required argument, I can use the Never declaration to show that this is invalid. What's not clear is how do you indicate that a method with no arguments is invalid without having to use # type: ignore ?
I think this is a valid use of Never, and Eric Traut from pyright agrees: microsoft/pyright#4653 (comment)
Could mypy do the same?