python / python/mypy

annotations on `self` are not understood with `Protocol`s

Offen
#16,291 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

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

Beschreibung

Bug Report

When interpreting a given type as a given Protocol, annotations on self in the Protocol are apparently ignored.

To Reproduce

mypy-play.net



from __future__ import annotations

from typing import *



                          #━━━━━━━━━━━━━━━━━#
                          #  EXISTING CODE  #
                          #━━━━━━━━━━━━━━━━━#


class ConcreteClass:

    # here 'transform()' is used, but we might use '__neg__()' or
    # '__invert__()' in a similar way (so many built-in/third-party
    # classes would qualify as 'TransformAware')

    def transform(self) -> int:
        return id(self)



                           #━━━━━━━━━━━━━━━━#
                           #  LIBRARY CODE  #
                           #━━━━━━━━━━━━━━━━#

# this can be changed


Ico = TypeVar('Ico', covariant=True)        # input, covariant
Oco = TypeVar('Oco', covariant=True)        # output, covariant


class TransformAware(Protocol[Ico, Oco]):

    def transform(self: Ico) -> Oco: ...



                      #━━━━━━━━━━━━━━━━━━━━━━━━━#
                      #  DEMONSTRATE PROBLEMS:  #
                      #━━━━━━━━━━━━━━━━━━━━━━━━━#


I = TypeVar('I')                            # input
O = TypeVar('O')                            # output


def interpret_transform_aware(_: Type[TransformAware[I, O]]) -> Tuple[I, O]:
    i: I
    o: O
    return i, o


reveal_type(interpret_transform_aware(ConcreteClass))
        # actual output:
        #   note: Revealed type is "Tuple[<nothing>, builtins.int]"
        # expected output:
        #   note: Revealed type is "Tuple[ConcreteClass, int]"



                           #───────────────#
                           #  MOTIVATION:  #
                           #───────────────#


class TransformDriver(Generic[I, O]):

    def __init__(self, klass: Type[TransformAware[I, O]]): ...

    def transform_value(self, value: I) -> O:
        use_value = cast(TransformAware[I, O], value)
        return use_value.transform()

Expected Behavior

(See: inline comments.)

Interpreting ConcreteClass as TransformAware should correctly infer both type variables.

Actual Behavior

(See: inline comments.)

Mypy gives the type of Ico as <nothing>.

Your Environment

  • Mypy version used: 1.6.1
  • Mypy command-line flags: (none necessary)
  • Mypy configuration options from mypy.ini (and other config files): (none necessary)
  • Python version used: 3.8, 3.11

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

Beginne mit dem mypy-play.net-Reproducer und dem Protocol-Verarbeitungscode; die Payload nennt keine Repository-Datei und keinen Test. Verfolge, wie Annotationen auf self bei der Interpretation von ConcreteClass als TransformAware verwendet werden, und füge Abdeckung hinzu, die zeigt, dass beide Typvariablen als ConcreteClass und int inferiert werden.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

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

Neue Issues direkt in Ihr Postfach

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