python / python/mypy

type inference is fragile for protocols like SupportsKeysAndGetItem

Offen
#16,236 7 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Repro: https://mypy-play.net/?mypy=latest&python=3.11&gist=d2f8dfa1fdfda5c0c286f1a73f5e39eb

Pasted below for convenience:

import typing as t

from _typeshed import SupportsKeysAndGetItem


KT = t.TypeVar("KT")
VT = t.TypeVar("VT")


def version1(obj: SupportsKeysAndGetItem[KT, VT] | t.Iterable[tuple[KT, VT]]):
    if hasattr(obj, "keys") and hasattr(obj, "__getitem__"):
        reveal_type(obj)  # SupportsKeysAndGetItem[KT, VT] | Iterable[tuple[KT, VT]] (as expected)
    else:
        reveal_type(obj)  # narrowed to Iterable[tuple[KT, VT]] as expected


def version2(obj: SupportsKeysAndGetItem[KT, VT] | t.Iterable[tuple[KT, VT]]):
    if hasattr(obj, "keys") and hasattr(obj, "__getitem__") and (obj_getitem := obj.__getitem__):
        reveal_type(obj)  # SupportsKeysAndGetItem[KT, VT] | Iterable[tuple[KT, VT]] (as expected)
    else:
        reveal_type(obj)  # NOT narrowed

I would expect version 2 to behave the same as version 1. Is that an improvement mypy could reasonably make?

I searched for relevant docs and existing issues, but didn't find anything specifically about this. Apologies if I missed something.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Führe die verlinkte mypy-play-Reproduktion aus und vergleiche die reveal_type-Ergebnisse in version1 und version2. Verfolge die Logik der Typ-Eingrenzung für die kombinierten hasattr-Prüfungen und die Walross-Zuweisung; als abgeschlossen gilt die Aufgabe, wenn version2 den else-Zweig konsistent mit version1 eingrenzt und eine Regressionstestabdeckung für das Beispiel vorhanden ist.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers, devtools
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Ruhig
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
48/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.