Skip to main content

Author and compose Mosaic clients as anywidgets.

Project description

boro

author and compose mosaic clients as anywidgets

install

uv add boro

what

mosaic is an architecture for interactive linked views over millions of rows: clients publish queries, a coordinator manages and cross-filters them against a data source (e.g., duckdb).

vgplot is how you usually author custom mosaic-based visualizations, a bundle with its own grammar and layout. boro is the same client/coordinator architecture, but each client is a standalone anywidget.

primitives

three anywidgets:

  • Coordinator — owns a DataSource and the js-side mosaic engine. brokers queries over arrow ipc. headless.
  • Selection — wraps a mosaic Selection. value syncs the array of clauses (sql predicates) to python.
  • Client — base class. Required coord; conventional filter_by (read side) and target (publish side) selection slots, both boro.SelectionTrait. Subclasses can declare further selection slots with boro.SelectionTrait().

The base accepts a unified selection= shortcut covering all four shapes:

Histogram(c, ..., selection=sel)              # crossfilter (both slots = sel)
Histogram(c, ..., selection=(scope, detail))  # asymmetric pair
Histogram(c, ..., selection=(sel, None))      # read-only (filter only)
Histogram(c, ..., selection=(None, sel))      # publish-only

Explicit filter_by= / target= kwargs override the shortcut.

each client is its own _esm and DOM. the mosaic engine and js deps live once, in the coordinator; clients reach it via host.getWidget(...).

hello world

import boro
import duckdb

con = duckdb.connect()
con.execute("CREATE TABLE flights AS SELECT * FROM read_parquet('flights.parquet')")

c = boro.Coordinator.connect(con)
sel = boro.Selection.crossfilter(c)
Histogram(c, table="flights", column="delay", selection=sel)
Scatter(c, table="flights", x="distance", y="delay", selection=sel)
>>> sel.value
[{'value': [5, 30], 'sql': '"delay" BETWEEN 5 AND 30', 'meta': {...}, 'source': '...'}]

writing a client

import boro
import traitlets


class RowCounter(boro.Client):
    _esm = """
    export default {
      async render({ model, host, signal, el }) {
        el.style.cssText = "font: 14px ui-sans-serif; padding: 6px 8px;";
        el.textContent = "…";
        const coord = await host.getWidget(model.get("coord"));
        const { Query, msql, createClient } = coord.exports;
        const ctx = await createClient({ model, host, signal });
        ctx.liveQuery({
          filterBy: ctx.filterBy,
          query: (filter) =>
            Query.from(model.get("table"))
              .select({ n: msql.count() })
              .where(filter ?? []),
          onResult: (result) => {
            if (!result.isSuccess) {
              return;
            }
            const n = Number(result.data.toColumns().n[0]);
            el.textContent = `${n.toLocaleString()} rows`;
          },
        });
      },
    };
    """
    table = traitlets.Unicode().tag(sync=True)

    def __init__(self, coord: boro.Coordinator, table: str, **kwargs):
        super().__init__(coord=coord, table=table, **kwargs)


RowCounter(c, table="flights", selection=sel)

coord.exports provides Query / msql (mosaic-sql), mc (mosaic-core), and createClient. createClient({ model, host, signal }) returns a ctx that exposes:

  • ctx.selections.<name> — resolved mosaic Selections, one per boro.SelectionTrait field on the Python class (filter_by / target come from the base; subclasses can declare more).
  • ctx.state(name, opts?) — a {get, set, subscribe} handle on a sync trait. Optional {target, clause} opts auto-derive a clause from the trait and publish it to a Selection on every change.
  • ctx.liveQuery({ filterBy }, queryFn, onState) — registers a filter-driven query. onState receives {status: 'idle'|'pending'|'success'|'error', data, error}.
  • ctx.coordinator — the mosaic Coordinator for one-shot ad-hoc queries (await ctx.coordinator.query(sql, { type: 'arrow' })).
  • ctx.client, ctx.clients, ctx.signal — the synthetic primary MosaicClient (clause source identity), the Set of all sibling clients used for cross-filter exclusion in state-derived clauses, and the abort signal scoped to this render.

example

uv run jupyterlab examples/

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

boro-0.0.0.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

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

boro-0.0.0-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file boro-0.0.0.tar.gz.

File metadata

  • Download URL: boro-0.0.0.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for boro-0.0.0.tar.gz
Algorithm Hash digest
SHA256 79b0621b125c93580de9bbf30784204b38e70a9fd883fe757f1a1560dd8df0bf
MD5 af435a994b2c3001728ad79563004edb
BLAKE2b-256 7b502a9cf15d0e46b3f1768b27e32e90006912f8fed6df7cef68b27cf8f6a7dd

See more details on using hashes here.

File details

Details for the file boro-0.0.0-py3-none-any.whl.

File metadata

  • Download URL: boro-0.0.0-py3-none-any.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for boro-0.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4657a987fc461998dcb52271fe374bbd7d87e15db67135a22d7e4e92d623fb8c
MD5 16446d831459b60289524b4ff022c4d3
BLAKE2b-256 b0d035df76979ae731ece4751b0cee8e3ccccc087d2b59dc3b3b7574a3b2969a

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