Skip to content

Binder: explicit submodule import keeps the proxy class (#323) - #326

Merged
b-re-w merged 1 commit into
developfrom
feat/binder-submodule-import-keeps-class
Oct 25, 2026
Merged

b-re-w merged 1 commit into
developfrom
feat/binder-submodule-import-keeps-class

Conversation

@b-re-w

@b-re-w b-re-w commented Oct 25, 2026

Copy link
Copy Markdown
Member

Closes #323

  • Cause: when androidx.compose.ui.Modifier is not yet in sys.modules, 'import androidx.compose.ui.Modifier' creates it through the finder. importlib then binds the module onto the parent (setattr after _load_unlocked), which shadows the proxy class. If the module is already loaded, CPython returns it without touching the parent.
  • Fix: the parent's module type guards setattr with class_wins_over_module (from Binder: a public companion object is reachable from Python as a value (Owner.Companion) #322), in the adapter's adapted modules and in PythonProxySource's per-module types. The class stays, and its getattr serves the module's statics. 'import androidx.compose.ui.Modifier as M' therefore binds the class. Reads are unchanged, since only writes go through setattr.
  • SPEC U-4: one sentence.
  • Tests (WalkedArtifactCompanionHandleTest), each removing the module from sys.modules first to force the finder path:
    • import then from-import gives the class.
    • from-import then import keeps the class.
    • A repeat import with the module already loaded keeps the class.
    • 'import ... as M' gives the class.
      Three of the four fail against the old code. The 'already loaded' case passes there too, as CPython predicts.
  • Binder: a companion-object module shadows a same-named factory function (TextRange(2)) #78's callable module (TextRange) is protected by the parent-declaration check. The compose fixture's TextFieldStateRenderTest exercises it and passes.
  • Results: artifact fixture 50/50, ksp app 80/80, compose 129/129, python-multiplatform desktopTest 643/643, androidNative compile.

…on its parent (#323)

When the import system creates pkg.Owner through the finder it binds the module onto pkg after the
loader returns, shadowing the proxy class pkg.Owner (a companion makes Owner both). The parent's
module type now guards __setattr__ with class_wins_over_module, in the adapter and in
PythonProxySource's per-module types, so the class stays and its __getattr__ serves the module's
statics; 'import pkg.Owner as M' binds the class. Reads are unchanged.
@b-re-w
b-re-w merged commit 966a897 into develop Oct 25, 2026
@b-re-w
b-re-w deleted the feat/binder-submodule-import-keeps-class branch October 25, 2026 11:52
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.

1 participant