Mypy isn't discovering all modules in namespace packages with multiple __path__ components

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

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

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
45/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
停滞
技術スタック
python
領域
devtools

調査の方向性

mypy/modulefinder.py の参照された行付近から始め、pkg_a/pkg_b 階層と MYPYPATH=pkg_b:pkg_a mypy --namespace-packages --strict -p foo コマンドを使って問題を再現します。source discovery に両方の namespace-package コンポーネントが含まれ、type checking が module1.py と module2.py のエラーを報告すれば完了です。

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

説明

bug

Bug Report

It seems that mypy isn't considering all parts of namespace package paths, and is only checking the sources corresponding to the first path in its path.

Hopefully the example below clarifies it. I searched quite a bit in the bug tracker/docs, but didn't find anything describing my scenario, so apologies if it's a dupe!

To Reproduce

Consider the following hierarchy

./pkg_a
./pkg_a/foo
./pkg_a/foo/module1.py
./pkg_a/foo/py.typed
./pkg_b
./pkg_b/foo
./pkg_b/foo/py.typed
./pkg_b/foo/module2.py

foo.module1 and foo.module2 simply contain a bit of code to demonstrate mypy error detection:

$ cat ./pkg_a/foo/module1.py
trigger_mypy_error: str = 123
$ cat ./pkg_b/foo/module2.py
trigger_mypy_error: str = 123

Just as expected, we have a namespace package, both modules are imported without issues:

$ PYTHONPATH=pkg_b:pkg_a python3 -c 'import foo; print(foo.__path__); import foo.module1; import foo.module2'
_NamespacePath(['/project/for_mypy_bugtracker/pkg_b/foo', '/project/for_mypy_bugtracker/pkg_a/foo'])

Actual Behavior

When type checking, mypy only detects module2.py and misses module1.py:

$ MYPYPATH=pkg_b:pkg_a mypy --namespace-packages --strict -p foo
pkg_b/foo/module2.py:1: error: Incompatible types in assignment (expression has type "int", variable has type "str")  [assignment]
    trigger_mypy_error: str = 123
                              ^~~
Found 1 error in 1 file (checked 2 source files)

Seems that the only sources detected are from pkg_b:

MYPYPATH=pkg_b:pkg_a mypy --namespace-packages -p foo -v 2>&1 | grep BuildSource
LOG:  Found source:           BuildSource(path='pkg_b/foo', module='foo', has_text=False, base_dir=None, followed=False)
LOG:  Found source:           BuildSource(path='pkg_b/foo/module2.py', module='foo.module2', has_text=False, base_dir=None, followed=False)

I dug a bit and I suspect it has something to do with this line
https://github.com/python/mypy/blob/1dd8e7fe654991b01bd80ef7f1f675d9e3910c3a/mypy/modulefinder.py#L559 -- the result of finding the module is just one path (pkg_b in this case), so it doesn't have a chance to explore pkg_a.

Expected Behavior

Mypy should detect both foo.module1 and foo.module2

Your Environment

  • Mypy version used: 1.7.1 (latest)
  • Python version used: 3.10
主要言語
Python
スター
20.6k
フォーク
3.3k
平均マージ
1日 18時間
マージ済み PR(30日)
54

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

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

はじめの一歩

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

python/mypy のほかの issue

python/mypy の issue をすべて見る

似ている issue

Python の issue をもっと見る

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

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