python / python/mypy

No error when subclass does not provide a value for ClassVar

Offen
#14,381 3 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

I've been trying to mypy to typecheck subclasses that need to provide a required value for a ClassVar in a base class that cannot provide the value itself (only has an unintialized attribute marker). The problem is that badly implemented subclasses can ignore this attribute without mypy raising errors about it (though interestingly if the value provided has incorrect type, mypy will raise errors about that).

To Reproduce

from abc import ABC
from typing import ClassVar, Type


class Base(ABC):
    my_super_important_value: ClassVar[str]


class GoodSubclass(Base):
    my_super_important_value = "1337"


# I want mypy to error about an unimplemented variable but it doesn't
class BadSubclass(Base):
    pass


def print_abc(cls: Type[Base]) -> None:
    print(cls.my_super_important_value)


print_abc(GoodSubclass)
# 1337
print_abc(BadSubclass)
# AttributeError: type object 'BadSubclass' has no attribute 'my_super_important_value'

mypy playground

Expected Behavior

Expected mypy to show an error about the BadSubclass class not providing a value for my_super_important_value.

Actual Behavior

No errors.

Your Environment

  • Mypy version used: 0.991
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.10

Note that the same code fails when using the Pyre type checker with this error:

14:0: Uninitialized attribute [13]: Attribute `my_super_important_value` inherited from abstract class `Base` in class `BadSubclass` to have type `str` but is never initialized. 

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 zunächst den Python-Reproducer aus dem Issue mit mypy --strict aus und bestätige, dass BadSubclass keinen Fehler erzeugt, während der Laufzeitzugriff fehlschlägt. Untersuche mypys Behandlung geerbter ClassVar-Deklarationen und abstrakter oder nicht initialisierter Attribute und verwende die Pyre-Diagnose als Verhaltensvergleich. Als erledigt gilt die Änderung, wenn mypy meldet, dass BadSubclass my_super_important_value bereitstellen muss, ohne den Fall GoodSubclass zu beeinträchtigen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers, devtools
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

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