Skip to content

false positive 'useless-import-alias' error for mypy-compatible explicit re-exportsΒ #6006

@jab

Description

@jab

Bug description

Suppose a package has the following layout:

package/
  _submodule1.py  # defines Api1
  _submodule2.py  # defines Api2
  __init__.py     # imports and re-exports Api1 and Api2

Since the submodules here implement public APIs, __init__.py imports and re-exports them, expecting users to import them from the public, top-level package, e.g. from package import Api1.

Since the implementations of Api1 and Api2 are complex, they are split into _submodule1.py and _submodule2.py for better maintainability and separation of concerns.

So __init__.py looks like this:

from ._submodule1 import Api1 as Api1
from ._submodule2 import APi2 as Api2

The reason for the as aliases here is to be explicit that these imports are for the purpose of re-export (without having to resort to defining __all__, which is error-prone). Without the as aliases, popular linters such as mypy will raise an "implicit re-export" error (docs -- part of mypy --strict).

However, pylint does not currently understand this usage, and raises "useless-import-alias" errors.

Example real-world code triggering pylint false positive errors: https://github.com/jab/bidict/blob/caf703e959ed4471bc391a7794411864c1d6ab9d/bidict/__init__.py#L61-L78

Configuration

No response

Command used

pylint

Pylint output

************* Module bidict
bidict/__init__.py:61:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:61:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:62:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:62:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:62:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:63:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:63:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:64:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:65:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:66:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:66:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:67:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:68:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:69:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:69:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:69:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:70:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:70:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:70:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:70:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:70:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:71:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:71:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:72:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:72:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:72:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:73:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)
bidict/__init__.py:74:0: C0414: Import alias does not rename original package (useless-import-alias)

Expected behavior

No "useless-import-alias" errors should be flagged.

Pylint version

pylint 2.13.2
astroid 2.11.2
Python 3.10.2 (main, Feb  2 2022, 07:36:01) [Clang 12.0.0 (clang-1200.0.32.29)]

OS / Environment

No response

Additional dependencies

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Enhancement ✨Improvement to a componentNeeds decision πŸ”’Needs a decision before implemention or rejectionNeeds specification πŸ”Accepted as a potential improvement, and needs to specify edge cases, message names, etc.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions