Mypy doesn't seem to use types from @overload-ed __sub__
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
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)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the reported inference error with the Python snippet and the stated mypy 0.910 environment. Read the overload declarations in arrow/arrow.py, then trace mypy's handling of the overloaded sub call; done means Arrow minus Arrow is inferred as timedelta and the shown assignment and total_seconds() calls type-check.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100