Skip to content

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

Open
@athariri

Description

@athariri

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

Metadata

Metadata

Assignees

Labels

Bug 🪲Needs PRThis issue is accepted, sufficiently specified and now needs an implementation

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions