How to use typing.Never to indicate a subclass method with zero arguments cannot be called?
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 20.6k
- Forks
- 3.3k
- Métriques de merge des PR
- Métriques de PR en attente
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:
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?
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par reproduire l’exemple Base/Sub fourni avec mypy 1.0.0 et comparez les diagnostics pour foo et goo avec le comportement attendu de Never. Le travail est terminé lorsqu’une méthode de sous-classe sans argument peut être déclarée comme non appelable sans type: ignore et que la redéfinition de goo est traitée de manière cohérente avec la règle de substitution de Liskov.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- python
- Domaine
- compilers
- Type d'issue
- Fonctionnalité
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 30/100