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.40.0) so offline notebooks work with no network at render time.

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 valuesNaN, 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.

Download files

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

Source Distribution

lattice_grid_jupyter-0.1.0.tar.gz (739.8 kB view details)

Uploaded Source

Built Distribution

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

lattice_grid_jupyter-0.1.0-py3-none-any.whl (741.4 kB view details)

Uploaded Python 3

File details

Details for the file lattice_grid_jupyter-0.1.0.tar.gz.

File metadata

  • Download URL: lattice_grid_jupyter-0.1.0.tar.gz
  • Upload date:
  • Size: 739.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lattice_grid_jupyter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b55be7b3c488a87049bf17f1314008416884812d7cce62a0e4a84d620165483e
MD5 e9f1e3dd89206979cee5a27df1fd602f
BLAKE2b-256 6709a31925e6a0e71eb5d1359e8acd441fc48f55f890ab5df162aec86d166347

See more details on using hashes here.

Provenance

The following attestation bundles were made for lattice_grid_jupyter-0.1.0.tar.gz:

Publisher: publish-pypi.yml on toclocoinc/lattice-grid-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lattice_grid_jupyter-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lattice_grid_jupyter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2470d9d9f8b566bd906be6d2866a297a04a04fd40cc3431640ee62468596b0de
MD5 f858c86deb40d7564dc4dd15ecb4a515
BLAKE2b-256 a9443dd418c4a1d176d9599662012fe1ef99d7e72ff4fec7d0c207b43c2ff24a

See more details on using hashes here.

Provenance

The following attestation bundles were made for lattice_grid_jupyter-0.1.0-py3-none-any.whl:

Publisher: publish-pypi.yml on toclocoinc/lattice-grid-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 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