astral-sh / astral-sh/ruff

[feature-request] Require first-party imports to target highest exporting non-ancestor module

Open
#1,107 3 comments 11 reactions 0 assignees View on GitHub
needs-decision rule
Dominant language
Rust
Stars
49.7k
Forks
2.4k
Avg merge
2d 1h
Merged PRs (30d)
458

Description

A symbol can be defined in one module and re-exported from several others. When importing a symbol from an external typed library, the convention is to import from as close to the root as possible. This is how popular auto-import resolution tools work (see my very similar post in [this pylance discussion](https://github.com/microsoft/pylance-release/discussions/3050#discussioncomment-3197660):

>If the same name is exported from multiple modules, the auto-import logic in pyright and pylance prefer the shortest module path. Only the shortest path is listed in the completion list, and the longer paths are de-duped.

In large projects, sometimes you have big submodules that you want to provide an "internal public" interface for-- e.g. if you have a large submodule `project.foo`, you might want project-internal code to import only from `project.foo` itself, rather than `project.foo.*` submodules.

I'd like to suggest that `ruff` offer a rule that enforces this by requiring internal imports resolve to the shortest module that exposes a symbol. So:

```
### project/foo/__init__.py
# redundant alias is necessary to expose `BAR` as public for `project.foo`
from .bar import BAR as BAR

### project/foo/bar.py
BAR = "BAR"

### project/baz.py
from project.foo.bar import BAR # ERROR: should import from project.foo instead
```

Contributor guide

Open the contributing guide

Research direction

No Ruff files, tests, or entry points are named in the issue. Start by locating Ruff’s existing first-party import resolution and related rule tests, then compare the reported project/foo example with current behavior. Done means internal imports resolve to the shortest non-ancestor module that exposes the symbol.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.