Skip to content

Idea: warn when a re-exported name is imported #13507

Open
@dimaqq

Description

@dimaqq

Consider a library like this:

# lib/__init__.py
from .exceptions import LibError
from .client import Client

__all__ = [
    "Client",
    "LibError",
]

# lib/exceptions.py
class LibError(Exception): ...

# lib/client.py
from .exceptions import LibError

class Client:
    def some_method(self):
        if something.bad:
            raise LibError("thou shalt not pass")

Then the user code imports these names:

from lib import LibError  # OK, explicitly re-exported

from lib.exceptions import LibError  # OK, that's where it's defined

from lib.client import LibError  # WARN: lib.exceptions.LibError is re-exported via lib.client

from lib.client import Client  # OK

The reason to warn is that lib.client can change, for example to raise exception.MoreSpecificError instead, which would not be a breaking change is MoreSpecificError inherits from LibError.

However, in that case, LibError may no longer be re-exported via lib.client.

Thus user code that depends on LibError name being present on lib.client is mistaken.

Ideas how this could be implemented:

  1. get the __qualname__ for the imported name
  2. check if the import path is different from qualname
  3. check if the imported name is also available at lib top level or
  4. check if the imported name is available at some intermediate level between lib and qualname
  5. suggest a more direct import

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-inferenceRequires more advanced type inference.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions