python / python/mypy

Does not catch variable declared global/nonlocal after appearing in the same scope.

Offen
#13,560 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

feature topic-variable-scope
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Bug Report

If a program references a variable and then declares it global or nonlocal, mypy does not catch this.

To Reproduce

foo.py:
x = 'x'

from typing import TYPE_CHECKING

def foo() -> None:
	x = 42
	global x
	if TYPE_CHECKING: reveal_type(x)
	print(x)
foo()

$ mypy foo.py
foo.py:8: note: Revealed type is 'builtins.str'

$ python3 foo.py
  File "foo.py", line 7
    global x
    ^
SyntaxError: name 'x' is assigned to before global declaration

Expected Behavior

mypy should report the error on line 7.
This applies to any other usage of 'x',

  • except (x): int (with no assignment)
    which is not a syntax error, as it is not a name binding for 'x'.
    When you fix mypy to catch these syntax errors, be sure and take this into account. The only difference between (x): int and x: int is in the value of ast3.AnnAssign.simple = 0 and 1, resp. ast3.AnnAssign.simple = 0 in both cases if there is an assignment.

Actual Behavior

No error (see above).

Suggestion

I would guess that the fix belongs in the semantic analyzer. When it encounters a global or nonlocal declaration, it should know that the variable name has already been used or bound.
Don't forget to check for ast3.AnnAssign.simple = 1 and not consider the variable to be bound, or even used, in this case.
Note that ast3.AnnAssign.target is an ast3.Name instance, and ast3.AnnAssign.target.expr_context is an ast3.Store instance. This is a bug in the parser. It should be ast3.Load(), or better yet, None, since the variable is not really used at all.

Your Environment

  • Mypy version used: 0.761
  • Python version used: 3.8.10
  • Operating system and version: Ubuntu (WSL on Windows)

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 im semantischen Analyzer von mypy und reproduziere das Problem mit dem Beispiel foo.py aus dem Bericht. Verfolge die Behandlung von global- und nonlocal-Deklarationen, einschließlich der Fälle ast3.AnnAssign.simple, und überprüfe, dass x bei x: int ohne Zuweisung nicht fälschlicherweise als verwendet oder gebunden behandelt wird. Erledigt ist die Aufgabe, wenn mypy den Syntaxfehler meldet und dabei die angegebene Ausnahme beibehält.

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
35/100

Neue Issues direkt in Ihr Postfach

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