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

E0601: used-before-assignment false positive for import under TYPE_CHECKING check #7368

Closed
Rogdham opened this issue Aug 27, 2022 · 5 comments · Fixed by #7370
Closed

E0601: used-before-assignment false positive for import under TYPE_CHECKING check #7368

Rogdham opened this issue Aug 27, 2022 · 5 comments · Fixed by #7370
Labels
C: used-before-assignment Issues related to 'used-before-assignment' check Control flow Requires control flow understanding False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Milestone

Comments

@Rogdham
Copy link
Contributor

Rogdham commented Aug 27, 2022

Bug description

# pylint: disable=missing-module-docstring, missing-function-docstring

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from typing_extensions import assert_type
else:

    def assert_type(val, _):
        return val

ANSWER = 42
assert_type(ANSWER, int)

Configuration

No response

Command used

pylint a.py

Pylint output

************* Module a
a.py:13:0: E0601: Using variable 'assert_type' before assignment (used-before-assignment)

------------------------------------------------------------------
Your code has been rated at 2.86/10 (previous run: 2.86/10, +0.00)

Expected behavior

This is a false positive, as assert_type is defined in both branches of the if.

Pylint version

pylint 2.15.0
astroid 2.12.4
Python 3.10.6 (main, Aug  3 2022, 17:39:45) [GCC 12.1.1 20220730]

OS / Environment

Archlinux

Additional dependencies

astroid==2.12.4
dill==0.3.5.1
isort==5.10.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
platformdirs==2.5.2
pylint==2.15.0
tomli==2.0.1
tomlkit==0.11.4
wrapt==1.14.1

@Rogdham Rogdham added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Aug 27, 2022
@Rogdham
Copy link
Contributor Author

Rogdham commented Aug 27, 2022

The issue is still here if the import is from stdlib instead of an external module:

# pylint: disable=missing-module-docstring, missing-function-docstring

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections import defaultdict
else:
    def defaultdict():
        return {}

defaultdict()
************* Module a
c.py:11:6: E0601: Using variable 'defaultdict' before assignment (used-before-assignment)

------------------------------------------------------------------
Your code has been rated at 1.67/10 (previous run: 1.67/10, +0.00)

@Pierre-Sassoulas Pierre-Sassoulas added the Control flow Requires control flow understanding label Aug 27, 2022
@jacobtylerwalls jacobtylerwalls added C: used-before-assignment Issues related to 'used-before-assignment' check Needs PR This issue is accepted, sufficiently specified and now needs an implementation and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Aug 27, 2022
@jacobtylerwalls
Copy link
Member

Good catch. 3159b17 only checked AssignName nodes, not FunctionDef nodes, as here. Would you like to prepare a PR?

@jacobtylerwalls jacobtylerwalls added the False Positive 🦟 A message is emitted but nothing is wrong with the code label Aug 27, 2022
@DanielNoord
Copy link
Collaborator

@jacobtylerwalls Just for my understanding, why are we special-casing TYPE_CHECKING here?

# pylint: disable=missing-module-docstring, missing-function-docstring

from typing import value

if value:
    from typing_extensions import assert_type
else:

    def assert_type(val, _):
        return val


ANSWER = 42
assert_type(ANSWER, int)

This doesn't raise, only a no-name-in-module warning.

@jacobtylerwalls
Copy link
Member

Assignments under if TYPE_CHECKING are always false at runtime, so from the perspective of used-before-assignment, we can assume they never happened. With some control-flow knowledge that the name is defined in the else, though, we can avoid assuming the name was never assigned. Here the else is only checked for assignments, not function definitions.

@Rogdham
Copy link
Contributor Author

Rogdham commented Aug 27, 2022

Would you like to prepare a PR?

@jacobtylerwalls I did what I could in #7370, but the pylint codebase is foreign to me so I'm sure I missed tons of things!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: used-before-assignment Issues related to 'used-before-assignment' check Control flow Requires control flow understanding False Positive 🦟 A message is emitted but nothing is wrong with the code Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants