Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't issue no-redef with conditional imports #13914

Open
bersbersbers opened this issue Oct 17, 2022 · 5 comments · Fixed by #13969
Open

Don't issue no-redef with conditional imports #13914

bersbersbers opened this issue Oct 17, 2022 · 5 comments · Fixed by #13969
Labels
bug mypy got something wrong

Comments

@bersbersbers
Copy link

bersbersbers commented Oct 17, 2022

Bug Report

When an exception is caught from a block with a single import statement, one can be certain that the import failed (right?).

When an import fails, a to-be-imported function is not defined.

If a function is not defined, mypy should not issue a no-redef message.

To Reproduce

pip install overrides

"""Feature request: detect failed imports and suppress no-redef."""
try:
    from overrides import overrides
except ModuleNotFoundError:
    # mypy issues no-redef
    def overrides() -> None:
        pass

print(overrides)

Expected Behavior

No message

Actual Behavior

bug.py:5: error: Name "overrides" already defined (possibly by an import) [no-redef]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: mypy 0.982 (compiled: yes)
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.10.8
@bersbersbers bersbersbers added the bug mypy got something wrong label Oct 17, 2022
@bersbersbers

This comment was marked as outdated.

@bersbersbers
Copy link
Author

A workaround can be found in mkorpela/overrides#109 (comment).

hauntsaninja added a commit that referenced this issue Nov 3, 2022
This changes our importing logic to be more consistent and to treat
import statements more like assignments.

Fixes #13803, fixes #13914, fixes half of #12965, probably fixes #12574

The primary motivation for this is when typing modules as protocols, as
in #13803. But it turns out we already allowed redefinition with "from"
imports, so this also seems like a nice consistency win.

We move shared logic from visit_import_all and visit_import_from (via
process_imported_symbol) into add_imported_symbol. We then reuse it in
visit_import.

To simplify stuff, we inline the code from add_module_symbol into
visit_import. Then we copy over logic from add_symbol, because MypyFile
is not a SymbolTableNode, but this isn't the worst thing ever.

Finally, we now need to check non-from import statements like
assignments, which was a thing we weren't doing earlier.
@bersbersbers
Copy link
Author

@hauntsaninja I may be missing something, but the code example I posted in #13914 (comment) still issues the same mypy error:

C:\Code\project>mypy --version
mypy 1.0.0+dev.a4da89e0543ee0d213b30216c9e15a5d00fcd578 (compiled: no)

C:\Code\project>mypy --no-incremental project\project.py
project\project.py:6: error: Name "overrides" already defined (possibly by an import)  [no-redef]
Found 1 error in 1 file (checked 1 source file)

Using overrides==7.3.1

@hauntsaninja hauntsaninja reopened this Nov 3, 2022
@bersbersbers
Copy link
Author

bersbersbers commented Feb 7, 2023

Just for the record (because I had been hoping it might have been fixed), this is still an issue on 1.0.0.

@bersbersbers
Copy link
Author

bersbersbers commented Feb 12, 2023

Some more details:

"""With `overrides==7.3.1` installed, mypy issues `no-redef` in `except`."""
from typing import Callable, TypeVar

F = TypeVar("F", bound=Callable)
try:
    from overrides import override
except ModuleNotFoundError:
    def override(method: F) -> F:
        return method

print(override)

The workaround works , but stops working when removing overrides:

"""The workaround silences `mypy`, but now mypy issues `no-redef` in *`try`* if `overrides` is *not* installed."""
from typing import Callable, TypeVar

F = TypeVar("F", bound=Callable)

# Workaround
override: Callable[[F], F]
try:
    from overrides import override
except ModuleNotFoundError:
    def override(method: F) -> F:
        return method

print(override)

This is a problem if one uses a construct such as this to import typing.override (from Python 3.12 on):

"""Prepare for Python 3.12."""
from typing import Callable, TypeVar

F = TypeVar("F", bound=Callable)

# Workaround
override: Callable[[F], F]
try:
    from typing import override
except ModuleNotFoundError:
    def override(method: F) -> F:
        return method

print(override)

For the record, this works:

"""Prepare for Python 3.12."""
import sys
from typing import Callable, TypeVar

F = TypeVar("F", bound=Callable)

if sys.version_info >= (3, 12):
    from typing import override
else:
    def override(method: F) -> F:
        return method

print(override)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants