Skip to content

warn of module level attributes that may get shadowed by importing submodules #10976

@philcerf

Description

@philcerf

Current problem

Consider:

.
└── mymod
    ├── mysubmod
    │   └── __init__.py
    └── __init__.py

With ./mymod/__init__.py having:

mysubmod = "foo"

def p():
    print(mysubmod)

As long as only mymod gets imported (and executed), mymod.mysubmod will be "foo", but once mymod.mysubmod gets imported, it will be the submodule:

>>> import mymod
>>> mymod.p()
foo XXX
>>> import mymod.mysubmod
>>> mymod.p()
<module 'mymod.mysubmod' from '/home/calestyo/test/pm/mymod/mysubmod/__init__.py'>
>>>

The same happens also with from … import …s.

Right now, pylint would only warn about the broken naming convention:

mymod/__init__.py:2:0: C0103: Constant name "mysubmod" doesn't conform to UPPER_CASE naming style (invalid-name)

but it may not immediately be clear that following that would have prevented one from more damage (assuming one would follow the convention to make module names all lower case).

Desired solution

IMO it would at least be nice if C0103 could mention that such names may easily be shadowed by module names.

Even better would be an actual check whether there's any submodule that could cause the shadowing.

The difficulty there is that this doesn't only affect names in __init__.py.
Consider e.g. a case where another_module.py in the package mymod does something like:

if bla:
    mymod.mysubmod = "stupid attribute"

which may either get overwritten itself or overwrite the imported sub module.

Thanks,
Philippe

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs triage 📥Just created, needs acknowledgment, triage, and proper labelling

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions