Observable JavaScript notebooks as reusable Python widgets
Project description
pyobservablejs
Observable JavaScript notebooks as Python widgets.
pyobservablejs renders Observable JavaScript cells from Python and runs them with
Observable Notebook Kit in the browser. Python owns the notebook model, synced
OJS variables, and cell widgets. TypeScript owns Notebook Kit evaluation,
rendering, and runtime metadata.
import pyobservablejs as obs
rows = [
{"letter": "A", "frequency": 0.0812},
{"letter": "B", "frequency": 0.0149},
{"letter": "C", "frequency": 0.0271},
{"letter": "D", "frequency": 0.0432},
{"letter": "E", "frequency": 0.1202},
]
obs.Notebook(
obs.md("# Letter frequencies"),
obs.ojs("""
Plot.plot({
height: 260,
marginLeft: 48,
y: {grid: true, label: "frequency"},
marks: [
Plot.ruleY([floor]),
Plot.barY(rows, {x: "letter", y: "frequency", tip: true})
]
})
"""),
variables={"rows": rows, "floor": 0.04},
)
Install
pip install pyobservablejs
or:
uv add pyobservablejs
pyobservablejs supports Python 3.10 through 3.14.
Notebook Model
obs.Notebook(...)builds a Notebook Kit notebook from Python-authored cells.variables={...}sets OJS variables. A matching notebook variable is overridden.notebook.update_variables(...)pushes Python-side changes into the live OJS runtime.name="..."gives Python a stable name for a cell.notebook.valuesandnotebook.cell("name").valueread browser-synchronized outputs after rendering.notebook.graphexposes Notebook Kit-derived cell definitions, references, and dependency edges.
Cell helpers keep the source mode explicit:
| Helper | Source mode |
|---|---|
obs.ojs(...) |
Observable JavaScript |
obs.js(...) |
ES module JavaScript |
obs.md(...) |
Markdown |
obs.html(...) |
HTML |
notebook = obs.Notebook(
obs.md("# Inputs"),
obs.ojs('viewof gain = Inputs.range([0, 11], {value: 5})', name="gain"),
obs.ojs("double = gain * 2", name="double"),
)
notebook.cell("gain")
After the notebook or cell widget has rendered in the browser, read the synced value from a later Python cell:
notebook.value("double")
Source Notebooks
Load Notebook Kit HTML from a string:
from pathlib import Path
path = Path("chart.html")
notebook = obs.Notebook.from_html(
path.read_text(encoding="utf-8"),
base_path=path.parent,
)
Local FileAttachment(...) references and relative JavaScript imports are
embedded by default so the widget can move between notebook frontends.
Load a public ObservableHQ notebook by URL, slug, or id:
notebook = obs.Notebook.from_observablehq("https://observablehq.com/@mbostock/saving-svg")
Remote FileAttachment(...) entries are registered as URL-backed attachments,
so Plot notebooks and examples with uploaded files can render in the widget.
Pass variables={...} to override variables in a loaded notebook with Python values.
Documentation
Built On
- anywidget and traitlets for widget composition and synced state
- Observable Notebook Kit and @observablehq/runtime for cell transpilation and browser execution
- Shiki for pinned source highlighting
Contributing
See CONTRIBUTING.md for local setup, workbench notebooks, and the check commands used before sending changes for review.
Acknowledgements
pyobservablejs builds on Observable Notebook Kit
and @observablehq/runtime.
pyobsplot informed the Python-to-OJS
variable API.
Thanks to @manzt (Trevor Manz) for the composable anywidgets demo that helped shape the widget design.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyobservablejs-0.0.0rc1.tar.gz.
File metadata
- Download URL: pyobservablejs-0.0.0rc1.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
155b792a161ba62d12d313d160da7b172186b83a05787e01c7c3b020d70e31a2
|
|
| MD5 |
6eaf4ad35f43fca866336108430ba537
|
|
| BLAKE2b-256 |
ee7f11ddbdd46c020e0dfd8fcfd89ebae90c681a746c42135ec22f422918e0ad
|
File details
Details for the file pyobservablejs-0.0.0rc1-py3-none-any.whl.
File metadata
- Download URL: pyobservablejs-0.0.0rc1-py3-none-any.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
64ffa5bf88129abbf35a51d7e4a2b30eebad15c46138cf10d55428ab645bb5f6
|
|
| MD5 |
f63c550c2bde60cd431a6d0629367973
|
|
| BLAKE2b-256 |
8b776de82fa856823e75cdd499f2eec18e2abb8d3ec1c19b43c7aa04bc78082b
|