-
Notifications
You must be signed in to change notification settings - Fork 406
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
compat: Register webbrowser.open hook for pyodide (#3864)
## 📝 Summary `import webbrowser.open` seems to be broken in WASM (which is fine, I think opening pages is potentially dangerous)- so this loads in a hook to insert an iframe into output if webbrowser is called instead of failing. As a result, the following code now works ```python import antigravity ``` but with some marimo tweaks that might make for good social engagement on 25/04/01  (PS: this needs a static upload) Had a spare hour and noticed it when looking through cpython/Lib Let me know if it's too irreverent and I can walk back the feature- but seems enabling this seems like full python support to me ## 📜 Reviewers <!-- Tag potential reviewers from the community or maintainers who might be interested in reviewing this pull request. Your PR will be reviewed more quickly if you can figure out the right person to tag with @ --> @akshayka OR @mscolnick --------- Co-authored-by: Myles Scolnick <[email protected]>
- Loading branch information
1 parent
1443d60
commit 39a607a
Showing
4 changed files
with
174 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Copyright 2025 Marimo. All rights reserved. | ||
from __future__ import annotations | ||
|
||
import webbrowser | ||
|
||
from marimo._runtime.context import get_context | ||
from marimo._runtime.context.types import ContextNotInitializedError | ||
|
||
|
||
def browser_open_fallback( | ||
url: str, new: int = 0, autoraise: bool = False | ||
) -> bool: | ||
""" | ||
Inserts an iframe with the given URL into the output. | ||
NB Returns false on failure. | ||
""" | ||
import inspect | ||
|
||
import marimo as mo | ||
|
||
del new, autoraise # unused | ||
|
||
try: | ||
ctx = get_context() | ||
except ContextNotInitializedError: | ||
return False | ||
|
||
if ctx.execution_context is None: | ||
return False | ||
|
||
# import antigravity is a real module in python. see: | ||
# github.com/python/cpython/blob/main/Lib/antigravity.py | ||
# which automatically triggers a webbrowser.open call to the relevant | ||
# comic. We patch webbrowser.open due to an incompatible stub: | ||
# https://pyodide.org/en/stable/usage/wasm-constraints.html | ||
# so may as well hook in to customize the easter egg. Especially since | ||
# iframe constraints actually block this from loading on marimo.app. | ||
# | ||
# For other python lore, try: | ||
# import this | ||
stack = inspect.stack() | ||
if len(stack) > 3 and ( | ||
stack[2].filename.endswith("antigravity.py") | ||
or (stack[1].filename.endswith("antigravity.py")) | ||
): | ||
mo.output.append( | ||
mo.image( | ||
"https://marimo.app/images/antigravity.png", | ||
alt=( | ||
"The image shows 2 stick figures in XKCD style. The one " | ||
'on the left says:"You\'re Flying! How?", a floating ' | ||
'stick figure on the right responds "marimo!"' | ||
), | ||
caption=( | ||
'Original alt text: "<i>I wrote 20 short programs in ' | ||
"Python yesterday." | ||
"<b> It was wonderful. </b>" | ||
"Perl, <u>I'm leaving you.</u></i>\"" | ||
"<br/> The technologies may have changed, but the " | ||
"sentiment remains. We agree Randall;<br /> Edited " | ||
"from <u><a " | ||
" href='https://xkcd.com/353'>" | ||
" XKCD/353" | ||
" </a></u> under CC-2.5;" | ||
), | ||
) | ||
) | ||
else: | ||
mo.output.append( | ||
mo.Html( | ||
f"<iframe src='{url}' style='width:100%;height:500px'></iframe>", | ||
) | ||
) | ||
return True | ||
|
||
|
||
def build_browser_fallback() -> "type[webbrowser.BaseBrowser]": | ||
""" | ||
Dynamically create the class since BaseBrowser does not exist in | ||
pyodide. | ||
""" | ||
|
||
# Construct like this to limit stack frames. | ||
MarimoBrowser = type( | ||
"MarimoBrowser", | ||
(webbrowser.BaseBrowser,), | ||
{"open": staticmethod(browser_open_fallback)}, | ||
) | ||
|
||
return MarimoBrowser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters