python / python/mypy

Issue inferring type with circular imports/future annotations

オープン
#12,874 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Python
スター
20.6k
フォーク
3.3k
PR マージ指標
PR 指標を取得中

説明

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

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

src/my_directory/a.py、src/b.py、およびパッケージの init.py ファイルを使って報告内容を再現し、その後キャッシュを削除した状態で mypy src を実行してください。コンストラクターのアノテーション、循環インポート、または future annotations を変更した場合の動作を比較してください。報告された例で、冗長なアノテーションを追加せずに bar.object が Object として推論され、引き続きエラーが報告されなければ完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
tooling
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。