Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
f7d5378
rough try of jupyterlite integration
amueller Jul 16, 2022
4696bae
try adding build dependency
amueller Jul 16, 2022
6e41ab5
fix typo in package name
amueller Jul 16, 2022
e02f846
make work with jupyterlite-sphinx master
amueller Jul 16, 2022
e9db8e3
try to fix requirements
amueller Jul 17, 2022
ddaefcf
try to fix dependencies again
amueller Jul 17, 2022
6577a80
add jupyterlite logo to package data
amueller Jul 17, 2022
e79861b
flake8
amueller Jul 17, 2022
6ea841b
typo
amueller Jul 17, 2022
398c0bb
try a different incantation
amueller Jul 17, 2022
8626d3e
try to fix jupyterlite content path
amueller Jul 17, 2022
473f290
this might make it work on circleci
amueller Jul 17, 2022
e75204f
Merge branch 'master' into jupyterlite_button
lesteve Nov 29, 2022
8864923
Fix
lesteve Nov 29, 2022
f632a59
Allow to build the doc with warnings
lesteve Nov 29, 2022
e7e360f
Do not use notebooks as doc sources
lesteve Nov 29, 2022
24d4b73
Revert "Allow to build the doc with warnings"
lesteve Nov 29, 2022
3a493bc
Trigger CI
lesteve Nov 29, 2022
aecb020
Merge upstream/master
lesteve Nov 29, 2022
946f374
FIX: Removed line
larsoner Nov 29, 2022
ccf4850
Add all notebooks to jupyterlite_contents
lesteve Nov 29, 2022
b59ba44
Merge branch 'master' into jupyterlite_button
larsoner Nov 30, 2022
84b5464
Minor clean-up:
lesteve Nov 30, 2022
2a9570a
Remove duplicated image
lesteve Jan 4, 2023
8cee6e3
Merge branch 'master' of https://github.com/sphinx-gallery/sphinx-gal…
lesteve Jan 4, 2023
2c8068a
tweak
lesteve Jan 4, 2023
c058673
Keep folder structure of notebooks
lesteve Jan 4, 2023
97e4967
Move Jupyterlite-related function to its own file
lesteve Jan 5, 2023
ac520c2
Slightly less hacky jupyterlite_contents setup
lesteve Jan 5, 2023
5fd4307
Remove keep-going to figure out which warnings are turned into errors
lesteve Jan 5, 2023
4f29129
Fix?
lesteve Jan 5, 2023
d0c9741
Revert "Remove keep-going to figure out which warnings are turned int…
lesteve Jan 5, 2023
dd338e7
Fix
lesteve Jan 5, 2023
7615440
Use a single file for binder + Jupyterlite
lesteve Jan 18, 2023
67389dc
Add jupyterlab/classic notebook flag
lesteve Jan 18, 2023
1387b25
Fix
lesteve Jan 18, 2023
4b6c9f6
iter
lesteve Jan 18, 2023
a6c6dcd
lint
lesteve Jan 18, 2023
7d420af
iter
lesteve Jan 19, 2023
fb17377
Fix regex capturing too much
lesteve Jan 19, 2023
2ff6f27
debug
lesteve Jan 19, 2023
4cd2d46
Fix debug
lesteve Jan 19, 2023
870a5cc
Update sphinx_gallery/interactive_example.py
lesteve Jan 24, 2023
66e4d9a
Merge branch 'master' of https://github.com/sphinx-gallery/sphinx-gal…
lesteve Feb 3, 2023
fd2ceb5
iter
lesteve Feb 3, 2023
884fd38
Debug source_suffix issue
lesteve Feb 3, 2023
feb9d27
smaller priority
lesteve Feb 3, 2023
3e0405a
Fix
lesteve Feb 3, 2023
a65cbf2
lint
lesteve Feb 3, 2023
60a0f7f
lint
lesteve Feb 3, 2023
559075e
debug
lesteve Feb 3, 2023
917f75b
Fix on Windows
lesteve Feb 3, 2023
b12a0ce
jupyterlite-sphinx 0.7.3
lesteve Feb 3, 2023
a68b279
Add more tests
lesteve Feb 3, 2023
95b835c
Remove comment
lesteve Feb 3, 2023
d1ddb6c
Revert to priority=100
lesteve Feb 3, 2023
5d4a036
Change JupyterLite badge
lesteve Feb 7, 2023
5ed1e8d
Mention JupyterLite in the goto to end note
lesteve Feb 7, 2023
8686749
iter
lesteve Feb 7, 2023
ed69e84
fix
lesteve Feb 7, 2023
8dba807
lint
lesteve Feb 7, 2023
106d97c
Copy and paste + slight modification of Binder doc
lesteve Feb 7, 2023
cae1b43
doc tweaks and todo
lesteve Feb 7, 2023
375df49
Update doc
lesteve Feb 8, 2023
d88c716
Fix rST
lesteve Feb 8, 2023
05c6673
clean-up + tests
lesteve Feb 8, 2023
23dc9ca
fix
lesteve Feb 8, 2023
ba78add
fix
lesteve Feb 8, 2023
7b6c2c5
Merge branch 'master' of https://github.com/sphinx-gallery/sphinx-gal…
lesteve Feb 10, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
command: |
pip install --progress-bar off --user --upgrade --only-binary ":all:" pip setuptools
pip install --progress-bar off --user --upgrade --only-binary ":all:" numpy matplotlib "pyqt5!=5.15.2,!=5.15.3,!=5.15.8" vtk
pip install --progress-bar off --user --upgrade seaborn statsmodels pillow joblib sphinx pytest traits mayavi pyvista memory_profiler "ipython!=8.7.0" plotly graphviz "docutils>=0.18"
pip install --progress-bar off --user --upgrade seaborn statsmodels pillow joblib sphinx pytest traits mayavi pyvista memory_profiler "ipython!=8.7.0" plotly graphviz "docutils>=0.18" jupyterlite-sphinx
pip install --progress-bar off --user --upgrade --pre pydata-sphinx-theme
- save_cache:
key: cache-pip
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@ target/

# Jupyter notebooks
.ipynb_checkpoints

# Default JupyterLite content
jupyterlite_contents
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ stages:
pip install --user --upgrade --progress-bar off "ipython!=8.7.0" numpy seaborn statsmodels matplotlib sphinx pillow pytest pytest-cov joblib "plotly>=4.0"
pip install --user --upgrade --progress-bar off --pre pydata-sphinx-theme
echo "Qt, plotly, VTK"
pip install --user --upgrade --progress-bar off pyvista "pyqt5!=5.15.8" plotly vtk
pip install --user --upgrade --progress-bar off pyvista "pyqt5!=5.15.8" plotly vtk jupyterlite-sphinx
echo "Mayavi"
pip install --user --upgrade --progress-bar off --no-build-isolation mayavi
displayName: Setup pip environment
Expand Down
2 changes: 1 addition & 1 deletion continuous_integration/azure/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if [ "$DISTRIB" == "conda" ]; then
echo "##vso[task.prependpath]$CONDA/bin"
export PATH=${CONDA}/bin:${PATH}
CONDA_TO_INSTALL="python=$PYTHON_VERSION pip numpy setuptools matplotlib pillow pytest pytest-cov coverage seaborn statsmodels 'plotly>=4.0' joblib flake8 wheel libiconv graphviz memory_profiler \"ipython!=8.7.0\" pypandoc"
PIP_DEPENDENCIES="check-manifest"
PIP_DEPENDENCIES="check-manifest jupyterlite-sphinx"
if [ "$SPHINX_VERSION" == "" ]; then
PIP_DEPENDENCIES="${PIP_DEPENDENCIES} sphinx jinja2<=3.0.3"
elif [ "$SPHINX_VERSION" == "dev" ]; then
Expand Down
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ plotly
absl-py
graphviz
packaging
jupyterlite-sphinx
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'sphinx.ext.mathjax',
'sphinx_gallery.gen_gallery',
'sphinx.ext.graphviz',
'jupyterlite_sphinx',
]

# Add any paths that contain templates here, relative to this directory.
Expand Down
103 changes: 103 additions & 0 deletions doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ file:
- ``show_memory`` (:ref:`show_memory`)
- ``show_signature`` (:ref:`show_signature`)
- ``binder`` (:ref:`binder_links`)
- ``jupyterlite`` (:ref:`jupyterlite`)
- ``promote_jupyter_magic`` (:ref:`promote_jupyter_magic`)
- ``first_notebook_cell`` and ``last_notebook_cell`` (:ref:`own_notebook_cell`)
- ``notebook_images`` (:ref:`notebook_images`)
Expand Down Expand Up @@ -1116,6 +1117,108 @@ See the Sphinx-Gallery `Sphinx configuration file
<https://github.com/sphinx-gallery/sphinx-gallery/blob/master/doc/conf.py>`_
for an example that uses the `public Binder server <https://mybinder.org>`_.

.. _jupyterlite:

Generate JupyterLite links for gallery notebooks (experimental)
===============================================================

Sphinx-Gallery automatically generates Jupyter notebooks for any examples built
with the gallery. `JupyterLite <https://jupyterlite.readthedocs.io>`__ makes it
possible to run an example in your browser. The functionality is quite similar
to Binder in the sense that you will get a Jupyter environment where you can
run the example interactively as a notebook. The main difference with Binder
are:

- with JupyterLite, the example actually runs in your browser, there is no need
for a separate machine in the cloud to run your Python code. That means that
starting a Jupyter server is genrally quicker, no need to wait for the Binder
image to be built
- with JupyterLite the first imports take time. At the time of writing
(February 2023) ``import scipy`` can take ~15-30s. Some innocuously looking
Python code may just not work and break in an unexpected fashion. The Jupyter
kernel is based on Pyodide, see some `here
<https://pyodide.org/en/latest/usage/wasm-constraints.html>`__ for some
Pyodide limitations.
- with JupyterLite environments are not as flexible as Binder, for example you
can not use a docker image but only the default `Pyodide
Copy link

@jtpio jtpio Mar 7, 2023

Choose a reason for hiding this comment

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

only the default Pyodide

Maybe there could be a quick mention that it's also be possible to use other kernels, for example Xeus Python: https://github.com/jupyterlite/xeus-python-kernel.

Copy link
Member

Choose a reason for hiding this comment

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

This is a good point. I tried to focus this PR on the simplest case i.e. the Pyolite kernel, but this is certainly something which could be mentioned in a follow-up PR.

Copy link

Choose a reason for hiding this comment

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

No problem it could definitely be mentioned later (just noticed while looking at the diff).

Copy link
Contributor

Choose a reason for hiding this comment

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

Especially with deeper instructions on how to package a kernel with built-in dependencies required to run the examples of a given project.

<https://pyodide.org/en/stable/index.html>`__ environment. That means that
some non pure-Python packages may not be available, see list of `available
packages in Pyodide
<https://pyodide.org/en/stable/usage/packages-in-pyodide.html>`__.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe you could expand this point a bit and explain that this it's possible to install extra, pure-python packages from pypi.org using the following construct:

try:
    # Manually install extra dependencies when running this example with
    # Pyodide:
    import micropip
    await micropip.install("package_name")
except ImportError:
    # Assume all the dependencies are already installed when running on other
    # types of hosts, such as binder.
    pass

Not protecting this snippet against ImportError would render the example pyodide-dependent as a result.

Copy link

Choose a reason for hiding this comment

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

Note that the %pip magic is also supported in the latest JupyterLite releases: https://jupyterlite.readthedocs.io/en/latest/howto/python/packages.html#installing-packages-at-runtime

%pip install package_name

Which could help make remove this try/ except block which could be awkward to some users.

Copy link
Member

Choose a reason for hiding this comment

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

Nice I didn't know this!


.. warning::

JupyterLite is still beta technology and less mature than Binder, so there
may be instability or unexpected behaviour in the experience of users who
click JupyterLite links.

In order to enable JupyterLite links with Sphinx-Gallery, you must install the
`jupyterlite-sphinx <https://jupyterlite-sphinx.readthedocs.io>`_ package and
add it to your extensions in ``conf.py``::

extensions = [
...,
...,
...,
'jupyterlite_sphinx',
]

You can configure JupyterLite integration by setting
``sphinx_gallery_conf['jupyterlite']`` in ``conf.py`` like this::

sphinx_gallery_conf = {
...
'jupyterlite': {
'jupyterlite_contents': <str> # JupyterLite contents where to copy the example notebooks (relative to Sphinx source directory)
'use_jupyter_lab': <bool> # Whether JupyterLite links should start Jupyter Lab instead of the Retrolab Notebook interface.
}
}

Below is a more complete explanation of each field.

use_jupyter_lab (type: bool, default: ``True``)
Whether the default interface activated by the JupyterLite link will be for
Jupyter Lab or the RetroLab Notebook interface.

jupyterlite_contents (type: string, default: ``jupyterlite_contents``) The name
of a folder where the built Jupyter notebooks will be copied, relative to the
Sphinx source directory. This is used as Jupyterlite contents.

You can set variables in ``conf.py`` to configure ``jupyterlite-sphinx``, see
its `jupyterlite-sphinx doc
<https://jupyterlite-sphinx.readthedocs.io/en/latest/configuration.html>`__ for
more details.

If a Sphinx-Gallery configuration for JupyterLite is discovered, the following
extra things will happen:

1. Configure ``jupyterlite-sphinx`` with some reasonable defaults, e.g. set
``jupyterlite_bind_ipynb_suffix = False``.
2. The built Jupyter Notebooks from the documentation will be copied to a
folder called ``<jupyterlite_contents>/`` (relative to Sphinx source
directory)
3. The rST output of each Sphinx-Gallery example will now have a
``launch JupyterLite`` button in it.
4. That button will point to a JupyterLite link which will start a Jupyter
server in your browser with the current example as notebook

If, for some reason, you want to enable the ``jupyterlite-sphinx`` extension
but not use sphinx-gallery Jupyterlite integration you can do::

extensions = [
...,
jupyterlite_sphinx,
]

sphinx_gallery_conf = {
...
'jupyterlite': None
}

See the Sphinx-Gallery `Sphinx configuration file
<https://github.com/sphinx-gallery/sphinx-gallery/blob/master/doc/conf.py>`_
for an example that uses the JupyterLite integration.

.. _promote_jupyter_magic:

Making cell magic executable in notebooks
Expand Down
2 changes: 1 addition & 1 deletion doc/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Sphinx-Gallery API Reference
notebook
downloads
sorting
binder
interactive_example
directives

.. currentmodule:: sphinx_gallery.utils
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
'_static/sg_gallery*.css',
'_static/no_image.png',
'_static/broken_example.png',
'_static/binder_badge_logo.svg'
'_static/binder_badge_logo.svg',
'_static/jupyterlite_badge_logo.svg'
]},
scripts=['bin/copy_sphinxgallery.sh', 'bin/sphx_glr_python_to_jupyter.py'],
url="https://sphinx-gallery.github.io",
Expand Down
3 changes: 3 additions & 0 deletions sphinx_gallery/_static/jupyterlite_badge_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions sphinx_gallery/_static/sg_gallery-binder.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ div.binder-badge {
margin: 1em auto;
vertical-align: middle;
}

div.lite-badge {
margin: 1em auto;
vertical-align: middle;
}
2 changes: 2 additions & 0 deletions sphinx_gallery/downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
.. container:: sphx-glr-footer sphx-glr-footer-example

{2}

{4}
.. container:: sphx-glr-download sphx-glr-download-python

:download:`Download Python source code: {0} <{0}>`
Expand Down
25 changes: 23 additions & 2 deletions sphinx_gallery/gen_gallery.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@
from .docs_resolv import embed_code_links
from .downloads import generate_zipfiles
from .sorting import NumberOfCodeLinesSortKey
from .binder import copy_binder_files, check_binder_conf
from .interactive_example import (
copy_binder_files, check_binder_conf, check_jupyterlite_conf
)
from .interactive_example import pre_configure_jupyterlite_sphinx
from .interactive_example import post_configure_jupyterlite_sphinx
from .interactive_example import create_jupyterlite_contents
from .directives import MiniGallery, ImageSg, imagesg_addnode


_KNOWN_CSS = ('sg_gallery', 'sg_gallery-binder', 'sg_gallery-dataframe',
'sg_gallery-rendered-html')

Expand Down Expand Up @@ -80,6 +84,7 @@ def __call__(self, gallery_conf, script_vars):
'thumbnail_size': (400, 280), # Default CSS does 0.4 scaling (160, 112)
'min_reported_time': 0,
'binder': {},
'jupyterlite': {},
'promote_jupyter_magic': False,
'image_scrapers': ('matplotlib',),
'compress_images': (),
Expand Down Expand Up @@ -371,6 +376,11 @@ def call_memory(func):
# binder
gallery_conf['binder'] = check_binder_conf(gallery_conf['binder'])

# jupyterlite
print('_complete_gallery_conf', gallery_conf.get('jupyterlite'))
gallery_conf['jupyterlite'] = check_jupyterlite_conf(
gallery_conf.get('jupyterlite', {}), app)

if not isinstance(gallery_conf['css'], (list, tuple)):
raise ConfigError('gallery_conf["css"] must be list or tuple, got %r'
% (gallery_conf['css'],))
Expand Down Expand Up @@ -1155,6 +1165,15 @@ def setup(app):
for key in ['plot_gallery', 'abort_on_example_error']:
app.add_config_value(key, get_default_config_value(key), 'html')

# set small priority value, so that pre_configure_jupyterlite_sphinx is
# called before jupyterlite_sphinx config-inited
app.connect(
'config-inited', pre_configure_jupyterlite_sphinx, priority=100)
# set high priority value, so that post_configure_jupyterlite_sphinx is
# called after jupyterlite_sphinx config-inited
app.connect(
'config-inited', post_configure_jupyterlite_sphinx, priority=900)

if 'sphinx.ext.autodoc' in app.extensions:
app.connect('autodoc-process-docstring', touch_empty_backreferences)
app.connect('autodoc-process-docstring', write_api_entries)
Expand All @@ -1168,6 +1187,8 @@ def setup(app):

app.connect('builder-inited', generate_gallery_rst)
app.connect('build-finished', copy_binder_files)
app.connect('build-finished', create_jupyterlite_contents)

app.connect('build-finished', summarize_failing_examples)
app.connect('build-finished', embed_code_links)
app.connect('build-finished', clean_files)
Expand Down
Loading