Repository: python/mypy

Issue:
error listed twice with wrong filename(capitalization) in output
given:
```
folder/
├─ src/
│  ├─ __init__.py
│  ├─ thing.py
├─ test.py
```

src/\_\_init__.py:
```py
from src.thing import Thing as Thing
```
src/thing.py:
```py
class Thing(asdf): ...
```

test.py:
```py
from src import Thing
```

```bash
> mypy -V
mypy 0.920+dev.1393e3fec49a9505fd3a31f3406ddd4e2e1c54b8
> mypy --strict test.py
src/thing.py:1: error: Name "asdf" is not defined
src/Thing.py:1: error: Name "asdf" is not defined
```

Edit:
This is observed with WSL on the windows file system and not WSL on the Linux fs
mypy gives valid-type errors with some import methods, seemingly inconsistently

**Bug Report**

Sorry in advance, this is going to be an non-ideal bug report. I've spent over an hour now trying to figure out how to create a simpler project that reproduces the issue, but I haven't been able to cause it to happen, so I'm going to have to use my real project as the example.

I recently updated mypy from 0.790 to 0.910, and it started giving a number of `[valid-type]` errors related to some of my classes, saying that I couldn't use them as type annotations. Here's one example:

```
tildes/models/group/group_subscription.py: note: In class "GroupSubscription":
tildes/models/group/group_subscription.py:43: error: Module
"tildes.models.user.User" is not valid as a type  [valid-type]
        user: User = relationship("User", innerjoin=True, backref="subscri...
              ^
```

I had to make some different modifications to how I was importing the classes to get rid of these errors:
1. If the class was from inside the same package, it had to be imported like `from .group import Group`. Using the full path like `from tildes.models.group import Group` would result in an error.
2. In one specific package, I had to specify the import even more exactly. These ones required me to do `from tildes.models.user.user import User`, where every other "sibling" package can do `from tildes.models.user import User` without mypy complaining (the class is imported in the `__init__.py` to allow that).

All of the changes I needed to make are [in this commit](https://gitlab.com/tildes/tildes/-/commit/31afe0a8ba574988be4e879c9ab33792ceec9533#59a0053b53b6b9dc6c1af44f14ee96b46e3ee2d4) if you want to look (there are also some fixes for legitimate typing issues in there too).

The second type of change above is the more interesting one, because I have some modules that are very close to identical, but require different import styles to make mypy happy.

If you compare these two files:

* [models/group/group_subscription.py](https://gitlab.com/tildes/tildes/-/blob/31afe0a8ba574988be4e879c9ab33792ceec9533/tildes/tildes/models/group/group_subscription.py)
* [models/topic/topic_vote.py](https://gitlab.com/tildes/tildes/-/blob/31afe0a8ba574988be4e879c9ab33792ceec9533/tildes/tildes/models/topic/topic_vote.py)

They're almost identical - the first one is a link between `User`+`Group`, and the other is a link between `User`+`Topic`. However, mypy needs me to do the `from tildes.models.user.user import User` import in `group_subscription.py`, but is fine with `from tildes.models.user import User` in `topic_vote.py`.

**To Reproduce**

(Sorry again for having to use my actual project here)

1. Clone https://gitlab.com/tildes/tildes
2. Open terminal inside the repo directory
3. `git checkout 9720040cb9a7c75fd590322479e821a0e8f13497 -- tildes/tildes/models/group/group_subscription.py` (reverts the fix I made to that single file)
4. Change into the `tildes/` subdirectory, and run `mypy .`
5. Get 4 errors, two of which are from files other than the one that was reverted:
```
tildes/models/user/user_permissions.py: note: In class "UserPermissions":
tildes/models/user/user_permissions.py:31: error: Module "tildes.models.group.Group" is not valid as a
type  [valid-type]
        group: Group = relationship("Group", innerjoin=True)
               ^
tildes/models/user/user_group_settings.py: note: In class "UserGroupSettings":
tildes/models/user/user_group_settings.py:34: error: Module "tildes.models.group.Group" is not valid as
a type  [valid-type]
        group: Group = relationship("Group", innerjoin=True)
               ^
tildes/models/group/group_subscription.py: note: In class "GroupSubscription":
tildes/models/group/group_subscription.py:43: error: Module "tildes.models.user.User" is not valid as a
type  [valid-type]
        user: User = relationship("User", innerjoin=True, backref="subscriptions")
              ^
tildes/models/group/group_subscription.py: note: In member "__init__" of class "GroupSubscription":
tildes/models/group/group_subscription.py:46: error: Module "tildes.models.user.User" is not valid as a
type  [valid-type]
        def __init__(self, user: User, group: Group):
                                 ^
Found 4 errors in 3 files (checked 145 source files)
```

**Expected Behavior**

mypy should support classes imported in any of the ways Python supports.

**Actual Behavior**

mypy seems to require specific import methods in certain cases.

**Your Environment**

- Mypy version used: 0.910
- Mypy command-line flags: None
- Mypy configuration options from `mypy.ini` (and other config files): https://gitlab.com/tildes/tildes/-/blob/31afe0a8ba574988be4e879c9ab33792ceec9533/tildes/mypy.ini
- Python version used: 3.9.5
- Operating system and version: Debian 10


Discussion:
Is this on an OS with case-insensitive files? We've had some similar issues.
Happens on wsl and not windows
Can you delete your mypy cache and then check if the following patch fixes:
```
diff --git a/mypy/fscache.py b/mypy/fscache.py
index c77b941c5..fb651326f 100644
--- a/mypy/fscache.py
+++ b/mypy/fscache.py
@@ -202,9 +202,6 @@ class FileSystemCache:
 
         The caller must ensure that prefix is a valid file system prefix of path.
         """
-        if sys.platform == "linux":
-            # Assume that the file system on Linux is case sensitive
-            return self.isfile(path)
         if not self.isfile(path):
             # Fast path
             return False
```
@hauntsaninja  did you know that github supports `diff` as a code block language.

```diff
diff --git a/mypy/fscache.py b/mypy/fscache.py
index c77b941c5..fb651326f 100644
--- a/mypy/fscache.py
+++ b/mypy/fscache.py
@@ -202,9 +202,6 @@ class FileSystemCache:
 
         The caller must ensure that prefix is a valid file system prefix of path.
         """
-        if sys.platform == "linux":
-            # Assume that the file system on Linux is case sensitive
-            return self.isfile(path)
         if not self.isfile(path):
             # Fast path
             return False
```


I knew that. Does the diff fix the issue or not? (I don't have a system I can repro the issue on)
testing it now
I think that change resolves the issue
Very strange, on another machine with the exact same files it doesn't follow the imports at all.
Raised it here #11697
> Happens on wsl and not windows

Is this happening on WSL 1 or 2? Also, are you using the Windows file system or the Linux file system?
wsl 2 on the windows file system, it does not happen with wsl + linux fs
This sounds similar to #10661.
Yes, definitely looks like it could be the same issue (I like that we both have similar apologies for not being able to simplify it too).

The problems I was seeing were inside a Vagrant VM (Virtualbox) running on a Windows host, with the code in a synced folder from the host, so it seems very similar to what @paulcwatts showed there with Docker. My repo includes the Vagrantfile, so you should be able to get an equivalent setup easily with Vagrant and Virtualbox if you have a Windows/Mac machine available (for a case-insensitive host).

Looking inside the `.mypy_cache` directory, I see some things that look like they could be wrong:

- Inside the `tildes/models/group` directory, there are `Group.data.json` and `Group.meta.json` (both capitalized), but inside the `user` directory there are `User.data.json` and `user.meta.json` (only one capitalized).
- In `Group.meta.json`:
    - `"id": "tildes.models.group.Group"` (a class)
    - `"path": "/opt/tildes/tildes/models/group/Group.py"` (worth noting: this capitalized filename does not exist, the filename is all lowercase)
- In `user.meta.json`:
    - `"id": "tildes.models.user.user"` (a module)
    - `"path": "./tildes/models/user/user.py"`

So it does seem like there might be conflicts in the cache due to case insensitivity, where the class and module are getting mixed up.
It's probably not surprising, but since I tested it: disabling incremental mode or using an sqlite cache both don't help.

Resolving patch:
diff --git a/mypy/fscache.py b/mypy/fscache.py
--- a/mypy/fscache.py
+++ b/mypy/fscache.py
@@ -30,7 +30,6 @@
 
 import os
 import stat
-import sys
 from typing import Dict, List, Set
 from mypy.util import hash_digest
 from mypy_extensions import mypyc_attr
@@ -202,9 +201,6 @@ def isfile_case(self, path: str, prefix: str) -> bool:
 
         The caller must ensure that prefix is a valid file system prefix of path.
         """
-        if sys.platform == "linux":
-            # Assume that the file system on Linux is case sensitive
-            return self.isfile(path)
         if not self.isfile(path):
             # Fast path
             return False


Test patch: