python / python/mypy

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

Aperta
#16,683 1 commento 4 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

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

Descrizione

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

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

Inizia in mypy/modulefinder.py intorno alla riga indicata, quindi riproduci il problema con la gerarchia pkg_a/pkg_b e il comando MYPYPATH=pkg_b:pkg_a mypy --namespace-packages --strict -p foo. Il lavoro è completo quando la ricerca del codice sorgente include entrambi i componenti del namespace package e il controllo dei tipi segnala errori da module1.py e module2.py.

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

Valutazione

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

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.