Skip to content

fix(parser): treat relative imports from __future__ as ordinary imports - #29870

Closed
bniladridas wants to merge 2 commits into
astral-sh:mainfrom
bniladridas:fix/relative-future-import
Closed

bniladridas wants to merge 2 commits into
astral-sh:mainfrom
bniladridas:fix/relative-future-import

Conversation

@bniladridas

Copy link
Copy Markdown

Summary

Ruff treated from .__future__ import x as a future import, even though the leading dot makes it an ordinary relative import of a sibling module named __future__. CPython accepts this statement.

Before this change, ruff check on from .__future__ import x reported F407 Future feature 'x' is not defined and from .__future__ import annotations enabled future annotations.

The fix requires level == 0 wherever __future__ imports are detected, so relative imports are no longer validated, bound, or tracked as future imports. Fixes #29683.

Test Plan

  • Reproduced with ruff check --isolated --stdin-filename pkg/e.py on from .__future__ import x: before the fix it reported F407; after the fix it reports F401 (unused import), which is the expected behavior for an ordinary import.
  • Verified from .__future__ import annotations no longer enables future annotations.
  • cargo test -p ruff_python_parser passed.
  • cargo test -p ruff_linter --lib passed (2832 tests).

No test files were added or modified.

A relative import such as `from .__future__ import x` names a sibling module, not the future-features module. Only treat a level-0 `from __future__ import ...` as a future import, so relative imports are no longer validated, bound, or tracked as future imports. Fixes astral-sh#29683.

Signed-off-by: Niladri Das <125604915+bniladridas@users.noreply.github.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-01T01:22:34.468032Z 614b8bf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 614b8bfe34

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
for alias in names {
if module != Some("__future__") && &alias.name == "*" {
if !(level == 0 && module == Some("__future__")) && &alias.name == "*" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply the absolute-import guard to PYI044

When Ruff analyzes a .pyi file, statement() still calls from_future_import for every StmtImportFrom, and that helper checks the module name but not level. As a result, from .__future__ import annotations still gets PYI044, whose fix can remove this ordinary sibling-module import. Gate the stub rule on level == 0 and add a .pyi regression case.

AGENTS.md reference: AGENTS.md:L210-L210

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cf83429.

// Skip the regular `from`-import validations after reporting the lazy-specific
// syntax error with the highest precedence.
} else if matches!(module.as_deref(), Some("__future__")) {
} else if *level == 0 && matches!(module.as_deref(), Some("__future__")) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Test the relative-future-import semantics

There are no parser or linter test cases for from .__future__ ..., so the new feature-validation and future-import-boundary behavior can regress without the suite detecting it. Add focused cases for a relative annotations import and for a relative import followed by an absolute future import.

AGENTS.md reference: AGENTS.md:L210-L210

Useful? React with 👍 / 👎.

Gate the stub rule on level == 0 so a relative import from a sibling module named __future__ is not flagged. Fixes the Codex P2 on PR astral-sh#29870.

Signed-off-by: Niladri Das <125604915+bniladridas@users.noreply.github.com>
@MichaReiser MichaReiser added the bot:ai-policy-close Auto-close a PR due to a violation of the org AI policy label Nov 1, 2026
@astral-automations-bot

Copy link
Copy Markdown
Contributor

We support using AI (i.e., LLMs) while coding. However, AI should not be used to communicate with maintainers.

Please read and follow our AI policy when submitting issues and pull requests.

@bniladridas

Copy link
Copy Markdown
Author

That's weird @MichaReiser , what you think AI is used in here for the pr body? or something specific? on the inline thread. perhaps if the closing was this pr was a mistake I can wait for your response anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:ai-policy-close Auto-close a PR due to a violation of the org AI policy

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Relative imports from a module named __future__ are treated as future imports

2 participants