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

Invalid no-name-in-module when shadowing a base module with an alias then calling a method named format on that alias #10193

Open
ahariri-splunk opened this issue Jan 19, 2025 · 0 comments
Labels
Bug 🪲 Needs PR This issue is accepted, sufficiently specified and now needs an implementation

Comments

@ahariri-splunk
Copy link

ahariri-splunk commented Jan 19, 2025

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
@ahariri-splunk ahariri-splunk added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Jan 19, 2025
@Pierre-Sassoulas Pierre-Sassoulas added Bug 🪲 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 Jan 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🪲 Needs PR This issue is accepted, sufficiently specified and now needs an implementation
Projects
None yet
Development

No branches or pull requests

2 participants