fix(lazy): return value takes precedence over imperative output in mo.lazy - #10128
fix(lazy): return value takes precedence over imperative output in mo.lazy#10128SarthakB11 wants to merge 1 commit into
Conversation
A deferred render passed to mo.lazy runs under the owning cell's execution context, so imperative mo.output.append/replace calls inside it broadcast to and overwrite that cell's output, hiding the lazy widget. A callable that both appended and returned a value therefore showed the appended content instead of the returned one. Isolate the deferred callable's imperative output into a throwaway CellOutputList and drop its broadcasts, then reconcile: the returned value wins, falling back to the accumulated imperative output only when the callable returns nothing. This mirrors how a cell reconciles its last expression with mo.output calls. Fixes marimo-team#9540 Signed-off-by: SarthakB11 <sarthak.bhardwaj21b@iiitg.ac.in>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
All contributors have signed the CLA ✍️ ✅ |
|
Thanks @SarthakB11 for the solid fix and tests here. I rebased this work onto current → #10195 Full credit remains with you ( |
|
I have read the CLA Document and I hereby sign the CLA |
|
@dmadisetti CLA is showing signed and all checks are passing on this PR. Happy to rebase onto current main if that helps, since the salvage attempt in #10195 got closed. Let me know if there's anything else needed to move this forward. |
|
Nice — thanks for signing the CLA, @SarthakB11. My salvage #10195 is already closed in favor of this one, so this is good to go on its own. Full credit to you 🙏 |
This pull request was authored by a coding agent.
What
A callable passed to
mo.lazythat both writes imperative output (mo.output.append/replace) and returns a value now shows the returned value, matching the display you get from a normal cell.Why
mo.lazy's load function runs under the owning cell's execution context. Imperativemo.outputcalls inside the deferred callable broadcast to that cell and overwrite its output, which hides the lazy widget. So the notebook from #9540 showed'a'instead of the table:Fixes #9540.
How
_loadnow runs the deferred callable with its imperative output isolated into a throwawayCellOutputList, and drops those broadcasts so they no longer overwrite the owning cell. It then reconciles the result: the returned value wins, and the accumulated imperative output is used only when the callable returns nothing. This is the same precedence a cell applies to its last expression versus itsmo.outputcalls.Tests
Two tests in
tests/_plugins/stateless/test_lazy.py, both driven through the fullfunction_call_requestRPC path (which installs the owning cell's execution context, the condition that surfaces the bug):test_lazy_return_value_takes_precedence_over_append: a callable that appends and returns shows the returned value, and the append no longer leaks into the owning cell's output.test_lazy_falls_back_to_appended_output_when_no_return: a callable that only appends still renders that output inside the widget.Both fail on
mainand pass with this change.make py-checkis clean (ruff and mypy).