python / python/mypy

Mypy doesn't seem to use types from @overload-ed __sub__

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

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

bug topic-overloads
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ả

Bug Report

The __sub__ method on the Arrow class from the arrow package has several @overloads:

@overload
def __sub__(self, other: Union[timedelta, relativedelta]) -> "Arrow":
    pass  # pragma: no cover

@overload
def __sub__(self, other: Union[dt_datetime, "Arrow"]) -> timedelta:
    pass  # pragma: no cover

def __sub__(self, other: Any) -> Union[timedelta, "Arrow"]:

    if isinstance(other, (timedelta, relativedelta)):
        return self.fromdatetime(self._datetime - other, self._datetime.tzinfo)

    elif isinstance(other, dt_datetime):
        return self._datetime - other

    elif isinstance(other, Arrow):
        return self._datetime - other._datetime

    return NotImplemented

In particular, one Arrow object minus another Arrow object will always yield a timedelta. However, it seems mypy does not see this, and mistakes the type for Arrow.

To Reproduce

I discovered the issue when finding the time diff between two arrow timestamps:

import arrow

a1 = arrow.get()
a2 = arrow.get()

diff = a2 - a1
print(diff.total_seconds())

Which, when run with mypy yields:

$ mypy test.py
test.py:6: error: "int" not callable
Found 1 error in 1 file (checked 1 source file)

Setting the type explicitly reviles that mypy thinks the type is Arrow, and not timedelta:

from datetime import timedelta
import arrow

a1 = arrow.get()
a2 = arrow.get()

diff: timedelta = a2 - a1
print(diff.total_seconds())

Running mypy:

$ mypy test.py
test.py:7: error: Incompatible types in assignment (expression has type "Arrow", variable has type "timedelta")
Found 1 error in 1 file (checked 1 source file)

Expected Behavior

The second @overload on Arrow's __sub__ method specifies that the diff of two Arrow objects is a timedelta. There should be no type error assigning that to a timedelta variable.

Actual Behavior

Mypy mistakenly thinks the diff is Arrow, which creates a false positive.

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.9.6
  • Operating system and version: Mac OS 11.6 (Big Sur)

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.

Hướng nghiên cứu

Bắt đầu bằng cách tái hiện lỗi suy luận được báo cáo bằng đoạn mã Python và môi trường mypy 0.910 đã nêu. Đọc các khai báo overload trong arrow/arrow.py, sau đó lần theo cách mypy xử lý lời gọi sub bị overload; được xem là hoàn tất khi Arrow trừ Arrow được suy luận là timedelta và phép gán được nêu cùng các lời gọi total_seconds() vượt qua kiểm tra kiểu.

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
tooling
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
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
35/100

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.