Skip to content

fix: propagate notebook __doc__ to cell execution namespace (#8634)#8636

Open
mscolnick wants to merge 5 commits intomainfrom
ms/doc
Open

fix: propagate notebook __doc__ to cell execution namespace (#8634)#8636
mscolnick wants to merge 5 commits intomainfrom
ms/doc

Conversation

@mscolnick
Copy link
Contributor

When a marimo notebook has a module-level docstring (e.g., """This is a test"""), cells referencing __doc__ would return "Created for the marimo kernel." instead of the notebook's actual docstring.

Root cause

create_main_module() in patches.py always hardcodes doc="Created for the marimo kernel." when creating the __main__ module. The
notebook's header docstring (parsed and stored in App._header) was
never propagated to the execution namespace.

Changes

  • Added extract_docstring_from_header() utility in patches.py that
    uses ast.get_docstring() to extract the actual string value from the
    raw header text.
  • Added optional doc parameter to create_main_module() and
    patch_main_module() to allow setting a custom __doc__.
  • Added docstring field to AppMetadata so it can be threaded from
    notebook loading through to kernel creation.
  • Updated all AppMetadata creation sites (session manager, export,
    pyodide bootstrap) to populate docstring from the app's header.
  • Updated AppScriptRunner and AppKernelRunner to pass the docstring
    directly to create_main_module().

Closes #8634

@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Mar 15, 2026 9:23pm

Request Review

Copy link
Collaborator

@dmadisetti dmadisetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original issue reports:

If you then delete the new import cell, the result is once again incorrect, but different: <builtin doc string>

I don't think this PR captures this case, just wires down the doc string for module creation.

if not header:
return None
try:
tree = ast.parse(header)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ast_parse since ast can emit stdout

@dmadisetti dmadisetti added the bug Something isn't working label Mar 12, 2026
@mscolnick mscolnick marked this pull request as ready for review March 12, 2026 21:04
Copilot AI review requested due to automatic review settings March 12, 2026 21:04
fix: propagate notebook __doc__ to cell execution namespace
Addresses review feedback from dmadisetti: ast.parse can emit
stdout, so use the project's ast_parse wrapper which suppresses
SyntaxWarnings.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes marimo’s execution namespace so that __doc__ reflects the notebook’s actual module docstring (from the notebook header) instead of always returning "Created for the marimo kernel.".

Changes:

  • Adds extract_docstring_from_header() and threads the extracted docstring through AppMetadata.
  • Extends create_main_module() / patch_main_module() to accept an optional doc used to initialize __main__.__doc__.
  • Updates kernel/script/pyodide runners and adds tests covering docstring vs default behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/_ast/test_app.py Adds regression tests ensuring __doc__ matches the notebook header docstring (or default when absent).
marimo/_runtime/patches.py Introduces header docstring extraction and supports passing a custom module __doc__ when creating/patching __main__.
marimo/_runtime/commands.py Extends AppMetadata with a docstring field to carry header docstrings to the kernel.
marimo/_runtime/runtime.py Passes app_metadata.docstring into patch_main_module() so kernel __main__.__doc__ is correct.
marimo/_runtime/app/script_runner.py Extracts header docstring once and passes it into create_main_module() for script-mode execution.
marimo/_runtime/app/kernel_runner.py Passes extracted header docstring into create_main_module() for embedded/kernel-runner execution.
marimo/_server/session_manager.py Populates AppMetadata.docstring from the loaded notebook header when creating sessions.
marimo/_server/export/init.py Populates AppMetadata.docstring during export-driven session creation.
marimo/_pyodide/bootstrap.py Populates AppMetadata.docstring for Pyodide sessions so WASM kernels get the right __doc__.
marimo/_pyodide/pyodide_session.py Passes app_metadata.docstring into patch_main_module() for Pyodide kernel initialization.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

When a cell that redefines __doc__ is deleted, the variable was
removed from the module dict, causing Python to fall through to
builtins.__doc__. Now __doc__ is restored to the notebook's
original docstring from app_metadata.
ast.parse raises ValueError on inputs with null bytes. Catch it
alongside SyntaxError to gracefully return None.
Fix unused `outputs` variable in test_run_with_docstring and
test_run_with_no_docstring (F841 lint warning).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

__doc__ does not act as expected

3 participants