Skip to content

enable interactive exploration of examples using jupyterlite-sphinx - #10299

Open
keewis wants to merge 52 commits into
pydata:mainfrom
keewis:jupyterlite
Open

enable interactive exploration of examples using jupyterlite-sphinx#10299
keewis wants to merge 52 commits into
pydata:mainfrom
keewis:jupyterlite

Conversation

@keewis

@keewis keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator

We're already using jupyterlite in the main website, but we could also make all the docstring examples executable using jupyterlite-sphinx.

This doesn't quite work at the moment because:


  • Tests added
  • User visible changes (including notable bug fixes) are documented in whats-new.rst
  • New functions/methods are listed in api.rst

@agriyakhetarpal

Copy link
Copy Markdown

Thank you for reporting the bug and playing around with it upstream, @keewis! It should be fixed with a 0.20.1 release, but please feel free to test it from my fork if you'd like to, just in case. I confirm that it resolves the original reproducer, by the way!

@agriyakhetarpal

Copy link
Copy Markdown
  • after fixing that locally it requires running a local http server (python -m http.server -b 127.0.0.1, for example) such that the browser does not block http requests because of the CORS headers

I'm slightly curious about this point, though – I imagine one would need to start a server to view the Sphinx docs anyway?

@github-actions github-actions Bot added CI Continuous Integration tools dependencies Pull requests that update a dependency file labels May 8, 2025
@keewis

keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator Author

you can use the file protocol to access static html files locally, which is what I had been doing to check the results of builds on my computer.

@agriyakhetarpal

Copy link
Copy Markdown

Ah, yes, that wouldn't work with JupyterLite indeed.

@keewis

keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator Author

@agriyakhetarpal, do you know if it's possible to globally add a preamble cell to each example notebook? The purpose would be to import common modules and set up the environment, like we do for pytest's doctest runner

@agriyakhetarpal

Copy link
Copy Markdown

@agriyakhetarpal, do you know if it's possible to globally add a preamble cell to each example notebook? The purpose would be to import common modules and set up the environment, like we do for pytest's doctest runner

Yes, this is currently not implemented, but it should be possible to include (I was working on a feature exactly like this some time back, but there's no PR yet). One thing I have to note here is that such code will be displayed to the user and would be included in a cell at the top of each example's generated notebook; it won't be hidden/silent, unfortunately – jupyterlite/jupyterlite#461 has some more details around this.

Making some code executed in a hidden has been a long-requested feature in JupyterLite in some ways (especially for installing packages at runtime with the Pyodide kernel but not showing the cell in which is done, for example, see jupyterlite/pyodide-kernel#60).

However, if you mean that each example can do simple things like import numpy, import matplotlib, set the random seed, etc. and such code doesn't necessarily mean to be hidden, that simplifies things :)

@keewis

keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator Author

I don't mind this being visible, so just inserting a code cell before / after the warning would be fine with me. I just played around with this by modifying my local installation of jupyterlite-sphinx, and this seems to be very easy to do.

@agriyakhetarpal

Copy link
Copy Markdown

don't mind this being visible, so just inserting a code cell before / after the warning would be fine with me.

Thanks for the clarification, that works!

I just played around with this by modifying my local installation of jupyterlite-sphinx, and this seems to be very easy to do.

Nice! Just to ensure that our codes don't conflict – could you please put together a PR when you have a chance? I've just pushed my (a little incomplete and possible conflicting with yours) changes to my branch at https://github.com/agriyakhetarpal/jupyterlite-sphinx/tree/feat/generic-notebook-modifications – I last worked on this a little more than a month ago.

Note that the original discussion around my changes is here: sphinx-gallery/sphinx-gallery#1427, which is where we should be settling down on the implementation after everything is done.

In short, the idea was that Sphinx-Gallery offers "notebook modification functions" for its JupyterLite notebook galleries (like the way you suggest) and it also uses jupyterlite-sphinx as an optional dependency, but I believed that such functionality belongs in jupyterlite-sphinx itself, and Sphinx-Gallery can simply reuse it from us if we provide APIs to do so.

I could go forward with my changes, but I don't intend to block yours at all, so please go for it or let me know what can work best! :)

@agriyakhetarpal

Copy link
Copy Markdown

In the meantime, the 0.20.1 release is out: https://github.com/jupyterlite/jupyterlite-sphinx/releases/tag/v0.20.1, on both PyPI and conda-forge.

@keewis

keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator Author

I've just pushed my (a little incomplete and possible conflicting with yours) changes to my branch

yours is a much bigger change, but I don't think it will conflict: I modified the return value of examples_to_notebook by calling nb.cells.insert(1, new_code_cell(preamble)), where preamble is read from a (hard-coded) file called try_examples_preamble.py (could also be a setting in conf.py, but that way we get autoformatting / linting). This change is thus confined to TryExamplesDirective.run, whereas yours appears to also apply to the other directives?

I'll open a draft PR to show you want I mean. Edit: see jupyterlite/jupyterlite-sphinx#293

@keewis

keewis commented May 8, 2025

Copy link
Copy Markdown
Collaborator Author

I can confirm that the examples here work in the RTD preview if I manually fill in the preamble we discussed above. If anyone's interested, it might be nice to style the buttons in a way that is in line with the sphinx theme we use.

I did notice that retrying with a different example appears to re-install everything, which is a bit wasteful (but not sure how easy that would be to fix)

@github-actions github-actions Bot added topic-backends Automation Github bots, testing workflows, release automation io labels Feb 24, 2026
@keewis keewis removed topic-backends CI Continuous Integration tools dependencies Pull requests that update a dependency file Automation Github bots, testing workflows, release automation io labels Feb 24, 2026
@github-actions github-actions Bot added the CI Continuous Integration tools label Feb 24, 2026
@keewis

keewis commented Feb 24, 2026

Copy link
Copy Markdown
Collaborator Author

@agriyakhetarpal, the unresolved issue here is that jupyterlite-sphinx clashes with nbsphinx, which we currently use to include rendered notebooks in the documentation (it looks like there are plans to move to myst-nb, but that will take some time):

In the current state, jupyterlite-sphinx extracts the doctests and surrounding text from the "examples" section, creates notebooks and writes them to the _contents directory. These notebooks are then moved over into a subdirectory of _build/html/lite at the end after creating the bundle of wasm libraries for the kernel.

However, this means that nbsphinx can detect the generated notebooks and possibly fail to execute them, which causes the build to fail (see https://app.readthedocs.org/projects/xray/builds/31545020/). The only way to ignore files for nbsphinx is through the exclude_patterns setting, but it looks like adding the _contents directory will somehow cause jupyterlite-sphinx to fail the copy / move step (a FileNotFoundError is raised). An example for that is https://app.readthedocs.org/projects/xray/builds/31545150/.

Do you have any ideas on how to resolve this?

@agriyakhetarpal

Copy link
Copy Markdown

@agriyakhetarpal, the unresolved issue here is that jupyterlite-sphinx clashes with nbsphinx, which we currently use to include rendered notebooks in the documentation (it looks like there are plans to move to myst-nb, but that will take some time):

In the current state, jupyterlite-sphinx extracts the doctests and surrounding text from the "examples" section, creates notebooks and writes them to the _contents directory. These notebooks are then moved over into a subdirectory of _build/html/lite at the end after creating the bundle of wasm libraries for the kernel.

However, this means that nbsphinx can detect the generated notebooks and possibly fail to execute them, which causes the build to fail (see app.readthedocs.org/projects/xray/builds/31545020). The only way to ignore files for nbsphinx is through the exclude_patterns setting, but it looks like adding the _contents directory will somehow cause jupyterlite-sphinx to fail the copy / move step (a FileNotFoundError is raised). An example for that is app.readthedocs.org/projects/xray/builds/31545150.

Do you have any ideas on how to resolve this?

Hi @keewis, I am glad to see the progress on this PR! Does https://jupyterlite-sphinx.readthedocs.io/en/stable/configuration.html#disable-the-ipynb-docs-source-binding work?

Also, for the longer term, maybe something we should explore in jupyterlite-sphinx is renaming our staging-area-like directory from _contents/ to _jupyterlite_contents/ to avoid the clash, if I understand correctly that nbsphinx is looking for notebooks in _contents/ as well?

(Commenting from my phone, so it's a bit hard to see the RTD build logs, sorry! I can take a closer look in the day)

@keewis

keewis commented Feb 25, 2026

Copy link
Copy Markdown
Collaborator Author

Does https://jupyterlite-sphinx.readthedocs.io/en/stable/configuration.html#disable-the-ipynb-docs-source-binding work?

It doesn't, unfortunately.

if I understand correctly that nbsphinx is looking for notebooks in _contents/ as well?

nbsphinx searches the docs directory and all its subdirs except for the excluded ones for notebook files. As such, I think our best bet would be to figure out why when added to exclude_patterns the _contents directory is deleted / cleared before jupyterlite-sphinx has a chance to copy the notebooks.

@agriyakhetarpal

Copy link
Copy Markdown

Hmm, makes sense. I have decided to take a look by running pixi run doc locally to investigate further, but I am running into problems following the Contributing guide:

Build logs
✨ Pixi task (_prepare-environment in doc): python create_environment.py

 ╭─ Running build for recipe: xarray-9999.0.0-pyh4616a5c_0
 │
 │ ╭─ Fetching source code
 │ │ No sources to fetch
 │ │
 │ ╰─────────────────── (took 0 seconds)
 │
 │ ╭─ Externally resolved dependencies recipe: xarray-9999.0.0-pyh4616a5c_0
 │ │ 
 │ │ Resolved build dependencies(xarray-9999.0.0-pyh4616a5c_0):
 │ │ ╭─────────┬──────┬─────────┬───────┬─────────┬──────╮
 │ │ │ Package ┆ Spec ┆ Version ┆ Build ┆ Channel ┆ Size │
 │ │ ╞═════════╪══════╪═════════╪═══════╪═════════╪══════╡
 │ │ ╰─────────┴──────┴─────────┴───────┴─────────┴──────╯
 │ │ Resolved host dependencies(xarray-9999.0.0-pyh4616a5c_0):
 │ │ ╭────────────────────┬────────────────┬───────────┬────────────────────┬─────────────┬────────────╮
 │ │ │ Package            ┆ Spec           ┆ Version   ┆ Build              ┆ Channel     ┆       Size │
 │ │ ╞════════════════════╪════════════════╪═══════════╪════════════════════╪═════════════╪════════════╡
 │ │ │ pip                ┆ pip            ┆ 26.0.1    ┆ pyh145f28c_0       ┆ conda-forge ┆   1.13 MiB │
 │ │ │ python             ┆ python >=3.11  ┆ 3.14.3    ┆ h4c637c5_101_cp314 ┆ conda-forge ┆  12.90 MiB │
 │ │ │ setuptools         ┆ setuptools     ┆ 82.0.0    ┆ pyh332efcf_0       ┆ conda-forge ┆ 622.56 KiB │
 │ │ │ setuptools_scm     ┆ setuptools_scm ┆ 9.2.2     ┆ hd8ed1ab_0         ┆ conda-forge ┆   6.50 KiB │
 │ │ │ bzip2              ┆                ┆ 1.0.8     ┆ hd037594_9         ┆ conda-forge ┆ 121.91 KiB │
 │ │ │ ca-certificates    ┆                ┆ 2026.2.25 ┆ hbd8a1cb_0         ┆ conda-forge ┆ 143.96 KiB │
 │ │ │ icu                ┆                ┆ 78.2      ┆ h38cb7af_0         ┆ conda-forge ┆  11.79 MiB │
 │ │ │ importlib-metadata ┆                ┆ 8.7.0     ┆ pyhe01879c_1       ┆ conda-forge ┆  33.83 KiB │
 │ │ │ libexpat           ┆                ┆ 2.7.4     ┆ hf6b4638_0         ┆ conda-forge ┆  66.60 KiB │
 │ │ │ libffi             ┆                ┆ 3.5.2     ┆ hcf2aa1b_0         ┆ conda-forge ┆  40.02 KiB │
 │ │ │ liblzma            ┆                ┆ 5.8.2     ┆ h8088a28_0         ┆ conda-forge ┆  90.08 KiB │
 │ │ │ libmpdec           ┆                ┆ 4.0.0     ┆ h84a0fba_1         ┆ conda-forge ┆  71.96 KiB │
 │ │ │ libsqlite          ┆                ┆ 3.51.2    ┆ h1ae2325_0         ┆ conda-forge ┆ 888.45 KiB │
 │ │ │ libzlib            ┆                ┆ 1.3.1     ┆ h8359307_2         ┆ conda-forge ┆  45.35 KiB │
 │ │ │ ncurses            ┆                ┆ 6.5       ┆ h5e97a16_3         ┆ conda-forge ┆ 778.35 KiB │
 │ │ │ openssl            ┆                ┆ 3.6.1     ┆ hd24854e_1         ┆ conda-forge ┆   2.96 MiB │
 │ │ │ packaging          ┆                ┆ 26.0      ┆ pyhcf101f3_0       ┆ conda-forge ┆  70.32 KiB │
 │ │ │ python_abi         ┆                ┆ 3.14      ┆ 8_cp314            ┆ conda-forge ┆   6.83 KiB │
 │ │ │ readline           ┆                ┆ 8.3       ┆ h46df422_0         ┆ conda-forge ┆ 306.57 KiB │
 │ │ │ setuptools-scm     ┆                ┆ 9.2.2     ┆ pyhd8ed1ab_0       ┆ conda-forge ┆  51.31 KiB │
 │ │ │ tk                 ┆                ┆ 8.6.13    ┆ h010d191_3         ┆ conda-forge ┆   2.98 MiB │
 │ │ │ tomli              ┆                ┆ 2.4.0     ┆ pyhcf101f3_0       ┆ conda-forge ┆  20.95 KiB │
 │ │ │ typing-extensions  ┆                ┆ 4.15.0    ┆ h396c80c_0         ┆ conda-forge ┆  89.24 KiB │
 │ │ │ typing_extensions  ┆                ┆ 4.15.0    ┆ pyhcf101f3_0       ┆ conda-forge ┆  50.48 KiB │
 │ │ │ tzdata             ┆                ┆ 2025c     ┆ hc9c84f9_1         ┆ conda-forge ┆ 116.34 KiB │
 │ │ │ zipp               ┆                ┆ 3.23.0    ┆ pyhcf101f3_1       ┆ conda-forge ┆  23.63 KiB │
 │ │ │ zstd               ┆                ┆ 1.5.7     ┆ hbf9d68e_6         ┆ conda-forge ┆ 423.25 KiB │
 │ │ ╰────────────────────┴────────────────┴───────────┴────────────────────┴─────────────┴────────────╯
 │ │ Resolved run dependencies(xarray-9999.0.0-pyh4616a5c_0):
 │ │ ╭──────────────────┬──────────────────────────╮
 │ │ │ Name             ┆ Spec                     │
 │ │ ╞══════════════════╪══════════════════════════╡
 │ │ │ Run dependencies ┆                          │
 │ │ │ git              ┆ *                        │
 │ │ │ numpy            ┆ *                        │
 │ │ │ packaging        ┆ 24.1.*                   │
 │ │ │ pandas           ┆ *                        │
 │ │ │ python           ┆ *                        │
 │ │ │                  ┆ * (RE of [host: python]) │
 │ │ ╰──────────────────┴──────────────────────────╯
 │ │
 │ ╰─────────────────── (took 0 seconds)
 │
 │ ╭─ Running build script
 │ │ Using pip 26.0.1 from $PREFIX/lib/python3.14/site-packages/pip (python 3.14)
 │ │ Non-user install because user site-packages disabled
 │ │ Ignoring indexes: https://pypi.org/simple
 │ │ Created temporary directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse
 │ │ Initialized build tracking at /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse
 │ │ Created build tracker: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse
 │ │ Entered build tracker: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse
 │ │ Created temporary directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-install-5wcxj723
 │ │ Created temporary directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea
 │ │ Obtaining file:///Users/agriyakhetarpal/Desktop/xarray
 │ │   Added file:///Users/agriyakhetarpal/Desktop/xarray to build tracker '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse'
 │ │   Checking if build backend supports build_editable: started
 │ │   Running command Checking if build backend supports build_editable
 │ │   Checking if build backend supports build_editable: finished with status 'done'
 │ │   Created temporary directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s
 │ │   Preparing editable metadata (pyproject.toml): started
 │ │   Running command Preparing editable metadata (pyproject.toml)
 │ │   $PREFIX/lib/python3.14/site-packages/setuptools_scm/_integration/version_inference.py:51: UserWarning: version of None already set
 │ │     warnings.warn(self.message)
 │ │   running dist_info
 │ │   creating /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info
 │ │   writing /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/PKG-INFO
 │ │   writing dependency_links to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/dependency_links.txt
 │ │   writing entry points to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/entry_points.txt
 │ │   writing requirements to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/requires.txt
 │ │   writing top-level names to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/top_level.txt
 │ │   writing manifest file '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/SOURCES.txt'
 │ │   adding license file 'LICENSE'
 │ │   writing manifest file '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray.egg-info/SOURCES.txt'
 │ │   creating '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-modern-metadata-f2w8hs4s/xarray-2026.2.1.dev59+gd8504a339.dist-info'
 │ │   Preparing editable metadata (pyproject.toml): finished with status 'done'
 │ │   Source in /Users/agriyakhetarpal/Desktop/xarray has version 2026.2.1.dev59+gd8504a339, which satisfies requirement xarray==2026.2.1.dev59+gd8504a339 from
 │ │  file:///Users/agriyakhetarpal/Desktop/xarray
 │ │   Removed xarray==2026.2.1.dev59+gd8504a339 from file:///Users/agriyakhetarpal/Desktop/xarray from build tracker '/private/var/folders/b3/2bq1m1_50bs4c7305
 │ │ j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse'
 │ │ Created temporary directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-unpack-io8hug3h
 │ │ Building wheels for collected packages: xarray
 │ │   Destination directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef46
 │ │ 22048d0d19292ef58b00b2da/tmpoj8s69z2
 │ │   Building editable for xarray (pyproject.toml): started
 │ │   Running command Building editable for xarray (pyproject.toml)
 │ │   $PREFIX/lib/python3.14/site-packages/setuptools_scm/_integration/version_inference.py:51: UserWarning: version of None already set
 │ │     warnings.warn(self.message)
 │ │   running editable_wheel
 │ │   creating /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622048d0d19292e
 │ │ f58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info
 │ │   writing /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622048d0d19292ef
 │ │ 58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/PKG-INFO
 │ │   writing dependency_links to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983
 │ │ cef4622048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/dependency_links.txt
 │ │   writing entry points to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4
 │ │ 622048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/entry_points.txt
 │ │   writing requirements to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4
 │ │ 622048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/requires.txt
 │ │   writing top-level names to /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983c
 │ │ ef4622048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/top_level.txt
 │ │   writing manifest file '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef46
 │ │ 22048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/SOURCES.txt'
 │ │   adding license file 'LICENSE'
 │ │   writing manifest file '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef46
 │ │ 22048d0d19292ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray.egg-info/SOURCES.txt'
 │ │   creating '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622048d0d19292
 │ │ ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray-2026.2.1.dev59+gd8504a339.dist-info'
 │ │   creating /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622048d0d19292e
 │ │ f58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray-2026.2.1.dev59+gd8504a339.dist-info/WHEEL
 │ │   running build_py
 │ │   running egg_info
 │ │   creating /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info
 │ │   writing /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/PKG-INFO
 │ │   writing dependency_links to /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/dependency_links.txt
 │ │   writing entry points to /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/entry_points.txt
 │ │   writing requirements to /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/requires.txt
 │ │   writing top-level names to /var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/top_level.txt
 │ │   writing manifest file '/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/SOURCES.txt'
 │ │   adding license file 'LICENSE'
 │ │   writing manifest file '/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/tmpkzxsp903.build-temp/xarray.egg-info/SOURCES.txt'
 │ │   Editable install will be performed using a meta path finder.
 │ │   Options like `package-data`, `include/exclude-package-data` or
 │ │   `packages.find.exclude/include` may have no effect.
 │ │   adding '__editable___xarray_2026_2_1_dev59_gd8504a339_finder.py'
 │ │   adding '__editable__.xarray-2026.2.1.dev59+gd8504a339.pth'
 │ │   creating '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622048d0d19292
 │ │ ef58b00b2da/tmpoj8s69z2/.tmp-seumosgf/xarray-2026.2.1.dev59+gd8504a339-0.editable-py3-none-any.whl' and adding '/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr000
 │ │ 0gn/T/tmp6r8m6cmqxarray-2026.2.1.dev59+gd8504a339-0.editable-py3-none-any.whl' to it
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/licenses/LICENSE'
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/METADATA'
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/WHEEL'
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/entry_points.txt'
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/top_level.txt'
 │ │   adding 'xarray-2026.2.1.dev59+gd8504a339.dist-info/RECORD'
 │ │   $PREFIX/lib/python3.14/site-packages/setuptools/command/editable_wheel.py:352: InformationOnly: Editable installation.
 │ │   !!
 │ │           ********************************************************************************
 │ │           Please be careful with folders in your working directory with the same
 │ │           name as your package as they may take precedence during imports.
 │ │           ********************************************************************************
 │ │   !!
 │ │     with strategy, WheelFile(wheel_path, "w") as wheel_obj:
 │ │   Building editable for xarray (pyproject.toml): finished with status 'done'
 │ │   Created wheel for xarray: filename=xarray-2026.2.1.dev59+gd8504a339-0.editable-py3-none-any.whl size=13072 sha256=04441b28f40f1716908e91d1054602f6d189ad6
 │ │ 89242e136bb34508b1b1217ca
 │ │   Stored in directory: /private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-ephem-wheel-cache-_l3ninea/wheels/c3/e2/a3/1c738493aaa35154a7983cef4622
 │ │ 048d0d19292ef58b00b2da
 │ │ Successfully built xarray
 │ │ Installing collected packages: xarray
 │ │ Successfully installed xarray-2026.2.1.dev59+gd8504a339
 │ │ Removed build tracker: '/private/var/folders/b3/2bq1m1_50bs4c7305j8vxcqr0000gn/T/pip-build-tracker-kxkmnhse'
 │ │
 │ ╰─────────────────── (took 29 seconds)
 │
 │ ╭─ Packaging new files
 │ │ Copying done!
 │ │ ⚠ warning Found dist-info folder with incorrect name or version: xarray-2026.2.1.dev59+gd8504a339.dist-info
 │ │ Post-processing done!
 │ │ Writing test files
 │ │ Writing metadata for package
 │ │ Copying license files
 │ │ Copying recipe files
 │ │ Creating entry points
 │ │ 
 │ │ Files in package:
 │ │   ├─ CACHEDIR.TAG (183 B)
 │ │   ├─ site-packages/__editable__.xarray-2026.2.1.dev59+gd8504a339.pth (123 B)
 │ │   ├─ site-packages/__editable___xarray_2026_2_1_dev59_gd8504a339_finder.py (3.41 KiB)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/INSTALLER (6 B)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/METADATA (12.24 KiB)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/RECORD (1.21 KiB)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/REQUESTED (0 B)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/WHEEL (91 B)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/direct_url.json (87 B)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/entry_points.txt (72 B)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/licenses/LICENSE (10.03 KiB)
 │ │   ├─ site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/top_level.txt (7 B)
 │ │   ├─ info/about.json (190 B)
 │ │   ├─ info/hash_input.json (29 B)
 │ │   ├─ info/index.json (307 B)
 │ │   ├─ info/link.json (75 B)
 │ │   ├─ info/paths.json (2.81 KiB)
 │ │   └─ info/tests/tests.yaml (3 B)
 │ │ 
 │ │ Package statistics: 18 files (12 content, 6 metadata), total size: 30.85 KiB
 │ │ Largest files:
 │ │   12.24 KiB - site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/METADATA
 │ │   10.03 KiB - site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/licenses/LICENSE
 │ │   3.41 KiB - site-packages/__editable___xarray_2026_2_1_dev59_gd8504a339_finder.py
 │ │   1.21 KiB - site-packages/xarray-2026.2.1.dev59+gd8504a339.dist-info/RECORD
 │ │   183 B - CACHEDIR.TAG
 │ │ Creating target folder '/Users/agriyakhetarpal/Desktop/xarray/.pixi/build/work/xarray-QZRx5ZYrqz8-TwLmj22Yeao/output/noarch'
 │ │ Creating empty build folder "/Users/agriyakhetarpal/Desktop/xarray/.pixi/build/work/xarray-QZRx5ZYrqz8-TwLmj22Yeao/output/osx-arm64"
 │ │ Compressing archive...
 │ │ Archive written to '/Users/agriyakhetarpal/Desktop/xarray/.pixi/build/work/xarray-QZRx5ZYrqz8-TwLmj22Yeao/output/noarch/xarray-9999.0.0-pyh4616a5c_0.conda'
 │ │
 │ ╰─────────────────── (took 0 seconds)
 │ Checking for symlinks ...
 │
 ╰─────────────────── (took 29 seconds)
Traceback (most recent call last):
  File "/Users/agriyakhetarpal/Desktop/xarray/doc/create_environment.py", line 25, in <module>
    main()
    ~~~~^^
  File "/Users/agriyakhetarpal/Desktop/xarray/doc/create_environment.py", line 12, in main
    raise RuntimeError(f"zero or more than one package found: {package_paths}")
RuntimeError: zero or more than one package found: []

@keewis

keewis commented Feb 25, 2026

Copy link
Copy Markdown
Collaborator Author

you need to run pixi run build first, otherwise the package is not available for inclusion in the jupyterlite bundle. You can also use pixi run build-and-host to run the full chain of commands (build, doc, host-static-doc).

@keewis

keewis commented Mar 9, 2026

Copy link
Copy Markdown
Collaborator Author

I've experimented a bit more, and it looks like moving _contents into _build works fine. jupyterlite-sphinx doesn't have that option yet (it uses f"{app.srcdir}/{CONTENT_DIR}", where CONTENT_DIR is hard-coded to _contents), but maybe it should?

@keewis keewis left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

after a long time this should be ready for a final review now

Comment thread pixi.toml
cfgrib = "*"
myst-parser = "*"
# use the official version once https://github.com/jupyterlite/jupyterlite-sphinx/pull/346 has been resolved
jupyterlite-sphinx = { version = "*", channel = "https://prefix.dev/keewis-oss" }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this is making use of a conda package I created using pixi publish and uploaded to prefix.dev. It contains the code from jupyterlite/jupyterlite-sphinx#346. As mentioned in the comment, once that PR has been resolved (whether that's merged, superseded, or simply because we figured out a better way), we can go back to the official version from conda-forge.

Comment thread doc/whats-new.rst
Documentation
~~~~~~~~~~~~~
- Use ``jupyterlite-sphinx`` to provide interactive examples (:pull:`10299`).
By `Justus Magin <https://github.com/keewis>`_.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

this will need to be moved to the most recent release section

- https://prefix.dev/conda-forge
dependencies:
- xeus-python
- "{{ local-package }}"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we can probably remove the templating step for the recipe (which would be nice, the additional step just makes this a bit trickier), but I will defer that to a separate PR

Comment thread pixi.toml
Comment on lines +393 to +402
cmd = [
"rattler-build",
"build",
"-c",
"conda-forge",
"--recipe",
"ci/recipe/recipe.yaml",
"--output-dir",
"local_channel",
]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

we can probably replace this with a call to pixi publish --target-dir .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI Continuous Integration tools skip-ci topic-documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants