mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Imports that shadow names cannot be made to type-check

Open xen0n opened this issue 1 year ago • 2 comments

Bug Report

--allow-redefinition does not come into effect for imports that shadow a previous import with incompatible types. Even if the previous name is first del'd the error still persists, whether --allow-redefinition is enabled or not.

I found this during work on https://github.com/python/typeshed/pull/11374#issuecomment-1968999481. The upstream library first does a star-import re-exporting hundreds of names, then shadows at least one of them with a wrapper type. The star-import cannot be rewritten due to the sheer number of imported names, but then the name shadowing cannot be prevented.

To Reproduce

Minimized multi-file example
# $ tree .
# .
# ├── bar.py
# ├── foo.py
# ├── __init__.py
# └── py.typed

# foo.py & bar.py
class Repository:
    pass

# __init__.py
from .foo import Repository
del Repository  # this doesn't work
from .bar import Repository

# Both fails in the same way:
# $ mypy .
# $ mypy --allow-redefinition .
#
# __init__.py:3: error: Incompatible import of "Repository" (imported name has type "type[p.bar.Repository]", local name has type "type[p.foo.Repository]")  [assignment]
# Found 1 error in 1 file (checked 3 source files)

One-file example:

  • Gist URL: https://gist.github.com/mypy-play/826f927d282282e8f8d51bc4411b4b94
  • Playground URL: https://mypy-play.net/?mypy=master&python=3.12&flags=allow-redefinition&gist=826f927d282282e8f8d51bc4411b4b94
from hashlib import md5 as foo
del foo
from sys import path as foo

Expected Behavior

No errors.

Actual Behavior

main.py:3: error: Incompatible import of "foo" (imported name has type "list[str]", local name has type "Callable[[Buffer, DefaultNamedArg(bool, 'usedforsecurity')], _Hash]")  [assignment]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.8.0 & master branch
  • Mypy command-line flags: none & --allow-redefinition
  • Mypy configuration options from mypy.ini (and other config files): n/a
  • Python version used: 3.11 & 3.12

xen0n avatar Mar 01 '24 08:03 xen0n

Here's your example modified a bit to use star imports:

from hashlib import *
from sys import path as md5  # error: Incompatible import of "md5" (imported name has type "list[str]", local name has type "Callable[[Buffer, DefaultNamedArg(bool, 'usedforsecurity')], _Hash]")  [assignment]

srittau avatar Mar 15 '24 12:03 srittau

MyPy and Pyright seem to disagree here, with Pyright reflecting the correct runtime type:

from sys import path as md5
from hashlib import *

reveal_type(md5)

Mypy:

main.py:2: error: Incompatible import of "md5" (imported name has type "Callable[[Buffer, DefaultNamedArg(bool, 'usedforsecurity')], _Hash]", local name has type "list[str]") [assignment] main.py:4: note: Revealed type is "builtins.list[builtins.str]" Found 1 error in 1 file (checked 1 source file)

https://mypy-play.net/?mypy=master&python=3.12&flags=allow-redefinition&gist=f2806f836ad111efc7de683277e35d7c

Pyright:

Type of "md5" is "(string: Buffer = b"", *, usedforsecurity: bool = True) -> _Hash"

https://pyright-play.net/?code=GYJw9gtgBAzgnjKBLCAHMIAuVUENMAWUuiEAJgKwCwAUKJFASQQDZIBGyaG2AVLbRABTAG5DcLAPqY4qIQApyFAJS0gA

kristapratico avatar Sep 10 '24 18:09 kristapratico