Skip to main content

lattice-grid-jupyter

Edit a pandas DataFrame as an interactive Lattice Grid inside Jupyter, with a live two-way round-trip back to Python.

import pandas as pd
from lattice_grid_jupyter import LatticeGridWidget

df = pd.DataFrame({"name": ["Ada", "Grace"], "score": [91, 88], "active": [True, False]})

w = LatticeGridWidget(df)   # renders an editable grid
w                           # display it in a notebook cell
# ...edit cells in the grid...
w.df                        # the DataFrame, reflecting your edits (dtypes preserved)

Built on anywidget, so it works in JupyterLab, classic Notebook, VS Code, Colab, and anywhere ipywidgets render.


Install

pip install lattice-grid-jupyter

Depends on anywidget and pandas. The wheel vendors the published Lattice Grid bundle (@toclocoinc/lattice-grid@1.71.3) so offline notebooks work with no network at render time.

Which grid am I getting?

The one the version number says. A wheel is numbered <grid version>.<revision> — 1.69.0.0 carries Lattice Grid 1.69.0 — so the answer is on the tin, and in Python:

import lattice_grid_pandas
lattice_grid_pandas.GRID_VERSION   # '1.69.0' -- read from the vendored bundle

All three packages (lattice-grid-pandas, lattice-grid-jupyter, lattice-grid-dash) share the number and are released together; the two host wrappers pin the shared one exactly, so a mixed install is refused rather than quietly assembled. A revision above 0 is a packaging fix for the same grid.

Every grid release rebuilds these wheels automatically, so pip install --upgrade lattice-grid-jupyter gets you the current grid.

The grid bundle: CDN vs vendored

Two ways the browser gets the grid JS/CSS, chosen per widget:

Mode How When
CDN (default) dynamic import() from jsDelivr at render time online notebooks; smallest saved-notebook size
Vendored (offline=True) the bundle text ships in the widget model air-gapped / offline notebooks
w = LatticeGridWidget(df)                # CDN (default)
w = LatticeGridWidget(df, offline=True)  # vendored, no network needed

The default is CDN. Vendored mode carries ~3 MB of grid JS in the widget model, which inflates a saved .ipynb; prefer CDN when you have network. (An alternative not implemented here would serve the vendored asset over Jupyter's own static handler instead of the comm; see Notes below.)

What the DataFrame maps to

dtypes -> grid column types

pandas dtype grid column type
int*, Int* (nullable), float* number
bool, boolean (nullable) boolean
datetime64 (naive or tz-aware) timestamp (ISO 8601)
category, object, string, timedelta text

Index

  • A default RangeIndex(0..n-1) is not shown as a column (it adds nothing).
  • A named / non-default index becomes one read-only leading column.
  • A MultiIndex becomes one read-only column per level.
  • Row identity is a stable, positional id (__row_id__), never the index label — so duplicate index labels and every other index shape work correctly and edits always land on the right row.

Missing values — NaN, NaT and pd.NA all serialize to JSON null.

Editing round-trip

Every committed cell edit in the grid flows back to w.df, cast to the column's dtype (an int column stays int, etc.). Index columns are read-only.

Live updates: Python -> grid

w.set_data(new_df)                 # replace the whole frame, repaint
keys = w.append_rows([{...}, ...]) # append rows (DataFrame or list-of-dicts)
w.append_rows(other_df)
w.delete_rows(keys)                # delete by the keys append_rows returned

append_rows / delete_rows push incremental changes to the grid (grid.rows.apply({add|remove})); set_data does a full grid.rows.load(). Row keys are stable, so keys returned by append_rows stay valid for delete_rows and for later edits.

Large DataFrames

The frame is serialized column-major ({field: [values...]}), not as a list-of-dicts:

  • field names are not repeated per row (roughly halves the payload for wide frames);
  • each column is built with a vectorized pass, not DataFrame.iterrows() — which is the real reason a naive list-of-dicts build stalls at 100k rows;
  • the grid's memory source virtualizes rendering, so only the visible window is ever in the DOM.

This handles a 100,000-row frame without freezing (see tests/ and the demo notebook). For frames far larger than fit in the browser (millions of rows), the grid also exposes paged / remote / stream source modes whose fetch callback would page back into the Python kernel over the comm — that is the documented extension point, not wired in this release.

Licensing

The grid renders fully and unwatermarked on localhost (the normal data-science case) with no key — that is the free tier. A widget served from a non-localhost origin (a deployed notebook server, Voila, Binder on a public host) should pass a key:

w = LatticeGridWidget(df, licence="LG-...")

The key is threaded straight into createGrid({ licence }); grid.licence.state() resolves to localhost, licensed, or trial.

Development / tests

pip install -e ".[dev]"
pytest tests/test_serialize.py tests/test_roundtrip.py   # Python round-trip (no browser)
pytest tests/test_smoke_browser.py                        # real-browser smoke test

The smoke test drives a real Chromium via Playwright: it renders the widget's front end, performs a real edit in the grid, and asserts the edit payload reached the (mocked) model — the one gap the headless Python tests cannot cover. It uses the vendored bundle, so it needs no network. If no browser is available it is skipped (never faked).

Notes / not in this release

  • Vendored mode transfers the bundle through the widget comm; serving it over Jupyter's static handler would keep saved notebooks small — a future option.
  • set_data assumes the same schema (columns/index shape). A different schema should use a fresh widget.
  • Binary (Arrow/typed-array) transfer would beat columnar-JSON for very wide numeric frames; columnar-JSON is what ships here.

Built with Lattice Grid, a JavaScript data grid with a Data Router: one live feed keeps grids, charts, boards, Gantt and KPI tiles in step. Documentation · Demos · Licence

Release files for lattice-grid-jupyter 1.71.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lattice-grid-jupyter 1.71.3.0
File Size Uploaded
lattice_grid_jupyter-1.71.3.0.tar.gz 716.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lattice-grid-jupyter 1.71.3.0
File Interpreter ABI Platform
lattice_grid_jupyter-1.71.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / lattice_grid_jupyter-1.71.3.0.tar.gz

Download URL lattice_grid_jupyter-1.71.3.0.tar.gz
Size 716.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9e6fcf3f68ed373e6e78b06dbd5cf13160ccda927ad1eba160c0614454779304
BLAKE2b-256 checksum
How to use checksums
610c55e703d4bd746ba56a8b9cb91a2c9efe37ec6d15ab69270828c6d9e3b7fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / lattice_grid_jupyter-1.71.3.0-py3-none-any.whl

Download URL lattice_grid_jupyter-1.71.3.0-py3-none-any.whl
Size 711.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70964fae35bdb26f1cb79552fc7324246cf274db1acc8b3a176a16a7efe4175a
BLAKE2b-256 checksum
How to use checksums
70f5f379fdd94d9106aa05c625256f840d1480d232998187d7306a14838cbb3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.71.3.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page