python / python/mypy

Mypy doesn't recognize relative imports as module names

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

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

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

説明

Bug Report

Mypy doesn't seem to recognize a relative import as a module-type.

To Reproduce

Given a sample package with the following structure

my_pkg/
├── __init__.py
└── my_module.py

__init__.py:

import types
from typing import List

from .my_module import *

__all__ = []
submodules: List[types.ModuleType] = [my_module]
for submodule in submodules:
    __all__.extend(submodule.__all__)

my_module.py:

__all__ = ["my_var"]

my_var = "hello!"

mypy output:

$ mypy my_pkg/
my_pkg/__init__.py:7: error: Name "my_module" is not defined
my_pkg/__init__.py:9: error: Module has no attribute "__all__"
Found 2 errors in 1 file (checked 2 source files)

Expected Behavior

I expected to see no errors, as the python is valid code.

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.8.10
  • Operating system and version: Ubuntu 20.04.2

Additional Info
Because the above is an odd pattern, I'd like to explain it.

Imagine I started with an app and a single module, my_module. I'd then use access the module inside the app like so

from my_app import my_module

print(my_module.my_var)

Now, as time goes on, my_module grows increasingly complex, so I decide to split up my_module into a package, my_pkg. Unfortunately, we now have to change our imports in the app:

from my_app.my_pkg import my_module

This isn't desirable, because any code that was using my_module now has to change its imports. To combat this, I name my_pkg the same name as my_module and include the above snippet of code in the __init__.py. Now, to the application, the fact that my_module was split into a package is completely abstracted and the import syntax remains the same:

from my_app import my_pkg

print(my_pkg.my_var)

Note, my_pkg would be have the same name as the original module.

I don't necessarily care that mypy doesn't deal with my above code well, but I do care that the desired behavior is supported by mypy somehow. If there is a better way to do what I've explained, I am all ears.

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

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

はじめの一歩

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

調査の方向性

my_pkg/init.py と my_pkg/my_module.py の再現コードから始め、mypy my_pkg/ を実行して報告されたエラーを確認します。相対インポートとワイルドカードインポートがどのように解釈されるかを追跡し、モジュールとその __all__ がエラーなしで正しく認識されること、またはサポートされている代替手段を文書化することを完了の条件とします。

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

評価

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

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

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