How to use typing.Never to indicate a subclass method with zero arguments cannot be called?
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 20.6k
- Fork
- 3.3k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
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?
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách tái hiện ví dụ Base/Sub được cung cấp với mypy 1.0.0 và so sánh các chẩn đoán cho foo và goo với hành vi Never dự kiến. Công việc hoàn tất khi một phương thức của lớp con không có đối số có thể được khai báo là không thể gọi mà không cần type: ignore, và override của goo được xử lý nhất quán với quy tắc thay thế Liskov.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- compilers
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 30/100