Metadata-Version: 2.4
Name: pyobservablejs
Version: 0.0.7
Summary: Observable JavaScript notebooks as reusable Python widgets
Project-URL: Homepage, https://github.com/peter-gy/pyobservablejs
Project-URL: Documentation, https://peter-gy.github.io/pyobservablejs/
Project-URL: Source, https://github.com/peter-gy/pyobservablejs
Project-URL: Issues, https://github.com/peter-gy/pyobservablejs/issues
Author-email: Peter Ferenc Gyarmati <dev.petergy@gmail.com>
Maintainer-email: Peter Ferenc Gyarmati <dev.petergy@gmail.com>
License-Expression: MIT
License-File: LICENSE
License-File: NOTICE
Keywords: anywidget,jupyter,marimo,notebooks,observable,visualization
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.11
Requires-Dist: anywidget-bundle==0.0.1
Requires-Dist: anywidget>=0.11.0
Requires-Dist: traitlets>=5
Description-Content-Type: text/markdown

# pyobservablejs

[![CI](https://github.com/peter-gy/pyobservablejs/actions/workflows/ci.yml/badge.svg)](https://github.com/peter-gy/pyobservablejs/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/pyobservablejs.svg)](https://pypi.org/project/pyobservablejs/)
[![Python versions](https://img.shields.io/pypi/pyversions/pyobservablejs.svg)](https://pypi.org/project/pyobservablejs/)
[![License](https://img.shields.io/pypi/l/pyobservablejs.svg)](https://github.com/peter-gy/pyobservablejs/blob/main/LICENSE)

`pyobservablejs` embeds reactive Observable notebooks in Python. Author cells or
load an existing notebook, render all or selected cells, synchronize Python
values, read structured browser results, and inspect the dependency graph.

![An authored notebook with an interactive filter and plot](https://files.peter.gy/projects/pyobservablejs/assets/from-code.gif)

It works in JupyterLab, marimo, VS Code notebooks, Google Colab, and other
environments that support [anywidget](https://anywidget.dev/).

## Install or try

Add `pyobservablejs` to an existing Python 3.11 or newer environment:

```sh
uv pip install pyobservablejs
```

Or open a disposable marimo environment with the package available:

```sh
uvx --with pyobservablejs marimo edit notebook.py
```

This command installs marimo and `pyobservablejs` in the temporary environment.

## Quickstart

Paste this into the marimo editor opened above:

```python
import marimo as mo
import observablejs as obs

control = obs.ojs(
    """
    viewof threshold = Inputs.range([0, 1], {
      value: 0.5,
      step: 0.1,
      label: "Threshold"
    })
    """,
    key="threshold",
)

result = obs.js(
    'html`<strong>Threshold: ${threshold}</strong>`',
    key="result",
)

notebook = obs.Notebook(
    control,
    result,
    variables={"threshold": 0.5},
)

mo.ui.anywidget(notebook.view())
```

Each cell `key` is its portable Python identity. Render one result with
`notebook.view("result")`.

## Capabilities

| Task                                                               | API                                                |
| ------------------------------------------------------------------ | -------------------------------------------------- |
| Author JavaScript, Observable JavaScript, Markdown, and HTML cells | `obs.js`, `obs.ojs`, `obs.md`, `obs.html`          |
| Load Notebook Kit HTML or an ObservableHQ notebook                 | `Notebook.from_html`, `Notebook.from_observablehq` |
| Render a whole notebook or selected keyed cells                    | `notebook.view()` and `notebook.view("chart")`     |
| Update Python-owned variables                                      | `notebook.update_variables({"threshold": 0.8})`    |
| Read pending, successful, and failed browser results               | `view.state` and `view.state.result("chart")`      |
| Inspect dependencies or export a diagram                           | `view.state.graph`, `to_mermaid()`, and `to_d2()`  |

Views from one `Notebook` share controller variables and supported browser
inputs. Each view keeps its own result state plus input and settled revision
metadata.

![Python and browser values updating one notebook](https://files.peter.gy/projects/pyobservablejs/assets/sync-variables.gif)

### Import notebooks

Notebook cells execute as JavaScript in the host page. Treat imported Notebook
Kit HTML, ObservableHQ notebooks, and remote modules as trusted code. See
[Browser execution](https://peter-gy.github.io/pyobservablejs/customize/browser-execution/).

```python
import marimo as mo
import observablejs as obs

notebook = obs.Notebook.from_observablehq("@d3/world-tour")
mo.ui.anywidget(notebook.view())
```

![An imported ObservableHQ notebook](https://files.peter.gy/projects/pyobservablejs/assets/from-slug.gif)

## Documentation

Read the [documentation](https://peter-gy.github.io/pyobservablejs/) for the
quickstart, task guides, recipes, troubleshooting, and API reference.

## Acknowledgements

Thanks to the Observable team for [Notebook
Kit](https://github.com/observablehq/notebook-kit), which provides the notebook
format and runtime. [`pyobsplot`](https://github.com/juba/pyobsplot) informed
the Python variable API. [Trevor Manz](https://github.com/manzt)'s anywidget
composition demo shaped the shared-session design.

## License

MIT
