After yesterday's release 0.780, our CI starting failing with the message Source file found twice under different module names: 'grader.testlib.framework' and 'testlib.framework' but we only have one file named framework.py in grader/testlib/framework.py. This error does not show up in version 0.770.
How are you invoking mypy, and what does your directory structure look like? Also, please share your config file/command line flags if possible.
Directory Structure:
/grader
/testlib
/components
framework.py
/testers
.mypy.ini
...
Invocation:
mypy grader/ --config-file grader/.mypy.ini
Config .mypy.ini
# Global options:
[mypy]
python_version = 3.6
mypy_path = grader
[mypy-pytest]
ignore_missing_imports = True
We're running into the same problem. I thought it might have been caused by mypy-protobuf, but it doesn't look like the OP was using that. I posted some details in the above issue, but here are some more:
Error message:
buildgrid/_protos/build/bazel/semver/semver_pb2.pyi: error: Source file found twice under different module names: 'buildgrid._protos.build.bazel.semver.semver_pb2' and 'build.bazel.semver.semver_pb2'
Found 1 error in 1 file (checked 144 source files)
Directory structure (all files outside of buildgrid/_protos omitted)
.
โโโ buildgrid
โ โโโ _app
โ โ โโโ bots
โ โ โโโ commands
โ โ โโโ settings
โ โโโ _protos
โ โ โโโ __init__.py
โ โ โโโ build
โ โ โ โโโ __init__.py
โ โ โ โโโ bazel
โ โ โ โโโ __init__.py
โ โ โ โโโ remote
โ โ โ โ โโโ __init__.py
โ โ โ โ โโโ execution
โ โ โ โ โโโ __init__.py
โ โ โ โ โโโ v2
โ โ โ โ โโโ __init__.py
โ โ โ โ โโโ remote_execution.proto
โ โ โ โ โโโ remote_execution_pb2.py
โ โ โ โ โโโ remote_execution_pb2.pyi
โ โ โ โ โโโ remote_execution_pb2_grpc.py
โ โ โ โโโ semver
โ โ โ โโโ __init__.py
โ โ โ โโโ semver.proto
โ โ โ โโโ semver_pb2.py
โ โ โ โโโ semver_pb2.pyi
โ โ โ โโโ semver_pb2_grpc.py
โ โ โโโ buildgrid
โ โ โ โโโ __init__.py
โ โ โ โโโ v2
โ โ โ โโโ __init__.py
โ โ โ โโโ monitoring.proto
โ โ โ โโโ monitoring_pb2.py
โ โ โ โโโ monitoring_pb2.pyi
โ โ โ โโโ monitoring_pb2_grpc.py
โ โ โโโ buildstream
โ โ โ โโโ __init__.py
โ โ โ โโโ v2
โ โ โ โโโ __init__.py
โ โ โ โโโ buildstream.proto
โ โ โ โโโ buildstream_pb2.py
โ โ โ โโโ buildstream_pb2.pyi
โ โ โ โโโ buildstream_pb2_grpc.py
โ โ โโโ google
โ โ โโโ __init__.py
โ โ โโโ api
โ โ โ โโโ __init__.py
โ โ โ โโโ annotations.proto
โ โ โ โโโ annotations_pb2.py
โ โ โ โโโ annotations_pb2.pyi
โ โ โ โโโ annotations_pb2_grpc.py
โ โ โ โโโ http.proto
โ โ โ โโโ http_pb2.py
โ โ โ โโโ http_pb2.pyi
โ โ โ โโโ http_pb2_grpc.py
โ โ โโโ bytestream
โ โ โ โโโ __init__.py
โ โ โ โโโ bytestream.proto
โ โ โ โโโ bytestream_pb2.py
โ โ โ โโโ bytestream_pb2.pyi
โ โ โ โโโ bytestream_pb2_grpc.py
โ โ โโโ devtools
โ โ โ โโโ __init__.py
โ โ โ โโโ remoteworkers
โ โ โ โโโ __init__.py
โ โ โ โโโ v1test2
โ โ โ โโโ __init__.py
โ โ โ โโโ artman_remoteworkers.yaml
โ โ โ โโโ bots.proto
โ โ โ โโโ bots_pb2.py
โ โ โ โโโ bots_pb2.pyi
โ โ โ โโโ bots_pb2_grpc.py
โ โ โ โโโ command.proto
โ โ โ โโโ command_pb2.py
โ โ โ โโโ command_pb2.pyi
โ โ โ โโโ command_pb2_grpc.py
โ โ โ โโโ remote_workers.yaml
โ โ โ โโโ remoteworkers_gapic.yaml
โ โ โ โโโ tasks.proto
โ โ โ โโโ tasks_pb2.py
โ โ โ โโโ tasks_pb2.pyi
โ โ โ โโโ tasks_pb2_grpc.py
โ โ โ โโโ worker.proto
โ โ โ โโโ worker_pb2.py
โ โ โ โโโ worker_pb2.pyi
โ โ โ โโโ worker_pb2_grpc.py
โ โ โโโ longrunning
โ โ โ โโโ __init__.py
โ โ โ โโโ operations.proto
โ โ โ โโโ operations_pb2.py
โ โ โ โโโ operations_pb2.pyi
โ โ โ โโโ operations_pb2_grpc.py
โ โ โโโ rpc
โ โ โโโ __init__.py
โ โ โโโ code.proto
โ โ โโโ code_pb2.py
โ โ โโโ code_pb2.pyi
โ โ โโโ code_pb2_grpc.py
โ โ โโโ status.proto
โ โ โโโ status_pb2.py
โ โ โโโ status_pb2.pyi
โ โ โโโ status_pb2_grpc.py
โ โโโ bot
โ โ โโโ hardware
โ โโโ cleanup
โ โโโ client
โ โโโ server
โ โโโ actioncache
โ โโโ bots
โ โโโ capabilities
โ โโโ cas
โ โ โโโ storage
โ โ โโโ index
โ โ โโโ sql_dialect_delegates
โ โโโ execution
โ โโโ operations
โ โโโ persistence
โ โ โโโ mem
โ โ โโโ sql
โ โ โโโ alembic
โ โ โโโ versions
โ โโโ referencestorage
โโโ data
โ โโโ bin
โ โโโ config
โ โโโ grafana
โ โโโ dashboards
โ โ โโโ buildgrid
โ โโโ datasources
โโโ dockerfile-scripts
โโโ docs
โ โโโ source
โ โโโ data
โ โโโ developer
โ โโโ user
โโโ tests
โโโ auth
โ โโโ data
โโโ cas
โ โโโ data
โ โ โโโ hello
โ โ โโโ docs
โ โ โ โโโ reference
โ โ โโโ utils
โ โโโ index
โโโ integration
โโโ persistence
โโโ stress-testing-dockerfiles
โ โโโ mnt
โ โโโ configs
โ โโโ scripts
โโโ utils
mypy.ini
[mypy]
plugins = sqlmypy
mypy_path = buildgrid/_protos
[mypy-botocore.*]
ignore_missing_imports = True
[mypy-alembic.*]
ignore_missing_imports = True
[mypy-grpc_reflection.*]
ignore_missing_imports = True
[mypy-janus.*]
ignore_missing_imports = True
mypy invocation (run from the root of the repository):
mypy buildgrid/
@ayushr2 @roitk it seems that mypy is now flagging those files as duplicates because they are both searched by being in the MYPYPATH and the sources list. This seems correct to me. This may have to do with a change in how mypy searches namespace packages but I am not sure.
I ran into this too, even though I'm not setting $MYPYPATH. It's dependent on exactly how I invoke mypy:
jelle@devshared28:~/ans/yo$ /home/jelle/ans/yo/.tox/py36/bin/python3.6 -m mypy --config-file /home/jelle/ans/yo/src/mypy.ini /home/jelle/ans/yo/src
src/__init__.py: error: Source file found twice under different module names: 'yo.src' and 'src'
Found 1 error in 1 file (checked 37 source files)
jelle@devshared28:~/ans/yo$ /home/jelle/ans/yo/.tox/py36/bin/python3.6 -m mypy --config-file /home/jelle/ans/yo/src/mypy.ini src
Success: no issues found in 37 source files
The config file doesn't have options that should be relevant, and the same error appears if I don't pass any config file.
Hm, then perhaps this is a regression after all? I think this definitely merits further investigation.
MYPYPATH (or mypy_path) should not point to a directory with an __init__.py file, as this can result in a package with an ambiguous name. Previously mypy sometimes accepted this. This could cause crashes so mypy now complains about it.
@ayushr2 If /grader/__init__.py exists, you've hit the above issue. You should perhaps point mypy_path to the parent directory of grader.
@roitk You have mypy_path that points to a directory with a __init__.py file, so mypy gets confused.
@JelleZijlstra Your issue might be different. Can you give a full example, including all relevant source files?
I suspect Jelle's issue is also a spurious __init__.py and that it manifests differently with relative paths because of how we crawl up to find the base directory: https://github.com/python/mypy/blob/3adb2e952cf9e16d4d493440a1c7be3de4d214ef/mypy/find_sources.py#L101
@hauntsaninja is correct. The directory structure in my example is as follows:
โโโ __init__.py
โโโ src
ย ย โโโ __init__.py
ย ย โโโ mypy.ini
ย ย โโโ yo_bot.py
(plus numerous other files not relevant here). If I remove the outer __init__.py, the error goes away.
I'm hitting this. It happens because I have to specify all the subfolders explicitly in order to get mypy to process them, since it doesn't process folders recursively (contrary to what its documentation says). e.g.
$ echo $MYPYPATH
$ mypy src test test/jobs
test/jobs/job_utils.py: error: Source file found twice under different module names: 'job_utils' and 'jobs.job_utils' [misc]
If I turn off namespace_packages it seems to work, but it's unclear to me what the ramifications of that will be (the documentation is unclear to its practical purpose, but seems to imply this will cause some modules I import to not be recognised, and thus not have their use by my code typechecked?).
I've noticed for some time that it was double-reporting everything, implying it's been processing things twice, but it didn't originally do that - I'm not certain, but I think this was a mypy change, not something I did. Alas I don't know which version of mypy introduced that duplicate processing.
mypy should recursively process your directories, and in fact it definitely is doing that to some extent, since it's clearly finding job_utils.py twice. Could you confirm whether mypy src test is checking job_utils.py (perhaps by introducing a type error)? Is there a tests/__init__.py?
I found I had this problem when upgrading from 0.770 to 0.780 in multiple projects. When I removed MYPY_PATH from the environment variable and defining mypy_path in mypy.ini as a gobal fixed the issue.
@wadetregaskis-linkedin You might be hitting #5759. Namespace package support is currently incomplete but a major update to namespace packages is being planned (#8584).
@httpstergeek It would be helpful if you can provide a simplified but complete example which reproduces your issue. It seems that things are working unexpectedly in some specific scenarios that we don't yet fully understand.
@hauntsaninja, no, it definitely doesn't process directories recursively _unless_ they're modules (i.e. it gets 'src' and all its subfolders, because 'src' has a 'foo' subfolder with an __init__.py in it, but the associated 'test' folder contains no __init__.pys, at any level). At one point I believe it did - I used to just provide 'src' and 'test' arguments - but that was a long time ago. I don't recall all the details now, but there's been quite a struggle over various different versions of mypy to get it to just process these two folders recursively.
The duplicates only arise when I specify all the subfolders explicitly, and only for the subfolders I specify (since otherwise mypy ignores them).
IIRC it _also_ reports things twice from not just the 'test' folder but also 'src', implying that somehow merely mentioning both, and having the files in 'test' import those from 'src', somehow causes it to do a redundant pass.
@JukkaL I also hit this issue after upgrade. I think it is the same issue reported here. Here is a minimal recreate (using CentOS 7):
mkdir -p lib/dir1/dir2/dir3/dir4
touch lib/dir1/dir2/dir3/file1.py
echo "import dir1.dir2.dir3.file1 as file1" > lib/dir1/dir2/dir3/dir4/file2.py
With mypy 0.781:
MYPYPATH=lib mypy --namespace-packages --strict-optional --strict lib/dir1/dir2/dir3/*
lib/dir1/dir2/dir3/file1.py: error: Source file found twice under different module names: 'file1' and 'dir1.dir2.dir3.file1'
Found 1 error in 1 file (checked 2 source files)
With mypy 0.770:
MYPYPATH=lib mypy --namespace-packages --strict-optional --strict lib/dir1/dir2/dir3/*
Success: no issues found in 2 source files
I have the same issue, but just a single __init__.py in our main directory. If I remove the __init__.py it works fine.
The same happens for https://github.com/typeddjango/djangorestframework-stubs
Output:
ยป mypy -p rest_framework-stubs
rest_framework-stubs/request.pyi: error: Source file found twice under different module names: 'rest_framework-stubs.request' and 'rest_framework.request' [misc]
Found 1 error in 1 file (checked 48 source files)
When I delete __init__.pyi - it works.
It also work when I downgrade to pip install 'mypy==0.770' (my current solution)
Related https://github.com/typeddjango/djangorestframework-stubs/pull/75
I experienced the opposite โ adding an __init__.py solved the issue. With every folder being a package, this worked fine:
mypy app/mailers app/models app/services utils
We are gradually adding typechecks to the project, and the next step was to add the app/rest folder. It didn't contain an __init__.py, which caused this:
app/rest/errors.py: error: Source file found twice under different module names: 'errors' and 'app.rest.errors'
At first I tried moving errors.py away, but then mypy complained about other files under app/rest. So, adding app/rest/__init__.py helped.
Edit: this must be #5759, as we use mypy with namespace_packages = True.
I am hitting this too today (mypy==0.782) after converting a library to use PEP 420 native namespacing. Here's the error message I'm seeing:
namespace/package/foo/bar.py: error: Source file found twice under different module names: 'package.foo.bar' and 'namespace.package.foo.bar' [misc]
As per @richtong 's suggestion above, removing the __init__.py in our subpackage_a directory solved the problem.
Unfortunately, that __init__.py contains important information, so deleting it isn't a viable solution in my use case.
Aside: what's interesting is this error is only triggered for one source file, even though this error could exist in many places within the library.
I am coming here for one question and one suggestion:
# type: ignore or # type: ignore[misc] at the top of the namespace/package/foo/bar.py module is not desirable for me and doesn't actually suppress this messagesetup.cfg:[mypy-namespace.package.foo.bar]
ignore_errors = True
@jamesbraza could you also share the command you use to run mypy?
@killthekitten yeah I use the files section of a config file, and just invoke mypy via entering solely mypy. Currently, I have three args to files:
.: to type check setup.py in my repo's rootnamespace: type check the actual packagetests: type check unit testsI noticed that if I get rid of the ., that this error actually goes away. So a new workaround for me is to no longer use files, and in my CI config just invoke mypy two times:
mypy namespace testsmypy setup.pyIn my opinion, the more desirable workaround would be to make this error message suppressible.
Update: I am no longer hitting this error, as it turns out (found out through https://github.com/python/mypy/issues/9341) I was improperly invoking mypy. I needed to use -p and -m as opposed to files in the config file.
Perhaps that might be the root of your problem @ayushr2 ?
ALL: The solution is to use mypy -p <folder> instead of mypy <folder>. This is because PEP 420 support only works on import, not on files/directories passed on the command line. The -p takes a package name which is treated as an import.
Most helpful comment
ALL: The solution is to use
mypy -p <folder>instead ofmypy <folder>. This is because PEP 420 support only works onimport, not on files/directories passed on the command line. The-ptakes a package name which is treated as an import.