Skip to main content

Generate static reports from Jupyter notebooks

Project description

leda

Generate static HTML reports with interactive widgets from Jupyter notebooks

PyPI version PyPI Supported Python Versions GitHub Actions (Tests)

Installation

leda is available on PyPI:

pip install leda

Quick Start

Generation

To generate a static HTML report from a Jupyter notebook, run:

python -m leda /path/to/nb.ipynb --output-dir ./outputs/

# Optional args:
python -m leda /path/to/nb.ipynb --output-dir ./outputs/ \
    -i "abc = 123" -k "other_kernel" --cell-timeout 100

This generation automatically includes tweaks to the notebook to make the output look more report-like (e.g., hiding all input code)

See the static demos being served by GitHub Pages.

leda is like:

  • voila, but static, with no need for live kernels
  • quarto, but with static interactive widgets
  • nbconvert/ nbviewer, but self-hosted, designed for reports, and with static interactive widgets
  • papermill, but designed for reports and with static interactive widgets
  • pretty-jupyter, but with static interactive widgets

The -i (--inject) arg is used to inject user code (and set report params) via a new cell prepended to the notebook during generation.

And the --template_name/--theme args allow you to choose between classic, lab (light/dark), and lab_narrow (light/dark).

Note: leda assumes that all code is run in a trusted environment, so please be careful.

Interaction/Widgets

leda also provides an %%interact magic that makes it easy to create outputs based on widgets that work in both dynamic and static modes, e.g.:

# In[ ]:


import leda
import numpy as np
import pandas as pd


# In[ ]:


# Loads `interact` magic when running in Jupyter notebook.
leda.init("matplotlib")


# In[ ]:


%%interact column=list("abcdefghij");mult=[1, 2, 3]
df = pd.DataFrame(
  np.random.RandomState(42).rand(100, 10), columns=list("abcdefghij")
)
title = f"column={column!r}, mult={mult}"
(df[[column]] * mult).plot(figsize=(15, 8), lw=2, title=title)

There are two types of interact modes: dynamic and static.

Dynamic mode is when you're running the Jupyter notebook live, in which case you will re-compute the cell output every time you select a different mult. We always use ipywidgets as the dynamic widget backend.

In static mode (using whichever static widget backend is configured), the library will pre-compute all possible combinations of widget outputs (see Cartesian product) and then render a static HTML report that contains widgets that look and feel like the dynamic widgets (despite being pre-rendered). See below for a list of supported static backends.

The non-magic equivalent of the last cell would be:

def func(column: str, mult: int) -> object:
    df = pd.DataFrame(
        np.random.RandomState(42).rand(100, 10), columns=list("abcdefghij")
    )
    title = f"column={column!r}, mult={mult}"
    return (df[[column]] * mult).plot(figsize=(15, 8), lw=2, title=title)


leda.interact(func, column=list("abcdefghij"), mult=[1, 2, 3])

Report Web UI Server

Unlike voila, because all report output is static HTML, you can stand up a report web UI server that suits your needs very easily. That means:

  • It's trivial to set up in many cases.
  • It's as scalable as your web server's ability to distribute static content.
  • It's more cost-efficient because there are no runtimes whatsoever.
  • You don't have to worry about old versions no longer working due to code or data changes, so the historical archive of old reports never expires or changes or breaks.

For example, you can generate the report to a file, upload that file to a shared location, and then stand up a bare-bones nginx server to serve the files. Instead of having a two-step process of generation + upload, you could alternatively implement your own leda.ReportPublisher and create a generation script of your own--or use it as a library in client script.

Another example is you can simply host a static S3 bucket, enable website hosting and then either use S3 as a web server publically or via locked down S3 endpoint.

You could also use GitHub Pages, much like the static demos page.

Params

Reports can be parametrized so that the user can set different values for each report run.

In the notebook, just use leda.get_param():

# In[ ]:


import leda


# In[ ]:


data_id = leda.get_param("data_id", dynamic_default=1, static_default=2)

And then change the injected code during each run:

python -m leda /path/to/nb.ipynb --output ./outputs/ -i "data_id = 100"

Modular

leda is built to work with multiple visualization and widget libraries.

It works with these visualization libraries:

With the default dynamic widget library:

And with these static widget libraries:

Testing

See the integration test environments in pixi.toml for version bundles that we currently test systematically.

Known Issues

  • There are multiple issues using matplotlib with panel, including:
    • The last widget output is not different from the penultimate one: https://github.com/holoviz/panel/issues/1222
    • All the widget outputs show up sequentially, instead of being hidden until chosen. This seems to be a known issue per the panel FAQ; however, using the example fix provided does not work.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leda-1.0.0.tar.gz (102.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

leda-1.0.0-py3-none-any.whl (48.7 kB view details)

Uploaded Python 3

File details

Details for the file leda-1.0.0.tar.gz.

File metadata

  • Download URL: leda-1.0.0.tar.gz
  • Upload date:
  • Size: 102.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for leda-1.0.0.tar.gz
Algorithm Hash digest
SHA256 62ed1bf86891e7847f3779cad5a8ce9039e02638391e23e0a7cdaf096a993668
MD5 1e8045ac657b7a37c6d3c1e0a9694b84
BLAKE2b-256 ecc443ac2c3152c9bbdfcae94883881c0467269d7307922e096a476d0a0de3f2

See more details on using hashes here.

File details

Details for the file leda-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: leda-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 48.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for leda-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a703cdb53c2b62e2246ac792c108517f37db141681a086b469c3ed21a0ae405
MD5 34e75e595dc131e684a36fdeacf10922
BLAKE2b-256 c9bd9cccf02ff98b8fd2e2c4a6248049cff479c9f63736fad87c2b2353461665

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page