Skip to content

Keep listed names that exist at runtime without a visible binding - #61

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

hakancelikdev merged 2 commits into
claude/issuelari-gorme-fpbbfdfrom
fix/keep-runtime-provided-names

Conversation

@hakancelikdev

Copy link
Copy Markdown
Owner

From the second review of the integration branch. These names were removed from __all__ (on main as well), so from m import * silently lost them. That contradicts the rule added in #47: names already listed that still exist are kept.

Cases

Case Why the name exists Stdlib examples
Submodule listed in a package's __init__.py from pkg import * imports listed submodules (importlib._handle_fromlist) xml/__init__.py
Module __getattr__ (PEP 562) served lazily concurrent.futures, typing, zoneinfo
globals().update(...), vars(), @enum.global_enum added to the namespace dynamically re, calendar, inspect
match captures (case (Cap,):, **rest) real module bindings, held as str not ast.Name –

Fix

  • Analyzer / Session.get_expected_all take an optional path, and main passes it. For a package's __init__.py, sibling *.py modules and subdirectories are collected as submodules.
  • _ModuleBindings.has_dynamic_namespace is set by a module-level def __getattr__, or by any globals/vars/global_enum reference. In that case every listed name is kept, the same as with a star import.
  • Match captures and mapping rests are bound in collect.
  • These only affect names that are already listed. Nothing new is added.
  • The docs are updated.

Tests

test_names_provided_at_runtime_are_kept (4 sub-cases) and test_listed_submodules_of_a_package_are_kept both fail before this change. I also checked end to end with the review's package repro: pkg/__init__.py is no longer changed. 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

These were removed from __all__, so `from m import *` silently lost them:
- submodules listed in a package's __init__.py, which the star import loads
- names served by a module __getattr__ (PEP 562)
- names added through globals() / vars() or @enum.global_enum
- match-statement captures, which were not seen as module bindings

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

# Conflicts:
#	src/unexport/analyzer.py
#	src/unexport/session.py
@hakancelikdev
hakancelikdev merged commit befabb6 into claude/issuelari-gorme-fpbbfd Sep 25, 2026
26 checks passed
hakancelikdev pushed a commit that referenced this pull request Oct 2, 2026
- Bump the version to 0.5.0.
- Date the changelog section and add the entries that were missing for
  #53, #54, #56, #57, #58, #60, #61 and #62.
- Fix license_files: `file: LICENSE` is not a valid glob, so LICENSE was
  left out of the built sdist and wheel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019P9bvuGwAyVCNUdsAYPB1V
@hakancelikdev
hakancelikdev deleted the fix/keep-runtime-provided-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