Bug Report
When the Python install path contains a symlink (common with Homebrew, pyenv, and python-build-standalone), mypy/pyinfo.py:getsyspath() fails to exclude the stdlib from SearchPaths.package_path. As a result, stdlib modules that are unavailable at the configured --python-version are reported as [import-untyped] instead of [import-not-found]. A pre-existing # type: ignore[import-not-found] comment that works on platforms without symlinks (e.g. a typical Linux CI runner) stops working for users on macOS Homebrew, even with everything else identical.
To Reproduce
Minimal repro, run on a host whose Python's stdlib path is reached via a symlink (Homebrew always installs formulae as opt/<name> → Cellar/<name>/<version>):
$ python --version
Python 3.13.7
$ echo "import tomllib" > /tmp/t.py
$ mypy --python-version=3.10 /tmp/t.py
/tmp/t.py:1: error: Skipping analyzing "tomllib": module is installed, but missing library stubs or py.typed marker [import-untyped]
Same command in python:3.13-slim Linux container (no symlinks in the install path):
/tmp/t.py:1: error: Cannot find implementation or library stub for module named "tomllib" [import-not-found]
Both behaviours are deterministic; reproduced with env -i HOME=/tmp/empty --no-incremental --cache-dir=/dev/null, and with pip freeze byte-identical between the two environments.
Expected Behavior
Same error code on both platforms. With --python-version=3.10, tomllib doesn't exist in the configured stdlib, so [import-not-found] is the right diagnosis regardless of whether the host's install path is symlinked.
Actual Behavior
Inspecting the module finder shows the divergence:
# macOS, Homebrew Python 3.13.7
package_path = (
'/opt/homebrew/Cellar/python@3.13/3.13.7/.../lib/python313.zip',
'/opt/homebrew/Cellar/python@3.13/3.13.7/.../lib/python3.13', # stdlib leaked in
'/opt/homebrew/Cellar/python@3.13/3.13.7/.../lib/python3.13/lib-dynload',
'/tmp/mypy-py313/lib/python3.13/site-packages',
)
find_module('tomllib') -> ModuleNotFoundReason.FOUND_WITHOUT_TYPE_HINTS
# Linux, python:3.13-slim
package_path = ('/usr/local/lib/python3.13/site-packages', ...)
find_module('tomllib') -> ModuleNotFoundReason.NOT_FOUND
As far as I can tell, the divergence comes from mypy/pyinfo.py:getsyspath(). It builds excludes from sys.base_exec_prefix and sysconfig.get_path("stdlib"), then filters sys.path with os.path.abspath, which does not resolve symlinks. On Homebrew, excludes contains /opt/homebrew/opt/python@3.13/... (the symlink path) while the entries in sys.path come pre-resolved to /opt/homebrew/Cellar/python@3.13/3.13.7/..., so the set membership check never matches and the stdlib stays in package_path:
>>> stdlib_in_excludes = sysconfig.get_path("stdlib")
>>> stdlib_in_sys_path = next(p for p in sys.path if p.endswith("/lib/python3.13"))
>>> os.path.abspath(stdlib_in_excludes) == os.path.abspath(stdlib_in_sys_path)
False
>>> os.path.realpath(stdlib_in_excludes) == os.path.realpath(stdlib_in_sys_path)
True
>>> os.path.samefile(stdlib_in_excludes, stdlib_in_sys_path)
True
I haven't tested a patch, but my guess is that using os.path.realpath (or os.path.samefile for the comparison) in getsyspath() (both for the excludes construction and the sys.path normalisation) would address this.
Environment
- Mypy version used: 1.20.2 (compiled: yes)
- Mypy command-line flags:
--python-version=3.10
- Mypy configuration: none required (reproduces with empty env and no config file)
- Python version used: 3.13.7 (Homebrew) and 3.13.13 (python-build-standalone via
uv) on macOS aarch64 — both reproduce. python:3.13-slim Linux container does not reproduce.
Bug Report
When the Python install path contains a symlink (common with Homebrew, pyenv, and python-build-standalone),
mypy/pyinfo.py:getsyspath()fails to exclude the stdlib fromSearchPaths.package_path. As a result, stdlib modules that are unavailable at the configured--python-versionare reported as[import-untyped]instead of[import-not-found]. A pre-existing# type: ignore[import-not-found]comment that works on platforms without symlinks (e.g. a typical Linux CI runner) stops working for users on macOS Homebrew, even with everything else identical.To Reproduce
Minimal repro, run on a host whose Python's stdlib path is reached via a symlink (Homebrew always installs formulae as
opt/<name>→Cellar/<name>/<version>):Same command in
python:3.13-slimLinux container (no symlinks in the install path):Both behaviours are deterministic; reproduced with
env -i HOME=/tmp/empty --no-incremental --cache-dir=/dev/null, and withpip freezebyte-identical between the two environments.Expected Behavior
Same error code on both platforms. With
--python-version=3.10,tomllibdoesn't exist in the configured stdlib, so[import-not-found]is the right diagnosis regardless of whether the host's install path is symlinked.Actual Behavior
Inspecting the module finder shows the divergence:
As far as I can tell, the divergence comes from
mypy/pyinfo.py:getsyspath(). It buildsexcludesfromsys.base_exec_prefixandsysconfig.get_path("stdlib"), then filterssys.pathwithos.path.abspath, which does not resolve symlinks. On Homebrew,excludescontains/opt/homebrew/opt/python@3.13/...(the symlink path) while the entries insys.pathcome pre-resolved to/opt/homebrew/Cellar/python@3.13/3.13.7/..., so thesetmembership check never matches and the stdlib stays inpackage_path:I haven't tested a patch, but my guess is that using
os.path.realpath(oros.path.samefilefor the comparison) ingetsyspath()(both for theexcludesconstruction and thesys.pathnormalisation) would address this.Environment
--python-version=3.10uv) on macOS aarch64 — both reproduce.python:3.13-slimLinux container does not reproduce.