Skip to content

fix: attribute action extension handlers by identity; add enabled_when action registration - #561

Merged
knipknap merged 1 commit into
mainfrom
fix/action-registration
Oct 12, 2026
Merged

knipknap merged 1 commit into
mainfrom
fix/action-registration

Conversation

@knipknap

Copy link
Copy Markdown
Contributor

Summary

Two related changes to the action registration machinery, preparing the
ground for #552:

Identity-keyed handler attribution. ActionExtensionRegistry keyed
its addon map by handler.__name__. Every addon following the
extension pattern names its module-level handlers _register_actions
and _update_action_states — sketcher and print-and-cut already
collide on main. Because the map held one entry per name, disabling the
addon that registered last removed all same-named handlers, and
disabling any other addon removed none (stale handlers survived
unload, and the next invoke_setup_handlers ran code from an unloaded
module). The map is now keyed by handler identity, and registering an
already-registered handler is a no-op.

Declarative action state (plugin API 22).
action_registry.register() accepts an enabled_when predicate that
receives the ActionManager and is evaluated on every action state
update, after the extension handlers. The register_actions hook is
also invoked again when an addon is enabled while the window exists
(MainWindow._on_addon_state_changed), so a runtime-enabled addon gets
its actions created without the extension registry. An addon can now
create, place, and enable/disable its actions in the
register_actions hook alone — this retires the
action_extension_registry indirection for new addons; migrating
sketcher and print-and-cut can follow separately.

Verification

  • New tests/ui_gtk/test_action_registries.py (6 tests): same-name
    handler attribution, idempotent setup/state registration,
    enabled_when storage, predicate evaluation, and isolation of a
    failing predicate.
  • pixi run lint and targeted suites: test_action_registries,
    test_move_head_here_action, test_mainwindow,
    addon_manager all pass.

ActionExtensionRegistry keyed its addon map by handler function name,
so addons registering same-named handlers (print-and-cut, sketcher)
collided: disabling one left stale handlers behind or stripped the
other addon's handlers. The map is now keyed by handler identity, and
registering an already-registered handler is a no-op.

The register_actions hook is now also invoked when an addon is enabled
while the window exists, and action_registry.register() accepts an
enabled_when predicate that ActionManager evaluates on every action
state update. Addons can therefore create, place and enable/disable
their actions in the register_actions hook alone, without
action_extension_registry.

Plugin API 22.
@knipknap
knipknap merged commit c3d521b into main Oct 12, 2026
31 checks passed
@github-actions

Copy link
Copy Markdown

🤖 Estimated LLM implementation cost

Replayed each of the 1 commits in this pull request and counted the code lines each commit added or rewrote:

Commit Message Lines (add/rewrite) Est. output tokens Est. output cost
9b5e99c9 fix: attribute action extension handlers by identity; add enabled_when 172 / 12 1,840 $0.0276
Total 184 1,840 $0.0276

Added lines by language: Python 163, Markdown 9

Full estimate

Component Est. tokens Est. cost
Code emission (184 add/rewrite lines) 1,840 $0.0276
Context input (reading touched files) 21,813 $0.0654
Conversation replay (≈15× output) 27,600 $0.0828
Prompting (pull request description) 291 $0.0009
Lower bound (output only) 1,840 $0.0276
Best estimate 51,544 $0.1767

Cost model: ≈10 tokens per code line at $15/Mtok output and $3/Mtok input (assuming heavy prompt caching); input ≈ 15× output for conversation replay; a review round ≈ 42,000 tokens; a failed CI run ≈ 21,000 tokens; file reads capped at 20 kB each.

Active window from first commit to merge: <1 day.

⚠️ Caveat: the lower bound covers only the tokens for emitting the code. The best estimate adds modeled overhead for exploration, conversation replay, review and debug turns, but real sessions vary by tool and task — treat it as an order-of-magnitude figure. Human engineering time is not included.

@knipknap
knipknap deleted the fix/action-registration branch October 15, 2026 12:25

This branch was previously deployed

1 inactive deployment
pypi — 9b5e99c9 Deployed Oct 12, 2026 by knipknap via Build and Publish Wheel #2280
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