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

E0602 (undefined-variable) - False positive #3298

Open
arquolo opened this issue Dec 9, 2019 · 11 comments
Open

E0602 (undefined-variable) - False positive #3298

arquolo opened this issue Dec 9, 2019 · 11 comments
Labels
C: undefined-variable Issues related to 'undefined-variable' check False Positive 🦟 A message is emitted but nothing is wrong with the code Import system namespace-package Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning

Comments

@arquolo
Copy link

arquolo commented Dec 9, 2019

Given:

> pylint --version
pylint 2.6.0
astroid 2.4.2
Python 3.8.5 (default, Sep  3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]

> tree .
.
├──bug
│  ├── __init__.py
│  └── module.py
└──run_bug.py

with bug/__init__.py:

from .module import *

__all__ = module.__all__

and bug/module.py:

__all__ = ['func']

def func() -> None:
    print('works')

and run_bug.py:

from bug import func

func()

code works:

> python -c "import bug ; bug.func()"
works

and this also works:

> python run_bug.py
works

and bug is here:

> pylint bug run_bug --disable=C
************* Module bug
bug\__init__.py:3:10: E1101: Class 'module' has no '__all__' member (no-member)
bug\__init__.py:3:10: E0602: Undefined variable 'module' (undefined-variable)

Problem is that when * is imported from bug.module, module becomes imported to bug, but PyLint thinks that it doesn't.
All I wanted is to delegate filling of __all__ to submodules, like in asyncio.
Explanation is here.

@jamesbraza
Copy link

I believe I'm hitting this same bug. Seems like the problem lies with some combination of:

  • __all__ in one file
  • Local folder + wildcard importing in another file

Minimal Repro

other_file:

__all__ = ["name"]

name = "foo"

main_file:

from .other_file import *

_ = name

This results in the following error message:

main_file.py: E0602: Undefined variable 'name' (undefined-variable)

Output of pylint --version:

pylint 2.6.0
astroid 2.4.2
Python 3.8.6 (default, Oct 27 2020, 11:18:42)
[Clang 12.0.0 (clang-1200.0.32.27)]

@hippo91
Copy link
Contributor

hippo91 commented Nov 19, 2020

@jamesbraza i'm trying to reproduce your case but i end up with ImportError: attempted relative import with no known parent package when running python3 main.py. The file structure is:

tree . 
.
├── main_file.py
└── other_file.py

0 directories, 2 files

@jamesbraza
Copy link

Hi @hippo91 sorry it looks like I was invoking my minimal repro differently. The error you're getting lies in the concepts from this stack overflow question: Relative imports in Python 3.

There are multiple options at invocations for directly with python3, including:

  • Removing the . from from .other_file import * in main_file.py and use python3 main_file.py
  • Adding a parent directory undef_var_bug and change import to include parent folder
undef_var_bug
├── main_file.py
└── other_file.py

Update import in from undef_var_bug.other_file import *, and invoke via python3 -m undef_var_bug.main_file.

Let me know if neither of those work for you.

@hippo91
Copy link
Contributor

hippo91 commented Nov 26, 2020

@jamesbraza , i tested with the first solution. So i have the following code structure:

tree bug_pylint_3298
bug_pylint_3298
├── main_file.py
└── other_file

with:

cat bug_pylint_3298/main_file.py
from other_file import *

_ = name

and

cat bug_pylint_3298/other_file.py
__all__ = ["name"]

name = "foo"

Then linting is ok:

pylint bug_pylint_3298
************* Module bug_pylint_3298.main_file
bug_pylint_3298/main_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/main_file.py:1:0: W0401: Wildcard import other_file (wildcard-import)
************* Module bug_pylint_3298.other_file
bug_pylint_3298/other_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/other_file.py:3:0: C0103: Constant name "name" doesn't conform to UPPER_CASE naming style (invalid-name)
pylint --version
pylint 2.6.1-dev1
astroid 2.5.0
Python 3.7.9 (default, Nov 26 2020, 08:29:18) 
[GCC 8.3.0]

The false positive undefined-variable message emission doesn't occur. Do you agree?

@arquolo
Copy link
Author

arquolo commented Nov 26, 2020

@hippo91
No, undefined-variable message does occur, you invoke it wrong. I have updated issue

@arquolo arquolo changed the title E0602 False positives E1101 False positive Nov 26, 2020
@jamesbraza
Copy link

@hippo91 so I copied what you'd set up, and I figured out the problem, I don't believe your code actually runs. I know because when I ran it via python -m bug_pylint_3298.main_file, the result was: ModuleNotFoundError: No module named 'other_file'

Your main_file.py begins with from other_file:

from other_file import *

However, it should be:

from bug_pylint_3298.other_file import *

And now the module executes as intended. And then when you invoke pylint, the bug surfaces:

(venv) ➜  bananas_dir pylint bug_pylint_3298
************* Module bug_pylint_3298.main_file
bug_pylint_3298/main_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/main_file.py:1:0: E0401: Unable to import 'bug_pylint_3298.other_file' (import-error)
bug_pylint_3298/main_file.py:1:0: W0401: Wildcard import bug_pylint_3298.other_file (wildcard-import)
bug_pylint_3298/main_file.py:3:4: E0602: Undefined variable 'name' (undefined-variable)
************* Module bug_pylint_3298.other_file
bug_pylint_3298/other_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/other_file.py:3:0: C0103: Constant name "name" doesn't conform to UPPER_CASE naming style (invalid-name)

To fix it in this case, one can add an __init__.py to the bug_pylint_3298 directory, and it seems the error disappears.

(venv) ➜  bananas_dir pylint bug_pylint_3298
************* Module bug_pylint_3298.main_file
bug_pylint_3298/main_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/main_file.py:1:0: W0401: Wildcard import bug_pylint_3298.other_file (wildcard-import)
************* Module bug_pylint_3298.other_file
bug_pylint_3298/other_file.py:1:0: C0114: Missing module docstring (missing-module-docstring)
bug_pylint_3298/other_file.py:3:0: C0103: Constant name "name" doesn't conform to UPPER_CASE naming style (invalid-name)

Seems like pylint:

  1. Fails to realize the code actually runs
  2. Then reports import-error
  3. Finally reports undefined-variable, since it can't seem to parse the wildcard import (hence the preceding import-error)

@jamesbraza
Copy link

However, @arquolo seems to have changed the issue to be from E0602 (undefined-variable) to E1101 (no-member) w.r.t. module.__all__, which now makes my contributions here being sort of off-topic.

@arquolo I think your problem may be in the fact that python -c is different from just invoking pylint.

Invoking via python -c runs the input as if it's a __main__, which is why this works. However, if you were to try and invoke in a plain way, you can see Python can't actually run:

(venv) ➜  bananas_dir tree bug
bug
├── __init__.py
└── module.py

(venv) ➜  bananas_dir python -m bug
/path/to/bin/python: No module named bug.__main__; 'bug' is a package and cannot be directly executed

This may be why pylint can't properly parse the wildcard import... somewhere behind the scenes the real problem may be that the module can't be run. Just my guess, but I am not sure.

@arquolo arquolo changed the title E1101 False positive E0602 False positive Nov 27, 2020
@arquolo
Copy link
Author

arquolo commented Nov 27, 2020

@jamesbraza
I have updated issue, and yet it's still E0602 (it was 2 am here, I misread the log).
It doesn't depend whether module is imported in python -c, or in a plain way in python script, it still works.
I'm not trying to run a package, but import it.
Problem is not with star import, but with star import from subpackage, what imports subpackage too, and Pylint fails with last.

@arquolo arquolo changed the title E0602 False positive E0602 (undefined-variable) - False positive Nov 27, 2020
@hippo91
Copy link
Contributor

hippo91 commented Nov 28, 2020

@arquolo and @jamesbraza thanks for your remarks. I'm now able to reproduce the bug.
Here is attached a reproducer. I can confirm that adding an empty __init__.py file makes the bug disappear. That's why this issue may be linked to #3944.
bug_pylint_3298.tar.gz

@NeilGirdhar
Copy link

I've been running into the same problem. It is as simple as

from .x import y
del x  # undefined-error!

in any file inside a package. Pylint just needs to do what Python does, which is to add an implicit import x.

@DanielNoord DanielNoord added the C: undefined-variable Issues related to 'undefined-variable' check label Nov 18, 2021
@Pierre-Sassoulas Pierre-Sassoulas added False Positive 🦟 A message is emitted but nothing is wrong with the code namespace-package Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning and removed Bug 🪲 labels Jul 4, 2022
@stdedos
Copy link
Contributor

stdedos commented Sep 19, 2023

Is this similar to

src/matplotlib-stubs/__init__.pyi:37:17: E0602: Undefined variable 'PathLike' (undefined-variable)

and https://github.com/hoel-bagard/matplotlib-stubs/blob/f24bcb7808881bf5a1dd7271ce50b0ad0fb0051f/src/matplotlib-stubs/__init__.pyi#L36-L38 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: undefined-variable Issues related to 'undefined-variable' check False Positive 🦟 A message is emitted but nothing is wrong with the code Import system namespace-package Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning
Projects
None yet
Development

No branches or pull requests

8 participants