You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At work, we have a standard project layout using namespace packages with dev/build/test dependencies declared in setup.py. It's a bit complex, but it worked well up until mypy 0.790. Since mypy 0.800, mypy is complaining: "Source file found twice under different module names".
This appears to be a rather obscure corner case requiring:
implicit namespace packages
dev dependencies declared in setup.py, rather than a requirements file
use of pip install -e .[dev] to install those dependencies
running mypy on directories and files (not packages or modules)
Remove any of those conditions and mypy behaves as expected (ie. back to what we had under 0.790). But since it worked nicely under 0.790, it sure feels like a regression to me.
Here's a simplified version of the project layout, for a package fn.common with one module and unit tests:
fn is an implicit namespace package named after the company. We're Python 3 only, so we have no need for legacy namespace packages. Every project, whether library or application, puts all production code in fn/<something>. Nice and clean and tidy and consistent.
The source code of the package isn't important. (There are type hints and no type errors.)
What matters is the contents of setup.py, the way we initialize our virtualenv, and how we run mypy. Here's setup.py:
$ mypy --ignore-missing-imports --check-untyped-defs fn tests *.py
Success: no issues found in 5 source files
If I upgrade to 0.812, it stops working:
$ pip install mypy==0.812
$ mypy --ignore-missing-imports --check-untyped-defs fn tests *.py
fn/common/__init__.py: error: Source file found twice under different module names: 'common' and 'fn.common'
Found 1 error in 1 file (errors prevented further checking)
The first release showing this behaviour was 0.800. I used git bisect to track down the responsible commit: e4131a5.
To Reproduce
get my source code:
$ wget https://www.gerg.ca/mypy/fnlib-common.tar.gz
$ tar -xzvf ~/fnlib-common.tar.gz
$ cd fnlib-common
$ mypy --ignore-missing-imports fn tests *.py
Success: no issues found in 5 source files
upgrade to mypy >= 0.800 and see the problem
$ pip install mypy==0.800 # or later
$ mypy --ignore-missing-imports fn tests *.py
fn/common/__init__.py: error: Source file found twice under different module names: 'common' and 'fn.common'
Found 1 error in 1 file (errors prevented further checking)
Expected Behavior
Same output from mypy >= 0.800 as from mypy 0.790, i.e. no errors.
This is a bit ugly and bound to be slower. If it's just startup overhead, I can live with it. But if there is cache thrashing, no thank you!
Workaround 2: fake __init__ files
I cannot create fn/__init__.py, because that breaks namespace packages. But I can create fn/__init__.pyi to fool mypy without angering python. I think this is the least bad option, but it will be easy to forget in new projects.
Workaround 3: undo the "pip install -e ."
The easiest way to install the dev dependencies declared in setup.py is with pip install -e '.[dev]'. But that also installs a link to the current project, fnlib-common, right in the local virtualenv. Remove that and mypy is happy:
$ pip uninstall fnlib-common
$ mypy --ignore-missing-imports fn tests *.py
Success: no issues found in 5 source files
Verrry strange.
HOWEVER, I vaguely recall that we had a good reason for doing pip install -e . somewhere, somewhy, somehow. It might have been because of flask or uwsgi in one of our web apps, and I just did it everywhere for consistency. Need to investigate to see if this is a good option.
Workaround 4: use a dev-requirements.txt file
Stop declaring dev dependencies in setup.py, and put them in a requirements file. Then I don't need pip install -e '.[dev]' ... unless, of course, I do need it for other reasons that I do not remember right now!
Bug Report
At work, we have a standard project layout using namespace packages with dev/build/test dependencies declared in setup.py. It's a bit complex, but it worked well up until mypy 0.790. Since mypy 0.800, mypy is complaining: "Source file found twice under different module names".
This appears to be a rather obscure corner case requiring:
pip install -e .[dev]
to install those dependenciesRemove any of those conditions and mypy behaves as expected (ie. back to what we had under 0.790). But since it worked nicely under 0.790, it sure feels like a regression to me.
Here's a simplified version of the project layout, for a package
fn.common
with one module and unit tests:fn
is an implicit namespace package named after the company. We're Python 3 only, so we have no need for legacy namespace packages. Every project, whether library or application, puts all production code infn/<something>
. Nice and clean and tidy and consistent.The source code of the package isn't important. (There are type hints and no type errors.)
What matters is the contents of
setup.py
, the way we initialize our virtualenv, and how we run mypy. Here'ssetup.py
:This lets us create a virtualenv as follows:
Since I've pinned mypy to 0.790, it works fine:
If I upgrade to 0.812, it stops working:
The first release showing this behaviour was 0.800. I used
git bisect
to track down the responsible commit: e4131a5.To Reproduce
Expected Behavior
Same output from mypy >= 0.800 as from mypy 0.790, i.e. no errors.
Actual Behavior
Errors from mypy >= 0.800.
Your Environment
host 1:
host 2:
Same results on host 1 and host 2.
No mypy config files -- command-line only.
The text was updated successfully, but these errors were encountered: