Comparing packages
A notebook that runs One package's numbers for four web frameworks through Ganymede's host API and compares the results; its first cell says what it needs. The copy below ran with ganymede execute, which grants on the command line and needs a Ganymede release after 0.9.0:
ganymede execute compare-packages.ipynb --grant run=package-stats.ipynbSee Other notebooks: jupyter.host().
This notebook runs another notebook, One package's numbers (package-stats.ipynb), once for each of four web frameworks, and compares the results. Each run starts a fresh kernel with the package name as its parameter and comes back with the named results.
It needs a Ganymede server, which answers jupyter.host(), and a grant that lets this notebook run the other:
ganymede grant compare-packages.ipynb run=package-stats.ipynbWithout a server, jupyter.host() resolves to null and the notebook stops at the first cell, as it would under plain Jupyter.
The host
const host = await jupyter.host();
if (!host) throw new Error("No Ganymede server: open this notebook under ganymede lab or ganymede execute.");
host.has("notebooks.run")trueRun the notebook for each package
host.notebooks.run runs the notebook to the end and answers with its named results. The runs here go one after another; Promise.all would run them at once, each in its own kernel.
const packages = ["express", "fastify", "hono", "koa"];
type Stats = { package: string; latest: string; stable_releases: number; first_release: string; weekly_downloads: number };
const rows: Stats[] = [];
for (const pkg of packages) {
const run = await host.notebooks.run({ path: "package-stats.ipynb", params: { pkg } });
rows.push(run.results as Stats);
}
rows.map((r) => `${r.package}: ${r.weekly_downloads}`)[ 'express: 195384165', 'fastify: 22307443', 'hono: 104726612', 'koa: 9568603' ]
The results are data the other notebook wrote, so this one treats them as values, never as code to run.
Compare
jupyter.md`| Package | Latest | Stable releases | First release | Downloads last week |
| --- | --- | ---: | --- | ---: |
${rows.map((r) => `| ${r.package} | ${r.latest} | ${r.stable_releases} | ${r.first_release} | ${r.weekly_downloads.toLocaleString("en")} |`).join("\n")}`| Package | Latest | Stable releases | First release | Downloads last week |
|---|---|---|---|---|
| express | 5.3.0 | 247 | 2010-12-29 | 195,384,165 |
| fastify | 5.12.8 | 301 | 2016-10-07 | 22,307,443 |
| hono | 4.13.18 | 415 | 2021-12-14 | 104,726,612 |
| koa | 3.3.0 | 112 | 2013-11-06 | 9,568,603 |
import * as vl from "npm:vega-lite-api@5";
vl.markBar()
.data(rows)
.encode(
vl.y().fieldN("package").sort("-x").title(null),
vl.x().fieldQ("weekly_downloads").title("downloads last week"),
vl.tooltip(["package", "latest", "weekly_downloads"]),
)
.width(460)
.height(160)Publish
This notebook is a program too: its own named results are there for whoever runs it.
const top = rows.toSorted((a, b) => b.weekly_downloads - a.weekly_downloads)[0];
jupyter.result("most_downloaded", top.package);
jupyter.result("downloads", Object.fromEntries(rows.map((r) => [r.package, r.weekly_downloads])));most_downloaded = "express"
downloads = {"express":195384165,"fastify":22307443,"hono":104726612,"koa":9568603}Next
- Other notebooks:
jupyter.host()has the other host calls:list,read,searchandresults. - Notebooks as programs in Ganymede's docs has the grants, and running a notebook from a link or a Shortcut.