Wrapped methods are not properly resolved until after the class definition

Đang mở
#16,397 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
35/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
python
Lĩnh vực
tooling

Hướng nghiên cứu

Tái hiện false negative và false positive trong main.py bằng các ví dụ mypy-play được liên kết, đồng thời so sánh vị trí của function, @wrapper và @property. Theo dõi cách decorator và kiểu của wrapped method được phân giải trước và sau class Impl; hoàn thành khi cả hai biến thể đều nhất quán báo cáo các chẩn đoán tương thích protocol như mong đợi.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug

Context & setup

Consider the following simple protocol:

class Proto(Protocol):
    @property
    def f(self) -> int:
        ...

One can implement this protocol wrongly as follows:

T = TypeVar("T")
P = ParamSpec("P")


def wrapper(f: Callable[P, T]) -> Callable[P, str]:
    def wrapped(*args: P.args, **kwargs: P.kwargs) -> str:
        return 0

    return wrapped

class Impl:
    @wrapper  # converts return type from `bool` to `str`, while the protocol expects `int`
    def f(self) -> bool:
        return False

# error: Incompatible return value type (got "Impl", expected "Proto")  [return-value]
# note: Following member(s) of "Impl" have conflicts:
# note:     Expected:
# note:         def f(self) -> int
# note:     Got:
# note:         def f(self) -> str
def b() -> Proto:
    return Impl()

The bug (false negative)

When this same function b is placed before class Impl, mypy does not report an error. Adding reveal_type(Impl.f) before and after the class definition hints at what is going on:

main.py:21: error: Expression has type "Any"  [misc]
main.py:21: error: Cannot determine type of "f"  [has-type]
main.py:21: note: Revealed type is "Any"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:28: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

If f is not decorated but explicitly returns str, one gets

main.py:21: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"
main.py:21: error: Name "Impl" is used before definition  [used-before-def]

main.py:27: note: Revealed type is "def (self: __main__.Impl) -> builtins.str"

as expected. This indicates that the wrapped decorator is only properly resolved for code after the class definition.

False positive variant

If f is decorated with @property, this can also produce false positives. This is how I encountered the issue in the first place. Playground.

Additional info

Python: 3.11
Mypy: 371219347a6d17e16924bbabf3e693c6874e7138
Flags: --strict --disallow-any-*

Ngôn ngữ chính
Python
Star
20.6k
Fork
3.3k
Merge trung bình
1 ngày 18 giờ
Pull request đã merge (30 ngày)
54

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của python/mypy

Tất cả issue của python/mypy

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.