Skip to content
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

Add JupyterLite build and instructions #4122

Merged
merged 19 commits into from
Nov 16, 2022
Merged

Add JupyterLite build and instructions #4122

merged 19 commits into from
Nov 16, 2022

Conversation

philippjfr
Copy link
Member

Fixes #3605
Fixes #4110

@codecov
Copy link

codecov bot commented Nov 15, 2022

Codecov Report

Merging #4122 (c350503) into master (07127ca) will decrease coverage by 9.02%.
The diff coverage is 30.95%.

❗ Current head c350503 differs from pull request most recent head 0e3d06e. Consider uploading reports for the commit 0e3d06e to get more accurate results

@@            Coverage Diff             @@
##           master    #4122      +/-   ##
==========================================
- Coverage   83.57%   74.54%   -9.03%     
==========================================
  Files         223      224       +1     
  Lines       33300    33355      +55     
==========================================
- Hits        27829    24866    -2963     
- Misses       5471     8489    +3018     
Flag Coverage Δ
ui-tests ?
unitexamples-tests 74.54% <30.95%> (-0.09%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
panel/io/pyodide.py 0.00% <0.00%> (ø)
panel/tests/ui/io/test_jupyterlite.py 32.43% <32.43%> (ø)
panel/config.py 75.52% <100.00%> (+0.59%) ⬆️
panel/tests/ui/widgets/test_tabulator.py 9.55% <0.00%> (-89.26%) ⬇️
panel/tests/ui/widgets/test_input.py 11.34% <0.00%> (-88.13%) ⬇️
panel/tests/ui/layout/test_accordion.py 14.72% <0.00%> (-85.28%) ⬇️
panel/tests/ui/widgets/test_sliders.py 15.42% <0.00%> (-84.58%) ⬇️
panel/tests/ui/layout/test_card.py 18.01% <0.00%> (-81.99%) ⬇️
panel/tests/ui/io/test_convert.py 15.92% <0.00%> (-79.65%) ⬇️
panel/tests/ui/test_reactive.py 26.53% <0.00%> (-73.47%) ⬇️
... and 38 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Member

@hoxbro hoxbro left a comment

Choose a reason for hiding this comment

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

I could not get the notebook to run. Even after I updated the first cell to

import piplite
await piplite.install(['panel', 'altair', 'pyodide_http'])
                       
import pyodide_http
pyodide_http.patch_all()  # Patch all libraries

Getting this traceback:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [9], line 33
     24     query = ' & '.join(
     25         f'{crange[0]:.3f} <= `{col}` <= {crange[1]:.3f}'
     26         for col, crange in selection.items()
     27     )
     28     return pn.pane.DataFrame(df.query(query), width=600)
     30 pn.Column(
     31     'Select points on the plot and watch the linked table update.',
     32     sizing_mode='stretch_width'
---> 33 ).servable()
     35 pn.Row(
     36     vega_pane,
     37     pn.Column(
   (...)
     40     )
     41 )

File /lib/python3.10/site-packages/panel/viewable.py:382, in ServableMixin.servable(self, title, location, area, target)
    380 elif state._is_pyodide:
    381     from .io.pyodide import _get_pyscript_target, write
--> 382     target = target or _get_pyscript_target()
    383     if target is not None:
    384         asyncio.create_task(write(target, self))

File /lib/python3.10/site-packages/panel/io/pyodide.py:258, in _get_pyscript_target()
    256     return sys.stdout._out # type: ignore
    257 else:
--> 258     raise ValueError("Could not determine target node to write to.")

ValueError: Could not determine target node to write to.

.github/workflows/docs.yaml Outdated Show resolved Hide resolved
doc/user_guide/Running_in_Webassembly.md Outdated Show resolved Hide resolved
doc/user_guide/Running_in_Webassembly.md Outdated Show resolved Hide resolved
scripts/build_pyodide_wheels.py Outdated Show resolved Hide resolved
scripts/build_pyodide_wheels.py Outdated Show resolved Hide resolved
scripts/generate_panelite_content.py Outdated Show resolved Hide resolved
scripts/generate_panelite_content.py Show resolved Hide resolved
doc/user_guide/Running_in_Webassembly.md Outdated Show resolved Hide resolved
@hoxbro
Copy link
Member

hoxbro commented Nov 15, 2022

I got the notebook to run with the following:

import piplite
await piplite.install(['panel', 'altair', 'pyodide_http'])
                       
import pyodide_http
pyodide_http.patch_all() 
import panel as pn
pn.extension('vega', comms="default")  # comms will be fixed in this PR
import altair as alt
import pandas as pd

import bokeh.models.sources
bokeh.models.sources.pd = pd

df = pd.read_json("https://raw.githubusercontent.com/vega/vega/master/docs/data/penguins.json")

brush = alt.selection_interval(name='brush')  # selection of type "interval"

chart = alt.Chart(df).mark_point().encode(
    x=alt.X('Beak Length (mm):Q', scale=alt.Scale(zero=False)),
    y=alt.Y('Beak Depth (mm):Q', scale=alt.Scale(zero=False)),
    color=alt.condition(brush, 'Species:N', alt.value('lightgray'))
).properties(
    width=250,
    height=250
).add_selection(
    brush
)

vega_pane = pn.pane.Vega(chart, debounce=10)

def filtered_table(selection):
    if selection is None:
        return '## No selection'
    query = ' & '.join(
        f'{crange[0]:.3f} <= `{col}` <= {crange[1]:.3f}'
        for col, crange in selection.items()
    )
    return pn.pane.DataFrame(df.query(query), width=600)

pn.Column(
    'Select points on the plot and watch the linked table update.',
    sizing_mode='stretch_width'
)# .servable()  <- Does not work if this is served. 
pn.Row(
    vega_pane,
    pn.Column(
        pn.bind(filtered_table, vega_pane.selection.param.brush),
        scroll=True, width=650, height=300
    )
)

@philippjfr
Copy link
Member Author

Instructions for building the Jupyterlite are as follows:

python ./scripts/build_pyodide_wheels.py lite/pypi
python ./scripts/generate_panelite_content.py
jupyter lite build --lite-dir lite --output-dir lite/dist

@MarcSkovMadsen
Copy link
Collaborator

Will we always have to make a special build to support Panel?

Or will it be supported in default build of Jupyter lite some day?

Copy link
Member

@jbednar jbednar left a comment

Choose a reason for hiding this comment

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

It sounds pretty complicated still!

doc/user_guide/Running_in_Webassembly.md Outdated Show resolved Hide resolved
doc/user_guide/Running_in_Webassembly.md Outdated Show resolved Hide resolved
setup.py Outdated Show resolved Hide resolved
@philippjfr
Copy link
Member Author

Will we always have to make a special build to support Panel?

Unless we can convince Jupyterlite folks to add pyviz_comms as a default extension this will indeed always be necessary.

@hoxbro
Copy link
Member

hoxbro commented Nov 16, 2022

Some more comments:

  • lite/ and .jupyterlite.doit.db should be added to .gitignore.
  • ../assets should be copied, so images are in the notebook. (user_guide/Performance_and_Debugging.ipynb)
  • pn.panel('Hello').app('localhost:8888') does not work. (user_guide/Display_and_Export.ipynb)
  • Threading.start() does not work. (user_guide/Async_and_Concurrency.ipynb)
  • croniter install missing. (user_guide/Session_State_and_Callbacks.ipynb)
  • sample_template.html missing. (user_guide/Templates.ipynb)

I like the idea of the script folder and want it to be used more and not necessarily limited to python files. Like why not have a build_jupyter_lite.sh which contains the build process below? This shell script can then be called from the Github action.

python ./scripts/build_pyodide_wheels.py lite/pypi
python ./scripts/generate_panelite_content.py
jupyter lite build --lite-dir lite --output-dir lite/dist

Maybe in a future PR, a more selective list of imports can be done per notebook for the piplite install, so it does not import a lot of unnecessary imports in all notebooks.

@MarcSkovMadsen
Copy link
Collaborator

I just tried panelite.holoviz.org and it does not work for me. I guess you know ?

image

@philippjfr
Copy link
Member Author

  • lite/ and .jupyterlite.doit.db should be added to .gitignore.
  • ../assets should be copied, so images are in the notebook. (user_guide/Performance_and_Debugging.ipynb)
  • pn.panel('Hello').app('localhost:8888') does not work. (user_guide/Display_and_Export.ipynb)
  • Threading.start() does not work. (user_guide/Async_and_Concurrency.ipynb)
  • croniter install missing. (user_guide/Session_State_and_Callbacks.ipynb)
  • sample_template.html missing. (user_guide/Templates.ipynb)

@philippjfr
Copy link
Member Author

philippjfr commented Nov 16, 2022

I just tried panelite.holoviz.org and it does not work for me. I guess you know ?

Hasn't been redeployed in over 6 months. That said it works fine as long as you don't try to install ipywidgets (OR pin ipywidgets<8)

@philippjfr philippjfr merged commit b01923d into master Nov 16, 2022
@philippjfr philippjfr deleted the jupyterlite_fix branch November 16, 2022 13:24
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.

Make Panel work in the Jupyterlite Pyolite repl Panel not working in Jupyterlite
4 participants