python / python/mypy

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

Ouverte
#11,613 6 commentaires 6 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

bug topic-overloads
Langage dominant
Python
Étoiles
20.6k
Forks
3.3k
Métriques de merge des PR
Métriques de PR en attente

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)

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par reproduire l’erreur d’inférence signalée avec l’extrait Python et l’environnement mypy 0.910 indiqué. Lisez les déclarations de surcharge dans arrow/arrow.py, puis suivez le traitement par mypy de l’appel surchargé à sub ; le travail est terminé lorsque Arrow moins Arrow est inféré comme timedelta et que l’affectation présentée ainsi que les appels à total_seconds() passent la vérification de typage.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
tooling
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.