Description
The following code is perfectly well-typed, but -- depending on the order files are passed to mypy
-- gives a cryptic error message:
$ head *
==> part1.py <==
from part3 import part3_thing
class FirstThing: pass
==> part2.py <==
from part4 import part4_thing
import socket
Thing = socket.socket
==> part3.py <==
from part2 import Thing
def part3_thing(x, *y): pass
_thing = Thing()
==> part4.py <==
MYPY = False
if MYPY:
from part1 import FirstThing
part4_thing = 1
On running mypy part[1234].py
, we get the result
part3.py:3: error: Cannot determine type of 'Thing'
The import cycle seems to be essential. The result is also sensitive to order -- for example, mypy part{1,3,2,4}.py
gives no error.
The repro can probably be reduced further; for example, I suspect there's a way to see it with three files, perhaps just two.
The code above obviously looks somewhat artificial -- it's stripped down from an example in a large internal codebase at Dropbox. We've seen several different people independently run into errors that look much like this in different parts of the same codebase, which has a number of import cycles, and I suspect the same thing is likely to happen in other large import-cycled codebases elsewhere. It'd be valuable to understand just what's going on here.
At a minimum, we should give a clear error message -- this one is pretty unhelpful for the user. Better yet we should fix the issue :), but import cycles have been tricky for us before so that might be difficult. If we can't immediately fix it, though, it'd be helpful even just to know what the obstacle is in this case.