Skip to content

Don't add names that are bound in only one branch of an undecidable if - #64

Merged
hakancelikdev merged 2 commits into
claude/issuelari-gorme-fpbbfdfrom
fix/conditional-names
Sep 25, 2026
Merged

hakancelikdev merged 2 commits into
claude/issuelari-gorme-fpbbfdfrom
fix/conditional-names

Conversation

@hakancelikdev

Copy link
Copy Markdown
Owner

From the core-dev review of the integration branch. The problem also exists on main.

Problem

if sys.platform == "win32":
    class WinOnly: ...

WinOnly was added to __all__, so from module import * raised AttributeError on every other platform. Stdlib modules such as ctypes, subprocess, selectors and multiprocessing.* follow this pattern.

Fix

  • New relate.is_conditional_only and rule _rule_not_conditional_only.
  • A name is not added when it is bound in only one branch of an if whose test can't be decided statically. Tests that can be decided (TYPE_CHECKING, the main guard, constants) are already handled by is_runtime_missing.
  • elif chains are followed: each level must bind the name in the other branch. A binding can be an assignment, def/class or import.
  • Names that are already listed are still kept. # unexport: public still adds a name explicitly.
  • Documented in "Useful features" and the changelog.

This is a behavior change: a name defined only inside e.g. if HAS_NUMPY: is no longer added automatically. I chose this conservative default because adding it produces an __all__ that breaks star imports on the other branch. try/except ImportError bodies are left as they were.

Tests

  • test_names_bound_in_one_branch_only covers if/elif/else binding in every branch, a def vs an assignment, an import in the other branch, and the # unexport: public override. It fails before this change.
  • test_listed_conditional_name_is_kept covers an already-listed conditional name.
  • 3.10 / 3.12 / 3.14, pre-commit, mypy and the self-check all pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_019P9bvuGwAyVCNUdsAYPB1V


Generated by Claude Code

`if sys.platform == "win32": class WinOnly: ...` added WinOnly to __all__,
so `from module import *` failed on every other platform. A name is only
added when every branch of such an if binds it (following elif chains).
Listed names are still kept and `# unexport: public` still adds one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019P9bvuGwAyVCNUdsAYPB1V
…nto fix/conditional-names

# Conflicts:
#	docs/changelog.md
@hakancelikdev
hakancelikdev merged commit 6eb851e into claude/issuelari-gorme-fpbbfd Sep 25, 2026
26 checks passed
@hakancelikdev
hakancelikdev deleted the fix/conditional-names branch October 2, 2026 22:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants