Skip to content

no-redundant-module-alias-exports

Do not manufacture public APIs from private names or replace the current module.

Why

Binding a public name to a private implementation creates two names for one API and disguises the intended visibility boundary. Replacing the current module similarly mutates import identity at runtime in a way static tools cannot model. Both forms make navigation, introspection, and compatibility ownership surprising.

Fix

Define maintained APIs under their public names and update local callers directly. Import the canonical path inside maintained code. If a compatibility module is still required, expose its supported names with explicit same-name imports grouped by source module.

Examples

Before — flagged Do not replace a compatibility module at runtime
legacy/settings.py
import sys
from canonical import settings as _canonical
sys.modules[__name__] = _canonical
After — preferred Expose the supported compatibility surface explicitly
legacy/settings.py
from canonical.settings import (
Settings as Settings,
load as load,
)
Before — flagged Define a public helper under its public name
pagination.py
def _encode_cursor(value: str) -> str:
return value
encode_phone_number_cursor = _encode_cursor
After — preferred Give the implementation its intended public name
pagination.py
def encode_phone_number_cursor(value: str) -> str:
return value