-
Notifications
You must be signed in to change notification settings - Fork 789
Embedding notebooks with parent->child exposure #6996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
recheck |
|
Hey @MaWeffm - this is something we are interested in exploring for sure, but we haven't landed on the API / feature-set for this. Our team can slot in some time this week to discuss how we want to prioritize this and what the solution should look like. |
|
Sounds fantastic, @mscolnick! Thank you for considering this! |
dmadisetti
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super interesting. I think we might need something a bit more scaled down, but maybe we can build a widget class?
Also just my opinion ! Interest to see what the rest of the team things
| return self._kernel.globals | ||
|
|
||
| # Simple read-only proxy that can be mutated behind the scenes. | ||
| class _ReadOnlyNamespace: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dataclass(frozen=True)
| - If `namespace=None`, exposed names are injected flat into child globals. This | ||
| is advanced, may be shadowed by child definitions, and should be avoided | ||
| unless that behavior is desired. | ||
| - In script mode, exposure is a one-time snapshot without reactivity. The namespace | ||
| is still read-only to prevent accidental mutation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think namespace scoping and read-only add potentially unneeded complexity. This logic could be downstreamed to mowidgets, and once a stable api we can upstream it
| - If running in a notebook, `expose` installs a **read-only** namespace that | ||
| is called `parent` by default inside the child kernel. The child must make a | ||
| **static reference** to that name (e.g., `parent` or `from parent import ...`) | ||
| for the analyzer to mark dependencies and enable targeted re-runs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on matching api with run? run has defs, I wonder if exposure works just by using state.
Exposure on a widget level does make sense though
📝 Summary
This PR adds read-only and reactive exposure of parent variables to embedded children notebooks via app.embed(). The goal was to improve modularity and enable bi-directional communication of variables between parent notebooks and embedded children. This topic has been discussed in #5092 and #6918. I am not a professional software developer and this PR has been implemented with the help of ChatGPT5. I could not find any community rules against this but understand potential reservations. If this PR is not acceptable, I hope that I at least triggers a discussion about parent->child exposure of variables.
This implementation could likely be improved to add some syntactic sugar to simplify usage of this feature. I'd also appreciate constructive feedback on the implementation and this PR, thanks!
🔍 Description of Changes
This PR entails larger changes and extends
App.embed()to accept three additional variablesexpose,namespace, andreadonly. In notebook mode, the exposures are registered with the child runner before the first run. In script mode, a one-shot namespace is injected into globals without reactivity.InternalAppis extended to be able to schedule child updates and minimal reruns./_runtime/app/kernel_runner.pywas extended to keep a registry of exposures for each runner by installing a read-only namespace object in the child kernel's globals./_runtime/runner/hooks_post_execution.pywas extended by adding a post-execution hook that pushes updated parent defs into children and schedules minimal re-runs of those child cells that reference the namespace.Examples were added to
/examples/reactive_embedding/. See screenshots of code of a parent app and the two child apps it embeds below, and a video of the parent notebook in action further down:child_1.py:

child_2.py

parent.py

See the parent notebook in action below, the children notebooks run stand-alone, too:
Screencast.from.2025-10-29.21-41-31.webm
📋 Checklist
I have read the CLA Document and I hereby sign the CLA.