python / python/mypy

Issue inferring type with circular imports/future annotations

Aperta
#12,874 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Hey! I ran into something which I think is a bug, although its a very small use case and can be fixed pretty easily. This is my first time reporting an issue so let me know if I need to supply anything more info, or if this isn't actually a bug

Bug Report

using future annotations with this circular import seems to cause issues with recognizing types

To reproduce:

create the following structure:

src
 ├──my_directory
     ├── __init__.py
     ├──a.py
 ├──__init__.py
 ├──b.py

with the following code in the files:

src/my_directory/init.py:

from .a import OBJECT_FACTORY, Object

src/my_directory/a.py

from .. import b

class Object():
    pass

class ObjectFactory:
    def make_object(self) -> Object:
        pass

OBJECT_FACTORY = ObjectFactory()

src/init.py

# empty file

src/b.py

from __future__ import annotations
from . import my_directory

def func(bar: Bar):
    print(bar.object)

class Bar:
    def __init__( 
        self,
        _: str, # if you delete this type annotation there will no longer be an error
    ):
        self.object = my_directory.OBJECT_FACTORY.make_object()

then run:
mypy src

Expected Behavior:

Should be able to infer that the type of bar.object is Object from the type annotation of the make_object method.

Actual Behavior

src/b.py:5: error: Cannot determine type of "object"
Found 1 error in 1 file (checked 4 source files)

Some interesting behaviors:

  • if you delete the str type annotation in the Bar class, mypy passes with no issues
  • defining func after Bar class passes with no issues
  • deleting the 'from .. import b' in a.py passes with no issues
  • using a static function make_object with the same annotation instead of in OBJECT_FACTORY will pass with no issues
  • running mypy src/b.py instead of mypy src will pass with no issues
    • subsequently, now running mypy src will actually pass without issues (likely due to .mypy_cache, deleting the cache will re-instate the bug)
  • you can fix this issue if you add the type annotation my_directory.Object to self.object in class Bar
My Environment:

mypy --version

mypy 0.960 (compiled: yes)

python --version

Python 3.8.6

  • Mypy command-line flags: no flags
  • OS: Windows 10

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Riproduci il report usando i file in src/my_directory/a.py, src/b.py e i file init.py del package, quindi esegui mypy src dopo aver rimosso la cache. Confronta il comportamento quando vengono modificati l’annotazione del costruttore, l’importazione circolare o future annotations. Il lavoro è completato quando l’esempio riportato inferisce bar.object come Object senza aggiungere un’annotazione ridondante e continua a non segnalare errori.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
tooling
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.