How to use typing.Never to indicate a subclass method with zero arguments cannot be called?
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
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:
from typing_extensions import Never
class Base:
def __init__(self):
pass
def foo(self) -> None:
print("foo")
def goo(self, x: int) -> None;
print("goo ", x)
class Sub(Base):
def foo(self: Never) -> None:
raise Exception("never")
def goo(self, x: Never) -> None:
raise Exception("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: https://github.com/microsoft/pyright/issues/4653#issuecomment-1434851320
Could mypy do the same?
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne damit, das bereitgestellte Base/Sub-Beispiel mit mypy 1.0.0 zu reproduzieren und die Diagnosen für foo und goo mit dem beabsichtigten Never-Verhalten zu vergleichen. Die Arbeit ist abgeschlossen, wenn eine parameterlose Methode einer Unterklasse als nicht aufrufbar deklariert werden kann, ohne ein type: ignore zu verwenden, und das goo-Override konsistent mit der Liskov-Substitutionsregel behandelt wird.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- compilers
- Issue-Typ
- Feature
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 30/100