pylint
pylint copied to clipboard
Invalid no-name-in-module when shadowing a base module with an alias then calling a method named format on that alias
Bug description
If you shadow a base module with an alias, and then call a method named format() on the alias in the code your are linting, checkers/variables.py:_infer_name_module yields the wrong module, causing checkers/variables.py:_check_module_attrs to fail on line 3120 (in pylint 3.3.3), and return an invalid no-name-in-module on line 3130.
As a simple example, let's say you have the following code structure:
- main.py
- my_module
- __init__.py
- utils.py
And utils.py has the following code:
def format():
pass
def other_method():
pass
If in main.py you have the following code:
import my_module.utils as my_module
my_module.format()
Then pylint will fail with main.py:1:0: E0611: No name 'utils' in module 'my_module.utils' (no-name-in-module). This is obviously invalid, because we're not trying to import utils from my_module.utils in the code as the message suggests, but _infer_name_module is returning the module my_method.utils and then _check_module_attrs is trying to access module.getattr(name)[0] where name is utils, causing this error.
Disclaimer: I know that import my_module.utils as my_module isn't good practice, but it is valid Python, and we have a legacy usecase for it that we unfortunately can't drop.
The wild thing to me is that if main.py instead just does the import, _infer_name_module correctly returns the my_module module, and there is no error. For example:
import my_module.utils as my_module
Even more wild, if you call any other method name on the alias in main.py (at least any that I have tried), _infer_name_module also correctly returns the my_module module, and there is no error. For example:
import my_module.utils as my_module
my_module.other_method()
Less surprising, is that if you don't shadow the base module with the alias, but still call format(), you also don't get an error:
import my_module.utils as different_alias
different_alias.format()
It is something specific about the combination of shadowing the base module with an alias and calling a method called .format() on that alias that causes _infer_name_module to do the inference incorrectly, resulting in this error.
Configuration
Command used
pylint main.py --disable=missing-docstring
Pylint output
************* Module main
main.py:1:0: E0611: No name 'utils' in module 'my_module.utils' (no-name-in-module)
Expected behavior
No failures
Pylint version
pylint 3.3.3
astroid 3.3.8
Python 3.12.4 (main, Aug 28 2024, 13:49:33) [Clang 15.0.0 (clang-1500.3.9.4)]
I also tried older versions, and got the same behavior, for example:
pylint 2.15.0
astroid 2.13.5
Python 3.12.4 (main, Aug 28 2024, 13:49:33) [Clang 15.0.0 (clang-1500.3.9.4)]
OS / Environment
macOS 15.1.1, ubuntu 20.04
Additional dependencies
None
Hi @athariri
Can I work on this issue?